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

Commit 22149c5d authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

Merge "New UserManagerInternal APIs for extra user / display assignment."

parents 89e9ae17 94744905
Loading
Loading
Loading
Loading
+32 −4
Original line number Original line Diff line number Diff line
@@ -388,8 +388,8 @@ public abstract class UserManagerInternal {
     * and the user is {@link UserManager#isUserVisible() visible}.
     * and the user is {@link UserManager#isUserVisible() visible}.
     *
     *
     * <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
     * <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
     * is started). If other clients (like {@code CarService} need to explicitly change the user /
     * is started); for extra unassignments, callers should call {@link
     * display assignment, we'll need to provide other APIs.
     * #assignUserToExtraDisplay(int, int)} instead.
     *
     *
     * <p><b>NOTE: </b>this method doesn't validate if the display exists, it's up to the caller to
     * <p><b>NOTE: </b>this method doesn't validate if the display exists, it's up to the caller to
     * pass a valid display id.
     * pass a valid display id.
@@ -397,15 +397,43 @@ public abstract class UserManagerInternal {
    public abstract @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
    public abstract @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
            @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId);
            @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId);


    /**
     * Assigns an extra display to the given user, so the user is visible on that display.
     *
     * <p>This method is meant to be used on automotive builds where a passenger zone has more than
     * one display (for example, the "main" display and a smaller display used for input).
     *
     * <p><b>NOTE: </b>this call will be ignored on devices that do not
     * {@link UserManager#isVisibleBackgroundUsersSupported() support visible background users}.
     *
     * @return whether the operation succeeded, in which case the user would be visible on the
     * display.
     */
    public abstract boolean assignUserToExtraDisplay(@UserIdInt int userId, int displayId);

    /**
    /**
     * Unassigns a user from its current display when it's stopping.
     * Unassigns a user from its current display when it's stopping.
     *
     *
     * <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
     * <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
     * is stopped). If other clients (like {@code CarService} need to explicitly change the user /
     * is stopped); for extra unassignments, callers should call
     * display assignment, we'll need to provide other APIs.
     * {@link #unassignUserFromExtraDisplay(int, int)} instead.
     */
     */
    public abstract void unassignUserFromDisplayOnStop(@UserIdInt int userId);
    public abstract void unassignUserFromDisplayOnStop(@UserIdInt int userId);


    /**
     * Unassigns the extra display from the given user.
     *
     * <p>This method is meant to be used on automotive builds where a passenger zone has more than
     * one display (for example, the "main" display and a smaller display used for input).
     *
     * <p><b>NOTE: </b>this call will be ignored on devices that do not
     * {@link UserManager#isVisibleBackgroundUsersSupported() support visible background users}.
     *
     * @return whether the operation succeeded, i.e., the user was previously
     *         {@link #assignUserToExtraDisplay(int, int) assigned to an extra display}.
     */
    public abstract boolean unassignUserFromExtraDisplay(@UserIdInt int userId, int displayId);

    /**
    /**
     * Returns {@code true} if the user is visible (as defined by
     * Returns {@code true} if the user is visible (as defined by
     * {@link UserManager#isUserVisible()}.
     * {@link UserManager#isUserVisible()}.
+10 −0
Original line number Original line Diff line number Diff line
@@ -7037,6 +7037,16 @@ public class UserManagerService extends IUserManager.Stub {
                    userStartMode, displayId);
                    userStartMode, displayId);
        }
        }


        @Override
        public boolean assignUserToExtraDisplay(int userId, int displayId) {
            return mUserVisibilityMediator.assignUserToExtraDisplay(userId, displayId);
        }

        @Override
        public boolean unassignUserFromExtraDisplay(int userId, int displayId) {
            return mUserVisibilityMediator.unassignUserFromExtraDisplay(userId, displayId);
        }

        @Override
        @Override
        public void unassignUserFromDisplayOnStop(@UserIdInt int userId) {
        public void unassignUserFromDisplayOnStop(@UserIdInt int userId) {
            mUserVisibilityMediator.unassignUserFromDisplayOnStop(userId);
            mUserVisibilityMediator.unassignUserFromDisplayOnStop(userId);
+176 −23
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ import static android.content.pm.UserInfo.NO_PROFILE_GROUP_ID;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;


import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
@@ -113,7 +114,18 @@ public final class UserVisibilityMediator implements Dumpable {
     */
     */
    @Nullable
    @Nullable
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final SparseIntArray mUsersOnDisplaysMap;
    private final SparseIntArray mUsersAssignedToDisplayOnStart;

    /**
     * Map of extra (i.e., not assigned on start, but by explicit calls to
     * {@link #assignUserToExtraDisplay(int, int)}) displays assigned to user (key is display id,
     * value is user id).
     *
     * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
     */
    @Nullable
    @GuardedBy("mLock")
    private final SparseIntArray mExtraDisplaysAssignedToUsers;


    /**
    /**
     * Mapping from each started user to its profile group.
     * Mapping from each started user to its profile group.
@@ -137,7 +149,13 @@ public final class UserVisibilityMediator implements Dumpable {
    @VisibleForTesting
    @VisibleForTesting
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
        mUsersOnDisplaysMap = mVisibleBackgroundUsersEnabled ? new SparseIntArray() : null;
        if (mVisibleBackgroundUsersEnabled) {
            mUsersAssignedToDisplayOnStart = new SparseIntArray();
            mExtraDisplaysAssignedToUsers = new SparseIntArray();
        } else {
            mUsersAssignedToDisplayOnStart = null;
            mExtraDisplaysAssignedToUsers = null;
        }
        mHandler = handler;
        mHandler = handler;
        // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
        // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
        mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
        mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
@@ -207,7 +225,7 @@ public final class UserVisibilityMediator implements Dumpable {
                    if (DBG) {
                    if (DBG) {
                        Slogf.d(TAG, "adding user / display mapping (%d -> %d)", userId, displayId);
                        Slogf.d(TAG, "adding user / display mapping (%d -> %d)", userId, displayId);
                    }
                    }
                    mUsersOnDisplaysMap.put(userId, displayId);
                    mUsersAssignedToDisplayOnStart.put(userId, displayId);
                    break;
                    break;
                case SECONDARY_DISPLAY_MAPPING_NOT_NEEDED:
                case SECONDARY_DISPLAY_MAPPING_NOT_NEEDED:
                    if (DBG) {
                    if (DBG) {
@@ -341,9 +359,9 @@ public final class UserVisibilityMediator implements Dumpable {
        }
        }


        // Check if display is available
        // Check if display is available
        for (int i = 0; i < mUsersOnDisplaysMap.size(); i++) {
        for (int i = 0; i < mUsersAssignedToDisplayOnStart.size(); i++) {
            int assignedUserId = mUsersOnDisplaysMap.keyAt(i);
            int assignedUserId = mUsersAssignedToDisplayOnStart.keyAt(i);
            int assignedDisplayId = mUsersOnDisplaysMap.valueAt(i);
            int assignedDisplayId = mUsersAssignedToDisplayOnStart.valueAt(i);
            if (DBG) {
            if (DBG) {
                Slogf.d(TAG, "%d: assignedUserId=%d, assignedDisplayId=%d",
                Slogf.d(TAG, "%d: assignedUserId=%d, assignedDisplayId=%d",
                        i, assignedUserId, assignedDisplayId);
                        i, assignedUserId, assignedDisplayId);
@@ -362,6 +380,100 @@ public final class UserVisibilityMediator implements Dumpable {
        return SECONDARY_DISPLAY_MAPPING_NEEDED;
        return SECONDARY_DISPLAY_MAPPING_NEEDED;
    }
    }


    /**
     * See {@link UserManagerInternal#assignUserToExtraDisplay(int, int)}.
     */
    public boolean assignUserToExtraDisplay(@UserIdInt int userId, int displayId) {
        if (DBG) {
            Slogf.d(TAG, "assignUserToExtraDisplay(%d, %d)", userId, displayId);
        }
        if (!mVisibleBackgroundUsersEnabled) {
            Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): called when not supported", userId,
                    displayId);
            return false;
        }
        if (displayId == INVALID_DISPLAY) {
            Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): called with INVALID_DISPLAY", userId,
                    displayId);
            return false;
        }
        if (displayId == DEFAULT_DISPLAY) {
            Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): DEFAULT_DISPLAY is automatically "
                    + "assigned to current user", userId, displayId);
            return false;
        }

        synchronized (mLock) {
            if (!isUserVisible(userId)) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is not visible",
                        userId, displayId);
                return false;
            }
            if (isStartedProfile(userId)) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
                        userId, displayId);
                return false;
            }

            if (mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is already "
                        + "assigned to that display", userId, displayId);
                return false;
            }

            int userAssignedToDisplay = getUserAssignedToDisplay(displayId,
                    /* returnCurrentUserByDefault= */ false);
            if (userAssignedToDisplay != USER_NULL) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because display was assigned"
                        + " to user %d on start", userId, displayId, userAssignedToDisplay);
                return false;
            }
            userAssignedToDisplay = mExtraDisplaysAssignedToUsers.get(userId, USER_NULL);
            if (userAssignedToDisplay != USER_NULL) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user %d was already "
                        + "assigned that extra display", userId, displayId, userAssignedToDisplay);
                return false;
            }
            if (DBG) {
                Slogf.d(TAG, "addding %d -> %d to map", displayId, userId);
            }
            mExtraDisplaysAssignedToUsers.put(displayId, userId);
        }
        return true;
    }

    /**
     * See {@link UserManagerInternal#unassignUserFromExtraDisplay(int, int)}.
     */
    public boolean unassignUserFromExtraDisplay(@UserIdInt int userId, int displayId) {
        if (DBG) {
            Slogf.d(TAG, "unassignUserFromExtraDisplay(%d, %d)", userId, displayId);
        }
        if (!mVisibleBackgroundUsersEnabled) {
            Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): called when not supported",
                    userId, displayId);
            return false;
        }
        synchronized (mLock) {
            int assignedUserId = mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL);
            if (assignedUserId == USER_NULL) {
                Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): not assigned to any user",
                        userId, displayId);
                return false;
            }
            if (assignedUserId != userId) {
                Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): was assigned to user %d",
                        userId, displayId, assignedUserId);
                return false;
            }
            if (DBG) {
                Slogf.d(TAG, "removing %d from map", displayId);
            }
            mExtraDisplaysAssignedToUsers.delete(displayId);
        }
        return true;
    }

    /**
    /**
     * See {@link UserManagerInternal#unassignUserFromDisplayOnStop(int)}.
     * See {@link UserManagerInternal#unassignUserFromDisplayOnStop(int)}.
     */
     */
