summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/preferredsim/PreferredAccountWorker.java
diff options
context:
space:
mode:
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);
}