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.SYSTEM_USER_CURRENT_MSG;
29 import static com.android.server.am.UserController.SYSTEM_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.assertWithMessage;
35 
36 import static org.junit.Assert.assertEquals;
37 import static org.junit.Assert.assertFalse;
38 import static org.junit.Assert.assertNotNull;
39 import static org.junit.Assert.assertTrue;
40 import static org.mockito.ArgumentMatchers.anyString;
41 import static org.mockito.Matchers.any;
42 import static org.mockito.Matchers.anyBoolean;
43 import static org.mockito.Matchers.anyInt;
44 import static org.mockito.Matchers.eq;
45 import static org.mockito.Mockito.doAnswer;
46 import static org.mockito.Mockito.doNothing;
47 import static org.mockito.Mockito.doReturn;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.never;
50 import static org.mockito.Mockito.spy;
51 import static org.mockito.Mockito.times;
52 import static org.mockito.Mockito.validateMockitoUsage;
53 import static org.mockito.Mockito.verify;
54 import static org.mockito.Mockito.when;
55 
56 import android.app.IUserSwitchObserver;
57 import android.content.Context;
58 import android.content.IIntentReceiver;
59 import android.content.Intent;
60 import android.content.pm.UserInfo;
61 import android.os.Binder;
62 import android.os.Bundle;
63 import android.os.Handler;
64 import android.os.HandlerThread;
65 import android.os.IRemoteCallback;
66 import android.os.Looper;
67 import android.os.Message;
68 import android.os.RemoteException;
69 import android.os.UserHandle;
70 import android.os.UserManagerInternal;
71 import android.os.storage.IStorageManager;
72 import android.platform.test.annotations.Presubmit;
73 import android.util.Log;
74 
75 
76 import androidx.test.filters.FlakyTest;
77 import androidx.test.filters.SmallTest;
78 
79 import com.android.server.FgThread;
80 import com.android.server.pm.UserManagerService;
81 import com.android.server.wm.WindowManagerService;
82 
83 import org.junit.After;
84 import org.junit.Before;
85 import org.junit.Test;
86 
87 import java.util.ArrayList;
88 import java.util.Arrays;
89 import java.util.Collections;
90 import java.util.HashMap;
91 import java.util.LinkedHashSet;
92 import java.util.List;
93 import java.util.Set;
94 
95 /**
96  * Tests for {@link UserController}.
97  *
98  * Build/Install/Run:
99  *  atest FrameworksServicesTests:UserControllerTest
100  */
101 @SmallTest
102 @Presubmit
103 
104 public class UserControllerTest {
105     // Use big enough user id to avoid picking up already active user id.
106     private static final int TEST_USER_ID = 100;
107     private static final int TEST_USER_ID1 = 101;
108     private static final int TEST_USER_ID2 = 102;
109     private static final int NONEXIST_USER_ID = 2;
110     private static final String TAG = UserControllerTest.class.getSimpleName();
111 
112     private static final long HANDLER_WAIT_TIME_MS = 100;
113 
114     private UserController mUserController;
115     private TestInjector mInjector;
116     private final HashMap<Integer, UserState> mUserStates = new HashMap<>();
117 
118     private static final List<String> START_FOREGROUND_USER_ACTIONS = newArrayList(
119             Intent.ACTION_USER_STARTED,
120             Intent.ACTION_USER_SWITCHED,
121             Intent.ACTION_USER_STARTING);
122 
123     private static final List<String> START_BACKGROUND_USER_ACTIONS = newArrayList(
124             Intent.ACTION_USER_STARTED,
125             Intent.ACTION_LOCKED_BOOT_COMPLETED,
126             Intent.ACTION_USER_STARTING);
127 
128     private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES = newHashSet(
129             REPORT_USER_SWITCH_MSG,
130             USER_SWITCH_TIMEOUT_MSG,
131             SYSTEM_USER_START_MSG,
132             SYSTEM_USER_CURRENT_MSG);
133 
134     private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
135             SYSTEM_USER_START_MSG,
136             REPORT_LOCKED_BOOT_COMPLETE_MSG);
137 
138     @Before
setUp()139     public void setUp() throws Exception {
140         runWithDexmakerShareClassLoader(() -> {
141             mInjector = spy(new TestInjector(getInstrumentation().getTargetContext()));
142             doNothing().when(mInjector).clearAllLockedTasks(anyString());
143             doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
144             doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
145             doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity();
146             doNothing().when(mInjector).systemServiceManagerCleanupUser(anyInt());
147             doNothing().when(mInjector).activityManagerForceStopPackage(anyInt(), anyString());
148             doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
149             doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
150             doNothing().when(mInjector).stackSupervisorRemoveUser(anyInt());
151             mUserController = new UserController(mInjector);
152             setUpUser(TEST_USER_ID, 0);
153         });
154     }
155 
156     @After
tearDown()157     public void tearDown() throws Exception {
158         mInjector.mHandlerThread.quit();
159         validateMockitoUsage();
160     }
161 
162     @Test
testStartUser_foreground()163     public void testStartUser_foreground() {
164         mUserController.startUser(TEST_USER_ID, true /* foreground */);
165         verify(mInjector.getWindowManager()).startFreezingScreen(anyInt(), anyInt());
166         verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
167         verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
168         verify(mInjector.getWindowManager()).setSwitchingUser(true);
169         verify(mInjector).clearAllLockedTasks(anyString());
170         startForegroundUserAssertions();
171     }
172 
173     @FlakyTest(bugId = 118932054)
174     @Test
testStartUser_background()175     public void testStartUser_background() {
176         mUserController.startUser(TEST_USER_ID, false /* foreground */);
177         verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
178         verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
179         verify(mInjector, never()).clearAllLockedTasks(anyString());
180         startBackgroundUserAssertions();
181     }
182 
183     @Test
testStartUserUIDisabled()184     public void testStartUserUIDisabled() {
185         mUserController.mUserSwitchUiEnabled = false;
186         mUserController.startUser(TEST_USER_ID, true /* foreground */);
187         verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
188         verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
189         verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
190         startForegroundUserAssertions();
191     }
192 
startUserAssertions( List<String> expectedActions, Set<Integer> expectedMessageCodes)193     private void startUserAssertions(
194             List<String> expectedActions, Set<Integer> expectedMessageCodes) {
195         assertEquals(expectedActions, getActions(mInjector.mSentIntents));
196         Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
197         assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes);
198     }
199 
startBackgroundUserAssertions()200     private void startBackgroundUserAssertions() {
201         startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES);
202     }
203 
startForegroundUserAssertions()204     private void startForegroundUserAssertions() {
205         startUserAssertions(START_FOREGROUND_USER_ACTIONS, START_FOREGROUND_USER_MESSAGE_CODES);
206         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
207         assertNotNull(reportMsg);
208         UserState userState = (UserState) reportMsg.obj;
209         assertNotNull(userState);
210         assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier());
211         assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state);
212         assertEquals("Unexpected old user id", 0, reportMsg.arg1);
213         assertEquals("Unexpected new user id", TEST_USER_ID, reportMsg.arg2);
214     }
215 
216     @Test
testFailedStartUserInForeground()217     public void testFailedStartUserInForeground() {
218         mUserController.mUserSwitchUiEnabled = false;
219         mUserController.startUserInForeground(NONEXIST_USER_ID);
220         verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
221         verify(mInjector.getWindowManager()).setSwitchingUser(false);
222     }
223 
224     @Test
testDispatchUserSwitch()225     public void testDispatchUserSwitch() throws RemoteException {
226         // Prepare mock observer and register it
227         IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
228         when(observer.asBinder()).thenReturn(new Binder());
229         doAnswer(invocation -> {
230             IRemoteCallback callback = (IRemoteCallback) invocation.getArguments()[1];
231             callback.sendResult(null);
232             return null;
233         }).when(observer).onUserSwitching(anyInt(), any());
234         mUserController.registerUserSwitchObserver(observer, "mock");
235         // Start user -- this will update state of mUserController
236         mUserController.startUser(TEST_USER_ID, true);
237         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
238         assertNotNull(reportMsg);
239         UserState userState = (UserState) reportMsg.obj;
240         int oldUserId = reportMsg.arg1;
241         int newUserId = reportMsg.arg2;
242         // Call dispatchUserSwitch and verify that observer was called only once
243         mInjector.mHandler.clearAllRecordedMessages();
244         mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
245         verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
246         Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG);
247         Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
248         assertEquals("Unexpected message sent", expectedCodes, actualCodes);
249         Message conMsg = mInjector.mHandler.getMessageForCode(CONTINUE_USER_SWITCH_MSG);
250         assertNotNull(conMsg);
251         userState = (UserState) conMsg.obj;
252         assertNotNull(userState);
253         assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier());
254         assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state);
255         assertEquals("Unexpected old user id", 0, conMsg.arg1);
256         assertEquals("Unexpected new user id", TEST_USER_ID, conMsg.arg2);
257     }
258 
259     @Test
testDispatchUserSwitchBadReceiver()260     public void testDispatchUserSwitchBadReceiver() throws RemoteException {
261         // Prepare mock observer which doesn't notify the callback and register it
262         IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
263         when(observer.asBinder()).thenReturn(new Binder());
264         mUserController.registerUserSwitchObserver(observer, "mock");
265         // Start user -- this will update state of mUserController
266         mUserController.startUser(TEST_USER_ID, true);
267         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
268         assertNotNull(reportMsg);
269         UserState userState = (UserState) reportMsg.obj;
270         int oldUserId = reportMsg.arg1;
271         int newUserId = reportMsg.arg2;
272         // Call dispatchUserSwitch and verify that observer was called only once
273         mInjector.mHandler.clearAllRecordedMessages();
274         mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
275         verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
276         // Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout)
277         Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
278         assertWithMessage("No messages should be sent").that(actualCodes).isEmpty();
279     }
280 
281     @Test
testContinueUserSwitch()282     public void testContinueUserSwitch() throws RemoteException {
283         // Start user -- this will update state of mUserController
284         mUserController.startUser(TEST_USER_ID, true);
285         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
286         assertNotNull(reportMsg);
287         UserState userState = (UserState) reportMsg.obj;
288         int oldUserId = reportMsg.arg1;
289         int newUserId = reportMsg.arg2;
290         mInjector.mHandler.clearAllRecordedMessages();
291         // Verify that continueUserSwitch worked as expected
292         mUserController.continueUserSwitch(userState, oldUserId, newUserId);
293         verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
294         continueUserSwitchAssertions(TEST_USER_ID, false);
295     }
296 
297     @Test
testContinueUserSwitchUIDisabled()298     public void testContinueUserSwitchUIDisabled() throws RemoteException {
299         mUserController.mUserSwitchUiEnabled = false;
300         // Start user -- this will update state of mUserController
301         mUserController.startUser(TEST_USER_ID, true);
302         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
303         assertNotNull(reportMsg);
304         UserState userState = (UserState) reportMsg.obj;
305         int oldUserId = reportMsg.arg1;
306         int newUserId = reportMsg.arg2;
307         mInjector.mHandler.clearAllRecordedMessages();
308         // Verify that continueUserSwitch worked as expected
309         mUserController.continueUserSwitch(userState, oldUserId, newUserId);
310         verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
311         continueUserSwitchAssertions(TEST_USER_ID, false);
312     }
313 
continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)314     private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)
315             throws RemoteException {
316         Set<Integer> expectedCodes = new LinkedHashSet<>();
317         expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
318         if (backgroundUserStopping) {
319             expectedCodes.add(0); // this is for directly posting in stopping.
320         }
321         Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
322         assertEquals("Unexpected message sent", expectedCodes, actualCodes);
323         Message msg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_COMPLETE_MSG);
324         assertNotNull(msg);
325         assertEquals("Unexpected userId", expectedUserId, msg.arg1);
326     }
327 
328     @Test
testDispatchUserSwitchComplete()329     public void testDispatchUserSwitchComplete() throws RemoteException {
330         // Prepare mock observer and register it
331         IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
332         when(observer.asBinder()).thenReturn(new Binder());
333         mUserController.registerUserSwitchObserver(observer, "mock");
334         // Start user -- this will update state of mUserController
335         mUserController.startUser(TEST_USER_ID, true);
336         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
337         assertNotNull(reportMsg);
338         int newUserId = reportMsg.arg2;
339         mInjector.mHandler.clearAllRecordedMessages();
340         // Mockito can't reset only interactions, so just verify that this hasn't been
341         // called with 'false' until after dispatchUserSwitchComplete.
342         verify(mInjector.getWindowManager(), never()).setSwitchingUser(false);
343         // Call dispatchUserSwitchComplete
344         mUserController.dispatchUserSwitchComplete(newUserId);
345         verify(observer, times(1)).onUserSwitchComplete(anyInt());
346         verify(observer).onUserSwitchComplete(TEST_USER_ID);
347         verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false);
348     }
349 
350     @Test
testExplicitSystenUserStartInBackground()351     public void testExplicitSystenUserStartInBackground() {
352         setUpUser(UserHandle.USER_SYSTEM, 0);
353         assertFalse(mUserController.isSystemUserStarted());
354         assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null));
355         assertTrue(mUserController.isSystemUserStarted());
356     }
357 
358     /**
359      * Test stopping of user from max running users limit.
360      */
361     @Test
testUserStoppingForMultipleUsersNormalMode()362     public void testUserStoppingForMultipleUsersNormalMode()
363             throws InterruptedException, RemoteException {
364         setUpUser(TEST_USER_ID1, 0);
365         setUpUser(TEST_USER_ID2, 0);
366         mUserController.mMaxRunningUsers = 3;
367         int numerOfUserSwitches = 1;
368         addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
369                 numerOfUserSwitches, false);
370         // running: user 0, USER_ID
371         assertTrue(mUserController.canStartMoreUsers());
372         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}),
373                 mUserController.getRunningUsersLU());
374 
375         numerOfUserSwitches++;
376         addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID,
377                 numerOfUserSwitches, false);
378         // running: user 0, USER_ID, USER_ID1
379         assertFalse(mUserController.canStartMoreUsers());
380         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID, TEST_USER_ID1}),
381                 mUserController.getRunningUsersLU());
382 
383         numerOfUserSwitches++;
384         addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
385                 numerOfUserSwitches, false);
386         UserState ussUser2 = mUserStates.get(TEST_USER_ID2);
387         // skip middle step and call this directly.
388         mUserController.finishUserSwitch(ussUser2);
389         waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS);
390         // running: user 0, USER_ID1, USER_ID2
391         // USER_ID should be stopped as it is least recently used non user0.
392         assertFalse(mUserController.canStartMoreUsers());
393         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID1, TEST_USER_ID2}),
394                 mUserController.getRunningUsersLU());
395     }
396 
397     /**
398      * This test tests delayed locking mode using 4 users. As core logic of delayed locking is
399      * happening in finishUserStopped call, the test also calls finishUserStopped while skipping
400      * all middle steps which takes too much work to mock.
401      */
402     @Test
testUserStoppingForMultipleUsersDelayedLockingMode()403     public void testUserStoppingForMultipleUsersDelayedLockingMode()
404             throws InterruptedException, RemoteException {
405         setUpUser(TEST_USER_ID1, 0);
406         setUpUser(TEST_USER_ID2, 0);
407         mUserController.mMaxRunningUsers = 3;
408         mUserController.mDelayUserDataLocking = true;
409         int numerOfUserSwitches = 1;
410         addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
411                 numerOfUserSwitches, false);
412         // running: user 0, USER_ID
413         assertTrue(mUserController.canStartMoreUsers());
414         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID}),
415                 mUserController.getRunningUsersLU());
416         numerOfUserSwitches++;
417 
418         addForegroundUserAndContinueUserSwitch(TEST_USER_ID1, TEST_USER_ID,
419                 numerOfUserSwitches, true);
420         // running: user 0, USER_ID1
421         // stopped + unlocked: USER_ID
422         numerOfUserSwitches++;
423         assertTrue(mUserController.canStartMoreUsers());
424         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID1}),
425                 mUserController.getRunningUsersLU());
426         // Skip all other steps and test unlock delaying only
427         UserState uss = mUserStates.get(TEST_USER_ID);
428         uss.setState(UserState.STATE_SHUTDOWN); // necessary state change from skipped part
429         mUserController.finishUserStopped(uss);
430         // Cannot mock FgThread handler, so confirm that there is no posted message left before
431         // checking.
432         waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
433         verify(mInjector.mStorageManagerMock, times(0))
434                 .lockUserKey(anyInt());
435 
436         addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
437                 numerOfUserSwitches, true);
438         // running: user 0, USER_ID2
439         // stopped + unlocked: USER_ID1
440         // stopped + locked: USER_ID
441         assertTrue(mUserController.canStartMoreUsers());
442         assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID2}),
443                 mUserController.getRunningUsersLU());
444         UserState ussUser1 = mUserStates.get(TEST_USER_ID1);
445         ussUser1.setState(UserState.STATE_SHUTDOWN);
446         mUserController.finishUserStopped(ussUser1);
447         waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
448         verify(mInjector.mStorageManagerMock, times(1))
449                 .lockUserKey(TEST_USER_ID);
450     }
451 
addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, int expectedNumberOfCalls, boolean expectOldUserStopping)452     private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
453             int expectedNumberOfCalls, boolean expectOldUserStopping)
454             throws RemoteException {
455         // Start user -- this will update state of mUserController
456         mUserController.startUser(newUserId, true);
457         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
458         assertNotNull(reportMsg);
459         UserState userState = (UserState) reportMsg.obj;
460         int oldUserId = reportMsg.arg1;
461         assertEquals(expectedOldUserId, oldUserId);
462         assertEquals(newUserId, reportMsg.arg2);
463         mUserStates.put(newUserId, userState);
464         mInjector.mHandler.clearAllRecordedMessages();
465         // Verify that continueUserSwitch worked as expected
466         mUserController.continueUserSwitch(userState, oldUserId, newUserId);
467         verify(mInjector.getWindowManager(), times(expectedNumberOfCalls))
468                 .stopFreezingScreen();
469         continueUserSwitchAssertions(newUserId, expectOldUserStopping);
470     }
471 
setUpUser(int userId, int flags)472     private void setUpUser(int userId, int flags) {
473         UserInfo userInfo = new UserInfo(userId, "User" + userId, flags);
474         when(mInjector.mUserManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo);
475     }
476 
getActions(List<Intent> intents)477     private static List<String> getActions(List<Intent> intents) {
478         List<String> result = new ArrayList<>();
479         for (Intent intent : intents) {
480             result.add(intent.getAction());
481         }
482         return result;
483     }
484 
waitForHandlerToComplete(Handler handler, long waitTimeMs)485     private void waitForHandlerToComplete(Handler handler, long waitTimeMs)
486             throws InterruptedException {
487         final Object lock = new Object();
488         synchronized (lock) {
489             handler.post(() -> {
490                 synchronized (lock) {
491                     lock.notify();
492                 }
493             });
494             lock.wait(waitTimeMs);
495         }
496     }
497 
498     // Should be public to allow mocking
499     private static class TestInjector extends UserController.Injector {
500         public final TestHandler mHandler;
501         public final HandlerThread mHandlerThread;
502         public final UserManagerService mUserManagerMock;
503         public final List<Intent> mSentIntents = new ArrayList<>();
504 
505         private final TestHandler mUiHandler;
506 
507         private final IStorageManager mStorageManagerMock;
508         private final UserManagerInternal mUserManagerInternalMock;
509         private final WindowManagerService mWindowManagerMock;
510 
511         private final Context mCtx;
512 
TestInjector(Context ctx)513         TestInjector(Context ctx) {
514             super(null);
515             mCtx = ctx;
516             mHandlerThread = new HandlerThread(TAG);
517             mHandlerThread.start();
518             mHandler = new TestHandler(mHandlerThread.getLooper());
519             mUiHandler = new TestHandler(mHandlerThread.getLooper());
520             mUserManagerMock = mock(UserManagerService.class);
521             mUserManagerInternalMock = mock(UserManagerInternal.class);
522             mWindowManagerMock = mock(WindowManagerService.class);
523             mStorageManagerMock = mock(IStorageManager.class);
524         }
525 
526         @Override
getHandler(Handler.Callback callback)527         protected Handler getHandler(Handler.Callback callback) {
528             return mHandler;
529         }
530 
531         @Override
getUiHandler(Handler.Callback callback)532         protected Handler getUiHandler(Handler.Callback callback) {
533             return mUiHandler;
534         }
535 
536         @Override
getUserManager()537         protected UserManagerService getUserManager() {
538             return mUserManagerMock;
539         }
540 
541         @Override
getUserManagerInternal()542         UserManagerInternal getUserManagerInternal() {
543             return mUserManagerInternalMock;
544         }
545 
546         @Override
getContext()547         protected Context getContext() {
548             return mCtx;
549         }
550 
551         @Override
checkCallingPermission(String permission)552         int checkCallingPermission(String permission) {
553             Log.i(TAG, "checkCallingPermission " + permission);
554             return PERMISSION_GRANTED;
555         }
556 
557         @Override
getWindowManager()558         WindowManagerService getWindowManager() {
559             return mWindowManagerMock;
560         }
561 
562         @Override
updateUserConfiguration()563         void updateUserConfiguration() {
564             Log.i(TAG, "updateUserConfiguration");
565         }
566 
567         @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)568         protected int broadcastIntent(Intent intent, String resolvedType,
569                 IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras,
570                 String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered,
571                 boolean sticky, int callingPid, int callingUid, int realCallingUid,
572                 int realCallingPid, int userId) {
573             Log.i(TAG, "broadcastIntentLocked " + intent);
574             mSentIntents.add(intent);
575             return 0;
576         }
577 
578         @Override
reportGlobalUsageEventLocked(int event)579         void reportGlobalUsageEventLocked(int event) {
580         }
581 
582         @Override
reportCurWakefulnessUsageEvent()583         void reportCurWakefulnessUsageEvent() {
584         }
585 
586         @Override
isRuntimeRestarted()587         boolean isRuntimeRestarted() {
588             // to pass all metrics related calls
589             return true;
590         }
591 
592         @Override
getStorageManager()593         protected IStorageManager getStorageManager() {
594             return mStorageManagerMock;
595         }
596     }
597 
598     private static class TestHandler extends Handler {
599         private final List<Message> mMessages = new ArrayList<>();
600 
TestHandler(Looper looper)601         TestHandler(Looper looper) {
602             super(looper);
603         }
604 
getMessageCodes()605         Set<Integer> getMessageCodes() {
606             Set<Integer> result = new LinkedHashSet<>();
607             for (Message msg : mMessages) {
608                 result.add(msg.what);
609             }
610             return result;
611         }
612 
getMessageForCode(int what)613         Message getMessageForCode(int what) {
614             for (Message msg : mMessages) {
615                 if (msg.what == what) {
616                     return msg;
617                 }
618             }
619             return null;
620         }
621 
clearAllRecordedMessages()622         void clearAllRecordedMessages() {
623             mMessages.clear();
624         }
625 
626         @Override
sendMessageAtTime(Message msg, long uptimeMillis)627         public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
628             Message copy = new Message();
629             copy.copyFrom(msg);
630             mMessages.add(copy);
631             return super.sendMessageAtTime(msg, uptimeMillis);
632         }
633     }
634 }
635