@@ -373,7 +485,7 @@ public final class UserVisibilityMediator implements Dumpable {
        synchronized (mLock) {
        synchronized (mLock) {
            visibleUsersBefore = getVisibleUsers();
            visibleUsersBefore = getVisibleUsers();


            unassignUserFromDisplayOnStopLocked(userId);
            unassignUserFromAllDisplaysOnStopLocked(userId);


            visibleUsersAfter = getVisibleUsers();
            visibleUsersAfter = getVisibleUsers();
        }
        }
@@ -381,7 +493,7 @@ public final class UserVisibilityMediator implements Dumpable {
    }
    }


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void unassignUserFromDisplayOnStopLocked(@UserIdInt int userId) {
    private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
        if (DBG) {
        if (DBG) {
            Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
            Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
                    mStartedProfileGroupIds);
                    mStartedProfileGroupIds);
@@ -395,10 +507,21 @@ public final class UserVisibilityMediator implements Dumpable {
            return;
            return;
        }
        }
        if (DBG) {
        if (DBG) {
            Slogf.d(TAG, "Removing %d from mUsersOnSecondaryDisplays (%s)", userId,
            Slogf.d(TAG, "Removing user %d from mUsersOnDisplaysMap (%s)", userId,
                    mUsersOnDisplaysMap);
                    mUsersAssignedToDisplayOnStart);
        }
        mUsersAssignedToDisplayOnStart.delete(userId);

        // Remove extra displays as well
        for (int i = mExtraDisplaysAssignedToUsers.size() - 1; i >= 0; i--) {
            if (mExtraDisplaysAssignedToUsers.valueAt(i) == userId) {
                if (DBG) {
                    Slogf.d(TAG, "Removing display %d from mExtraDisplaysAssignedToUsers (%s)",
                            mExtraDisplaysAssignedToUsers.keyAt(i), mExtraDisplaysAssignedToUsers);
                }
                mExtraDisplaysAssignedToUsers.removeAt(i);
            }
        }
        }
        mUsersOnDisplaysMap.delete(userId);
    }
    }


    /**
    /**
@@ -424,7 +547,7 @@ public final class UserVisibilityMediator implements Dumpable {


        boolean visible;
        boolean visible;
        synchronized (mLock) {
        synchronized (mLock) {
            visible = mUsersOnDisplaysMap.indexOfKey(userId) >= 0;
            visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
        }
        }
        if (DBG) {
        if (DBG) {
            Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
            Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
@@ -448,7 +571,12 @@ public final class UserVisibilityMediator implements Dumpable {
        }
        }


        synchronized (mLock) {
        synchronized (mLock) {
            return mUsersOnDisplaysMap.get(userId, Display.INVALID_DISPLAY) == displayId;
            if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
                // User assigned to display on start
                return true;
            }
            // Check for extra assignment
            return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
        }
        }
    }
    }


@@ -465,24 +593,34 @@ public final class UserVisibilityMediator implements Dumpable {
        }
        }


        synchronized (mLock) {
        synchronized (mLock) {
            return mUsersOnDisplaysMap.get(userId, Display.INVALID_DISPLAY);
            return mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY);
        }
        }
    }
    }


    /**
    /**
     * See {@link UserManagerInternal#getUserAssignedToDisplay(int)}.
     * See {@link UserManagerInternal#getUserAssignedToDisplay(int)}.
     */
     */
    public int getUserAssignedToDisplay(@UserIdInt int displayId) {
    public @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId) {
        if (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled) {
        return getUserAssignedToDisplay(displayId, /* returnCurrentUserByDefault= */ true);
    }

    /**
     * Gets the user explicitly assigned to a display, or the current user when no user is assigned
     * to it (and {@code returnCurrentUserByDefault} is {@code true}).
     */
    private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
            boolean returnCurrentUserByDefault) {
        if (returnCurrentUserByDefault
                && (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
            return getCurrentUserId();
            return getCurrentUserId();
        }
        }


        synchronized (mLock) {
        synchronized (mLock) {
            for (int i = 0; i < mUsersOnDisplaysMap.size(); i++) {
            for (int i = 0; i < mUsersAssignedToDisplayOnStart.size(); i++) {
                if (mUsersOnDisplaysMap.valueAt(i) != displayId) {
                if (mUsersAssignedToDisplayOnStart.valueAt(i) != displayId) {
                    continue;
                    continue;
                }
                }
                int userId = mUsersOnDisplaysMap.keyAt(i);
                int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
                if (!isStartedProfile(userId)) {
                if (!isStartedProfile(userId)) {
                    return userId;
                    return userId;
                } else if (DBG) {
                } else if (DBG) {
@@ -491,6 +629,13 @@ public final class UserVisibilityMediator implements Dumpable {
                }
                }
            }
            }
        }
        }
        if (!returnCurrentUserByDefault) {
            if (DBG) {
                Slogf.d(TAG, "getUserAssignedToDisplay(%d): no user assigned to display, returning "
                        + "USER_NULL instead", displayId);
            }
            return USER_NULL;
        }


        int currentUserId = getCurrentUserId();
        int currentUserId = getCurrentUserId();
        if (DBG) {
        if (DBG) {
@@ -618,9 +763,11 @@ public final class UserVisibilityMediator implements Dumpable {
            ipw.print("Supports visible background users on displays: ");
            ipw.print("Supports visible background users on displays: ");
            ipw.println(mVisibleBackgroundUsersEnabled);
            ipw.println(mVisibleBackgroundUsersEnabled);


            if (mUsersOnDisplaysMap != null) {
            dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
                dumpSparseIntArray(ipw, mUsersOnDisplaysMap, "user / display", "u", "d");

            }
            dumpSparseIntArray(ipw, mExtraDisplaysAssignedToUsers, "extra display / user",
                    "d", "u");

            int numberListeners = mListeners.size();
            int numberListeners = mListeners.size();
            ipw.print("Number of listeners: ");
            ipw.print("Number of listeners: ");
            ipw.println(numberListeners);
            ipw.println(numberListeners);
@@ -638,8 +785,14 @@ public final class UserVisibilityMediator implements Dumpable {
        ipw.decreaseIndent();
        ipw.decreaseIndent();
    }
    }


    private static void dumpSparseIntArray(IndentingPrintWriter ipw, SparseIntArray array,
    private static void dumpSparseIntArray(IndentingPrintWriter ipw, @Nullable SparseIntArray array,
            String arrayDescription, String keyName, String valueName) {
            String arrayDescription, String keyName, String valueName) {
        if (array == null) {
            ipw.print("No ");
            ipw.print(arrayDescription);
            ipw.println(" mappings");
            return;
        }
        ipw.print("Number of ");
        ipw.print("Number of ");
        ipw.print(arrayDescription);
        ipw.print(arrayDescription);
        ipw.print(" mappings: ");
        ipw.print(" mappings: ");
+3 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
        int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
                DEFAULT_DISPLAY);
                DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        expectUserCannotBeUnassignedFromDisplay(USER_ID, DEFAULT_DISPLAY);


        expectUserIsVisible(USER_ID);
        expectUserIsVisible(USER_ID);
        expectUserIsNotVisibleOnDisplay(USER_ID, INVALID_DISPLAY);
        expectUserIsNotVisibleOnDisplay(USER_ID, INVALID_DISPLAY);
@@ -80,6 +81,7 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
        int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
        int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
                DEFAULT_DISPLAY);
                DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        expectUserCannotBeUnassignedFromDisplay(currentUserId, DEFAULT_DISPLAY);


        expectUserIsVisible(currentUserId);
        expectUserIsVisible(currentUserId);
        expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
        expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
@@ -110,6 +112,7 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
                BG_VISIBLE, DEFAULT_DISPLAY);
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);


        expectUserIsVisible(PROFILE_USER_ID);
        expectUserIsVisible(PROFILE_USER_ID);
        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+95 −4
Original line number Original line Diff line number Diff line
@@ -165,12 +165,16 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(USER_ID);
        expectNoDisplayAssignedToUser(USER_ID);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);


        assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


    @Test
    @Test
    public final void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
    public final void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
        visibleBgUserCannotBeStartedOnDefaultDisplayTest();
        visibleBgUserCannotBeStartedOnDefaultDisplayTest();

        assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
    }
    }


    protected final void visibleBgUserCannotBeStartedOnDefaultDisplayTest() throws Exception {
    protected final void visibleBgUserCannotBeStartedOnDefaultDisplayTest() throws Exception {
@@ -180,8 +184,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
                DEFAULT_DISPLAY);
                DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);


        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
        expectUserIsNotVisibleAtAll(USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(USER_ID);


        listener.verify();
        listener.verify();
    }
    }
