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