diff options
Diffstat (limited to 'java/com/android/dialer/preferredsim/PreferredAccountWorker.java')
-rw-r--r-- | java/com/android/dialer/preferredsim/PreferredAccountWorker.java | 269 |
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); } |