1 /*
2  * Copyright (C) 2022 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 package com.android.server.pm;
17 
18 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
19 
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 import static com.google.common.truth.Truth.assertWithMessage;
25 
26 import static org.junit.Assert.assertThrows;
27 import static org.mockito.Mockito.any;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.when;
30 
31 import android.annotation.UserIdInt;
32 import android.app.ActivityManagerInternal;
33 import android.content.Context;
34 import android.content.pm.PackageManagerInternal;
35 import android.content.pm.UserInfo;
36 import android.os.UserHandle;
37 import android.os.UserManager;
38 import android.os.storage.StorageManager;
39 import android.provider.Settings;
40 import android.util.Log;
41 import android.util.Pair;
42 import android.util.SparseArray;
43 
44 import androidx.test.annotation.UiThreadTest;
45 
46 import com.android.internal.widget.LockSettingsInternal;
47 import com.android.server.ExtendedMockitoRule;
48 import com.android.server.LocalServices;
49 import com.android.server.am.UserState;
50 import com.android.server.pm.UserManagerService.UserData;
51 import com.android.server.storage.DeviceStorageMonitorInternal;
52 
53 import org.junit.After;
54 import org.junit.Before;
55 import org.junit.Rule;
56 import org.junit.Test;
57 import org.mockito.Mock;
58 
59 /**
60  * Run as {@code atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest}
61  */
62 public final class UserManagerServiceTest {
63 
64     private static final String TAG = UserManagerServiceTest.class.getSimpleName();
65 
66     /**
67      * Id for a simple user (that doesn't have profiles).
68      */
69     private static final int USER_ID = 600;
70 
71     /**
72      * Id for another simple user.
73      */
74     private static final int OTHER_USER_ID = 666;
75 
76     /**
77      * Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
78      *
79      * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
80      */
81     private static final int PARENT_USER_ID = 642;
82 
83     /**
84      * Id for a profile whose parent is {@link #PARENTUSER_ID}.
85      *
86      * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
87      */
88     private static final int PROFILE_USER_ID = 643;
89 
90     @Rule
91     public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
92             .spyStatic(UserManager.class)
93             .spyStatic(LocalServices.class)
94             .mockStatic(Settings.Global.class)
95             .build();
96 
97     private final Object mPackagesLock = new Object();
98     private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
99             .getTargetContext();
100     private final SparseArray<UserData> mUsers = new SparseArray<>();
101 
102     private Context mSpiedContext;
103 
104     private @Mock PackageManagerService mMockPms;
105     private @Mock UserDataPreparer mMockUserDataPreparer;
106     private @Mock ActivityManagerInternal mActivityManagerInternal;
107     private @Mock DeviceStorageMonitorInternal mDeviceStorageMonitorInternal;
108     private @Mock StorageManager mStorageManager;
109     private @Mock LockSettingsInternal mLockSettingsInternal;
110     private @Mock PackageManagerInternal mPackageManagerInternal;
111 
112     /**
113      * Reference to the {@link UserManagerService} being tested.
114      */
115     private UserManagerService mUms;
116 
117     /**
118      * Reference to the {@link UserManagerInternal} being tested.
119      */
120     private UserManagerInternal mUmi;
121 
122     @Before
123     @UiThreadTest // Needed to initialize main handler
setFixtures()124     public void setFixtures() {
125         mSpiedContext = spy(mRealContext);
126 
127         // Called when WatchedUserStates is constructed
128         doNothing().when(() -> UserManager.invalidateIsUserUnlockedCache());
129 
130         // Called when creating new users
131         when(mDeviceStorageMonitorInternal.isMemoryLow()).thenReturn(false);
132         mockGetLocalService(DeviceStorageMonitorInternal.class, mDeviceStorageMonitorInternal);
133         when(mSpiedContext.getSystemService(StorageManager.class)).thenReturn(mStorageManager);
134         mockGetLocalService(LockSettingsInternal.class, mLockSettingsInternal);
135         mockGetLocalService(PackageManagerInternal.class, mPackageManagerInternal);
136         doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any());
137 
138         // Must construct UserManagerService in the UiThread
139         mUms = new UserManagerService(mSpiedContext, mMockPms, mMockUserDataPreparer,
140                 mPackagesLock, mRealContext.getDataDir(), mUsers);
141         mUmi = LocalServices.getService(UserManagerInternal.class);
142         assertWithMessage("LocalServices.getService(UserManagerInternal.class)").that(mUmi)
143                 .isNotNull();
144     }
145 
146     @After
resetUserManagerInternal()147     public void resetUserManagerInternal() {
148         // LocalServices follows the "Highlander rule" - There can be only one!
149         LocalServices.removeServiceForTest(UserManagerInternal.class);
150     }
151 
152     @Test
testGetCurrentUserId_amInternalNotReady()153     public void testGetCurrentUserId_amInternalNotReady() {
154         mockGetLocalService(ActivityManagerInternal.class, null);
155 
156         assertWithMessage("getCurrentUserId()").that(mUms.getCurrentUserId())
157                 .isEqualTo(UserHandle.USER_NULL);
158     }
159 
160     @Test
testGetCurrentAndTargetUserIds()161     public void testGetCurrentAndTargetUserIds() {
162         mockCurrentAndTargetUser(USER_ID, OTHER_USER_ID);
163 
164         assertWithMessage("getCurrentAndTargetUserIds()")
165                 .that(mUms.getCurrentAndTargetUserIds())
166                 .isEqualTo(new Pair<>(USER_ID, OTHER_USER_ID));
167     }
168 
169     @Test
testGetCurrentUserId()170     public void testGetCurrentUserId() {
171         mockCurrentUser(USER_ID);
172 
173         assertWithMessage("getCurrentUserId()").that(mUms.getCurrentUserId())
174                 .isEqualTo(USER_ID);
175     }
176 
177     @Test
testIsCurrentUserOrRunningProfileOfCurrentUser_currentUser()178     public void testIsCurrentUserOrRunningProfileOfCurrentUser_currentUser() {
179         mockCurrentUser(USER_ID);
180 
181         assertWithMessage("isCurrentUserOrRunningProfileOfCurrentUser(%s)", USER_ID)
182                 .that(mUms.isCurrentUserOrRunningProfileOfCurrentUser(USER_ID)).isTrue();
183     }
184 
185     @Test
testIsCurrentUserOrRunningProfileOfCurrentUser_notCurrentUser()186     public void testIsCurrentUserOrRunningProfileOfCurrentUser_notCurrentUser() {
187         mockCurrentUser(OTHER_USER_ID);
188 
189         assertWithMessage("isCurrentUserOrRunningProfileOfCurrentUser(%s)", USER_ID)
190                 .that(mUms.isCurrentUserOrRunningProfileOfCurrentUser(USER_ID)).isFalse();
191     }
192 
193     @Test
testIsCurrentUserOrRunningProfileOfCurrentUser_startedProfileOfCurrentUser()194     public void testIsCurrentUserOrRunningProfileOfCurrentUser_startedProfileOfCurrentUser() {
195         addDefaultProfileAndParent();
196         startDefaultProfile();
197         mockCurrentUser(PARENT_USER_ID);
198 
199         assertWithMessage("isCurrentUserOrRunningProfileOfCurrentUser(%s)", PROFILE_USER_ID)
200                 .that(mUms.isCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID)).isTrue();
201     }
202 
203     @Test
testIsCurrentUserOrRunningProfileOfCurrentUser_stoppedProfileOfCurrentUser()204     public void testIsCurrentUserOrRunningProfileOfCurrentUser_stoppedProfileOfCurrentUser() {
205         addDefaultProfileAndParent();
206         stopDefaultProfile();
207         mockCurrentUser(PARENT_USER_ID);
208 
209         assertWithMessage("isCurrentUserOrRunningProfileOfCurrentUser(%s)", PROFILE_USER_ID)
210                 .that(mUms.isCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID)).isFalse();
211     }
212 
213     @Test
testIsCurrentUserOrRunningProfileOfCurrentUser_profileOfNonCurrentUSer()214     public void testIsCurrentUserOrRunningProfileOfCurrentUser_profileOfNonCurrentUSer() {
215         addDefaultProfileAndParent();
216         mockCurrentUser(OTHER_USER_ID);
217 
218         assertWithMessage("isCurrentUserOrRunningProfileOfCurrentUser(%s)", PROFILE_USER_ID)
219                 .that(mUms.isCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID)).isFalse();
220     }
221 
222     @Test
testIsUserRunning_StartedUserShouldReturnTrue()223     public void testIsUserRunning_StartedUserShouldReturnTrue() {
224         addUser(USER_ID);
225         startUser(USER_ID);
226 
227         assertWithMessage("isUserRunning(%s)", USER_ID)
228                 .that(mUms.isUserRunning(USER_ID)).isTrue();
229     }
230 
231     @Test
testIsUserRunning_StoppedUserShouldReturnFalse()232     public void testIsUserRunning_StoppedUserShouldReturnFalse() {
233         addUser(USER_ID);
234         stopUser(USER_ID);
235 
236         assertWithMessage("isUserRunning(%s)", USER_ID)
237                 .that(mUms.isUserRunning(USER_ID)).isFalse();
238     }
239 
240     @Test
testIsUserRunning_CurrentUserStartedWorkProfileShouldReturnTrue()241     public void testIsUserRunning_CurrentUserStartedWorkProfileShouldReturnTrue() {
242         addDefaultProfileAndParent();
243         startDefaultProfile();
244 
245         assertWithMessage("isUserRunning(%s)", PROFILE_USER_ID)
246                 .that(mUms.isUserRunning(PROFILE_USER_ID)).isTrue();
247     }
248 
249     @Test
testIsUserRunning_CurrentUserStoppedWorkProfileShouldReturnFalse()250     public void testIsUserRunning_CurrentUserStoppedWorkProfileShouldReturnFalse() {
251         addDefaultProfileAndParent();
252         stopDefaultProfile();
253 
254         assertWithMessage("isUserRunning(%s)", PROFILE_USER_ID)
255                 .that(mUms.isUserRunning(PROFILE_USER_ID)).isFalse();
256     }
257 
258     @Test
testSetBootUser_SuppliedUserIsSwitchable()259     public void testSetBootUser_SuppliedUserIsSwitchable() throws Exception {
260         addUser(USER_ID);
261         addUser(OTHER_USER_ID);
262 
263         mUms.setBootUser(OTHER_USER_ID);
264 
265         assertWithMessage("getBootUser")
266                 .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
267     }
268 
269     @Test
testSetBootUser_NotHeadless_SuppliedUserIsNotSwitchable()270     public void testSetBootUser_NotHeadless_SuppliedUserIsNotSwitchable() throws Exception {
271         setSystemUserHeadless(false);
272         addUser(USER_ID);
273         addUser(OTHER_USER_ID);
274         addDefaultProfileAndParent();
275 
276         mUms.setBootUser(PROFILE_USER_ID);
277 
278         assertWithMessage("getBootUser")
279                 .that(mUmi.getBootUser(/* waitUntilSet= */ false))
280                 .isEqualTo(UserHandle.USER_SYSTEM);
281     }
282 
283     @Test
testSetBootUser_Headless_SuppliedUserIsNotSwitchable()284     public void testSetBootUser_Headless_SuppliedUserIsNotSwitchable() throws Exception {
285         setSystemUserHeadless(true);
286         addUser(USER_ID);
287         setLastForegroundTime(USER_ID, 1_000_000L);
288         addUser(OTHER_USER_ID);
289         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
290         addDefaultProfileAndParent();
291 
292         mUms.setBootUser(PROFILE_USER_ID);
293 
294         // Boot user not switchable so return most recently in foreground.
295         assertWithMessage("getBootUser")
296                 .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
297     }
298 
299     @Test
testGetBootUser_NotHeadless_ReturnsSystemUser()300     public void testGetBootUser_NotHeadless_ReturnsSystemUser() throws Exception {
301         setSystemUserHeadless(false);
302         addUser(USER_ID);
303         addUser(OTHER_USER_ID);
304 
305         assertWithMessage("getBootUser")
306                 .that(mUmi.getBootUser(/* waitUntilSet= */ false))
307                 .isEqualTo(UserHandle.USER_SYSTEM);
308     }
309 
310     @Test
testGetBootUser_Headless_ReturnsMostRecentlyInForeground()311     public void testGetBootUser_Headless_ReturnsMostRecentlyInForeground() throws Exception {
312         setSystemUserHeadless(true);
313         addUser(USER_ID);
314         setLastForegroundTime(USER_ID, 1_000_000L);
315 
316         addUser(OTHER_USER_ID);
317         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
318 
319         assertWithMessage("getBootUser")
320                 .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
321     }
322 
323     @Test
testGetBootUser_Headless_ThrowsIfOnlySystemUserExists()324     public void testGetBootUser_Headless_ThrowsIfOnlySystemUserExists() throws Exception {
325         setSystemUserHeadless(true);
326 
327         assertThrows(UserManager.CheckedUserOperationException.class,
328                 () -> mUmi.getBootUser(/* waitUntilSet= */ false));
329     }
330 
331     @Test
testGetPreviousFullUserToEnterForeground()332     public void testGetPreviousFullUserToEnterForeground() throws Exception {
333         addUser(USER_ID);
334         setLastForegroundTime(USER_ID, 1_000_000L);
335         addUser(OTHER_USER_ID);
336         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
337 
338         assertWithMessage("getPreviousFullUserToEnterForeground")
339                 .that(mUms.getPreviousFullUserToEnterForeground())
340                 .isEqualTo(OTHER_USER_ID);
341     }
342 
343     @Test
testGetPreviousFullUserToEnterForeground_SkipsCurrentUser()344     public void testGetPreviousFullUserToEnterForeground_SkipsCurrentUser() throws Exception {
345         addUser(USER_ID);
346         setLastForegroundTime(USER_ID, 1_000_000L);
347         addUser(OTHER_USER_ID);
348         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
349 
350         mockCurrentUser(OTHER_USER_ID);
351         assertWithMessage("getPreviousFullUserToEnterForeground should skip current user")
352                 .that(mUms.getPreviousFullUserToEnterForeground())
353                 .isEqualTo(USER_ID);
354     }
355 
356     @Test
testGetPreviousFullUserToEnterForeground_SkipsNonFullUsers()357     public void testGetPreviousFullUserToEnterForeground_SkipsNonFullUsers() throws Exception {
358         addUser(USER_ID);
359         setLastForegroundTime(USER_ID, 1_000_000L);
360         addUser(OTHER_USER_ID);
361         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
362 
363         mUsers.get(OTHER_USER_ID).info.flags &= ~UserInfo.FLAG_FULL;
364         assertWithMessage("getPreviousFullUserToEnterForeground should skip non-full users")
365                 .that(mUms.getPreviousFullUserToEnterForeground())
366                 .isEqualTo(USER_ID);
367     }
368 
369     @Test
testGetPreviousFullUserToEnterForeground_SkipsPartialUsers()370     public void testGetPreviousFullUserToEnterForeground_SkipsPartialUsers() throws Exception {
371         addUser(USER_ID);
372         setLastForegroundTime(USER_ID, 1_000_000L);
373         addUser(OTHER_USER_ID);
374         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
375 
376         mUsers.get(OTHER_USER_ID).info.partial = true;
377         assertWithMessage("getPreviousFullUserToEnterForeground should skip partial users")
378                 .that(mUms.getPreviousFullUserToEnterForeground())
379                 .isEqualTo(USER_ID);
380     }
381 
382     @Test
testGetPreviousFullUserToEnterForeground_SkipsDisabledUsers()383     public void testGetPreviousFullUserToEnterForeground_SkipsDisabledUsers() throws Exception {
384         addUser(USER_ID);
385         setLastForegroundTime(USER_ID, 1_000_000L);
386         addUser(OTHER_USER_ID);
387         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
388 
389         mUsers.get(OTHER_USER_ID).info.flags |= UserInfo.FLAG_DISABLED;
390         assertWithMessage("getPreviousFullUserToEnterForeground should skip disabled users")
391                 .that(mUms.getPreviousFullUserToEnterForeground())
392                 .isEqualTo(USER_ID);
393     }
394 
395     @Test
testGetPreviousFullUserToEnterForeground_SkipsRemovingUsers()396     public void testGetPreviousFullUserToEnterForeground_SkipsRemovingUsers() throws Exception {
397         addUser(USER_ID);
398         setLastForegroundTime(USER_ID, 1_000_000L);
399         addUser(OTHER_USER_ID);
400         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
401 
402         mUms.addRemovingUserId(OTHER_USER_ID);
403         assertWithMessage("getPreviousFullUserToEnterForeground should skip removing users")
404                 .that(mUms.getPreviousFullUserToEnterForeground())
405                 .isEqualTo(USER_ID);
406     }
407 
408     @Test
testCreateUserWithLongName_TruncatesName()409     public void testCreateUserWithLongName_TruncatesName() {
410         UserInfo user = mUms.createUserWithThrow(generateLongString(), USER_TYPE_FULL_SECONDARY, 0);
411         assertThat(user.name.length()).isEqualTo(UserManager.MAX_USER_NAME_LENGTH);
412         UserInfo user1 = mUms.createUserWithThrow("Test", USER_TYPE_FULL_SECONDARY, 0);
413         assertThat(user1.name.length()).isEqualTo(4);
414     }
415 
generateLongString()416     private String generateLongString() {
417         String partialString = "Test Name Test Name Test Name Test Name Test Name Test Name Test "
418                 + "Name Test Name Test Name Test Name "; //String of length 100
419         StringBuilder resultString = new StringBuilder();
420         for (int i = 0; i < 660; i++) {
421             resultString.append(partialString);
422         }
423         return resultString.toString();
424     }
425 
mockCurrentUser(@serIdInt int userId)426     private void mockCurrentUser(@UserIdInt int userId) {
427         mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal);
428 
429         when(mActivityManagerInternal.getCurrentUserId()).thenReturn(userId);
430     }
431 
mockCurrentAndTargetUser(@serIdInt int currentUserId, @UserIdInt int targetUserId)432     private void mockCurrentAndTargetUser(@UserIdInt int currentUserId,
433             @UserIdInt int targetUserId) {
434         mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal);
435 
436         when(mActivityManagerInternal.getCurrentAndTargetUserIds())
437                 .thenReturn(new Pair<>(currentUserId, targetUserId));
438     }
439 
mockGetLocalService(Class<T> serviceClass, T service)440     private <T> void mockGetLocalService(Class<T> serviceClass, T service) {
441         doReturn(service).when(() -> LocalServices.getService(serviceClass));
442     }
443 
addDefaultProfileAndParent()444     private void addDefaultProfileAndParent() {
445         addUser(PARENT_USER_ID);
446         addProfile(PROFILE_USER_ID, PARENT_USER_ID);
447     }
448 
addProfile(@serIdInt int profileId, @UserIdInt int parentId)449     private void addProfile(@UserIdInt int profileId, @UserIdInt int parentId) {
450         TestUserData profileData = new TestUserData(profileId);
451         profileData.info.flags = UserInfo.FLAG_PROFILE;
452         profileData.info.profileGroupId = parentId;
453 
454         addUserData(profileData);
455     }
456 
addUser(@serIdInt int userId)457     private void addUser(@UserIdInt int userId) {
458         TestUserData userData = new TestUserData(userId);
459         userData.info.flags = UserInfo.FLAG_FULL;
460         addUserData(userData);
461     }
462 
startDefaultProfile()463     private void startDefaultProfile() {
464         startUser(PROFILE_USER_ID);
465     }
466 
stopDefaultProfile()467     private void stopDefaultProfile() {
468         stopUser(PROFILE_USER_ID);
469     }
470 
startUser(@serIdInt int userId)471     private void startUser(@UserIdInt int userId) {
472         setUserState(userId, UserState.STATE_RUNNING_UNLOCKED);
473     }
474 
stopUser(@serIdInt int userId)475     private void stopUser(@UserIdInt int userId) {
476         setUserState(userId, UserState.STATE_STOPPING);
477     }
478 
setUserState(@serIdInt int userId, int userState)479     private void setUserState(@UserIdInt int userId, int userState) {
480         mUmi.setUserState(userId, userState);
481     }
482 
addUserData(TestUserData userData)483     private void addUserData(TestUserData userData) {
484         Log.d(TAG, "Adding " + userData);
485         mUsers.put(userData.info.id, userData);
486     }
487 
setSystemUserHeadless(boolean headless)488     private void setSystemUserHeadless(boolean headless) {
489         UserData systemUser = mUsers.get(UserHandle.USER_SYSTEM);
490         if (headless) {
491             systemUser.info.flags &= ~UserInfo.FLAG_FULL;
492             systemUser.info.userType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
493         } else {
494             systemUser.info.flags |= UserInfo.FLAG_FULL;
495             systemUser.info.userType = UserManager.USER_TYPE_FULL_SYSTEM;
496         }
497         doReturn(headless).when(() -> UserManager.isHeadlessSystemUserMode());
498     }
499 
setLastForegroundTime(@serIdInt int userId, long timeMillis)500     private void setLastForegroundTime(@UserIdInt int userId, long timeMillis) {
501         UserData userData = mUsers.get(userId);
502         userData.mLastEnteredForegroundTimeMillis = timeMillis;
503     }
504 
505     private static final class TestUserData extends UserData {
506 
507         @SuppressWarnings("deprecation")
TestUserData(@serIdInt int userId)508         TestUserData(@UserIdInt int userId) {
509             info = new UserInfo();
510             info.id = userId;
511         }
512 
513         @Override
toString()514         public String toString() {
515             return "TestUserData[" + info.toFullString() + "]";
516         }
517     }
518 }
519