• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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