summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/preferredsim/PreferredAccountWorker.java
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2018-05-01 13:46:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-05-01 13:46:37 +0000
commitcccd332af6185505101df03ebee11923d7ee5fd4 (patch)
treeb70c83971f5281b4afc9e2d0534da21c8d5fbc6a /java/com/android/dialer/preferredsim/PreferredAccountWorker.java
parenteac73f3067acefffaa8eec7b7a9d8b3cc176e674 (diff)
parent2e36647b63e859c299d8242736226c00071836d9 (diff)
Merge changes If140d716,I89a186fa,Iee4e5c09,I5df97f0c,I55f75dc3, ...
* changes: Don't start emergency call in background calling mode. Make call configuration package visibility public. Don't save transcript if it's empty. Cancel all legacy voicemail notification when SIMs are removed on multi-SIM devices Fix bug that transcript button is visible for voice call. Refactor PreferredAccountWorker to provide the dialog to be shown. Fix bug that displaying local message is not in sync. Don't show dialog if in call activity is not visible. Bubble changes for background calling. Store RTT transcript message received when UI is in background. Update RTT transcript advisory text. Implement "Add to favorites" option in suggestions menu.
Diffstat (limited to 'java/com/android/dialer/preferredsim/PreferredAccountWorker.java')
-rw-r--r--java/com/android/dialer/preferredsim/PreferredAccountWorker.java269
1 files changed, 46 insertions, 223 deletions
diff --git a/java/com/android/dialer/preferredsim/PreferredAccountWorker.java b/java/com/android/dialer/preferredsim/PreferredAccountWorker.java
index df743c342..965d08843 100644
--- a/java/com/android/dialer/preferredsim/PreferredAccountWorker.java
+++ b/java/com/android/dialer/preferredsim/PreferredAccountWorker.java
@@ -16,47 +16,35 @@
package com.android.dialer.preferredsim;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.PhoneLookup;
-import android.provider.ContactsContract.QuickContact;
-import android.provider.ContactsContract.RawContacts;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.support.annotation.WorkerThread;
import android.telecom.PhoneAccountHandle;
-import android.text.TextUtils;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutor.Worker;
-import com.android.dialer.configprovider.ConfigProviderBindings;
-import com.android.dialer.preferredsim.PreferredAccountWorker.Result;
-import com.android.dialer.preferredsim.PreferredSimFallbackContract.PreferredSim;
-import com.android.dialer.preferredsim.suggestion.SimSuggestionComponent;
+import com.android.contacts.common.widget.SelectPhoneAccountDialogOptions;
import com.android.dialer.preferredsim.suggestion.SuggestionProvider.Suggestion;
-import com.android.dialer.util.PermissionsUtil;
import com.google.auto.value.AutoValue;
import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
/** Query a preferred SIM to make a call with. */
-public class PreferredAccountWorker implements Worker<Context, Result> {
+@SuppressWarnings({"missingPermission", "Guava"})
+public interface PreferredAccountWorker {
- /** The result of the worker. */
+ /** Result of the query. */
@AutoValue
- public abstract static class Result {
+ abstract class Result {
- /** The preferred phone account for the number. Absent if not set or invalid. */
- public abstract Optional<PhoneAccountHandle> getPhoneAccountHandle();
+ /**
+ * The phone account to dial with for the number. Absent if no account can be auto selected. If
+ * absent, {@link #getSelectedPhoneAccountHandle()} will be present to show a dialog for the
+ * user to manually select.
+ */
+ public abstract Optional<PhoneAccountHandle> getSelectedPhoneAccountHandle();
+
+ /**
+ * The {@link SelectPhoneAccountDialogOptions} that should be used to show the selection dialog.
+ * Absent if {@link #getSelectedPhoneAccountHandle()} is present, which should be used directly
+ * instead of asking the user.
+ */
+ public abstract Optional<SelectPhoneAccountDialogOptions.Builder> getDialogOptionsBuilder();
/**
* {@link android.provider.ContactsContract.Data#_ID} of the row matching the number. If the
@@ -66,207 +54,42 @@ public class PreferredAccountWorker implements Worker<Context, Result> {
public abstract Optional<Suggestion> getSuggestion();
- static Builder builder() {
- return new AutoValue_PreferredAccountWorker_Result.Builder();
+ public static Builder builder(PhoneAccountHandle selectedPhoneAccountHandle) {
+ return new AutoValue_PreferredAccountWorker_Result.Builder()
+ .setSelectedPhoneAccountHandle(selectedPhoneAccountHandle);
}
- @AutoValue.Builder
- abstract static class Builder {
-
- public abstract Builder setPhoneAccountHandle(
- Optional<PhoneAccountHandle> phoneAccountHandle);
-
- public abstract Builder setDataId(Optional<String> dataId);
-
- public abstract Builder setSuggestion(Optional<Suggestion> suggestion);
-
- public abstract Result build();
+ public static Builder builder(SelectPhoneAccountDialogOptions.Builder optionsBuilder) {
+ return new AutoValue_PreferredAccountWorker_Result.Builder()
+ .setDialogOptionsBuilder(optionsBuilder);
}
- }
-
- @VisibleForTesting
- public static final String METADATA_SUPPORTS_PREFERRED_SIM =
- "supports_per_number_preferred_account";
- private final String phoneNumber;
-
- public PreferredAccountWorker(String phoneNumber) {
- this.phoneNumber = phoneNumber;
- }
-
- @NonNull
- @Override
- @WorkerThread
- public Result doInBackground(Context context) throws Throwable {
- Result.Builder resultBuilder = Result.builder();
- if (!isPreferredSimEnabled(context)) {
- return resultBuilder.build();
- }
- if (!PermissionsUtil.hasContactsReadPermissions(context)) {
- LogUtil.i("PreferredAccountWorker.doInBackground", "missing READ_CONTACTS permission");
- return resultBuilder.build();
- }
- Optional<String> dataId = getDataId(context, phoneNumber);
- Optional<PhoneAccountHandle> phoneAccountHandle = Optional.absent();
- if (dataId.isPresent()) {
- resultBuilder.setDataId(dataId);
- phoneAccountHandle = getPreferredAccount(context, dataId.get());
- }
- resultBuilder.setPhoneAccountHandle(phoneAccountHandle);
- Optional<Suggestion> suggestion = Optional.absent();
- if (!phoneAccountHandle.isPresent()) {
- suggestion =
- SimSuggestionComponent.get(context)
- .getSuggestionProvider()
- .getSuggestion(context, phoneNumber);
- resultBuilder.setSuggestion(suggestion);
- }
- return resultBuilder.build();
- }
-
- @WorkerThread
- @NonNull
- private static Optional<String> getDataId(
- @NonNull Context context, @Nullable String phoneNumber) {
- Assert.isWorkerThread();
- if (TextUtils.isEmpty(phoneNumber)) {
- return Optional.absent();
- }
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(
- Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)),
- new String[] {PhoneLookup.DATA_ID},
- null,
- null,
- null)) {
- if (cursor == null) {
- return Optional.absent();
- }
- ImmutableSet<String> validAccountTypes = PreferredAccountUtil.getValidAccountTypes(context);
- String result = null;
- while (cursor.moveToNext()) {
- Optional<String> accountType =
- getAccountType(context.getContentResolver(), cursor.getLong(0));
- if (accountType.isPresent() && !validAccountTypes.contains(accountType.get())) {
- // Empty accountType is treated as writable
- LogUtil.i("CallingAccountSelector.getDataId", "ignoring non-writable " + accountType);
- continue;
- }
- if (result != null && !result.equals(cursor.getString(0))) {
- // TODO(twyen): if there are multiple entries attempt to grab from the contact that
- // initiated the call.
- LogUtil.i("CallingAccountSelector.getDataId", "lookup result not unique, ignoring");
- return Optional.absent();
- }
- result = cursor.getString(0);
- }
- return Optional.fromNullable(result);
- }
- }
+ /** For implementations of {@link PreferredAccountWorker} only. */
+ @AutoValue.Builder
+ public abstract static class Builder {
- @WorkerThread
- private static Optional<String> getAccountType(ContentResolver contentResolver, long dataId) {
- Assert.isWorkerThread();
- Optional<Long> rawContactId = getRawContactId(contentResolver, dataId);
- if (!rawContactId.isPresent()) {
- return Optional.absent();
- }
- try (Cursor cursor =
- contentResolver.query(
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId.get()),
- new String[] {RawContacts.ACCOUNT_TYPE},
- null,
- null,
- null)) {
- if (cursor == null || !cursor.moveToFirst()) {
- return Optional.absent();
- }
- return Optional.fromNullable(cursor.getString(0));
- }
- }
+ abstract Builder setSelectedPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle);
- @WorkerThread
- private static Optional<Long> getRawContactId(ContentResolver contentResolver, long dataId) {
- Assert.isWorkerThread();
- try (Cursor cursor =
- contentResolver.query(
- ContentUris.withAppendedId(Data.CONTENT_URI, dataId),
- new String[] {Data.RAW_CONTACT_ID},
- null,
- null,
- null)) {
- if (cursor == null || !cursor.moveToFirst()) {
- return Optional.absent();
- }
- return Optional.of(cursor.getLong(0));
- }
- }
+ public abstract Builder setDataId(String dataId);
- @WorkerThread
- @NonNull
- private static Optional<PhoneAccountHandle> getPreferredAccount(
- @NonNull Context context, @NonNull String dataId) {
- Assert.isWorkerThread();
- Assert.isNotNull(dataId);
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(
- PreferredSimFallbackContract.CONTENT_URI,
- new String[] {
- PreferredSim.PREFERRED_PHONE_ACCOUNT_COMPONENT_NAME,
- PreferredSim.PREFERRED_PHONE_ACCOUNT_ID
- },
- PreferredSim.DATA_ID + " = ?",
- new String[] {dataId},
- null)) {
- if (cursor == null) {
- return Optional.absent();
- }
- if (!cursor.moveToFirst()) {
- return Optional.absent();
- }
- return PreferredAccountUtil.getValidPhoneAccount(
- context, cursor.getString(0), cursor.getString(1));
- }
- }
+ abstract Builder setDialogOptionsBuilder(
+ SelectPhoneAccountDialogOptions.Builder optionsBuilder);
- @WorkerThread
- private static boolean isPreferredSimEnabled(Context context) {
- Assert.isWorkerThread();
- if (!ConfigProviderBindings.get(context).getBoolean("preferred_sim_enabled", true)) {
- return false;
- }
+ public abstract Builder setSuggestion(Suggestion suggestion);
- Intent quickContactIntent = getQuickContactIntent();
- ResolveInfo resolveInfo =
- context
- .getPackageManager()
- .resolveActivity(quickContactIntent, PackageManager.GET_META_DATA);
- if (resolveInfo == null
- || resolveInfo.activityInfo == null
- || resolveInfo.activityInfo.applicationInfo == null
- || resolveInfo.activityInfo.applicationInfo.metaData == null) {
- LogUtil.e("CallingAccountSelector.isPreferredSimEnabled", "cannot resolve quick contact app");
- return false;
- }
- if (!resolveInfo.activityInfo.applicationInfo.metaData.getBoolean(
- METADATA_SUPPORTS_PREFERRED_SIM, false)) {
- LogUtil.i(
- "CallingAccountSelector.isPreferredSimEnabled",
- "system contacts does not support preferred SIM");
- return false;
+ public abstract Result build();
}
- return true;
}
- @VisibleForTesting
- public static Intent getQuickContactIntent() {
- Intent intent = new Intent(QuickContact.ACTION_QUICK_CONTACT);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setData(Contacts.CONTENT_URI.buildUpon().appendPath("1").build());
- return intent;
- }
+ /**
+ * @return a {@link SelectPhoneAccountDialogOptions} for a dialog to select SIM for voicemail call
+ */
+ SelectPhoneAccountDialogOptions getVoicemailDialogOptions();
+
+ /**
+ * Return {@link Result} for the best {@link PhoneAccountHandle} among {@code candidates} to call
+ * the number with. If none are eligible, a {@link SelectPhoneAccountDialogOptions} will be
+ * provided to show a dialog for the user to manually select.
+ */
+ ListenableFuture<Result> selectAccount(String phoneNumber, List<PhoneAccountHandle> candidates);
}