Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 294ade62 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "Remove obsolete AndroidTestCase""

parents 12a2b2ec 1965af25
Loading
Loading
Loading
Loading
+16 −37
Original line number Original line Diff line number Diff line
@@ -16,60 +16,39 @@


package com.android.server.am;
package com.android.server.am;


import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;

import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.IActivityManager;
import android.app.IActivityManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.os.RemoteException;

import android.test.AndroidTestCase;
import org.junit.Before;
import org.junit.Test;


import java.util.List;
import java.util.List;


import androidx.test.filters.FlakyTest;
public class ActivityManagerTest extends AndroidTestCase {


/**
    IActivityManager service;
 * Tests for {@link ActivityManager}.
    @Override
 *
 * Build/Install/Run:
 *  atest FrameworksServicesTests:com.android.server.am.ActivityManagerTest
 */
@Presubmit
@FlakyTest(detail = "Promote to presubmit if stable")
public class ActivityManagerTest {

    private IActivityManager service;

    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        super.setUp();
        service = ActivityManager.getService();
        service = ActivityManager.getService();
    }
    }


    @Test
    public void testTaskIdsForRunningUsers() throws RemoteException {
    public void testTaskIdsForRunningUsers() throws RemoteException {
        int[] runningUserIds = service.getRunningUserIds();
        for(int userId : service.getRunningUserIds()) {
        assertThat(runningUserIds).isNotEmpty();
        for (int userId : runningUserIds) {
            testTaskIdsForUser(userId);
            testTaskIdsForUser(userId);
        }
        }
    }
    }


    private void testTaskIdsForUser(int userId) throws RemoteException {
    private void testTaskIdsForUser(int userId) throws RemoteException {
        List<?> recentTasks = service.getRecentTasks(100, 0, userId).getList();
        List<ActivityManager.RecentTaskInfo> recentTasks = service.getRecentTasks(
        assertThat(recentTasks).isNotNull();
                100, 0, userId).getList();
        assertThat(recentTasks).isNotEmpty();
        if(recentTasks != null) {
        for (Object elem : recentTasks) {
            for(ActivityManager.RecentTaskInfo recentTask : recentTasks) {
            assertThat(elem).isInstanceOf(RecentTaskInfo.class);
                int taskId = recentTask.persistentId;
            RecentTaskInfo recentTask = (RecentTaskInfo) elem;
            int taskId = recentTask.taskId;
                assertEquals("The task id " + taskId + " should not belong to user " + userId,
                assertEquals("The task id " + taskId + " should not belong to user " + userId,
                        taskId / UserHandle.PER_USER_RANGE, userId);
                        taskId / UserHandle.PER_USER_RANGE, userId);
            }
            }
        }
        }
    }
    }
}
+23 −29
Original line number Original line Diff line number Diff line
@@ -16,43 +16,34 @@


package com.android.server.am;
package com.android.server.am;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import static androidx.test.InstrumentationRegistry.getTargetContext;

import android.content.pm.UserInfo;
import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseBooleanArray;


import org.junit.After;
import com.android.server.am.TaskPersister;
import org.junit.Before;
import org.junit.Test;


import androidx.test.filters.FlakyTest;
import java.io.File;
import java.util.Random;


/**
/**
 * Tests for {@link TaskPersister}.
 *
 * Build/Install/Run:
 * atest FrameworksServicesTests:TaskPersisterTest
 * atest FrameworksServicesTests:TaskPersisterTest
 */
 */
@Presubmit
public class TaskPersisterTest extends AndroidTestCase {
@FlakyTest(detail = "Promote to presubmit if stable")
public class TaskPersisterTest {
    private static final String TEST_USER_NAME = "AM-Test-User";
    private static final String TEST_USER_NAME = "AM-Test-User";


    private TaskPersister mTaskPersister;
    private TaskPersister mTaskPersister;
    private int testUserId;
    private int testUserId;
    private UserManager mUserManager;
    private UserManager mUserManager;


