1d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov/* 2d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * Copyright (C) 2016 The Android Open Source Project 3d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * 4d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * Licensed under the Apache License, Version 2.0 (the "License"); 5d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * you may not use this file except in compliance with the License. 6d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * You may obtain a copy of the License at 7d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * 8d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * http://www.apache.org/licenses/LICENSE-2.0 9d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * 10d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * Unless required by applicable law or agreed to in writing, software 11d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * distributed under the License is distributed on an "AS IS" BASIS, 12d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * See the License for the specific language governing permissions and 14d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov * limitations under the License 15d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov */ 16d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 17d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovpackage com.android.server.am; 18d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 195c2cf03f5f8e26f715931370004d21ee217edcdeTony Makimport android.app.ActivityManager; 203b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport android.app.IUserSwitchObserver; 21d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.content.Context; 22d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.content.IIntentReceiver; 23d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.content.Intent; 24d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.content.pm.UserInfo; 253b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport android.os.Binder; 26d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.os.Bundle; 27d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.os.Handler; 28d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.os.HandlerThread; 293b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport android.os.IRemoteCallback; 303b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport android.os.Looper; 313b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport android.os.Message; 32d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.os.RemoteException; 33d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.os.UserManagerInternal; 34d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.test.AndroidTestCase; 359bc8543d45fc7f2edf857181940d3719e480a597Fyodor Kupolovimport android.test.suitebuilder.annotation.SmallTest; 36d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport android.util.Log; 37d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 38d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport com.android.server.pm.UserManagerService; 39d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport com.android.server.wm.WindowManagerService; 40d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 41d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport org.mockito.Mockito; 42d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 43d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport java.util.ArrayList; 44d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport java.util.Arrays; 453b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport java.util.Collections; 463b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport java.util.HashSet; 473b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport java.util.LinkedHashSet; 48d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport java.util.List; 493b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport java.util.Set; 50d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 51d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static android.content.pm.PackageManager.PERMISSION_GRANTED; 523b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.CONTINUE_USER_SWITCH_MSG; 535c2cf03f5f8e26f715931370004d21ee217edcdeTony Makimport static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG; 543b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG; 553b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG; 563b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG; 573b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG; 583b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG; 595c2cf03f5f8e26f715931370004d21ee217edcdeTony Makimport static org.mockito.ArgumentMatchers.anyString; 605c2cf03f5f8e26f715931370004d21ee217edcdeTony Makimport static org.mockito.ArgumentMatchers.nullable; 613b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static org.mockito.Matchers.any; 623e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Roskyimport static org.mockito.Matchers.anyBoolean; 63d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static org.mockito.Matchers.anyInt; 64d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static org.mockito.Matchers.eq; 653b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static org.mockito.Mockito.doAnswer; 665c2cf03f5f8e26f715931370004d21ee217edcdeTony Makimport static org.mockito.Mockito.doNothing; 67d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static org.mockito.Mockito.mock; 68d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static org.mockito.Mockito.never; 693b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolovimport static org.mockito.Mockito.times; 70d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovimport static org.mockito.Mockito.when; 71d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 72d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolovpublic class UserControllerTest extends AndroidTestCase { 733b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov private static final int TEST_USER_ID = 10; 743e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky private static final int NONEXIST_USER_ID = 2; 75d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private static String TAG = UserControllerTest.class.getSimpleName(); 76d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private UserController mUserController; 77d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private TestInjector mInjector; 78d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 795c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private static final List<String> START_FOREGROUND_USER_ACTIONS = 805c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Arrays.asList( 815c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_USER_STARTED, 825c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_USER_SWITCHED, 835c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_USER_STARTING); 845c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 855c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private static final List<String> START_BACKGROUND_USER_ACTIONS = 865c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Arrays.asList( 875c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_USER_STARTED, 885c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_LOCKED_BOOT_COMPLETED, 895c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Intent.ACTION_USER_STARTING); 905c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 915c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES = 925c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak new HashSet<>(Arrays.asList(REPORT_USER_SWITCH_MSG, USER_SWITCH_TIMEOUT_MSG, 935c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak SYSTEM_USER_START_MSG, SYSTEM_USER_CURRENT_MSG)); 945c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 955c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = 965c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak new HashSet<>(Arrays.asList(SYSTEM_USER_START_MSG, REPORT_LOCKED_BOOT_COMPLETE_MSG)); 975c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 98d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 99d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov public void setUp() throws Exception { 100d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov super.setUp(); 1015c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak System.setProperty("dexmaker.share_classloader", "true"); 102d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov mInjector = new TestInjector(getContext()); 103d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov mUserController = new UserController(mInjector); 1043b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov setUpUser(TEST_USER_ID, 0); 105d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 106d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 107d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 108d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected void tearDown() throws Exception { 109d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov super.tearDown(); 110d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov mInjector.handlerThread.quit(); 111d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 112d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 1139bc8543d45fc7f2edf857181940d3719e480a597Fyodor Kupolov @SmallTest 1145c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak public void testStartUser_foreground() throws RemoteException { 1155c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak mUserController.startUser(TEST_USER_ID, true /* foreground */); 116d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov Mockito.verify(mInjector.getWindowManager()).startFreezingScreen(anyInt(), anyInt()); 117d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 1183e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); 1193e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(true); 1205c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Mockito.verify(mInjector.getActivityStackSupervisor()).setLockTaskModeLocked( 1215c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak nullable(TaskRecord.class), 1225c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak eq(ActivityManager.LOCK_TASK_MODE_NONE), 1235c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak anyString(), 1245c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak anyBoolean()); 1255c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak startForegroundUserAssertions(); 1265c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak } 1275c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 1285c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak @SmallTest 1295c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak public void testStartUser_background() throws RemoteException { 1305c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak mUserController.startUser(TEST_USER_ID, false /* foreground */); 1315c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Mockito.verify( 1325c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); 1335c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); 1345c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Mockito.verify(mInjector.getActivityStackSupervisor(), never()).setLockTaskModeLocked( 1355c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak nullable(TaskRecord.class), 1365c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak eq(ActivityManager.LOCK_TASK_MODE_NONE), 1375c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak anyString(), 1385c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak anyBoolean()); 1395c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak startBackgroundUserAssertions(); 1403e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 1413e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 1423e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky @SmallTest 1433e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky public void testStartUserUIDisabled() throws RemoteException { 1443e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.mUserSwitchUiEnabled = false; 1455c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak mUserController.startUser(TEST_USER_ID, true /* foreground */); 1463e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), never()) 1473e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky .startFreezingScreen(anyInt(), anyInt()); 1483e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 1493e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); 1505c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak startForegroundUserAssertions(); 1513e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 1523e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 1535c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private void startUserAssertions( 1545c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak List<String> expectedActions, Set<Integer> expectedMessageCodes) 1555c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak throws RemoteException { 156d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov assertEquals(expectedActions, getActions(mInjector.sentIntents)); 1573b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> actualCodes = mInjector.handler.getMessageCodes(); 1585c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes); 1595c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak } 1605c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 1615c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private void startBackgroundUserAssertions() throws RemoteException { 1625c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES); 1635c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak } 1645c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak 1655c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak private void startForegroundUserAssertions() throws RemoteException { 1665c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak startUserAssertions(START_FOREGROUND_USER_ACTIONS, START_FOREGROUND_USER_MESSAGE_CODES); 1673b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 1683b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(reportMsg); 1693b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov UserState userState = (UserState) reportMsg.obj; 1703b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(userState); 1713b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier()); 1723b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state); 1733b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected old user id", 0, reportMsg.arg1); 1743b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected new user id", TEST_USER_ID, reportMsg.arg2); 1753b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 1763b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 1779bc8543d45fc7f2edf857181940d3719e480a597Fyodor Kupolov @SmallTest 1783e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky public void testFailedStartUserInForeground() throws RemoteException { 1793e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.mUserSwitchUiEnabled = false; 1803e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.startUserInForeground(NONEXIST_USER_ID); 1813e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); 1823e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(false); 1833e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 1843e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 1853e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky @SmallTest 1863b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov public void testDispatchUserSwitch() throws RemoteException { 1873b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Prepare mock observer and register it 1883b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 1893b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov when(observer.asBinder()).thenReturn(new Binder()); 1903b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov doAnswer(invocation -> { 1913b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov IRemoteCallback callback = (IRemoteCallback) invocation.getArguments()[1]; 1923b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov callback.sendResult(null); 1933b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov return null; 1943b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov }).when(observer).onUserSwitching(anyInt(), any()); 1953b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.registerUserSwitchObserver(observer, "mock"); 1963b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Start user -- this will update state of mUserController 1973b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.startUser(TEST_USER_ID, true); 1983b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 1993b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(reportMsg); 2003b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov UserState userState = (UserState) reportMsg.obj; 2013b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int oldUserId = reportMsg.arg1; 2023b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int newUserId = reportMsg.arg2; 2033b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Call dispatchUserSwitch and verify that observer was called only once 2043b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mInjector.handler.clearAllRecordedMessages(); 2053b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.dispatchUserSwitch(userState, oldUserId, newUserId); 2063b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Mockito.verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any()); 2073b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG); 2083b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> actualCodes = mInjector.handler.getMessageCodes(); 2093b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected message sent", expectedCodes, actualCodes); 2103b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message conMsg = mInjector.handler.getMessageForCode(CONTINUE_USER_SWITCH_MSG); 2113b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(conMsg); 2123b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov userState = (UserState) conMsg.obj; 2133b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(userState); 2143b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals(TEST_USER_ID, userState.mHandle.getIdentifier()); 2153b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("User must be in STATE_BOOTING", UserState.STATE_BOOTING, userState.state); 2163b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected old user id", 0, conMsg.arg1); 2173b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected new user id", TEST_USER_ID, conMsg.arg2); 2183b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 2193b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 2209bc8543d45fc7f2edf857181940d3719e480a597Fyodor Kupolov @SmallTest 2213b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov public void testDispatchUserSwitchBadReceiver() throws RemoteException { 2223b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Prepare mock observer which doesn't notify the callback and register it 2233b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 2243b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov when(observer.asBinder()).thenReturn(new Binder()); 2253b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.registerUserSwitchObserver(observer, "mock"); 2263b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Start user -- this will update state of mUserController 2273b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.startUser(TEST_USER_ID, true); 2283b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 2293b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(reportMsg); 2303b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov UserState userState = (UserState) reportMsg.obj; 2313b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int oldUserId = reportMsg.arg1; 2323b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int newUserId = reportMsg.arg2; 2333b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Call dispatchUserSwitch and verify that observer was called only once 2343b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mInjector.handler.clearAllRecordedMessages(); 2353b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.dispatchUserSwitch(userState, oldUserId, newUserId); 2363b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Mockito.verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any()); 2373b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout) 2383b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> actualCodes = mInjector.handler.getMessageCodes(); 2393b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertTrue("No messages should be sent", actualCodes.isEmpty()); 2403b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 2413b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 2429bc8543d45fc7f2edf857181940d3719e480a597Fyodor Kupolov @SmallTest 2433b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov public void testContinueUserSwitch() throws RemoteException { 2443b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Start user -- this will update state of mUserController 2453b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.startUser(TEST_USER_ID, true); 2463b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 2473b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(reportMsg); 2483b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov UserState userState = (UserState) reportMsg.obj; 2493b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int oldUserId = reportMsg.arg1; 2503b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov int newUserId = reportMsg.arg2; 2513b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mInjector.handler.clearAllRecordedMessages(); 2523b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov // Verify that continueUserSwitch worked as expected 2533b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mUserController.continueUserSwitch(userState, oldUserId, newUserId); 2543b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Mockito.verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen(); 2553e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky continueUserSwitchAssertions(); 2563e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 2573e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 2583e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky @SmallTest 2593e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky public void testContinueUserSwitchUIDisabled() throws RemoteException { 2603e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.mUserSwitchUiEnabled = false; 2613e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Start user -- this will update state of mUserController 2623e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.startUser(TEST_USER_ID, true); 2633e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 2643e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky assertNotNull(reportMsg); 2653e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky UserState userState = (UserState) reportMsg.obj; 2663e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky int oldUserId = reportMsg.arg1; 2673e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky int newUserId = reportMsg.arg2; 2683e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mInjector.handler.clearAllRecordedMessages(); 2693e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Verify that continueUserSwitch worked as expected 2703e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.continueUserSwitch(userState, oldUserId, newUserId); 2713e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); 2723e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky continueUserSwitchAssertions(); 2733e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 2743e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 2753e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky private void continueUserSwitchAssertions() throws RemoteException { 2763b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> expectedCodes = Collections.singleton(REPORT_USER_SWITCH_COMPLETE_MSG); 2773b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> actualCodes = mInjector.handler.getMessageCodes(); 2783b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected message sent", expectedCodes, actualCodes); 2793b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message msg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_COMPLETE_MSG); 2803b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertNotNull(msg); 2813b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov assertEquals("Unexpected userId", TEST_USER_ID, msg.arg1); 282d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 283d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 2843e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky @SmallTest 2853e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky public void testDispatchUserSwitchComplete() throws RemoteException { 2863e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Prepare mock observer and register it 2873e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky IUserSwitchObserver observer = mock(IUserSwitchObserver.class); 2883e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky when(observer.asBinder()).thenReturn(new Binder()); 2893e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.registerUserSwitchObserver(observer, "mock"); 2903e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Start user -- this will update state of mUserController 2913e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.startUser(TEST_USER_ID, true); 2923e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG); 2933e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky assertNotNull(reportMsg); 2943e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky int newUserId = reportMsg.arg2; 2953e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mInjector.handler.clearAllRecordedMessages(); 2963e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Mockito can't reset only interactions, so just verify that this hasn't been 2973e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // called with 'false' until after dispatchUserSwitchComplete. 2983e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(false); 2993e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky // Call dispatchUserSwitchComplete 3003e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky mUserController.dispatchUserSwitchComplete(newUserId); 3013e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(observer, times(1)).onUserSwitchComplete(anyInt()); 3023e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(observer).onUserSwitchComplete(TEST_USER_ID); 3033e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false); 3043e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky } 3053e0c25bf099e2942ee98b908ee01f82ce5e0bc82Evan Rosky 306d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private void setUpUser(int userId, int flags) { 307d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov UserInfo userInfo = new UserInfo(userId, "User" + userId, flags); 308d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov when(mInjector.userManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo); 309d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 310d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 311d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private static List<String> getActions(List<Intent> intents) { 312d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov List<String> result = new ArrayList<>(); 313d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov for (Intent intent : intents) { 314d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov result.add(intent.getAction()); 315d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 316d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return result; 317d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 318d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 319d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private static class TestInjector extends UserController.Injector { 320d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov final Object lock = new Object(); 3213b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov TestHandler handler; 322d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov HandlerThread handlerThread; 323d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov UserManagerService userManagerMock; 324d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov UserManagerInternal userManagerInternalMock; 325d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov WindowManagerService windowManagerMock; 3265c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak ActivityStackSupervisor activityStackSupervisor; 327d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov private Context mCtx; 328d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov List<Intent> sentIntents = new ArrayList<>(); 329d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 330d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov TestInjector(Context ctx) { 331d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov super(null); 332d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov mCtx = ctx; 333d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov handlerThread = new HandlerThread(TAG); 334d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov handlerThread.start(); 3353b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov handler = new TestHandler(handlerThread.getLooper()); 336d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov userManagerMock = mock(UserManagerService.class); 337d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov userManagerInternalMock = mock(UserManagerInternal.class); 338d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov windowManagerMock = mock(WindowManagerService.class); 3395c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak activityStackSupervisor = mock(ActivityStackSupervisor.class); 340d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 341d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 342d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 343d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected Object getLock() { 344d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return lock; 345d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 346d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 347d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 348d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected Handler getHandler() { 349d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return handler; 350d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 351d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 352d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 353d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected UserManagerService getUserManager() { 354d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return userManagerMock; 355d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 356d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 357d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 358d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov UserManagerInternal getUserManagerInternal() { 359d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return userManagerInternalMock; 360d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 361d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 362d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 363d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected Context getContext() { 364d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return mCtx; 365d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 366d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 367d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 368d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov int checkCallingPermission(String permission) { 369d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov Log.i(TAG, "checkCallingPermission " + permission); 370d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return PERMISSION_GRANTED; 371d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 372d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 373d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 374d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov WindowManagerService getWindowManager() { 375d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return windowManagerMock; 376d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 377d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 378d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 379d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov void updateUserConfigurationLocked() { 380d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov Log.i(TAG, "updateUserConfigurationLocked"); 381d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 382d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 383d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 384d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov protected int broadcastIntentLocked(Intent intent, String resolvedType, 385d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, 386d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, 387d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov boolean sticky, int callingPid, int callingUid, int userId) { 388d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov Log.i(TAG, "broadcastIntentLocked " + intent); 389d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov sentIntents.add(intent); 390d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov return 0; 391d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 392d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 393d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 3945c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak void startHomeActivityLocked(int userId, String reason) { 3955c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak Log.i(TAG, "startHomeActivityLocked " + userId); 396d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 397d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov 398d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov @Override 3995c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak ActivityStackSupervisor getActivityStackSupervisor() { 4005c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak return activityStackSupervisor; 401d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov } 4025c2cf03f5f8e26f715931370004d21ee217edcdeTony Mak } 4033b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4043b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov private static class TestHandler extends Handler { 4053b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov private final List<Message> mMessages = new ArrayList<>(); 4063b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4073b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov TestHandler(Looper looper) { 4083b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov super(looper); 4093b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4103b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4113b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> getMessageCodes() { 4123b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Set<Integer> result = new LinkedHashSet<>(); 4133b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov for (Message msg : mMessages) { 4143b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov result.add(msg.what); 4153b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4163b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov return result; 4173b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4183b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4193b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message getMessageForCode(int what) { 4203b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov for (Message msg : mMessages) { 4213b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov if (msg.what == what) { 4223b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov return msg; 4233b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4243b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4253b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov return null; 4263b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4273b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4283b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov void clearAllRecordedMessages() { 4293b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mMessages.clear(); 4303b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4313b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov 4323b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov @Override 4333b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 4343b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov Message copy = new Message(); 4353b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov copy.copyFrom(msg); 4363b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov mMessages.add(copy); 4373b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov return super.sendMessageAtTime(msg, uptimeMillis); 4383b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 4393b24e5b9d06be5740383e132c02929ff9bfe8715Fyodor Kupolov } 440d6038db83d06524daa4f411081fbe48e595e7a2cFyodor Kupolov}