From b3b437048465ab8da902fb9107c883331481da2c Mon Sep 17 00:00:00 2001 From: twyen Date: Wed, 3 Jan 2018 11:11:14 -0800 Subject: Only consider writable accounts for preferred SIM Some apps will add their own account to contacts and cause PhoneLookup to return multiple accounts. Since Contacts cannot write to these accounts the preferred SIM settings on them does not make sense. In this CL a reduced version of AccountTypeManager is used to determine if the account is writable. External accounts (which capabilities are determined by parsing their sync adapter) are not supported. Bug: 70689051 Test: CallingAccountSelectorTest PiperOrigin-RevId: 180693656 Change-Id: I24e93860cd576777c6d3861f65f75baa234dac87 --- .../precall/impl/CallingAccountSelector.java | 69 +++++++++++++++++++--- .../dialer/precall/impl/PreferredAccountUtil.java | 22 +++++++ 2 files changed, 82 insertions(+), 9 deletions(-) (limited to 'java/com/android') diff --git a/java/com/android/dialer/precall/impl/CallingAccountSelector.java b/java/com/android/dialer/precall/impl/CallingAccountSelector.java index a61a3b1c6..d407296da 100644 --- a/java/com/android/dialer/precall/impl/CallingAccountSelector.java +++ b/java/com/android/dialer/precall/impl/CallingAccountSelector.java @@ -18,6 +18,7 @@ package com.android.dialer.precall.impl; import android.app.Activity; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; @@ -28,8 +29,10 @@ import android.net.Uri; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; 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.MainThread; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -59,6 +62,7 @@ import com.android.dialer.preferredsim.suggestion.SimSuggestionComponent; import com.android.dialer.preferredsim.suggestion.SuggestionProvider.Suggestion; import com.android.dialer.telecom.TelecomUtil; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -296,7 +300,7 @@ public class CallingAccountSelector implements PreCallAction { if (!isPreferredSimEnabled(context)) { return result; } - result.dataId = getDataId(context.getContentResolver(), phoneNumber); + result.dataId = getDataId(context, phoneNumber); if (result.dataId.isPresent()) { result.phoneAccountHandle = getPreferredAccount(context, result.dataId.get()); } @@ -313,24 +317,33 @@ public class CallingAccountSelector implements PreCallAction { @WorkerThread @NonNull private static Optional getDataId( - @NonNull ContentResolver contentResolver, @Nullable String phoneNumber) { + @NonNull Context context, @Nullable String phoneNumber) { Assert.isWorkerThread(); if (VERSION.SDK_INT < VERSION_CODES.N) { return Optional.absent(); } try (Cursor cursor = - contentResolver.query( - Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)), - new String[] {PhoneLookup.DATA_ID}, - null, - null, - null)) { + 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 validAccountTypes = PreferredAccountUtil.getValidAccountTypes(context); Set result = new ArraySet<>(); while (cursor.moveToNext()) { - result.add(cursor.getString(0)); + Optional accountType = + getAccountType(context.getContentResolver(), cursor.getLong(0)); + if (accountType.isPresent() && validAccountTypes.contains(accountType.get())) { + result.add(cursor.getString(0)); + } else { + LogUtil.i("CallingAccountSelector.getDataId", "ignoring non-writable " + accountType); + } } // TODO(twyen): if there are multiples attempt to grab from the contact that initiated the // call. @@ -343,6 +356,44 @@ public class CallingAccountSelector implements PreCallAction { } } + @WorkerThread + private static Optional getAccountType(ContentResolver contentResolver, long dataId) { + Assert.isWorkerThread(); + Optional 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.of(cursor.getString(0)); + } + } + + @WorkerThread + private static Optional 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)); + } + } + @WorkerThread @NonNull private static Optional getPreferredAccount( diff --git a/java/com/android/dialer/precall/impl/PreferredAccountUtil.java b/java/com/android/dialer/precall/impl/PreferredAccountUtil.java index a41cb6e78..650588829 100644 --- a/java/com/android/dialer/precall/impl/PreferredAccountUtil.java +++ b/java/com/android/dialer/precall/impl/PreferredAccountUtil.java @@ -30,7 +30,9 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderComponent; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; /** * Utilities for looking up and validating preferred {@link PhoneAccountHandle}. Contacts should @@ -91,4 +93,24 @@ public class PreferredAccountUtil { } return false; } + + /** + * Return a set of {@link android.accounts.Account#type} that is known to have writable contacts. + * This is a light weight implementation of {@link + * com.android.contacts.common.model.AccountTypeManager#getAccountTypes(boolean)}. External + * accounts are not supported. + */ + public static ImmutableSet getValidAccountTypes(Context context) { + return ImmutableSet.copyOf( + ConfigProviderComponent.get(context) + .getConfigProvider() + .getString( + "preferred_sim_valid_account_types", + "com.google;" + + "com.osp.app.signin;" + + "com.android.exchange;" + + "com.google.android.exchange;" + + "com.google.android.gm.exchange") + .split(";")); + } } -- cgit v1.2.3