Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a23542e authored by Doris Ling's avatar Doris Ling Committed by android-build-merger
Browse files

Merge "Also update the account preferences in displayPreference()." into oc-dev

am: cf162d53

Change-Id: I73133604ea118457e49def80edbdcddb553e9bcd
parents 3a32750e cf162d53
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -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"
+54 −13
Original line number Diff line number Diff line
@@ -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;

@@ -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,
@@ -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()) {
@@ -189,7 +204,6 @@ public class AccountPreferenceController extends PreferenceController

    @Override
    public void onResume() {
        cleanUpPreferences();
        updateUi();
        mManagedProfileBroadcastReceiver.register(mContext);
        listenToAccountUpdates();
@@ -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());
@@ -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
@@ -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;
@@ -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() {
@@ -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 =
@@ -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);
@@ -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)) {
@@ -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();
+176 −19
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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)
@@ -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
@@ -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());
        }
    }

}