@@ -194,8 +198,11 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
                SECONDARY_DISPLAY_ID);
                SECONDARY_DISPLAY_ID);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);


        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
        expectUserIsNotVisibleAtAll(USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(USER_ID);

        assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
        assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);


        listener.verify();
        listener.verify();
    }
    }
@@ -217,6 +224,9 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(USER_SYSTEM);
        expectNoDisplayAssignedToUser(USER_SYSTEM);
        expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
        expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);


        assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, SECONDARY_DISPLAY_ID);
        assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, OTHER_SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -256,6 +266,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectUserAssignedToDisplay(DEFAULT_DISPLAY, OTHER_USER_ID);
        expectUserAssignedToDisplay(DEFAULT_DISPLAY, OTHER_USER_ID);


        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -289,6 +301,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);


        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -305,6 +319,10 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);


        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
                OTHER_SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -320,6 +338,10 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);


        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
                OTHER_SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -336,6 +358,9 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);


        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -351,6 +376,10 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
        expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);


        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
                OTHER_SECONDARY_DISPLAY_ID);

        listener.verify();
        listener.verify();
    }
    }


@@ -481,6 +510,63 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
                        .that(actualResult).isEqualTo(expectedResult);
                        .that(actualResult).isEqualTo(expectedResult);
    }
    }


    protected void assertBgUserBecomesInvisibleOnStop(@UserIdInt int userId) {
        Log.d(TAG, "Stopping user " + userId);
        mMediator.unassignUserFromDisplayOnStop(userId);
        expectUserIsNotVisibleAtAll(userId);
    }

    /**
     * Assigns and unassigns the user to / from an extra display, asserting the visibility state in
     * between.
     *
     * <p>It assumes the user was not visible in the display beforehand.
     */
    protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
        assertUserCanBeAssignedExtraDisplay(userId, displayId, /* unassign= */ true);
    }

    protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId,
            boolean unassign) {

        expectUserIsNotVisibleOnDisplay(userId, displayId);

        Log.d(TAG, "Calling assignUserToExtraDisplay(" + userId + ", " + displayId + ")");
        assertWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
                .that(mMediator.assignUserToExtraDisplay(userId, displayId))
                .isTrue();
        expectUserIsVisibleOnDisplay(userId, displayId);

        if (unassign) {
            Log.d(TAG, "Calling unassignUserFromExtraDisplay(" + userId + ", " + displayId + ")");
            assertWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
                    .that(mMediator.unassignUserFromExtraDisplay(userId, displayId))
                    .isTrue();
            expectUserIsNotVisibleOnDisplay(userId, displayId);
        }
    }

    /**
     * Asserts that a user (already visible or not) cannot be assigned to an extra display (and
     * hence won't be visible on that display).
     */
    protected void assertUserCannotBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
        expectWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
                .that(mMediator.assignUserToExtraDisplay(userId, displayId))
                .isFalse();
        expectUserIsNotVisibleOnDisplay(userId, displayId);
    }

    /**
     * Asserts that an invisible user cannot be assigned to an extra display.
     */
    protected void assertInvisibleUserCannotBeAssignedExtraDisplay(@UserIdInt int userId,
            int displayId) {
        assertUserCannotBeAssignedExtraDisplay(userId, displayId);
        expectNoDisplayAssignedToUser(userId);
        expectInitialCurrentUserAssignedToDisplay(displayId);
    }

    protected void expectUserIsVisible(@UserIdInt int userId) {
    protected void expectUserIsVisible(@UserIdInt int userId) {
        expectWithMessage("isUserVisible(%s)", userId)
        expectWithMessage("isUserVisible(%s)", userId)
                .that(mMediator.isUserVisible(userId))
                .that(mMediator.isUserVisible(userId))
@@ -534,6 +620,11 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
                .that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
                .that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
    }
    }


    protected void expectUserCannotBeUnassignedFromDisplay(@UserIdInt int userId, int displayId) {
        expectWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
                .that(mMediator.unassignUserFromExtraDisplay(userId, displayId)).isFalse();
    }

    protected void expectUserAssignedToDisplay(int displayId, @UserIdInt int userId) {
    protected void expectUserAssignedToDisplay(int displayId, @UserIdInt int userId) {
        expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
        expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
                .that(mMediator.getUserAssignedToDisplay(displayId)).isEqualTo(userId);
                .that(mMediator.getUserAssignedToDisplay(displayId)).isEqualTo(userId);
Loading