Merge "Add OnAccountsUpdateListener in ContactsStorageSettings to refresh the account when there's account change." into main

This commit is contained in:
Dongzhuo Zhang
2024-11-15 21:37:25 +00:00
committed by Android (Google) Code Review
2 changed files with 120 additions and 23 deletions

View File

@@ -25,7 +25,6 @@ import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState; import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState;
@@ -58,7 +57,8 @@ import java.util.Map;
*/ */
@SearchIndexable @SearchIndexable
public class ContactsStorageSettings extends DashboardFragment public class ContactsStorageSettings extends DashboardFragment
implements SelectorWithWidgetPreference.OnClickListener, OnPreferenceClickListener { implements SelectorWithWidgetPreference.OnClickListener, OnPreferenceClickListener,
AuthenticatorHelper.OnAccountsUpdateListener {
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.contacts_storage_settings); new BaseSearchIndexProvider(R.xml.contacts_storage_settings);
private static final String TAG = "ContactsStorageSettings"; private static final String TAG = "ContactsStorageSettings";
@@ -72,13 +72,15 @@ public class ContactsStorageSettings extends DashboardFragment
public void onAttach(@NonNull Context context) { public void onAttach(@NonNull Context context) {
super.onAttach(context); super.onAttach(context);
mAuthenticatorHelper = new AuthenticatorHelper(context, mAuthenticatorHelper = new AuthenticatorHelper(context,
new UserHandle(UserHandle.myUserId()), null); new UserHandle(UserHandle.myUserId()), this);
String[] accountTypes = getEligibleAccountTypes(); mAuthenticatorHelper.listenToAccountUpdates();
for (String accountType : accountTypes) { preloadEligibleAccountIcon();
// Preload the drawable for the account type to avoid the latency when rendering the
// account preference.
mAuthenticatorHelper.preloadDrawableForType(context, accountType);
} }
@Override
public void onDetach() {
super.onDetach();
mAuthenticatorHelper.stopListeningToAccountUpdates();
} }
@UiThread @UiThread
@@ -126,6 +128,12 @@ public class ContactsStorageSettings extends DashboardFragment
return false; return false;
} }
@Override
public void onAccountsUpdate(UserHandle userHandle) {
preloadEligibleAccountIcon();
refreshUI();
}
@Override @Override
public void onCreatePreferences(@NonNull Bundle savedInstanceState, public void onCreatePreferences(@NonNull Bundle savedInstanceState,
@NonNull String rootKey) { @NonNull String rootKey) {
@@ -139,6 +147,7 @@ public class ContactsStorageSettings extends DashboardFragment
// when creating eligible account preferences. // when creating eligible account preferences.
mAccountMap.clear(); mAccountMap.clear();
final PreferenceGroup preferenceGroup = findPreference(PREF_KEY_ACCOUNT_CATEGORY); final PreferenceGroup preferenceGroup = findPreference(PREF_KEY_ACCOUNT_CATEGORY);
preferenceGroup.removeAll();
// If the default account is SIM, we should show in the page, otherwise don't show. // If the default account is SIM, we should show in the page, otherwise don't show.
SelectorWithWidgetPreference simAccountPreference = buildSimAccountPreference(); SelectorWithWidgetPreference simAccountPreference = buildSimAccountPreference();
if (simAccountPreference != null) { if (simAccountPreference != null) {
@@ -152,12 +161,21 @@ public class ContactsStorageSettings extends DashboardFragment
// If there's no eligible account types, the "Add Account" preference should // If there's no eligible account types, the "Add Account" preference should
// not be shown to the users. // not be shown to the users.
if (getEligibleAccountTypes().length > 0) { if (getEligibleAccountTypes().length > 0) {
getPreferenceScreen().addPreference(buildAddAccountPreference(accounts.isEmpty())); preferenceGroup.addPreference(buildAddAccountPreference(accounts.isEmpty()));
} }
setupDeviceOnlyPreference(); setupDeviceOnlyPreference();
setDefaultAccountPreference(preferenceGroup); setDefaultAccountPreference(preferenceGroup);
} }
private void preloadEligibleAccountIcon() {
String[] accountTypes = getEligibleAccountTypes();
for (String accountType : accountTypes) {
// Preload the drawable for the account type to avoid the latency when rendering the
// account preference.
mAuthenticatorHelper.preloadDrawableForType(getContext(), accountType);
}
}
private void setupDeviceOnlyPreference() { private void setupDeviceOnlyPreference() {
SelectorWithWidgetPreference preference = findPreference(PREF_KEY_DEVICE_ONLY); SelectorWithWidgetPreference preference = findPreference(PREF_KEY_DEVICE_ONLY);
if (preference != null) { if (preference != null) {

View File

@@ -38,10 +38,13 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState; import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState;
import android.provider.SearchIndexableResource; import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceGroup;
@@ -51,7 +54,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accounts.AddAccountSettings; import com.android.settings.accounts.AddAccountSettings;
import com.android.settings.testutils.shadow.ShadowAuthenticationHelper; import com.android.settingslib.accounts.AuthenticatorHelper;
import com.android.settingslib.widget.SelectorWithWidgetPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.Before; import org.junit.Before;
@@ -66,22 +69,24 @@ import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowAuthenticationHelper.class) @Config(shadows = ContactsStorageSettingsTest.ShadowAuthenticatorHelper.class)
public class ContactsStorageSettingsTest { public class ContactsStorageSettingsTest {
private static final String PREF_KEY_DEVICE_ONLY = "device_only_account_preference"; private static final String PREF_KEY_DEVICE_ONLY = "device_only_account_preference";
private static final String PREF_KEY_ACCOUNT_CATEGORY = "account_category"; private static final String PREF_KEY_ACCOUNT_CATEGORY = "account_category";
private static final String PREF_KEY_ADD_ACCOUNT = "add_account"; private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
private static final Account TEST_ACCOUNT1 = new Account("test@gmail.com", "type1"); private static final Account TEST_ACCOUNT1 = new Account("test@gmail.com", "com.google");
private static final Account TEST_ACCOUNT2 = new Account("test@samsung.com", "type2"); private static final Account TEST_ACCOUNT2 = new Account("test@samsung.com", "com.samsung");
private static final Account TEST_ACCOUNT3 = new Account("test@outlook.com", "type3"); private static final Account TEST_ACCOUNT3 = new Account("test@outlook.com", "com.outlook");
private static final Account SIM_ACCOUNT = new Account("SIM", "SIM"); private static final Account SIM_ACCOUNT = new Account("SIM", "SIM");
@@ -100,7 +105,8 @@ public class ContactsStorageSettingsTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
mContactsStorageSettings = spy(new TestContactsStorageSettings(mContext, mContentResolver)); mContactsStorageSettings = spy(
new TestContactsStorageSettings(mContext, mContentResolver));
when(mContentResolver.acquireContentProviderClient( when(mContentResolver.acquireContentProviderClient(
eq(ContactsContract.AUTHORITY_URI))).thenReturn(mContentProviderClient); eq(ContactsContract.AUTHORITY_URI))).thenReturn(mContentProviderClient);
mPreferenceManager = new PreferenceManager(mContext); mPreferenceManager = new PreferenceManager(mContext);
@@ -116,6 +122,7 @@ public class ContactsStorageSettingsTest {
when(mContactsStorageSettings.findPreference(eq(PREF_KEY_ACCOUNT_CATEGORY))).thenReturn( when(mContactsStorageSettings.findPreference(eq(PREF_KEY_ACCOUNT_CATEGORY))).thenReturn(
accountCategory); accountCategory);
when(mContactsStorageSettings.getPreferenceScreen()).thenReturn(mScreen); when(mContactsStorageSettings.getPreferenceScreen()).thenReturn(mScreen);
mContactsStorageSettings.setEligibleAccountTypes(new String[]{"com.google"});
mContactsStorageSettings.onAttach(mContext); mContactsStorageSettings.onAttach(mContext);
} }
@@ -179,7 +186,6 @@ public class ContactsStorageSettingsTest {
new ArrayList<>()); new ArrayList<>());
when(mContentProviderClient.call(eq(QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD), any(), when(mContentProviderClient.call(eq(QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD), any(),
any())).thenReturn(eligibleAccountBundle); any())).thenReturn(eligibleAccountBundle);
mContactsStorageSettings.setEligibleAccountTypes(new String[]{"com.google"});
mContactsStorageSettings.refreshUI(); mContactsStorageSettings.refreshUI();
@@ -244,13 +250,13 @@ public class ContactsStorageSettingsTest {
SelectorWithWidgetPreference account1Preference = accountCategory.findPreference( SelectorWithWidgetPreference account1Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT1.hashCode())); String.valueOf(TEST_ACCOUNT1.hashCode()));
assertThat(account1Preference.getTitle()).isEqualTo("Device and LABEL1"); assertThat(account1Preference.getTitle()).isEqualTo("Device and Google");
assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com"); assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com");
assertThat(account1Preference.getIcon()).isNotNull(); assertThat(account1Preference.getIcon()).isNotNull();
SelectorWithWidgetPreference account2Preference = accountCategory.findPreference( SelectorWithWidgetPreference account2Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT2.hashCode())); String.valueOf(TEST_ACCOUNT2.hashCode()));
assertThat(account2Preference.getTitle()).isEqualTo("Device and LABEL2"); assertThat(account2Preference.getTitle()).isEqualTo("Device and Samsung");
assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com"); assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com");
assertThat(account2Preference.getIcon()).isNotNull(); assertThat(account2Preference.getIcon()).isNotNull();
@@ -265,7 +271,7 @@ public class ContactsStorageSettingsTest {
assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_NAME)).isEqualTo( assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_NAME)).isEqualTo(
"test@samsung.com"); "test@samsung.com");
assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_TYPE)).isEqualTo( assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_TYPE)).isEqualTo(
"type2"); "com.samsung");
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture()); verify(mContext).startActivity(intentCaptor.capture());
@@ -298,19 +304,19 @@ public class ContactsStorageSettingsTest {
SelectorWithWidgetPreference account1Preference = accountCategory.findPreference( SelectorWithWidgetPreference account1Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT1.hashCode())); String.valueOf(TEST_ACCOUNT1.hashCode()));
assertThat(account1Preference.getTitle()).isEqualTo("Device and LABEL1"); assertThat(account1Preference.getTitle()).isEqualTo("Device and Google");
assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com"); assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com");
assertThat(account1Preference.getIcon()).isNotNull(); assertThat(account1Preference.getIcon()).isNotNull();
SelectorWithWidgetPreference account2Preference = accountCategory.findPreference( SelectorWithWidgetPreference account2Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT2.hashCode())); String.valueOf(TEST_ACCOUNT2.hashCode()));
assertThat(account2Preference.getTitle()).isEqualTo("Device and LABEL2"); assertThat(account2Preference.getTitle()).isEqualTo("Device and Samsung");
assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com"); assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com");
assertThat(account2Preference.getIcon()).isNotNull(); assertThat(account2Preference.getIcon()).isNotNull();
SelectorWithWidgetPreference account3Preference = accountCategory.findPreference( SelectorWithWidgetPreference account3Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT3.hashCode())); String.valueOf(TEST_ACCOUNT3.hashCode()));
assertThat(account3Preference.getTitle()).isEqualTo("Device and LABEL3"); assertThat(account3Preference.getTitle()).isEqualTo("Device and Outlook");
assertThat(account3Preference.getSummary()).isEqualTo("test@outlook.com"); assertThat(account3Preference.getSummary()).isEqualTo("test@outlook.com");
assertThat(account3Preference.getIcon()).isNotNull(); assertThat(account3Preference.getIcon()).isNotNull();
@@ -345,6 +351,40 @@ public class ContactsStorageSettingsTest {
assertThat(simPreference.isChecked()).isTrue(); assertThat(simPreference.isChecked()).isTrue();
} }
@Test
public void verifyAccountPreference_newAccountAdded_accountAddedToAccountPreference()
throws Exception {
Bundle currentDefaultAccount = new Bundle();
currentDefaultAccount.putInt(KEY_DEFAULT_ACCOUNT_STATE,
DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD);
currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_NAME, TEST_ACCOUNT1.name);
currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_TYPE, TEST_ACCOUNT1.type);
when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
any())).thenReturn(currentDefaultAccount);
Bundle eligibleAccountBundle = new Bundle();
ArrayList<Account> eligibleAccounts = new ArrayList<>(
List.of(TEST_ACCOUNT1, TEST_ACCOUNT2));
eligibleAccountBundle.putParcelableArrayList(KEY_ELIGIBLE_DEFAULT_ACCOUNTS,
eligibleAccounts);
when(mContentProviderClient.call(eq(QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD), any(),
any())).thenReturn(eligibleAccountBundle);
mContactsStorageSettings.onAccountsUpdate(null);
// onAccountsUpdate should refresh the icon and layouts.
SelectorWithWidgetPreference account1Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT1.hashCode()));
assertThat(account1Preference.getTitle()).isEqualTo("Device and Google");
assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com");
assertThat(account1Preference.getIcon()).isNotNull();
SelectorWithWidgetPreference account2Preference = accountCategory.findPreference(
String.valueOf(TEST_ACCOUNT2.hashCode()));
assertThat(account2Preference.getTitle()).isEqualTo("Device and Samsung");
assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com");
assertThat(account2Preference.getIcon()).isNotNull();
}
@Test @Test
public void searchIndexProvider_shouldIndexResource() { public void searchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes = final List<SearchIndexableResource> indexRes =
@@ -388,4 +428,43 @@ public class ContactsStorageSettingsTest {
mEligibleAccountTypes = eligibleAccountTypes; mEligibleAccountTypes = eligibleAccountTypes;
} }
} }
@Implements(AuthenticatorHelper.class)
public static class ShadowAuthenticatorHelper {
boolean preloadDrawableForType = false;
@Implementation
public void listenToAccountUpdates() {
}
@Implementation
public void onAccountsUpdated(Account[] accounts) {
}
@Implementation
public void preloadDrawableForType(final Context context, final String accountType) {
preloadDrawableForType = true;
}
@Implementation
protected Drawable getDrawableForType(Context context, final String accountType) {
if (preloadDrawableForType) {
return context.getPackageManager().getDefaultActivityIcon();
}
return null;
}
@Implementation
protected CharSequence getLabelForType(Context context, final String accountType) {
if (TextUtils.equals(accountType, "com.google")) {
return "Google";
} else if (TextUtils.equals(accountType, "com.samsung")) {
return "Samsung";
} else if (TextUtils.equals(accountType, "com.outlook")) {
return "Outlook";
}
return null;
}
}
} }