1 /* 2 * Copyright (C) 2016 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.server.am; 18 19 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 20 import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader; 21 22 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 23 24 import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG; 25 import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG; 26 import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG; 27 import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG; 28 import static com.android.server.am.UserController.USER_CURRENT_MSG; 29 import static com.android.server.am.UserController.USER_START_MSG; 30 import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG; 31 32 import static com.google.android.collect.Lists.newArrayList; 33 import static com.google.android.collect.Sets.newHashSet; 34 import static com.google.common.truth.Truth.assertThat; 35 import static com.google.common.truth.Truth.assertWithMessage; 36 37 import static org.junit.Assert.assertEquals; 38 import static org.junit.Assert.assertFalse; 39 import static org.junit.Assert.assertNotNull; 40 import static org.junit.Assert.assertTrue; 41 import static org.mockito.ArgumentMatchers.anyString; 42 import static org.mockito.Matchers.any; 43 import static org.mockito.Matchers.anyBoolean; 44 import static org.mockito.Matchers.anyInt; 45 import static org.mockito.Matchers.eq; 46 import static org.mockito.Mockito.doAnswer; 47 import static org.mockito.Mockito.doNothing; 48 import static org.mockito.Mockito.doReturn; 49 import static org.mockito.Mockito.mock; 50 import static org.mockito.Mockito.never; 51 import static org.mockito.Mockito.spy; 52 import static org.mockito.Mockito.times; 53 import static org.mockito.Mockito.validateMockitoUsage; 54 import static org.mockito.Mockito.verify; 55 import static org.mockito.Mockito.when; 56 import static org.testng.Assert.assertThrows; 57 58 import android.annotation.Nullable; 59 import android.annotation.UserIdInt; 60 import android.app.ActivityManager; 61 import android.app.IUserSwitchObserver; 62 import android.content.Context; 63 import android.content.IIntentReceiver; 64 import android.content.Intent; 65 import android.content.pm.UserInfo; 66 import android.content.pm.UserInfo.UserInfoFlag; 67 import android.os.Binder; 68 import android.os.Bundle; 69 import android.os.Handler; 70 import android.os.HandlerThread; 71 import android.os.IRemoteCallback; 72 import android.os.Looper; 73 import android.os.Message; 74 import android.os.RemoteException; 75 import android.os.UserHandle; 76 import android.os.UserManager; 77 import android.os.storage.IStorageManager; 78 import android.platform.test.annotations.Presubmit; 79 import android.util.Log; 80 81 import androidx.test.filters.SmallTest; 82 83 import com.android.server.FgThread; 84 import com.android.server.am.UserState.KeyEvictedCallback; 85 import com.android.server.pm.UserManagerInternal; 86 import com.android.server.pm.UserManagerService; 87 import com.android.server.wm.WindowManagerService; 88 89 import org.junit.After; 90 import org.junit.Before; 91 import org.junit.Test; 92 93 import java.util.ArrayList; 94 import java.util.Arrays; 95 import java.util.Collections; 96 import java.util.HashMap; 97 import java.util.LinkedHashSet; 98 import java.util.List; 99 import java.util.Set; 100 101 /** 102 * Tests for {@link UserController}. 103 * 104 * Build/Install/Run: 105 * atest FrameworksServicesTests:UserControllerTest 106 */ 107 @SmallTest 108 @Presubmit 109 110 public class UserControllerTest { 111 // Use big enough user id to avoid picking up already active user id. 112 private static final int TEST_USER_ID = 100; 113 private static final int TEST_USER_ID1 = 101; 114 private static final int TEST_USER_ID2 = 102; 115 private static final int TEST_USER_ID3 = 103; 116 private static final int NONEXIST_USER_ID = 2; 117 private static final int TEST_PRE_CREATED_USER_ID = 103; 118 119 private static final int NO_USERINFO_FLAGS = 0; 120 121 private static final String TAG = UserControllerTest.class.getSimpleName(); 122 123 private static final long HANDLER_WAIT_TIME_MS = 100; 124 125 private UserController mUserController; 126 private TestInjector mInjector; 127 private final HashMap<Integer, UserState> mUserStates = new HashMap<>(); 128 129 private final KeyEvictedCallback mKeyEvictedCallback = (userId) -> { /* ignore */ }; 130 131 private static final List<String> START_FOREGROUND_USER_ACTIONS = newArrayList( 132 Intent.ACTION_USER_STARTED, 133 Intent.ACTION_USER_SWITCHED, 134 Intent.ACTION_USER_STARTING); 135 136 private static final List<String> START_BACKGROUND_USER_ACTIONS = newArrayList( 137 Intent.ACTION_USER_STARTED, 138 Intent.ACTION_LOCKED_BOOT_COMPLETED, 139 Intent.ACTION_USER_STARTING); 140 141 private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES = newHashSet( 142 REPORT_USER_SWITCH_MSG, 143 USER_SWITCH_TIMEOUT_MSG, 144 USER_START_MSG, 145 USER_CURRENT_MSG); 146 147 private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet( 148 USER_START_MSG, 149 REPORT_LOCKED_BOOT_COMPLETE_MSG); 150 151 @Before setUp()152 public void setUp() throws Exception { 153 runWithDexmakerShareClassLoader(() -> { 154 mInjector = spy(new TestInjector(getInstrumentation().getTargetContext())); 155 doNothing().when(mInjector).clearAllLockedTasks(anyString()); 156 doNothing().when(mInjector).startHomeActivity(anyInt(), anyString()); 157 doReturn(false).when(mInjector).taskSupervisorSwitchUser(anyInt(), any()); 158 doNothing().when(mInjector).taskSupervisorResumeFocusedStackTopActivity(); 159 doNothing().when(mInjector).systemServiceManagerOnUserStopped(anyInt()); 160 doNothing().when(mInjector).activityManagerForceStopPackage(anyInt(), anyString()); 161 doNothing().when(mInjector).activityManagerOnUserStopped(anyInt()); 162 doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt()); 163 doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt()); 164 // All UserController params are set to default. 165 mUserController = new UserController(mInjector); 166 setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS); 167 setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated=*/ true, null); 168 }); 169 } 170 171 @After tearDown()172 public void tearDown() throws Exception { 173 mInjector.mHandlerThread.quit(); 174 validateMockitoUsage(); 175 } 176 177 @Test testStartUser_foreground()178 public void testStartUser_foreground() { 179 mUserController.startUser(TEST_USER_ID, true /* foreground */); 180 verify(mInjector.getWindowManager()).startFreezingScreen(anyInt(), anyInt()); 181 verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 182 verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); 183 verify(mInjector.getWindowManager()).setSwitchingUser(true); 184 verify(mInjector).clearAllLockedTasks(anyString()); 185 startForegroundUserAssertions(); 186 } 187 188 @Test testStartUser_background()189 public void testStartUser_background() { 190 mUserController.startUser(TEST_USER_ID, false /* foreground */); 191 verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); 192 verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); 193 verify(mInjector, never()).clearAllLockedTasks(anyString()); 194 startBackgroundUserAssertions(); 195 } 196 197 @Test testStartUserUIDisabled()198 public void testStartUserUIDisabled() { 199 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false, 200 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); 201 202 mUserController.startUser(TEST_USER_ID, true /* foreground */); 203 verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); 204 verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 205 verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); 206 startForegroundUserAssertions(); 207 } 208 209 @Test testStartPreCreatedUser_foreground()210 public void testStartPreCreatedUser_foreground() { 211 assertFalse(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ true)); 212 // Make sure no intents have been fired for pre-created users. 213 assertTrue(mInjector.mSentIntents.isEmpty()); 214 } 215 216 @Test testStartPreCreatedUser_background()217 public void testStartPreCreatedUser_background() throws Exception { 218 assertTrue(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ false)); 219 // Make sure no intents have been fired for pre-created users. 220 assertTrue(mInjector.mSentIntents.isEmpty()); 221 222 verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); 223 verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); 224 verify(mInjector, never()).clearAllLockedTasks(anyString()); 225 226 assertWithMessage("should not have received intents") 227 .that(getActions(mInjector.mSentIntents)).isEmpty(); 228 // TODO(b/140868593): should have received a USER_UNLOCK_MSG message as well, but it doesn't 229 // because StorageManager.isUserKeyUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to 230 // properly fix it, we'd need to move this class to FrameworksMockingServicesTests so we can 231 // mock static methods (but moving this class would involve changing the presubmit tests, 232 // and the cascade effect goes on...). In fact, a better approach would to not assert the 233 // binder calls, but their side effects (in this case, that the user is stopped right away) 234 assertWithMessage("wrong binder message calls").that(mInjector.mHandler.getMessageCodes()) 235 .containsExactly(USER_START_MSG); 236 } 237 startUserAssertions( List<String> expectedActions, Set<Integer> expectedMessageCodes)238 private void startUserAssertions( 239 List<String> expectedActions, Set<Integer> expectedMessageCodes) { 240 assertEquals(expectedActions, getActions(mInjector.mSentIntents)); 241 Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes(); 242 assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes); 243 } 244 startBackgroundUserAssertions()245 private void startBackgroundUserAssertions() { 246 startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES); 247 } 248 startForegroundUserAssertions()249 private void startForegroundUserAssertions() { 250 startUserAssertions(START_FOREGROUND_USER_ACTIONS, START_FOREGROUND_USER_MESSAGE_CODES); 251 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 252 assertNotNull(reportMsg); 253 UserState userState = (UserState) reportMsg.obj; 254 assertNotNull(userState); 255 assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier()); 256 assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state); 257 assertEquals("Unexpected old user id", 0, reportMsg.arg1); 258 assertEquals("Unexpected new user id", TEST_USER_ID, reportMsg.arg2); 259 } 260 261 @Test testFailedStartUserInForeground()262 public void testFailedStartUserInForeground() { 263 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false, 264 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); 265 266 mUserController.startUserInForeground(NONEXIST_USER_ID); 267 verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); 268 verify(mInjector.getWindowManager()).setSwitchingUser(false); 269 } 270 271 @Test testDispatchUserSwitch()272 public void testDispatchUserSwitch() throws RemoteException { 273 // Prepare mock observer and register it 274 IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 275 when(observer.asBinder()).thenReturn(new Binder()); 276 doAnswer(invocation -> { 277 IRemoteCallback callback = (IRemoteCallback) invocation.getArguments()[1]; 278 callback.sendResult(null); 279 return null; 280 }).when(observer).onUserSwitching(anyInt(), any()); 281 mUserController.registerUserSwitchObserver(observer, "mock"); 282 // Start user -- this will update state of mUserController 283 mUserController.startUser(TEST_USER_ID, true); 284 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 285 assertNotNull(reportMsg); 286 UserState userState = (UserState) reportMsg.obj; 287 int oldUserId = reportMsg.arg1; 288 int newUserId = reportMsg.arg2; 289 // Call dispatchUserSwitch and verify that observer was called only once 290 mInjector.mHandler.clearAllRecordedMessages(); 291 mUserController.dispatchUserSwitch(userState, oldUserId, newUserId); 292 verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any()); 293 Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG); 294 Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes(); 295 assertEquals("Unexpected message sent", expectedCodes, actualCodes); 296 Message conMsg = mInjector.mHandler.getMessageForCode(CONTINUE_USER_SWITCH_MSG); 297 assertNotNull(conMsg); 298 userState = (UserState) conMsg.obj; 299 assertNotNull(userState); 300 assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier()); 301 assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state); 302 assertEquals("Unexpected old user id", 0, conMsg.arg1); 303 assertEquals("Unexpected new user id", TEST_USER_ID, conMsg.arg2); 304 } 305 306 @Test testDispatchUserSwitchBadReceiver()307 public void testDispatchUserSwitchBadReceiver() throws RemoteException { 308 // Prepare mock observer which doesn't notify the callback and register it 309 IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 310 when(observer.asBinder()).thenReturn(new Binder()); 311 mUserController.registerUserSwitchObserver(observer, "mock"); 312 // Start user -- this will update state of mUserController 313 mUserController.startUser(TEST_USER_ID, true); 314 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 315 assertNotNull(reportMsg); 316 UserState userState = (UserState) reportMsg.obj; 317 int oldUserId = reportMsg.arg1; 318 int newUserId = reportMsg.arg2; 319 // Call dispatchUserSwitch and verify that observer was called only once 320 mInjector.mHandler.clearAllRecordedMessages(); 321 mUserController.dispatchUserSwitch(userState, oldUserId, newUserId); 322 verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any()); 323 // Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout) 324 Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes(); 325 assertWithMessage("No messages should be sent").that(actualCodes).isEmpty(); 326 } 327 328 @Test testContinueUserSwitch()329 public void testContinueUserSwitch() throws RemoteException { 330 // Start user -- this will update state of mUserController 331 mUserController.startUser(TEST_USER_ID, true); 332 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 333 assertNotNull(reportMsg); 334 UserState userState = (UserState) reportMsg.obj; 335 int oldUserId = reportMsg.arg1; 336 int newUserId = reportMsg.arg2; 337 mInjector.mHandler.clearAllRecordedMessages(); 338 // Verify that continueUserSwitch worked as expected 339 mUserController.continueUserSwitch(userState, oldUserId, newUserId); 340 verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen(); 341 continueUserSwitchAssertions(TEST_USER_ID, false); 342 } 343 344 @Test testContinueUserSwitchUIDisabled()345 public void testContinueUserSwitchUIDisabled() throws RemoteException { 346 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false, 347 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); 348 349 // Start user -- this will update state of mUserController 350 mUserController.startUser(TEST_USER_ID, true); 351 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 352 assertNotNull(reportMsg); 353 UserState userState = (UserState) reportMsg.obj; 354 int oldUserId = reportMsg.arg1; 355 int newUserId = reportMsg.arg2; 356 mInjector.mHandler.clearAllRecordedMessages(); 357 // Verify that continueUserSwitch worked as expected 358 mUserController.continueUserSwitch(userState, oldUserId, newUserId); 359 verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 360 continueUserSwitchAssertions(TEST_USER_ID, false); 361 } 362 continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)363 private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping) 364 throws RemoteException { 365 Set<Integer> expectedCodes = new LinkedHashSet<>(); 366 expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG); 367 if (backgroundUserStopping) { 368 expectedCodes.add(0); // this is for directly posting in stopping. 369 } 370 Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes(); 371 assertEquals("Unexpected message sent", expectedCodes, actualCodes); 372 Message msg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_COMPLETE_MSG); 373 assertNotNull(msg); 374 assertEquals("Unexpected userId", expectedUserId, msg.arg1); 375 } 376 377 @Test testDispatchUserSwitchComplete()378 public void testDispatchUserSwitchComplete() throws RemoteException { 379 // Prepare mock observer and register it 380 IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 381 when(observer.asBinder()).thenReturn(new Binder()); 382 mUserController.registerUserSwitchObserver(observer, "mock"); 383 // Start user -- this will update state of mUserController 384 mUserController.startUser(TEST_USER_ID, true); 385 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 386 assertNotNull(reportMsg); 387 int newUserId = reportMsg.arg2; 388 mInjector.mHandler.clearAllRecordedMessages(); 389 // Mockito can't reset only interactions, so just verify that this hasn't been 390 // called with 'false' until after dispatchUserSwitchComplete. 391 verify(mInjector.getWindowManager(), never()).setSwitchingUser(false); 392 // Call dispatchUserSwitchComplete 393 mUserController.dispatchUserSwitchComplete(newUserId); 394 verify(observer, times(1)).onUserSwitchComplete(anyInt()); 395 verify(observer).onUserSwitchComplete(TEST_USER_ID); 396 verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false); 397 } 398 399 @Test testExplicitSystenUserStartInBackground()400 public void testExplicitSystenUserStartInBackground() { 401 setUpUser(UserHandle.USER_SYSTEM, 0); 402 assertFalse(mUserController.isSystemUserStarted()); 403 assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null)); 404 assertTrue(mUserController.isSystemUserStarted()); 405 } 406 407 /** 408 * Test stopping of user from max running users limit. 409 */ 410 @Test testUserLockingFromUserSwitchingForMultipleUsersNonDelayedLocking()411 public void testUserLockingFromUserSwitchingForMultipleUsersNonDelayedLocking() 412 throws InterruptedException, RemoteException { 413 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, 414 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); 415 416 setUpUser(TEST_USER_ID1, 0); 417 setUpUser(TEST_USER_ID2, 0); 418 int numerOfUserSwitches = 1; 419 addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM, 420 numerOfUserSwitches, false); 421 // running: user 0, USER_ID 422 assertTrue(mUserController.canStartMoreUsers()); 423 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}), 424 mUserController.getRunningUsersLU()); 425 426 numerOfUserSwitches++; 427 addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID, 428 numerOfUserSwitches, false); 429 // running: user 0, USER_ID, USER_ID1 430 assertFalse(mUserController.canStartMoreUsers()); 431 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID, TEST_USER_ID1}), 432 mUserController.getRunningUsersLU()); 433 434 numerOfUserSwitches++; 435 addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, 436 numerOfUserSwitches, false); 437 UserState ussUser2 = mUserStates.get(TEST_USER_ID2); 438 // skip middle step and call this directly. 439 mUserController.finishUserSwitch(ussUser2); 440 waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); 441 // running: user 0, USER_ID1, USER_ID2 442 // USER_ID should be stopped as it is least recently used non user0. 443 assertFalse(mUserController.canStartMoreUsers()); 444 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID1, TEST_USER_ID2}), 445 mUserController.getRunningUsersLU()); 446 } 447 448 /** 449 * This test tests delayed locking mode using 4 users. As core logic of delayed locking is 450 * happening in finishUserStopped call, the test also calls finishUserStopped while skipping 451 * all middle steps which takes too much work to mock. 452 */ 453 @Test testUserLockingFromUserSwitchingForMultipleUsersDelayedLockingMode()454 public void testUserLockingFromUserSwitchingForMultipleUsersDelayedLockingMode() 455 throws InterruptedException, RemoteException { 456 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, 457 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true); 458 459 setUpUser(TEST_USER_ID1, 0); 460 setUpUser(TEST_USER_ID2, 0); 461 int numerOfUserSwitches = 1; 462 addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM, 463 numerOfUserSwitches, false); 464 // running: user 0, USER_ID 465 assertTrue(mUserController.canStartMoreUsers()); 466 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}), 467 mUserController.getRunningUsersLU()); 468 numerOfUserSwitches++; 469 470 addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID, 471 numerOfUserSwitches, true); 472 // running: user 0, USER_ID1 473 // stopped + unlocked: USER_ID 474 numerOfUserSwitches++; 475 assertTrue(mUserController.canStartMoreUsers()); 476 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID1}), 477 mUserController.getRunningUsersLU()); 478 // Skip all other steps and test unlock delaying only 479 UserState uss = mUserStates.get(TEST_USER_ID); 480 uss.setState(UserState.STATE_SHUTDOWN); // necessary state change from skipped part 481 mUserController.finishUserStopped(uss, /* allowDelayedLocking= */ true); 482 // Cannot mock FgThread handler, so confirm that there is no posted message left before 483 // checking. 484 waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); 485 verify(mInjector.mStorageManagerMock, times(0)) 486 .lockUserKey(anyInt()); 487 488 addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, 489 numerOfUserSwitches, true); 490 // running: user 0, USER_ID2 491 // stopped + unlocked: USER_ID1 492 // stopped + locked: USER_ID 493 assertTrue(mUserController.canStartMoreUsers()); 494 assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID2}), 495 mUserController.getRunningUsersLU()); 496 UserState ussUser1 = mUserStates.get(TEST_USER_ID1); 497 ussUser1.setState(UserState.STATE_SHUTDOWN); 498 mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); 499 waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); 500 verify(mInjector.mStorageManagerMock, times(1)) 501 .lockUserKey(TEST_USER_ID); 502 } 503 504 /** 505 * Test locking user with mDelayUserDataLocking false. 506 */ 507 @Test testUserLockingWithStopUserForNonDelayedLockingMode()508 public void testUserLockingWithStopUserForNonDelayedLockingMode() throws Exception { 509 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, 510 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false); 511 512 setUpAndStartUserInBackground(TEST_USER_ID); 513 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID, /* delayedLocking= */ true, 514 /* keyEvictedCallback= */ null, /* expectLocking= */ true); 515 516 setUpAndStartUserInBackground(TEST_USER_ID1); 517 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true, 518 /* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true); 519 520 setUpAndStartUserInBackground(TEST_USER_ID2); 521 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID2, /* delayedLocking= */ false, 522 /* keyEvictedCallback= */ null, /* expectLocking= */ true); 523 524 setUpAndStartUserInBackground(TEST_USER_ID3); 525 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID3, /* delayedLocking= */ false, 526 /* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true); 527 } 528 529 /** 530 * Test conditional delayed locking with mDelayUserDataLocking true. 531 */ 532 @Test testUserLockingForDelayedLockingMode()533 public void testUserLockingForDelayedLockingMode() throws Exception { 534 mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, 535 /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ true); 536 537 // delayedLocking set and no KeyEvictedCallback, so it should not lock. 538 setUpAndStartUserInBackground(TEST_USER_ID); 539 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID, /* delayedLocking= */ true, 540 /* keyEvictedCallback= */ null, /* expectLocking= */ false); 541 542 setUpAndStartUserInBackground(TEST_USER_ID1); 543 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true, 544 /* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true); 545 546 setUpAndStartUserInBackground(TEST_USER_ID2); 547 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID2, /* delayedLocking= */ false, 548 /* keyEvictedCallback= */ null, /* expectLocking= */ true); 549 550 setUpAndStartUserInBackground(TEST_USER_ID3); 551 assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID3, /* delayedLocking= */ false, 552 /* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true); 553 } 554 555 @Test testStartProfile_fullUserFails()556 public void testStartProfile_fullUserFails() { 557 setUpUser(TEST_USER_ID1, 0); 558 assertThrows(IllegalArgumentException.class, 559 () -> mUserController.startProfile(TEST_USER_ID1)); 560 } 561 562 @Test testStopProfile_fullUserFails()563 public void testStopProfile_fullUserFails() throws Exception { 564 setUpAndStartUserInBackground(TEST_USER_ID1); 565 assertThrows(IllegalArgumentException.class, 566 () -> mUserController.stopProfile(TEST_USER_ID1)); 567 } 568 569 @Test testStartProfile_disabledProfileFails()570 public void testStartProfile_disabledProfileFails() { 571 setUpUser(TEST_USER_ID1, UserInfo.FLAG_PROFILE | UserInfo.FLAG_DISABLED, /* preCreated= */ 572 false, UserManager.USER_TYPE_PROFILE_MANAGED); 573 assertThat(mUserController.startProfile(TEST_USER_ID1)).isFalse(); 574 } 575 576 @Test testStartProfile()577 public void testStartProfile() throws Exception { 578 setUpAndStartProfileInBackground(TEST_USER_ID1); 579 startBackgroundUserAssertions(); 580 } 581 582 @Test testStopProfile()583 public void testStopProfile() throws Exception { 584 setUpAndStartProfileInBackground(TEST_USER_ID1); 585 assertProfileLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* expectLocking= */ true); 586 } 587 setUpAndStartUserInBackground(int userId)588 private void setUpAndStartUserInBackground(int userId) throws Exception { 589 setUpUser(userId, 0); 590 mUserController.startUser(userId, /* foreground= */ false); 591 verify(mInjector.mStorageManagerMock, times(1)) 592 .unlockUserKey(userId, /* serialNumber= */ 0, /* token= */ null, /* secret= */ 593 null); 594 mUserStates.put(userId, mUserController.getStartedUserState(userId)); 595 } 596 setUpAndStartProfileInBackground(int userId)597 private void setUpAndStartProfileInBackground(int userId) throws Exception { 598 setUpUser(userId, UserInfo.FLAG_PROFILE, false, UserManager.USER_TYPE_PROFILE_MANAGED); 599 assertThat(mUserController.startProfile(userId)).isTrue(); 600 601 verify(mInjector.mStorageManagerMock, times(1)) 602 .unlockUserKey(userId, /* serialNumber= */ 0, /* token= */ null, /* secret= */ 603 null); 604 mUserStates.put(userId, mUserController.getStartedUserState(userId)); 605 } 606 assertUserLockedOrUnlockedAfterStopping(int userId, boolean delayedLocking, KeyEvictedCallback keyEvictedCallback, boolean expectLocking)607 private void assertUserLockedOrUnlockedAfterStopping(int userId, boolean delayedLocking, 608 KeyEvictedCallback keyEvictedCallback, boolean expectLocking) throws Exception { 609 int r = mUserController.stopUser(userId, /* force= */ true, /* delayedLocking= */ 610 delayedLocking, null, keyEvictedCallback); 611 assertThat(r).isEqualTo(ActivityManager.USER_OP_SUCCESS); 612 assertUserLockedOrUnlockedState(userId, delayedLocking, expectLocking); 613 } 614 assertProfileLockedOrUnlockedAfterStopping(int userId, boolean expectLocking)615 private void assertProfileLockedOrUnlockedAfterStopping(int userId, boolean expectLocking) 616 throws Exception { 617 boolean profileStopped = mUserController.stopProfile(userId); 618 assertThat(profileStopped).isTrue(); 619 assertUserLockedOrUnlockedState(userId, /* delayedLocking= */ false, expectLocking); 620 } 621 assertUserLockedOrUnlockedState(int userId, boolean delayedLocking, boolean expectLocking)622 private void assertUserLockedOrUnlockedState(int userId, boolean delayedLocking, 623 boolean expectLocking) throws InterruptedException, RemoteException { 624 // fake all interim steps 625 UserState ussUser = mUserStates.get(userId); 626 ussUser.setState(UserState.STATE_SHUTDOWN); 627 // Passing delayedLocking invalidates incorrect internal data passing but currently there is 628 // no easy way to get that information passed through lambda. 629 mUserController.finishUserStopped(ussUser, delayedLocking); 630 waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); 631 verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0)) 632 .lockUserKey(userId); 633 } 634 addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, int expectedNumberOfCalls, boolean expectOldUserStopping)635 private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, 636 int expectedNumberOfCalls, boolean expectOldUserStopping) 637 throws RemoteException { 638 // Start user -- this will update state of mUserController 639 mUserController.startUser(newUserId, true); 640 Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG); 641 assertNotNull(reportMsg); 642 UserState userState = (UserState) reportMsg.obj; 643 int oldUserId = reportMsg.arg1; 644 assertEquals(expectedOldUserId, oldUserId); 645 assertEquals(newUserId, reportMsg.arg2); 646 mUserStates.put(newUserId, userState); 647 mInjector.mHandler.clearAllRecordedMessages(); 648 // Verify that continueUserSwitch worked as expected 649 mUserController.continueUserSwitch(userState, oldUserId, newUserId); 650 verify(mInjector.getWindowManager(), times(expectedNumberOfCalls)) 651 .stopFreezingScreen(); 652 continueUserSwitchAssertions(newUserId, expectOldUserStopping); 653 } 654 setUpUser(@serIdInt int userId, @UserInfoFlag int flags)655 private void setUpUser(@UserIdInt int userId, @UserInfoFlag int flags) { 656 setUpUser(userId, flags, /* preCreated= */ false, /* userType */ null); 657 } 658 setUpUser(@serIdInt int userId, @UserInfoFlag int flags, boolean preCreated, @Nullable String userType)659 private void setUpUser(@UserIdInt int userId, @UserInfoFlag int flags, boolean preCreated, 660 @Nullable String userType) { 661 if (userType == null) { 662 userType = UserInfo.getDefaultUserType(flags); 663 } 664 UserInfo userInfo = new UserInfo(userId, "User" + userId, /* iconPath= */ null, flags, 665 userType); 666 userInfo.preCreated = preCreated; 667 when(mInjector.mUserManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo); 668 when(mInjector.mUserManagerMock.isPreCreated(userId)).thenReturn(preCreated); 669 } 670 getActions(List<Intent> intents)671 private static List<String> getActions(List<Intent> intents) { 672 List<String> result = new ArrayList<>(); 673 for (Intent intent : intents) { 674 result.add(intent.getAction()); 675 } 676 return result; 677 } 678 waitForHandlerToComplete(Handler handler, long waitTimeMs)679 private void waitForHandlerToComplete(Handler handler, long waitTimeMs) 680 throws InterruptedException { 681 final Object lock = new Object(); 682 synchronized (lock) { 683 handler.post(() -> { 684 synchronized (lock) { 685 lock.notify(); 686 } 687 }); 688 lock.wait(waitTimeMs); 689 } 690 } 691 692 // Should be public to allow mocking 693 private static class TestInjector extends UserController.Injector { 694 public final TestHandler mHandler; 695 public final HandlerThread mHandlerThread; 696 public final UserManagerService mUserManagerMock; 697 public final List<Intent> mSentIntents = new ArrayList<>(); 698 699 private final TestHandler mUiHandler; 700 701 private final IStorageManager mStorageManagerMock; 702 private final UserManagerInternal mUserManagerInternalMock; 703 private final WindowManagerService mWindowManagerMock; 704 705 private final Context mCtx; 706 TestInjector(Context ctx)707 TestInjector(Context ctx) { 708 super(null); 709 mCtx = ctx; 710 mHandlerThread = new HandlerThread(TAG); 711 mHandlerThread.start(); 712 mHandler = new TestHandler(mHandlerThread.getLooper()); 713 mUiHandler = new TestHandler(mHandlerThread.getLooper()); 714 mUserManagerMock = mock(UserManagerService.class); 715 mUserManagerInternalMock = mock(UserManagerInternal.class); 716 mWindowManagerMock = mock(WindowManagerService.class); 717 mStorageManagerMock = mock(IStorageManager.class); 718 } 719 720 @Override getHandler(Handler.Callback callback)721 protected Handler getHandler(Handler.Callback callback) { 722 return mHandler; 723 } 724 725 @Override getUiHandler(Handler.Callback callback)726 protected Handler getUiHandler(Handler.Callback callback) { 727 return mUiHandler; 728 } 729 730 @Override getUserManager()731 protected UserManagerService getUserManager() { 732 return mUserManagerMock; 733 } 734 735 @Override getUserManagerInternal()736 UserManagerInternal getUserManagerInternal() { 737 return mUserManagerInternalMock; 738 } 739 740 @Override getContext()741 protected Context getContext() { 742 return mCtx; 743 } 744 745 @Override checkCallingPermission(String permission)746 int checkCallingPermission(String permission) { 747 Log.i(TAG, "checkCallingPermission " + permission); 748 return PERMISSION_GRANTED; 749 } 750 751 @Override getWindowManager()752 WindowManagerService getWindowManager() { 753 return mWindowManagerMock; 754 } 755 756 @Override updateUserConfiguration()757 void updateUserConfiguration() { 758 Log.i(TAG, "updateUserConfiguration"); 759 } 760 761 @Override broadcastIntent(Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid, int realCallingPid, int userId)762 protected int broadcastIntent(Intent intent, String resolvedType, 763 IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, 764 String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, 765 boolean sticky, int callingPid, int callingUid, int realCallingUid, 766 int realCallingPid, int userId) { 767 Log.i(TAG, "broadcastIntentLocked " + intent); 768 mSentIntents.add(intent); 769 return 0; 770 } 771 772 @Override reportGlobalUsageEvent(int event)773 void reportGlobalUsageEvent(int event) { 774 } 775 776 @Override reportCurWakefulnessUsageEvent()777 void reportCurWakefulnessUsageEvent() { 778 } 779 780 @Override isRuntimeRestarted()781 boolean isRuntimeRestarted() { 782 // to pass all metrics related calls 783 return true; 784 } 785 786 @Override getStorageManager()787 protected IStorageManager getStorageManager() { 788 return mStorageManagerMock; 789 } 790 } 791 792 private static class TestHandler extends Handler { 793 private final List<Message> mMessages = new ArrayList<>(); 794 TestHandler(Looper looper)795 TestHandler(Looper looper) { 796 super(looper); 797 } 798 getMessageCodes()799 Set<Integer> getMessageCodes() { 800 Set<Integer> result = new LinkedHashSet<>(); 801 for (Message msg : mMessages) { 802 result.add(msg.what); 803 } 804 return result; 805 } 806 getMessageForCode(int what)807 Message getMessageForCode(int what) { 808 for (Message msg : mMessages) { 809 if (msg.what == what) { 810 return msg; 811 } 812 } 813 return null; 814 } 815 clearAllRecordedMessages()816 void clearAllRecordedMessages() { 817 mMessages.clear(); 818 } 819 820 @Override sendMessageAtTime(Message msg, long uptimeMillis)821 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 822 Message copy = new Message(); 823 copy.copyFrom(msg); 824 mMessages.add(copy); 825 return super.sendMessageAtTime(msg, uptimeMillis); 826 } 827 } 828 } 829