    @Before
    @Override
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        mUserManager = UserManager.get(getTargetContext());
        super.setUp();
        mTaskPersister = new TaskPersister(getTargetContext().getFilesDir());
        mUserManager = UserManager.get(getContext());
        mTaskPersister = new TaskPersister(getContext().getFilesDir());
        // In ARC, the maximum number of supported users is one, which is different from the ones of
        // In ARC, the maximum number of supported users is one, which is different from the ones of
        // most phones (more than 4). This prevents TaskPersisterTest from creating another user for
        // most phones (more than 4). This prevents TaskPersisterTest from creating another user for
        // test. However, since guest users can be added as much as possible, we create guest user
        // test. However, since guest users can be added as much as possible, we create guest user
@@ -60,8 +51,9 @@ public class TaskPersisterTest {
        testUserId = createUser(TEST_USER_NAME, UserInfo.FLAG_GUEST);
        testUserId = createUser(TEST_USER_NAME, UserInfo.FLAG_GUEST);
    }
    }


    @After
    @Override
    public void tearDown() throws Exception {
    public void tearDown() throws Exception {
        super.tearDown();
        mTaskPersister.unloadUserDataFromMemory(testUserId);
        mTaskPersister.unloadUserDataFromMemory(testUserId);
        removeUser(testUserId);
        removeUser(testUserId);
    }
    }
@@ -72,7 +64,6 @@ public class TaskPersisterTest {
        return taskId;
        return taskId;
    }
    }


    @Test
    public void testTaskIdsPersistence() {
    public void testTaskIdsPersistence() {
        SparseBooleanArray taskIdsOnFile = new SparseBooleanArray();
        SparseBooleanArray taskIdsOnFile = new SparseBooleanArray();
        for (int i = 0; i < 100; i++) {
        for (int i = 0; i < 100; i++) {
@@ -81,18 +72,21 @@ public class TaskPersisterTest {
        mTaskPersister.writePersistedTaskIdsForUser(taskIdsOnFile, testUserId);
        mTaskPersister.writePersistedTaskIdsForUser(taskIdsOnFile, testUserId);
        SparseBooleanArray newTaskIdsOnFile = mTaskPersister
        SparseBooleanArray newTaskIdsOnFile = mTaskPersister
                .loadPersistedTaskIdsForUser(testUserId);
                .loadPersistedTaskIdsForUser(testUserId);
        assertEquals("TaskIds written differ from TaskIds read back from file",
        assertTrue("TaskIds written differ from TaskIds read back from file",
                taskIdsOnFile, newTaskIdsOnFile);
                taskIdsOnFile.equals(newTaskIdsOnFile));
    }
    }


    private int createUser(String name, int flags) {
    private int createUser(String name, int flags) {
        UserInfo user = mUserManager.createUser(name, flags);
        UserInfo user = mUserManager.createUser(name, flags);
        assertNotNull("Error while creating the test user: " + TEST_USER_NAME, user);
        if (user == null) {
            fail("Error while creating the test user: " + TEST_USER_NAME);
        }
        return user.id;
        return user.id;
    }
    }


    private void removeUser(int userId) {
    private void removeUser(int userId) {
        boolean userRemoved = mUserManager.removeUser(userId);
        if (!mUserManager.removeUser(userId)) {
        assertTrue("Error while removing the test user: " + TEST_USER_NAME, userRemoved);
            fail("Error while removing the test user: " + TEST_USER_NAME);
        }
    }
    }
}
}
 No newline at end of file
+96 −109
Original line number Original line Diff line number Diff line
@@ -16,41 +16,6 @@


package com.android.server.am;
package com.android.server.am;


import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;

import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;

import static com.google.android.collect.Lists.newArrayList;
import static com.google.android.collect.Sets.newHashSet;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static androidx.test.InstrumentationRegistry.getTargetContext;

import android.app.IUserSwitchObserver;
import android.app.IUserSwitchObserver;
import android.content.Context;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentReceiver;
@@ -66,62 +31,80 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.Log;


import com.android.server.pm.UserManagerService;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
import com.android.server.wm.WindowManagerService;


import org.junit.After;
import org.mockito.Mockito;
import org.junit.Before;
import org.junit.Test;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;


import androidx.test.filters.SmallTest;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;


/**
/**
 * Tests for {@link UserController}.
 * Usage: bit FrameworksServicesTests:com.android.server.am.UserControllerTest
 *
 * Build/Install/Run:
 *  atest FrameworksServicesTests:com.android.server.am.UserControllerTest
 */
 */
@Presubmit
@Presubmit
@SmallTest
public class UserControllerTest extends AndroidTestCase {
public class UserControllerTest {
    private static final int TEST_USER_ID = 10;
    private static final int TEST_USER_ID = 10;
    private static final int NONEXIST_USER_ID = 2;
    private static final int NONEXIST_USER_ID = 2;
    private static String TAG = UserControllerTest.class.getSimpleName();
    private static String TAG = UserControllerTest.class.getSimpleName();
    private UserController mUserController;
    private UserController mUserController;
    private TestInjector mInjector;
    private TestInjector mInjector;


    private static final List<String> START_FOREGROUND_USER_ACTIONS = newArrayList(
    private static final List<String> START_FOREGROUND_USER_ACTIONS =
            Arrays.asList(
                    Intent.ACTION_USER_STARTED,
                    Intent.ACTION_USER_STARTED,
                    Intent.ACTION_USER_SWITCHED,
                    Intent.ACTION_USER_SWITCHED,
                    Intent.ACTION_USER_STARTING);
                    Intent.ACTION_USER_STARTING);


    private static final List<String> START_BACKGROUND_USER_ACTIONS = newArrayList(
    private static final List<String> START_BACKGROUND_USER_ACTIONS =
            Arrays.asList(
                    Intent.ACTION_USER_STARTED,
                    Intent.ACTION_USER_STARTED,
                    Intent.ACTION_LOCKED_BOOT_COMPLETED,
                    Intent.ACTION_LOCKED_BOOT_COMPLETED,
                    Intent.ACTION_USER_STARTING);
                    Intent.ACTION_USER_STARTING);


    private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES = newHashSet(
    private static final Set<Integer> START_FOREGROUND_USER_MESSAGE_CODES =
            REPORT_USER_SWITCH_MSG,
            new HashSet<>(Arrays.asList(REPORT_USER_SWITCH_MSG, USER_SWITCH_TIMEOUT_MSG,
            USER_SWITCH_TIMEOUT_MSG,
                    SYSTEM_USER_START_MSG, SYSTEM_USER_CURRENT_MSG));
            SYSTEM_USER_START_MSG,
            SYSTEM_USER_CURRENT_MSG);


    private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
    private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES =
            SYSTEM_USER_START_MSG,
            new HashSet<>(Arrays.asList(SYSTEM_USER_START_MSG, REPORT_LOCKED_BOOT_COMPLETE_MSG));
            REPORT_LOCKED_BOOT_COMPLETE_MSG);


    @Before
    @Override
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        super.setUp();
        runWithDexmakerShareClassLoader(() -> {
        runWithDexmakerShareClassLoader(() -> {
            mInjector = spy(new TestInjector(getTargetContext()));
            mInjector = Mockito.spy(new TestInjector(getContext()));
            doNothing().when(mInjector).clearAllLockedTasks(anyString());
            doNothing().when(mInjector).clearAllLockedTasks(anyString());
            doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
            doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
            doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
            doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
@@ -131,54 +114,58 @@ public class UserControllerTest {
        });
        });
    }
    }


    @After
    @Override
    public void tearDown() throws Exception {
    protected void tearDown() throws Exception {
        super.tearDown();
        mInjector.handlerThread.quit();
        mInjector.handlerThread.quit();
        validateMockitoUsage();
        Mockito.validateMockitoUsage();
    }
    }


    @Test
    @SmallTest
    public void testStartUser_foreground() {
    public void testStartUser_foreground() throws RemoteException {
        mUserController.startUser(TEST_USER_ID, true /* foreground */);
        mUserController.startUser(TEST_USER_ID, true /* foreground */);
        verify(mInjector.getWindowManager()).startFreezingScreen(anyInt(), anyInt());
        Mockito.verify(mInjector.getWindowManager()).startFreezingScreen(anyInt(), anyInt());
        verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
        Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
        verify(mInjector.getWindowManager()).setSwitchingUser(true);
        Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(true);
        verify(mInjector).clearAllLockedTasks(anyString());
        Mockito.verify(mInjector).clearAllLockedTasks(anyString());
        startForegroundUserAssertions();
        startForegroundUserAssertions();
    }
    }


    @Test
    @SmallTest
    public void testStartUser_background() {
    public void testStartUser_background() throws RemoteException {
        mUserController.startUser(TEST_USER_ID, false /* foreground */);
        mUserController.startUser(TEST_USER_ID, false /* foreground */);
        verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
        Mockito.verify(
        verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
                mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
        verify(mInjector, never()).clearAllLockedTasks(anyString());
        Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
        Mockito.verify(mInjector, never()).clearAllLockedTasks(anyString());
        startBackgroundUserAssertions();
        startBackgroundUserAssertions();
    }
    }


    @Test
    @SmallTest
    public void testStartUserUIDisabled() {
    public void testStartUserUIDisabled() throws RemoteException {
        mUserController.mUserSwitchUiEnabled = false;
        mUserController.mUserSwitchUiEnabled = false;
        mUserController.startUser(TEST_USER_ID, true /* foreground */);
        mUserController.startUser(TEST_USER_ID, true /* foreground */);
        verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
        Mockito.verify(mInjector.getWindowManager(), never())
        verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
                .startFreezingScreen(anyInt(), anyInt());
        verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
        Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
        startForegroundUserAssertions();
        startForegroundUserAssertions();
    }
    }


    private void startUserAssertions(
    private void startUserAssertions(
            List<String> expectedActions, Set<Integer> expectedMessageCodes) {
            List<String> expectedActions, Set<Integer> expectedMessageCodes)
            throws RemoteException {
        assertEquals(expectedActions, getActions(mInjector.sentIntents));
        assertEquals(expectedActions, getActions(mInjector.sentIntents));
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes);
        assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes);
    }
    }


    private void startBackgroundUserAssertions() {
    private void startBackgroundUserAssertions() throws RemoteException {
        startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES);
        startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES);
    }
    }


    private void startForegroundUserAssertions() {
    private void startForegroundUserAssertions() throws RemoteException {
        startUserAssertions(START_FOREGROUND_USER_ACTIONS, START_FOREGROUND_USER_MESSAGE_CODES);
        startUserAssertions(START_FOREGROUND_USER_ACTIONS, START_FOREGROUND_USER_MESSAGE_CODES);
        Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG);
        Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG);
        assertNotNull(reportMsg);
        assertNotNull(reportMsg);
