Loading AndroidManifest.xml +0 −2 Original line number Diff line number Diff line Loading @@ -2373,8 +2373,6 @@ </intent-filter> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.accounts" /> <meta-data android:name="com.android.settings.summary" android:resource="@string/summary_empty"/> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.users.UserSettings" /> <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" Loading src/com/android/settings/accounts/AccountPreferenceController.java +54 −13 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; Loading Loading @@ -117,6 +118,14 @@ public class AccountPreferenceController extends PreferenceController * The {@link UserInfo} of the profile. */ public UserInfo userInfo; /** * The {@link UserInfo} of the profile. */ public boolean pendingRemoval; /** * The map from account name to account preference */ public ArrayMap<CharSequence, AccountTypePreference> accountPreferences = new ArrayMap<>(); } public AccountPreferenceController(Context context, SettingsPreferenceFragment parent, Loading Loading @@ -149,6 +158,12 @@ public class AccountPreferenceController extends PreferenceController return null; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); updateUi(); } @Override public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) { if (!isAvailable()) { Loading Loading @@ -189,7 +204,6 @@ public class AccountPreferenceController extends PreferenceController @Override public void onResume() { cleanUpPreferences(); updateUi(); mManagedProfileBroadcastReceiver.register(mContext); listenToAccountUpdates(); Loading Loading @@ -253,6 +267,9 @@ public class AccountPreferenceController extends PreferenceController return; } for (int i = 0, size = mProfiles.size(); i < size; i++) { mProfiles.valueAt(i).pendingRemoval = true; } if (mUm.isLinkedUser()) { // Restricted user or similar UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId()); Loading @@ -264,6 +281,7 @@ public class AccountPreferenceController extends PreferenceController updateProfileUi(profiles.get(i)); } } cleanUpPreferences(); // Add all preferences, starting with one for the primary profile. // Note that we're relying on the ordering given by the SparseArray keys, and on the Loading @@ -278,6 +296,11 @@ public class AccountPreferenceController extends PreferenceController if (mParent.getPreferenceManager() == null) { return; } final ProfileData data = mProfiles.get(userInfo.id); if (data != null) { data.pendingRemoval = false; return; } final Context context = mContext; final ProfileData profileData = new ProfileData(); profileData.userInfo = userInfo; Loading Loading @@ -366,12 +389,14 @@ public class AccountPreferenceController extends PreferenceController if (screen == null) { return; } for (int i = 0; i < mProfiles.size(); i++) { final PreferenceGroup preferenceGroup = mProfiles.valueAt(i).preferenceGroup; screen.removePreference(preferenceGroup); final int count = mProfiles.size(); for (int i = count-1; i >= 0; i--) { final ProfileData data = mProfiles.valueAt(i); if (data.pendingRemoval) { screen.removePreference(data.preferenceGroup); mProfiles.removeAt(i); } } mProfiles.clear(); mAccountProfileOrder = ORDER_ACCOUNT_PROFILES; } private void listenToAccountUpdates() { Loading Loading @@ -400,18 +425,31 @@ public class AccountPreferenceController extends PreferenceController // This could happen if activity is finishing return; } profileData.preferenceGroup.removeAll(); if (profileData.userInfo.isEnabled()) { final ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove = new ArrayMap<>(profileData.accountPreferences); final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences( profileData.authenticatorHelper, profileData.userInfo.getUserHandle()); profileData.authenticatorHelper, profileData.userInfo.getUserHandle(), preferenceToRemove); final int count = preferences.size(); for (int i = 0; i < count; i++) { final AccountTypePreference preference = preferences.get(i); preference.setOrder(i); if (!profileData.accountPreferences.containsValue(preference)) { profileData.preferenceGroup.addPreference(preferences.get(i)); profileData.accountPreferences.put(preference.getTitle(), preference); } } if (profileData.addAccountPreference != null) { profileData.preferenceGroup.addPreference(profileData.addAccountPreference); } for (CharSequence name : preferenceToRemove.keySet()) { profileData.preferenceGroup.removePreference( profileData.accountPreferences.get(name)); profileData.accountPreferences.remove(name); } } else { profileData.preferenceGroup.removeAll(); // Put a label instead of the accounts list if (mProfileNotAvailablePreference == null) { mProfileNotAvailablePreference = Loading @@ -433,7 +471,8 @@ public class AccountPreferenceController extends PreferenceController } private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper, UserHandle userHandle) { UserHandle userHandle, ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove) { final String[] accountTypes = helper.getEnabledAccountTypes(); final ArrayList<AccountTypePreference> accountTypePreferences = new ArrayList<>(accountTypes.length); Loading @@ -453,13 +492,16 @@ public class AccountPreferenceController extends PreferenceController final Account[] accounts = AccountManager.get(mContext) .getAccountsByTypeAsUser(accountType, userHandle); final boolean skipToAccount = accounts.length == 1 && !helper.hasAccountPreferences(accountType); final Drawable icon = helper.getDrawableForType(mContext, accountType); final Context prefContext = mParent.getPreferenceManager().getContext(); // Add a preference row for each individual account for (Account account : accounts) { final AccountTypePreference preference = preferenceToRemove.remove(account.name); if (preference != null) { accountTypePreferences.add(preference); continue; } final ArrayList<String> auths = helper.getAuthoritiesForAccountType(account.type); if (!AccountRestrictionHelper.showAccount(mAuthorities, auths)) { Loading Loading @@ -531,7 +573,6 @@ public class AccountPreferenceController extends PreferenceController || action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) { // Clean old state stopListeningToAccountUpdates(); cleanUpPreferences(); // Build new state updateUi(); listenToAccountUpdates(); Loading tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java +176 −19 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import com.android.settings.AccessiblePreferenceCategory; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; Loading @@ -39,6 +40,7 @@ import com.android.settings.testutils.shadow.ShadowContentResolver; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; Loading @@ -51,20 +53,22 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public class AccountPreferenceControllerTest { @Mock(answer = RETURNS_DEEP_STUBS) private PreferenceScreen mScreen; @Mock(answer = RETURNS_DEEP_STUBS) private UserManager mUserManager; @Mock(answer = RETURNS_DEEP_STUBS) Loading Loading @@ -145,43 +149,56 @@ public class AccountPreferenceControllerTest { @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneProfiles_shouldRemoveOneAccountCategory() { public void onResume_noProfileChange_shouldNotAddOrRemoveAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); infos.add(new UserInfo(1, "user 1", 0)); infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); // First time resume will build the UI mController.onResume(); reset(mScreen); // First time resume will build the UI, 2nd time will refresh the UI mController.onResume(); verify(mScreen, never()).addPreference(any(PreferenceGroup.class)); verify(mScreen, never()).removePreference(any(PreferenceGroup.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneNewProfile_shouldAddOneAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); // First time resume will build the UI mController.onResume(); // add a new profile infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); reset(mScreen); verify(mScreen, times(1)).removePreference(any(PreferenceGroup.class)); verify(mScreen).removePreference(preferenceGroup); mController.onResume(); verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_twoProfiles_shouldRemoveTwoAccountCategory() { public void onResume_oneProfileRemoved_shouldRemoveOneAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); // First time resume will build the UI, 2nd time will refresh the UI mController.onResume(); // First time resume will build the UI mController.onResume(); // remove a profile infos.remove(1); verify(mScreen, times(2)).removePreference(any(PreferenceGroup.class)); verify(mScreen, times(2)).removePreference(preferenceGroup); mController.onResume(); verify(mScreen, times(1)).removePreference(any(PreferenceGroup.class)); } @Test Loading Loading @@ -348,4 +365,144 @@ public class AccountPreferenceControllerTest { verify(preferenceGroup, times(3)).addPreference(any(Preference.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_noAccountChange_shouldNotAddAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); mController.onResume(); // each account should be added only once verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct12"))); } @Test public void onResume_oneNewAccount_shouldAddOneAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); // add a new account accountType1 = new Account[3]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); accountType1[2] = new Account("Acct13", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); mController.onResume(); // each account should be added only once verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct13"))); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneAccountRemoved_shouldRemoveOneAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); // remove an account accountType1 = new Account[1]; accountType1[0] = new Account("Acct11", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); mController.onResume(); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); verify(preferenceGroup, times(1)).removePreference( argThat(new PreferenceMatcher("Acct12"))); } private static class PreferenceMatcher extends ArgumentMatcher<Preference> { private final String mExpectedTitle; public PreferenceMatcher(String title) { mExpectedTitle = title; } @Override public boolean matches(Object arg) { final Preference preference = (Preference) arg; return TextUtils.equals(mExpectedTitle, preference.getTitle()); } } } Loading
AndroidManifest.xml +0 −2 Original line number Diff line number Diff line Loading @@ -2373,8 +2373,6 @@ </intent-filter> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.accounts" /> <meta-data android:name="com.android.settings.summary" android:resource="@string/summary_empty"/> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.users.UserSettings" /> <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" Loading
src/com/android/settings/accounts/AccountPreferenceController.java +54 −13 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; Loading Loading @@ -117,6 +118,14 @@ public class AccountPreferenceController extends PreferenceController * The {@link UserInfo} of the profile. */ public UserInfo userInfo; /** * The {@link UserInfo} of the profile. */ public boolean pendingRemoval; /** * The map from account name to account preference */ public ArrayMap<CharSequence, AccountTypePreference> accountPreferences = new ArrayMap<>(); } public AccountPreferenceController(Context context, SettingsPreferenceFragment parent, Loading Loading @@ -149,6 +158,12 @@ public class AccountPreferenceController extends PreferenceController return null; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); updateUi(); } @Override public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) { if (!isAvailable()) { Loading Loading @@ -189,7 +204,6 @@ public class AccountPreferenceController extends PreferenceController @Override public void onResume() { cleanUpPreferences(); updateUi(); mManagedProfileBroadcastReceiver.register(mContext); listenToAccountUpdates(); Loading Loading @@ -253,6 +267,9 @@ public class AccountPreferenceController extends PreferenceController return; } for (int i = 0, size = mProfiles.size(); i < size; i++) { mProfiles.valueAt(i).pendingRemoval = true; } if (mUm.isLinkedUser()) { // Restricted user or similar UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId()); Loading @@ -264,6 +281,7 @@ public class AccountPreferenceController extends PreferenceController updateProfileUi(profiles.get(i)); } } cleanUpPreferences(); // Add all preferences, starting with one for the primary profile. // Note that we're relying on the ordering given by the SparseArray keys, and on the Loading @@ -278,6 +296,11 @@ public class AccountPreferenceController extends PreferenceController if (mParent.getPreferenceManager() == null) { return; } final ProfileData data = mProfiles.get(userInfo.id); if (data != null) { data.pendingRemoval = false; return; } final Context context = mContext; final ProfileData profileData = new ProfileData(); profileData.userInfo = userInfo; Loading Loading @@ -366,12 +389,14 @@ public class AccountPreferenceController extends PreferenceController if (screen == null) { return; } for (int i = 0; i < mProfiles.size(); i++) { final PreferenceGroup preferenceGroup = mProfiles.valueAt(i).preferenceGroup; screen.removePreference(preferenceGroup); final int count = mProfiles.size(); for (int i = count-1; i >= 0; i--) { final ProfileData data = mProfiles.valueAt(i); if (data.pendingRemoval) { screen.removePreference(data.preferenceGroup); mProfiles.removeAt(i); } } mProfiles.clear(); mAccountProfileOrder = ORDER_ACCOUNT_PROFILES; } private void listenToAccountUpdates() { Loading Loading @@ -400,18 +425,31 @@ public class AccountPreferenceController extends PreferenceController // This could happen if activity is finishing return; } profileData.preferenceGroup.removeAll(); if (profileData.userInfo.isEnabled()) { final ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove = new ArrayMap<>(profileData.accountPreferences); final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences( profileData.authenticatorHelper, profileData.userInfo.getUserHandle()); profileData.authenticatorHelper, profileData.userInfo.getUserHandle(), preferenceToRemove); final int count = preferences.size(); for (int i = 0; i < count; i++) { final AccountTypePreference preference = preferences.get(i); preference.setOrder(i); if (!profileData.accountPreferences.containsValue(preference)) { profileData.preferenceGroup.addPreference(preferences.get(i)); profileData.accountPreferences.put(preference.getTitle(), preference); } } if (profileData.addAccountPreference != null) { profileData.preferenceGroup.addPreference(profileData.addAccountPreference); } for (CharSequence name : preferenceToRemove.keySet()) { profileData.preferenceGroup.removePreference( profileData.accountPreferences.get(name)); profileData.accountPreferences.remove(name); } } else { profileData.preferenceGroup.removeAll(); // Put a label instead of the accounts list if (mProfileNotAvailablePreference == null) { mProfileNotAvailablePreference = Loading @@ -433,7 +471,8 @@ public class AccountPreferenceController extends PreferenceController } private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper, UserHandle userHandle) { UserHandle userHandle, ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove) { final String[] accountTypes = helper.getEnabledAccountTypes(); final ArrayList<AccountTypePreference> accountTypePreferences = new ArrayList<>(accountTypes.length); Loading @@ -453,13 +492,16 @@ public class AccountPreferenceController extends PreferenceController final Account[] accounts = AccountManager.get(mContext) .getAccountsByTypeAsUser(accountType, userHandle); final boolean skipToAccount = accounts.length == 1 && !helper.hasAccountPreferences(accountType); final Drawable icon = helper.getDrawableForType(mContext, accountType); final Context prefContext = mParent.getPreferenceManager().getContext(); // Add a preference row for each individual account for (Account account : accounts) { final AccountTypePreference preference = preferenceToRemove.remove(account.name); if (preference != null) { accountTypePreferences.add(preference); continue; } final ArrayList<String> auths = helper.getAuthoritiesForAccountType(account.type); if (!AccountRestrictionHelper.showAccount(mAuthorities, auths)) { Loading Loading @@ -531,7 +573,6 @@ public class AccountPreferenceController extends PreferenceController || action.equals(Intent.ACTION_MANAGED_PROFILE_ADDED)) { // Clean old state stopListeningToAccountUpdates(); cleanUpPreferences(); // Build new state updateUi(); listenToAccountUpdates(); Loading
tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java +176 −19 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import com.android.settings.AccessiblePreferenceCategory; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; Loading @@ -39,6 +40,7 @@ import com.android.settings.testutils.shadow.ShadowContentResolver; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; Loading @@ -51,20 +53,22 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public class AccountPreferenceControllerTest { @Mock(answer = RETURNS_DEEP_STUBS) private PreferenceScreen mScreen; @Mock(answer = RETURNS_DEEP_STUBS) private UserManager mUserManager; @Mock(answer = RETURNS_DEEP_STUBS) Loading Loading @@ -145,43 +149,56 @@ public class AccountPreferenceControllerTest { @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneProfiles_shouldRemoveOneAccountCategory() { public void onResume_noProfileChange_shouldNotAddOrRemoveAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); infos.add(new UserInfo(1, "user 1", 0)); infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); // First time resume will build the UI mController.onResume(); reset(mScreen); // First time resume will build the UI, 2nd time will refresh the UI mController.onResume(); verify(mScreen, never()).addPreference(any(PreferenceGroup.class)); verify(mScreen, never()).removePreference(any(PreferenceGroup.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneNewProfile_shouldAddOneAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); // First time resume will build the UI mController.onResume(); // add a new profile infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); reset(mScreen); verify(mScreen, times(1)).removePreference(any(PreferenceGroup.class)); verify(mScreen).removePreference(preferenceGroup); mController.onResume(); verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_twoProfiles_shouldRemoveTwoAccountCategory() { public void onResume_oneProfileRemoved_shouldRemoveOneAccountCategory() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); // First time resume will build the UI, 2nd time will refresh the UI mController.onResume(); // First time resume will build the UI mController.onResume(); // remove a profile infos.remove(1); verify(mScreen, times(2)).removePreference(any(PreferenceGroup.class)); verify(mScreen, times(2)).removePreference(preferenceGroup); mController.onResume(); verify(mScreen, times(1)).removePreference(any(PreferenceGroup.class)); } @Test Loading Loading @@ -348,4 +365,144 @@ public class AccountPreferenceControllerTest { verify(preferenceGroup, times(3)).addPreference(any(Preference.class)); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_noAccountChange_shouldNotAddAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); mController.onResume(); // each account should be added only once verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct12"))); } @Test public void onResume_oneNewAccount_shouldAddOneAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); // add a new account accountType1 = new Account[3]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); accountType1[2] = new Account("Acct13", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); mController.onResume(); // each account should be added only once verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct13"))); } @Test @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public void onResume_oneAccountRemoved_shouldRemoveOneAccountPreference() { final List<UserInfo> infos = new ArrayList<>(); infos.add(new UserInfo(1, "user 1", 0)); when(mUserManager.isManagedProfile()).thenReturn(false); when(mUserManager.isLinkedUser()).thenReturn(false); when(mUserManager.getProfiles(anyInt())).thenReturn(infos); Account[] accounts = {new Account("Acct1", "com.acct1")}; when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); Account[] accountType1 = new Account[2]; accountType1[0] = new Account("Acct11", "com.acct1"); accountType1[1] = new Account("Acct12", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); AuthenticatorDescription[] authDescs = { new AuthenticatorDescription("com.acct1", "com.android.settings", R.string.account_settings_title, 0, 0, 0, false) }; when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( preferenceGroup); mController.onResume(); // remove an account accountType1 = new Account[1]; accountType1[0] = new Account("Acct11", "com.acct1"); when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) .thenReturn(accountType1); mController.onResume(); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); verify(preferenceGroup, times(1)).removePreference( argThat(new PreferenceMatcher("Acct12"))); } private static class PreferenceMatcher extends ArgumentMatcher<Preference> { private final String mExpectedTitle; public PreferenceMatcher(String title) { mExpectedTitle = title; } @Override public boolean matches(Object arg) { final Preference preference = (Preference) arg; return TextUtils.equals(mExpectedTitle, preference.getTitle()); } } }