1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.users;
18 
19 import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
20 import static android.os.UserManager.SWITCHABILITY_STATUS_USER_IN_CALL;
21 import static android.os.UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.ArgumentMatchers.notNull;
30 import static org.mockito.Mockito.doNothing;
31 import static org.mockito.Mockito.doReturn;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.spy;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.robolectric.Shadows.shadowOf;
38 
39 import android.app.settings.SettingsEnums;
40 import android.content.ComponentName;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.content.SharedPreferences;
44 import android.content.pm.PackageManager;
45 import android.content.pm.ResolveInfo;
46 import android.content.pm.UserInfo;
47 import android.graphics.Bitmap;
48 import android.graphics.drawable.Drawable;
49 import android.os.Bundle;
50 import android.os.Looper;
51 import android.os.UserHandle;
52 import android.os.UserManager;
53 import android.provider.Settings;
54 import android.text.SpannableStringBuilder;
55 import android.view.Menu;
56 import android.view.MenuInflater;
57 import android.view.MenuItem;
58 
59 import androidx.fragment.app.FragmentActivity;
60 import androidx.preference.Preference;
61 import androidx.preference.PreferenceCategory;
62 import androidx.preference.PreferenceManager;
63 import androidx.preference.PreferenceScreen;
64 
65 import com.android.settings.SettingsActivity;
66 import com.android.settings.SubSettings;
67 import com.android.settings.testutils.shadow.SettingsShadowResources;
68 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
69 import com.android.settings.testutils.shadow.ShadowUserManager;
70 import com.android.settingslib.RestrictedLockUtils;
71 import com.android.settingslib.RestrictedPreference;
72 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
73 import com.android.settingslib.search.SearchIndexableRaw;
74 
75 import org.junit.After;
76 import org.junit.Before;
77 import org.junit.Ignore;
78 import org.junit.Test;
79 import org.junit.runner.RunWith;
80 import org.mockito.AdditionalMatchers;
81 import org.mockito.ArgumentCaptor;
82 import org.mockito.Mock;
83 import org.mockito.MockitoAnnotations;
84 import org.robolectric.RobolectricTestRunner;
85 import org.robolectric.RuntimeEnvironment;
86 import org.robolectric.android.controller.ActivityController;
87 import org.robolectric.annotation.Config;
88 import org.robolectric.shadows.ShadowIntent;
89 import org.robolectric.util.ReflectionHelpers;
90 
91 import java.util.ArrayList;
92 import java.util.Arrays;
93 import java.util.Collections;
94 import java.util.List;
95 
96 @RunWith(RobolectricTestRunner.class)
97 @Config(shadows = {
98         ShadowUserManager.class,
99         ShadowDevicePolicyManager.class,
100         SettingsShadowResources.class,
101         com.android.settings.testutils.shadow.ShadowFragment.class,
102 })
103 public class UserSettingsTest {
104 
105     private static final String KEY_USER_GUEST = "user_guest";
106     private static final String KEY_ALLOW_MULTIPLE_USERS = "allow_multiple_users";
107     private static final String KEY_USER_SETTINGS_SCREEN = "user_settings_screen";
108     private static final int ACTIVE_USER_ID = 0;
109     private static final int INACTIVE_ADMIN_USER_ID = 1;
110     private static final int INACTIVE_SECONDARY_USER_ID = 14;
111     private static final int INACTIVE_RESTRICTED_USER_ID = 21;
112     private static final int INACTIVE_GUEST_USER_ID = 23;
113     private static final int MANAGED_USER_ID = 11;
114     private static final String ADMIN_USER_NAME = "Owner";
115     private static final String SECONDARY_USER_NAME = "Tom";
116     private static final String RESTRICTED_USER_NAME = "Bob";
117     private static final String GUEST_USER_NAME = "Guest";
118     private static final String MANAGED_USER_NAME = "Work profile";
119     private int mProvisionedBackupValue;
120 
121     @Mock
122     private Drawable mDefaultIconDrawable;
123     @Mock
124     private PreferenceManager mMockPreferenceManager;
125     @Mock
126     private UserPreference mMePreference;
127     @Mock
128     private RestrictedPreference mAddUserPreference;
129     @Mock
130     private RestrictedPreference mAddSupervisedUserPreference;
131     @Mock
132     private RestrictedPreference mAddGuestPreference;
133     @Mock
134     private UserManager mUserManager;
135     @Mock
136     private PackageManager mPackageManager;
137     @Mock
138     private MetricsFeatureProvider mMetricsFeatureProvider;
139 
140     private FragmentActivity mActivity;
141     private Context mContext;
142     private UserSettings mFragment;
143     private UserCapabilities mUserCapabilities;
144 
145     @Before
setUp()146     public void setUp() {
147         MockitoAnnotations.initMocks(this);
148         mActivity = spy(ActivityController.of(new FragmentActivity()).get());
149         mContext = spy(RuntimeEnvironment.application);
150         mUserCapabilities = UserCapabilities.create(mContext);
151         mUserCapabilities.mUserSwitcherEnabled = true;
152 
153         mFragment = spy(new UserSettings());
154         ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController",
155                 mock(AddUserWhenLockedPreferenceController.class));
156         ReflectionHelpers.setField(mFragment, "mGuestTelephonyPreferenceController",
157                 mock(GuestTelephonyPreferenceController.class));
158         ReflectionHelpers.setField(mFragment, "mMultiUserTopIntroPreferenceController",
159                 mock(MultiUserTopIntroPreferenceController.class));
160         ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
161         ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
162         ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
163         ReflectionHelpers.setField(mFragment, "mAddingUser", false);
164         ReflectionHelpers.setField(mFragment, "mMetricsFeatureProvider", mMetricsFeatureProvider);
165         ReflectionHelpers.setField(mFragment, "mRemoveGuestOnExitPreferenceController",
166                 mock(RemoveGuestOnExitPreferenceController.class));
167 
168         doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
169         doReturn(mPackageManager).when(mActivity).getPackageManager();
170 
171         doReturn(mActivity).when(mFragment).getActivity();
172         doReturn(mContext).when(mFragment).getContext();
173         doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
174         doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
175         doReturn(mPackageManager).when(mContext).getPackageManager();
176 
177         mProvisionedBackupValue = Settings.Global.getInt(mContext.getContentResolver(),
178                 Settings.Global.DEVICE_PROVISIONED, 0);
179         Settings.Global.putInt(mContext.getContentResolver(),
180                 Settings.Global.DEVICE_PROVISIONED, 1); //default state
181 
182         final SharedPreferences prefs = mock(SharedPreferences.class);
183 
184         doReturn(prefs).when(mMockPreferenceManager).getSharedPreferences();
185         doReturn(mContext).when(mMockPreferenceManager).getContext();
186         doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
187         doReturn(ACTIVE_USER_ID).when(mContext).getUserId();
188 
189         mFragment.mMePreference = mMePreference;
190         mFragment.mAddUser = mAddUserPreference;
191         mFragment.mAddSupervisedUser = mAddSupervisedUserPreference;
192         mFragment.mAddGuest = mAddGuestPreference;
193         mFragment.mUserListCategory = mock(PreferenceCategory.class);
194         mFragment.mGuestUserCategory = mock(PreferenceCategory.class);
195         mFragment.mGuestCategory = mock(PreferenceCategory.class);
196         mFragment.mGuestResetPreference = mock(Preference.class);
197         mFragment.mGuestExitPreference = mock(Preference.class);
198     }
199 
200     @After
tearDown()201     public void tearDown() {
202         Settings.Global.putInt(mContext.getContentResolver(),
203                 Settings.Global.DEVICE_PROVISIONED, mProvisionedBackupValue);
204         SettingsShadowResources.reset();
205     }
206 
207     @Test
testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash()208     public void testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash() {
209         // Should not crash here
210         assertThat(UserSettings.assignDefaultPhoto(null, ACTIVE_USER_ID)).isFalse();
211     }
212 
213     @Test
testGetRawDataToIndex_returnAllIndexablePreferences()214     public void testGetRawDataToIndex_returnAllIndexablePreferences() {
215         String[] expectedKeys = {KEY_ALLOW_MULTIPLE_USERS, KEY_USER_SETTINGS_SCREEN};
216         List<String> keysResultList = new ArrayList<>();
217         ShadowUserManager.getShadow().setSupportsMultipleUsers(true);
218         List<SearchIndexableRaw> rawData =
219                 UserSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true);
220 
221         for (SearchIndexableRaw rawDataItem : rawData) {
222             keysResultList.add(rawDataItem.key);
223         }
224 
225         assertThat(keysResultList).containsExactly(expectedKeys);
226     }
227 
228     @Test
testAssignDefaultPhoto_hasDefaultUserIconSize()229     public void testAssignDefaultPhoto_hasDefaultUserIconSize() {
230         doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
231         int size = 100;
232         try {
233             SettingsShadowResources.overrideResource(
234                     com.android.internal.R.dimen.user_icon_size,
235                     size);
236             assertThat(UserSettings.assignDefaultPhoto(mContext, ACTIVE_USER_ID)).isTrue();
237 
238             int pxSize = mContext.getResources()
239                     .getDimensionPixelSize(com.android.internal.R.dimen.user_icon_size);
240 
241             ArgumentCaptor<Bitmap> captor = ArgumentCaptor.forClass(Bitmap.class);
242             verify(mUserManager).setUserIcon(eq(ACTIVE_USER_ID), captor.capture());
243             Bitmap bitmap = captor.getValue();
244             assertThat(bitmap.getWidth()).isEqualTo(pxSize);
245             assertThat(bitmap.getHeight()).isEqualTo(pxSize);
246         } finally {
247             SettingsShadowResources.reset();
248         }
249     }
250 
251     @Test
testExitGuest_ShouldLogAction()252     public void testExitGuest_ShouldLogAction() {
253         mUserCapabilities.mIsGuest = true;
254         mFragment.clearAndExitGuest();
255         verify(mMetricsFeatureProvider).action(any(),
256                 eq(SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED));
257     }
258 
259     @Test
testExitGuestWhenNotGuest_ShouldNotLogAction()260     public void testExitGuestWhenNotGuest_ShouldNotLogAction() {
261         mUserCapabilities.mIsGuest = false;
262         mFragment.clearAndExitGuest();
263         verify(mMetricsFeatureProvider, never()).action(any(),
264                 eq(SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED));
265     }
266 
267     @Test
withDisallowRemoveUser_ShouldDisableRemoveUser()268     public void withDisallowRemoveUser_ShouldDisableRemoveUser() {
269         // TODO(b/115781615): Tidy robolectric tests
270         // Arrange
271         final int userId = UserHandle.myUserId();
272         final List<UserManager.EnforcingUser> enforcingUsers = Collections.singletonList(
273                 new UserManager.EnforcingUser(userId,
274                         UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)
275         );
276         ShadowUserManager.getShadow().setUserRestrictionSources(
277                 UserManager.DISALLOW_REMOVE_USER,
278                 UserHandle.of(userId),
279                 enforcingUsers);
280 
281         ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
282                 new ComponentName("test", "test"));
283 
284         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
285         mUserCapabilities.mIsAdmin = false;
286 
287         Menu menu = mock(Menu.class);
288         MenuItem menuItem = mock(MenuItem.class);
289         final String title = "title";
290 
291         doReturn(title).when(menuItem).getTitle();
292         doReturn(menuItem).when(menu).add(
293                 anyInt(), eq(Menu.FIRST), anyInt(), any(CharSequence.class));
294 
295         // Act
296         mFragment.onCreateOptionsMenu(menu, mock(MenuInflater.class));
297 
298         // Assert
299         // Expect that the click will be overridden and the color will be faded
300         // (by RestrictedLockUtilsInternal)
301         verify(menuItem).setOnMenuItemClickListener(notNull());
302         SpannableStringBuilder defaultTitle = new SpannableStringBuilder(title);
303         verify(menuItem).setTitle(AdditionalMatchers.not(eq(defaultTitle)));
304     }
305 
306     @Test
withoutDisallowRemoveUser_ShouldNotDisableRemoveUser()307     public void withoutDisallowRemoveUser_ShouldNotDisableRemoveUser() {
308         // Arrange
309         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
310         mUserCapabilities.mIsAdmin = false;
311 
312         Menu menu = mock(Menu.class);
313         MenuItem menuItem = mock(MenuItem.class);
314         final String title = "title";
315 
316         doReturn(title).when(menuItem).getTitle();
317         doReturn(menuItem).when(menu).add(
318                 anyInt(), eq(Menu.FIRST), anyInt(), any(CharSequence.class));
319 
320         // Act
321         mFragment.onCreateOptionsMenu(menu, mock(MenuInflater.class));
322 
323         // Assert
324         // Expect that a click listener will not be added and the title will not be changed
325         verify(menuItem, never()).setOnMenuItemClickListener(notNull());
326         SpannableStringBuilder defaultTitle = new SpannableStringBuilder(title);
327         verify(menuItem, never()).setTitle(AdditionalMatchers.not(eq(defaultTitle)));
328     }
329 
330     @Test
updateUserList_canAddUserAndSwitchUser_shouldShowAddUser()331     public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
332         mUserCapabilities.mCanAddUser = true;
333         doReturn(true)
334                 .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_SECONDARY));
335         doReturn(true).when(mAddUserPreference).isEnabled();
336         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
337 
338         mFragment.updateUserList();
339 
340         verify(mAddUserPreference).setVisible(true);
341         verify(mAddUserPreference).setSummary(null);
342         verify(mAddUserPreference).setEnabled(true);
343         verify(mAddUserPreference).setDisabledByAdmin(null);
344         verify(mAddUserPreference).setSelectable(true);
345     }
346 
347     @Test
updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest()348     public void updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest() {
349         mUserCapabilities.mCanAddGuest = true;
350         doReturn(true)
351                 .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_GUEST));
352         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
353 
354         mFragment.updateUserList();
355 
356         verify(mAddGuestPreference).setVisible(true);
357         verify(mAddGuestPreference).setEnabled(true);
358         verify(mAddGuestPreference).setSelectable(true);
359     }
360 
361     @Test
updateUserList_cannotSwitchUser_shouldDisableAddUser()362     public void updateUserList_cannotSwitchUser_shouldDisableAddUser() {
363         mUserCapabilities.mCanAddUser = true;
364         doReturn(true).when(mUserManager).canAddMoreUsers(anyString());
365         doReturn(true).when(mAddUserPreference).isEnabled();
366         doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
367                 .when(mUserManager).getUserSwitchability();
368 
369         mFragment.updateUserList();
370 
371         verify(mAddUserPreference).setVisible(true);
372         verify(mAddUserPreference).setSummary(null);
373         verify(mAddUserPreference).setEnabled(false);
374         verify(mAddUserPreference).setSelectable(true);
375     }
376 
377     @Test
updateUserList_canNotAddMoreUsers_shouldDisableAddUserWithSummary()378     public void updateUserList_canNotAddMoreUsers_shouldDisableAddUserWithSummary() {
379         mUserCapabilities.mCanAddUser = true;
380         doReturn(false).when(mUserManager).canAddMoreUsers(anyString());
381         doReturn(false).when(mAddUserPreference).isEnabled();
382         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
383         doReturn(4).when(mFragment).getRealUsersCount();
384 
385         mFragment.updateUserList();
386 
387         verify(mAddUserPreference).setVisible(true);
388         verify(mAddUserPreference).setSummary(
389                 "You can\u2019t add any more users. Remove a user to add a new one.");
390         verify(mAddUserPreference).setEnabled(false);
391         verify(mAddUserPreference).setSelectable(true);
392     }
393 
394     @Test
updateUserList_cannotSwitchUser_shouldDisableAddGuest()395     public void updateUserList_cannotSwitchUser_shouldDisableAddGuest() {
396         mUserCapabilities.mCanAddGuest = true;
397         doReturn(true)
398                 .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_GUEST));
399         doReturn(SWITCHABILITY_STATUS_USER_IN_CALL).when(mUserManager).getUserSwitchability();
400 
401         mFragment.updateUserList();
402 
403         verify(mAddGuestPreference).setVisible(true);
404         verify(mAddGuestPreference).setEnabled(false);
405         verify(mAddGuestPreference).setSelectable(true);
406     }
407 
408     @Test
updateUserList_addUserDisallowedByAdmin_shouldNotShowAddUser()409     public void updateUserList_addUserDisallowedByAdmin_shouldNotShowAddUser() {
410         RestrictedLockUtils.EnforcedAdmin enforcedAdmin = mock(
411                 RestrictedLockUtils.EnforcedAdmin.class);
412         mUserCapabilities.mEnforcedAdmin = enforcedAdmin;
413         mUserCapabilities.mCanAddUser = false;
414         mUserCapabilities.mDisallowAddUser = true;
415         mUserCapabilities.mDisallowAddUserSetByAdmin = true;
416         doReturn(true).when(mAddUserPreference).isEnabled();
417 
418         mFragment.updateUserList();
419 
420         verify(mAddUserPreference).setVisible(false);
421     }
422 
423     @Test
updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser()424     public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
425         mUserCapabilities.mCanAddUser = false;
426 
427         mFragment.updateUserList();
428 
429         verify(mAddUserPreference).setVisible(false);
430     }
431 
432     @Test
updateUserList_canNotAddGuest_shouldNotShowAddGuest()433     public void updateUserList_canNotAddGuest_shouldNotShowAddGuest() {
434         mUserCapabilities.mCanAddGuest = false;
435 
436         mFragment.updateUserList();
437 
438         verify(mAddGuestPreference).setVisible(false);
439     }
440 
441     @Test
updateUserList_notProvisionedDevice_shouldNotShowAddUser()442     public void updateUserList_notProvisionedDevice_shouldNotShowAddUser() {
443         Settings.Global.putInt(mContext.getContentResolver(),
444                 Settings.Global.DEVICE_PROVISIONED, 0);
445         mUserCapabilities.mCanAddUser = true;
446 
447         mFragment.updateUserList();
448 
449         verify(mAddUserPreference).setVisible(false);
450     }
451 
452     @Test
updateUserList_notProvisionedDevice_shouldNotShowAddGuest()453     public void updateUserList_notProvisionedDevice_shouldNotShowAddGuest() {
454         Settings.Global.putInt(mContext.getContentResolver(),
455                 Settings.Global.DEVICE_PROVISIONED, 0);
456         mUserCapabilities.mCanAddGuest = true;
457 
458         mFragment.updateUserList();
459 
460         verify(mAddGuestPreference).setVisible(false);
461     }
462 
463     @Test
updateUserList_userSwitcherDisabled_shouldNotShowAddUser()464     public void updateUserList_userSwitcherDisabled_shouldNotShowAddUser() {
465         givenUsers(getAdminUser(true));
466         mUserCapabilities.mCanAddUser = true;
467         mUserCapabilities.mUserSwitcherEnabled = false;
468 
469         mFragment.updateUserList();
470 
471         verify(mAddUserPreference).setVisible(false);
472     }
473 
474     @Test
updateUserList_userSwitcherDisabled_shouldNotShowAddGuest()475     public void updateUserList_userSwitcherDisabled_shouldNotShowAddGuest() {
476         givenUsers(getAdminUser(true));
477         mUserCapabilities.mCanAddGuest = true;
478         mUserCapabilities.mUserSwitcherEnabled = false;
479 
480         mFragment.updateUserList();
481 
482         verify(mAddGuestPreference).setVisible(false);
483     }
484 
485     @Test
updateUserList_shouldAddAdminUserPreference()486     public void updateUserList_shouldAddAdminUserPreference() {
487         givenUsers(getAdminUser(true));
488 
489         mFragment.updateUserList();
490 
491         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
492         verify(mFragment.mUserListCategory).addPreference(captor.capture());
493         UserPreference adminPref = captor.getValue();
494         assertThat(adminPref).isSameInstanceAs(mMePreference);
495     }
496 
497     @Test
updateUserList_existingGuest_shouldAddGuestUserPreference()498     public void updateUserList_existingGuest_shouldAddGuestUserPreference() {
499         givenUsers(getAdminUser(true), getGuest(false));
500 
501         mFragment.updateUserList();
502 
503         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
504         verify(mFragment.mGuestUserCategory, times(1))
505                 .addPreference(captor.capture());
506         UserPreference guestPref = captor.getAllValues().get(0);
507         assertThat(guestPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
508         assertThat(guestPref.getTitle()).isEqualTo("Guest");
509         assertThat(guestPref.getIcon()).isNotNull();
510         assertThat(guestPref.getKey()).isEqualTo(KEY_USER_GUEST);
511         assertThat(guestPref.isEnabled()).isEqualTo(true);
512         assertThat(guestPref.isSelectable()).isEqualTo(true);
513         assertThat(guestPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
514     }
515 
516     @Test
updateUserList_existingSecondaryUser_shouldAddSecondaryUserPreference()517     public void updateUserList_existingSecondaryUser_shouldAddSecondaryUserPreference() {
518         givenUsers(getAdminUser(true), getSecondaryUser(false));
519 
520         mFragment.updateUserList();
521 
522         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
523         verify(mFragment.mUserListCategory, times(2))
524                 .addPreference(captor.capture());
525         UserPreference userPref = captor.getAllValues().get(1);
526         assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
527         assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
528         assertThat(userPref.getIcon()).isNotNull();
529         assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
530         assertThat(userPref.isEnabled()).isEqualTo(true);
531         assertThat(userPref.isSelectable()).isEqualTo(true);
532         assertThat(userPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
533     }
534 
535     @Test
updateUserList_existingSecondaryUser_shouldAddOnlyCurrUser_MultiUserIsDisabled()536     public void updateUserList_existingSecondaryUser_shouldAddOnlyCurrUser_MultiUserIsDisabled() {
537         givenUsers(getAdminUser(true), getSecondaryUser(false));
538         mUserCapabilities.mUserSwitcherEnabled = false;
539 
540         mFragment.updateUserList();
541 
542         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
543         verify(mFragment.mUserListCategory, times(1))
544                 .addPreference(captor.capture());
545 
546         List<UserPreference> userPrefs = captor.getAllValues();
547         assertThat(userPrefs.size()).isEqualTo(1);
548         assertThat(userPrefs.get(0)).isSameInstanceAs(mMePreference);
549     }
550 
551     @Test
updateUserList_existingSecondaryUser_shouldAddSecondaryUser_MultiUserIsEnabled()552     public void updateUserList_existingSecondaryUser_shouldAddSecondaryUser_MultiUserIsEnabled() {
553         givenUsers(getAdminUser(true), getSecondaryUser(false));
554 
555         mFragment.updateUserList();
556 
557         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
558         verify(mFragment.mUserListCategory, times(2))
559                 .addPreference(captor.capture());
560 
561         List<UserPreference> userPrefs = captor.getAllValues();
562         UserPreference adminPref = userPrefs.get(0);
563         UserPreference secondaryPref = userPrefs.get(1);
564 
565         assertThat(userPrefs.size()).isEqualTo(2);
566         assertThat(adminPref).isSameInstanceAs(mMePreference);
567         assertThat(secondaryPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
568         assertThat(secondaryPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
569         assertThat(secondaryPref.getIcon()).isNotNull();
570         assertThat(secondaryPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
571         assertThat(secondaryPref.isEnabled()).isEqualTo(true);
572         assertThat(secondaryPref.isSelectable()).isEqualTo(true);
573         assertThat(secondaryPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
574     }
575 
576     @Test
updateUserList_existingRestrictedUser_shouldAddRestrictedUserPreference()577     public void updateUserList_existingRestrictedUser_shouldAddRestrictedUserPreference() {
578         givenUsers(getAdminUser(true), getRestrictedUser(false));
579 
580         mFragment.updateUserList();
581 
582         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
583         verify(mFragment.mUserListCategory, times(2))
584                 .addPreference(captor.capture());
585         UserPreference userPref = captor.getAllValues().get(1);
586         assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
587         assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
588         assertThat(userPref.getIcon()).isNotNull();
589         assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
590         assertThat(userPref.getSummary()).isEqualTo("Restricted profile");
591         assertThat(userPref.isEnabled()).isEqualTo(true);
592         assertThat(userPref.isSelectable()).isEqualTo(true);
593         assertThat(userPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
594     }
595 
596     @Test
updateUserList_existingManagedUser_shouldNotAddUserPreference()597     public void updateUserList_existingManagedUser_shouldNotAddUserPreference() {
598         givenUsers(getAdminUser(true), getManagedUser());
599 
600         mFragment.updateUserList();
601 
602         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
603         verify(mFragment.mUserListCategory).addPreference(captor.capture());
604         List<UserPreference> userPreferences = captor.getAllValues();
605         assertThat(userPreferences.size()).isEqualTo(1);
606         assertThat(userPreferences.get(0).getUserId()).isEqualTo(ACTIVE_USER_ID);
607     }
608 
609     @Test
updateUserList_uninitializedRestrictedUser_shouldAddUserPreference()610     public void updateUserList_uninitializedRestrictedUser_shouldAddUserPreference() {
611         UserInfo restrictedUser = getRestrictedUser(false);
612         removeFlag(restrictedUser, UserInfo.FLAG_INITIALIZED);
613         givenUsers(getAdminUser(true), restrictedUser);
614         doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
615         mUserCapabilities.mDisallowSwitchUser = false;
616 
617         mFragment.updateUserList();
618 
619         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
620         verify(mFragment.mUserListCategory, times(2))
621                 .addPreference(captor.capture());
622         UserPreference userPref = captor.getAllValues().get(1);
623         assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
624         assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
625         assertThat(userPref.getIcon()).isNotNull();
626         assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
627         assertThat(userPref.getSummary()).isEqualTo("Not set up - Restricted profile");
628         assertThat(userPref.isEnabled()).isEqualTo(true);
629         assertThat(userPref.isSelectable()).isEqualTo(true);
630         assertThat(userPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
631     }
632 
633     @Test
updateUserList_uninitializedUserAndCanNotSwitchUser_shouldDisablePref()634     public void updateUserList_uninitializedUserAndCanNotSwitchUser_shouldDisablePref() {
635         UserInfo uninitializedUser = getSecondaryUser(false);
636         removeFlag(uninitializedUser, UserInfo.FLAG_INITIALIZED);
637         givenUsers(getAdminUser(true), uninitializedUser);
638         doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
639                 .when(mUserManager).getUserSwitchability();
640         mUserCapabilities.mDisallowSwitchUser = false;
641 
642         mFragment.updateUserList();
643 
644         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
645         verify(mFragment.mUserListCategory, times(2))
646                 .addPreference(captor.capture());
647         UserPreference userPref = captor.getAllValues().get(1);
648         assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
649         assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
650         assertThat(userPref.getIcon()).isNotNull();
651         assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
652         assertThat(userPref.getSummary()).isEqualTo("Not set up");
653         assertThat(userPref.isEnabled()).isEqualTo(false);
654         assertThat(userPref.isSelectable()).isEqualTo(true);
655         assertThat(userPref.getOnPreferenceClickListener()).isSameInstanceAs(mFragment);
656     }
657 
658     @Test
updateUserList_guestWithoutInitializedFlag_shouldNotSetSummary()659     public void updateUserList_guestWithoutInitializedFlag_shouldNotSetSummary() {
660         UserInfo guest = getGuest(false);
661         removeFlag(guest, UserInfo.FLAG_INITIALIZED);
662         givenUsers(getAdminUser(true), guest);
663 
664         mFragment.updateUserList();
665 
666         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
667         verify(mFragment.mGuestUserCategory, times(1))
668                 .addPreference(captor.capture());
669         UserPreference userPref = captor.getAllValues().get(0);
670         assertThat(userPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
671         assertThat(userPref.getSummary()).isNull();
672     }
673 
674     @Test
updateUserList_activeUserWithoutInitializedFlag_shouldNotSetSummary()675     public void updateUserList_activeUserWithoutInitializedFlag_shouldNotSetSummary() {
676         UserInfo activeUser = getSecondaryUser(true);
677         removeFlag(activeUser, UserInfo.FLAG_INITIALIZED);
678         givenUsers(activeUser);
679 
680         mFragment.updateUserList();
681 
682         ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
683         verify(mFragment.mUserListCategory).addPreference(captor.capture());
684         UserPreference userPref = captor.getValue();
685         assertThat(userPref.getUserId()).isEqualTo(ACTIVE_USER_ID);
686         assertThat(userPref.getSummary()).isNull();
687     }
688 
689     @Test
updateUserList_guestIsAlreadyCreated_shouldNotShowAddGuest()690     public void updateUserList_guestIsAlreadyCreated_shouldNotShowAddGuest() {
691         givenUsers(getAdminUser(true), getGuest(true));
692         mUserCapabilities.mCanAddGuest = true;
693 
694         mFragment.updateUserList();
695 
696         verify(mAddGuestPreference).setVisible(false);
697     }
698 
699     @Test
updateUserList_userIconLoaded_shouldNotLoadIcon()700     public void updateUserList_userIconLoaded_shouldNotLoadIcon() {
701         UserInfo currentUser = getAdminUser(true);
702         currentUser.iconPath = "/data/system/users/0/photo.png";
703         givenUsers(currentUser);
704         mFragment.mUserIcons.put(ACTIVE_USER_ID,
705                 Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
706 
707         mFragment.updateUserList();
708 
709         verify(mUserManager, never()).getUserIcon(anyInt());
710         // updateUserList should be called only once
711         verify(mUserManager).getAliveUsers();
712     }
713 
714     @Ignore
715     @Test
updateUserList_userIconMissing_shouldLoadIcon()716     public void updateUserList_userIconMissing_shouldLoadIcon() {
717         UserInfo currentUser = getAdminUser(true);
718         currentUser.iconPath = "/data/system/users/0/photo.png";
719         givenUsers(currentUser);
720         // create a non-empty sparsearray
721         mFragment.mUserIcons.put(5, Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
722         Bitmap userIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
723         doReturn(userIcon).when(mUserManager).getUserIcon(ACTIVE_USER_ID);
724 
725         mFragment.updateUserList();
726         shadowOf(Looper.getMainLooper()).idle();
727 
728         verify(mUserManager).getUserIcon(ACTIVE_USER_ID);
729         // updateUserList should be called another time after loading the icons
730         verify(mUserManager, times(2)).getAliveUsers();
731     }
732 
733     @Test
onPreferenceClick_addGuestClicked_createGuestAndOpenDetails()734     public void onPreferenceClick_addGuestClicked_createGuestAndOpenDetails() {
735         UserInfo createdGuest = getGuest(false);
736         removeFlag(createdGuest, UserInfo.FLAG_INITIALIZED);
737         doReturn(createdGuest).when(mUserManager).createGuest(mActivity);
738         doReturn(mActivity).when(mFragment).getContext();
739 
740         mFragment.onPreferenceClick(mAddGuestPreference);
741 
742         verify(mUserManager).createGuest(mActivity);
743         Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
744         ShadowIntent shadowIntent = shadowOf(startedIntent);
745         assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
746         assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
747                 .isEqualTo(UserDetailsSettings.class.getName());
748         Bundle arguments = startedIntent.getBundleExtra(
749                 SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
750         assertThat(arguments).isNotNull();
751         assertThat(arguments.getInt(UserDetailsSettings.EXTRA_USER_ID, 0))
752                 .isEqualTo(createdGuest.id);
753         assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false))
754                 .isEqualTo(true);
755         verify(mMetricsFeatureProvider).action(any(), eq(SettingsEnums.ACTION_USER_GUEST_ADD));
756     }
757 
758     @Test
onPreferenceClick_addSupervisedUserClicked_startIntentWithAction()759     public void onPreferenceClick_addSupervisedUserClicked_startIntentWithAction() {
760         final String intentPackage = "testPackage";
761         final String intentAction = UserManager.ACTION_CREATE_SUPERVISED_USER;
762         final int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
763         final int metricsAction = SettingsEnums.ACTION_USER_SUPERVISED_ADD;
764         try {
765             setConfigSupervisedUserCreationPackage(intentPackage);
766             doReturn(new ResolveInfo()).when(mPackageManager).resolveActivity(any(), anyInt());
767             doNothing().when(mFragment).startActivity(any());
768 
769             mFragment.onPreferenceClick(mAddSupervisedUserPreference);
770 
771             final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
772             verify(mFragment).startActivity(captor.capture());
773             assertThat(captor.getValue().getPackage()).isEqualTo(intentPackage);
774             assertThat(captor.getValue().getAction()).isEqualTo(intentAction);
775             assertThat(captor.getValue().getFlags() & intentFlags).isGreaterThan(0);
776 
777             verify(mMetricsFeatureProvider).action(any(), eq(metricsAction));
778         } finally {
779             SettingsShadowResources.reset();
780         }
781     }
782 
783     @Test
getRealUsersCount_onlyAdmin_shouldCount()784     public void getRealUsersCount_onlyAdmin_shouldCount() {
785         givenUsers(getAdminUser(true));
786 
787         int result = mFragment.getRealUsersCount();
788 
789         assertThat(result).isEqualTo(1);
790         verify(mUserManager).getUsers();
791     }
792 
793     @Test
getRealUsersCount_secondaryUser_shouldCount()794     public void getRealUsersCount_secondaryUser_shouldCount() {
795         givenUsers(getAdminUser(true), getSecondaryUser(false));
796 
797         int result = mFragment.getRealUsersCount();
798 
799         assertThat(result).isEqualTo(2);
800         verify(mUserManager).getUsers();
801     }
802 
803     @Test
getRealUsersCount_restrictedUser_shouldCount()804     public void getRealUsersCount_restrictedUser_shouldCount() {
805         givenUsers(getAdminUser(true), getSecondaryUser(false));
806 
807         int result = mFragment.getRealUsersCount();
808 
809         assertThat(result).isEqualTo(2);
810         verify(mUserManager).getUsers();
811     }
812 
813     @Test
getRealUsersCount_guest_shouldNotCount()814     public void getRealUsersCount_guest_shouldNotCount() {
815         givenUsers(getAdminUser(true), getGuest(false));
816 
817         int result = mFragment.getRealUsersCount();
818 
819         assertThat(result).isEqualTo(1);
820         verify(mUserManager).getUsers();
821     }
822 
823     @Test
getRealUsersCount_managedUser_shouldNotCount()824     public void getRealUsersCount_managedUser_shouldNotCount() {
825         givenUsers(getAdminUser(true), getManagedUser());
826 
827         int result = mFragment.getRealUsersCount();
828 
829         assertThat(result).isEqualTo(1);
830         verify(mUserManager).getUsers();
831     }
832 
setConfigSupervisedUserCreationPackage(String value)833     private void setConfigSupervisedUserCreationPackage(String value) {
834         SettingsShadowResources.overrideResource(
835                 com.android.internal.R.string.config_supervisedUserCreationPackage,
836                 value
837         );
838         mFragment.setConfigSupervisedUserCreationPackage();
839         mUserCapabilities.mCanAddUser = true;
840         mFragment.updateUserList();
841     }
842 
843     @Test
addSupervisedUserOption_resourceIsDefined_shouldBeDisplayed()844     public void addSupervisedUserOption_resourceIsDefined_shouldBeDisplayed() {
845         try {
846             setConfigSupervisedUserCreationPackage("test");
847             verify(mAddSupervisedUserPreference).setVisible(true);
848         } finally {
849             SettingsShadowResources.reset();
850         }
851     }
852 
853     @Test
addSupervisedUserOption_resourceIsNotDefined_shouldBeHidden()854     public void addSupervisedUserOption_resourceIsNotDefined_shouldBeHidden() {
855         try {
856             setConfigSupervisedUserCreationPackage("");
857             verify(mAddSupervisedUserPreference).setVisible(false);
858         } finally {
859             SettingsShadowResources.reset();
860         }
861     }
862 
givenUsers(UserInfo... userInfo)863     private void givenUsers(UserInfo... userInfo) {
864         List<UserInfo> users = Arrays.asList(userInfo);
865         doReturn(users).when(mUserManager).getUsers();
866         doReturn(users).when(mUserManager).getAliveUsers();
867         users.forEach(user ->
868                 doReturn(user).when(mUserManager).getUserInfo(user.id));
869     }
870 
removeFlag(UserInfo userInfo, int flag)871     private static void removeFlag(UserInfo userInfo, int flag) {
872         userInfo.flags &= ~flag;
873     }
874 
getAdminUser(boolean active)875     private static UserInfo getAdminUser(boolean active) {
876         return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_ADMIN_USER_ID, ADMIN_USER_NAME,
877                 null,
878                 UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN,
879                 UserManager.USER_TYPE_FULL_SYSTEM);
880     }
881 
getSecondaryUser(boolean active)882     private static UserInfo getSecondaryUser(boolean active) {
883         return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_SECONDARY_USER_ID,
884                 SECONDARY_USER_NAME, null,
885                 UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED,
886                 UserManager.USER_TYPE_FULL_SECONDARY);
887     }
888 
getRestrictedUser(boolean active)889     private static UserInfo getRestrictedUser(boolean active) {
890         return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_RESTRICTED_USER_ID,
891                 RESTRICTED_USER_NAME, null,
892                 UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_RESTRICTED,
893                 UserManager.USER_TYPE_FULL_RESTRICTED);
894     }
895 
getManagedUser()896     private static UserInfo getManagedUser() {
897         return new UserInfo(MANAGED_USER_ID,
898                 MANAGED_USER_NAME, null,
899                 UserInfo.FLAG_PROFILE | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE,
900                 UserManager.USER_TYPE_PROFILE_MANAGED);
901     }
902 
getGuest(boolean active)903     private static UserInfo getGuest(boolean active) {
904         return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_GUEST_USER_ID, GUEST_USER_NAME,
905                 null,
906                 UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_GUEST,
907                 UserManager.USER_TYPE_FULL_GUEST);
908     }
909 
910 
911 }
912