@@ -190,15 +177,15 @@ public class UserControllerTest {
        assertEquals("Unexpected new user id", TEST_USER_ID, reportMsg.arg2);
        assertEquals("Unexpected new user id", TEST_USER_ID, reportMsg.arg2);
    }
    }


    @Test
    @SmallTest
    public void testFailedStartUserInForeground() {
    public void testFailedStartUserInForeground() throws RemoteException {
        mUserController.mUserSwitchUiEnabled = false;
        mUserController.mUserSwitchUiEnabled = false;
        mUserController.startUserInForeground(NONEXIST_USER_ID);
        mUserController.startUserInForeground(NONEXIST_USER_ID);
        verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
        Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean());
        verify(mInjector.getWindowManager()).setSwitchingUser(false);
        Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(false);
    }
    }


    @Test
    @SmallTest
    public void testDispatchUserSwitch() throws RemoteException {
    public void testDispatchUserSwitch() throws RemoteException {
        // Prepare mock observer and register it
        // Prepare mock observer and register it
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
@@ -219,7 +206,7 @@ public class UserControllerTest {
        // Call dispatchUserSwitch and verify that observer was called only once
        // Call dispatchUserSwitch and verify that observer was called only once
        mInjector.handler.clearAllRecordedMessages();
        mInjector.handler.clearAllRecordedMessages();
        mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
        mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
        verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
        Mockito.verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
        Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG);
        Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG);
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        assertEquals("Unexpected message sent", expectedCodes, actualCodes);
        assertEquals("Unexpected message sent", expectedCodes, actualCodes);
@@ -233,7 +220,7 @@ public class UserControllerTest {
        assertEquals("Unexpected new user id", TEST_USER_ID, conMsg.arg2);
        assertEquals("Unexpected new user id", TEST_USER_ID, conMsg.arg2);
    }
    }


    @Test
    @SmallTest
    public void testDispatchUserSwitchBadReceiver() throws RemoteException {
    public void testDispatchUserSwitchBadReceiver() throws RemoteException {
        // Prepare mock observer which doesn't notify the callback and register it
        // Prepare mock observer which doesn't notify the callback and register it
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
@@ -249,14 +236,14 @@ public class UserControllerTest {
        // Call dispatchUserSwitch and verify that observer was called only once
        // Call dispatchUserSwitch and verify that observer was called only once
        mInjector.handler.clearAllRecordedMessages();
        mInjector.handler.clearAllRecordedMessages();
        mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
        mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
        verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
        Mockito.verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
        // Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout)
        // Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout)
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        assertWithMessage("No messages should be sent").that(actualCodes).isEmpty();
        assertTrue("No messages should be sent", actualCodes.isEmpty());
    }
    }


    @Test
    @SmallTest
    public void testContinueUserSwitch() {
    public void testContinueUserSwitch() throws RemoteException {
        // Start user -- this will update state of mUserController
        // Start user -- this will update state of mUserController
        mUserController.startUser(TEST_USER_ID, true);
        mUserController.startUser(TEST_USER_ID, true);
        Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG);
        Message reportMsg = mInjector.handler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -267,12 +254,12 @@ public class UserControllerTest {
        mInjector.handler.clearAllRecordedMessages();
        mInjector.handler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        // Verify that continueUserSwitch worked as expected
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
        Mockito.verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
        continueUserSwitchAssertions();
        continueUserSwitchAssertions();
    }
    }


    @Test
    @SmallTest
    public void testContinueUserSwitchUIDisabled() {
    public void testContinueUserSwitchUIDisabled() throws RemoteException {
        mUserController.mUserSwitchUiEnabled = false;
        mUserController.mUserSwitchUiEnabled = false;
        // Start user -- this will update state of mUserController
        // Start user -- this will update state of mUserController
        mUserController.startUser(TEST_USER_ID, true);
        mUserController.startUser(TEST_USER_ID, true);
@@ -284,11 +271,11 @@ public class UserControllerTest {
        mInjector.handler.clearAllRecordedMessages();
        mInjector.handler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        // Verify that continueUserSwitch worked as expected
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        continueUserSwitchAssertions();
        continueUserSwitchAssertions();
    }
    }


    private void continueUserSwitchAssertions() {
    private void continueUserSwitchAssertions() throws RemoteException {
        Set<Integer> expectedCodes = Collections.singleton(REPORT_USER_SWITCH_COMPLETE_MSG);
        Set<Integer> expectedCodes = Collections.singleton(REPORT_USER_SWITCH_COMPLETE_MSG);
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        Set<Integer> actualCodes = mInjector.handler.getMessageCodes();
        assertEquals("Unexpected message sent", expectedCodes, actualCodes);
        assertEquals("Unexpected message sent", expectedCodes, actualCodes);
@@ -297,7 +284,7 @@ public class UserControllerTest {
        assertEquals("Unexpected userId", TEST_USER_ID, msg.arg1);
        assertEquals("Unexpected userId", TEST_USER_ID, msg.arg1);
    }
    }


    @Test
    @SmallTest
    public void testDispatchUserSwitchComplete() throws RemoteException {
    public void testDispatchUserSwitchComplete() throws RemoteException {
        // Prepare mock observer and register it
        // Prepare mock observer and register it
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
        IUserSwitchObserver observer = mock(IUserSwitchObserver.class);
@@ -311,12 +298,12 @@ public class UserControllerTest {
        mInjector.handler.clearAllRecordedMessages();
        mInjector.handler.clearAllRecordedMessages();
        // Mockito can't reset only interactions, so just verify that this hasn't been
        // Mockito can't reset only interactions, so just verify that this hasn't been
        // called with 'false' until after dispatchUserSwitchComplete.
        // called with 'false' until after dispatchUserSwitchComplete.
        verify(mInjector.getWindowManager(), never()).setSwitchingUser(false);
        Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(false);
        // Call dispatchUserSwitchComplete
        // Call dispatchUserSwitchComplete
        mUserController.dispatchUserSwitchComplete(newUserId);
        mUserController.dispatchUserSwitchComplete(newUserId);
        verify(observer, times(1)).onUserSwitchComplete(anyInt());
        Mockito.verify(observer, times(1)).onUserSwitchComplete(anyInt());
        verify(observer).onUserSwitchComplete(TEST_USER_ID);
        Mockito.verify(observer).onUserSwitchComplete(TEST_USER_ID);
        verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false);
        Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false);
    }
    }


    private void setUpUser(int userId, int flags) {
    private void setUpUser(int userId, int flags) {
@@ -333,7 +320,7 @@ public class UserControllerTest {
    }
    }


    // Should be public to allow mocking
    // Should be public to allow mocking
    private static class TestInjector extends UserController.Injector {
    public static class TestInjector extends UserController.Injector {
        TestHandler handler;
        TestHandler handler;
        TestHandler uiHandler;
        TestHandler uiHandler;
        HandlerThread handlerThread;
        HandlerThread handlerThread;