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