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

Commit 2c4a5939 authored by Felipe Leme's avatar Felipe Leme
Browse files

UserVisibilityMediator: allow visible bg users on default display.

So far only the current user is visible in the default display and
other users could only be started visible on secondary displays, but
that restriction must be lift for automotive builds that only support
passengers (for example, when a 2nd instance of Android is run on the
back seat of a car).

This CL changes UserVisibilityMediator to allow that scenario,
although it's not hooked with other parts of the system yet (which
will require a new config and new CTS tests).

Test: atest UserVisibilityMediatorMUPANDTest \
            UserVisibilityMediatorMUMDTest \
	    UserVisibilityMediatorSUSDTest
Fixes: 261538337
Change-Id: Ia7989f5ce2af41c7be2b1d578ab0e0e2aecc4e9d
parent 843cd7b1
Loading
Loading
Loading
Loading
+126 −42
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.annotation.UserIdInt;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.DebugUtils;
import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
@@ -80,6 +81,7 @@ public final class UserVisibilityMediator implements Dumpable {

    private static final String TAG = UserVisibilityMediator.class.getSimpleName();

    private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
    public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
    public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
    public static final int SECONDARY_DISPLAY_MAPPING_FAILED = -1;
@@ -88,7 +90,7 @@ public final class UserVisibilityMediator implements Dumpable {
     * Whether a user / display assignment requires adding an entry to the
     * {@code mUsersOnSecondaryDisplays} map.
     */
    @IntDef(flag = false, prefix = {"SECONDARY_DISPLAY_MAPPING_"}, value = {
    @IntDef(flag = false, prefix = {PREFIX_SECONDARY_DISPLAY_MAPPING}, value = {
            SECONDARY_DISPLAY_MAPPING_NEEDED,
            SECONDARY_DISPLAY_MAPPING_NOT_NEEDED,
            SECONDARY_DISPLAY_MAPPING_FAILED
@@ -102,6 +104,7 @@ public final class UserVisibilityMediator implements Dumpable {
    private final Object mLock = new Object();

    private final boolean mVisibleBackgroundUsersEnabled;
    private final boolean mVisibleBackgroundUserOnDefaultDisplayAllowed;

    @UserIdInt
    @GuardedBy("mLock")
@@ -110,7 +113,7 @@ public final class UserVisibilityMediator implements Dumpable {
    /**
     * Map of background users started visible on displays (key is user id, value is display id).
     *
     * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
     * <p>Only set when {@code mVisibleBackgroundUsersEnabled} is {@code true}.
     */
    @Nullable
    @GuardedBy("mLock")
@@ -121,7 +124,7 @@ public final class UserVisibilityMediator implements Dumpable {
     * {@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}.
     * <p>Only set when {@code mVisibleBackgroundUsersEnabled} is {@code true}.
     */
    @Nullable
    @GuardedBy("mLock")
@@ -143,12 +146,17 @@ public final class UserVisibilityMediator implements Dumpable {
            new CopyOnWriteArrayList<>();

    UserVisibilityMediator(Handler handler) {
        this(UserManager.isVisibleBackgroundUsersEnabled(), handler);
        this(UserManager.isVisibleBackgroundUsersEnabled(),
                // TODO(b/261538232): get visibleBackgroundUserOnDefaultDisplayAllowed from UM
                /* visibleBackgroundUserOnDefaultDisplayAllowed= */ false, handler);
    }

    @VisibleForTesting
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled,
            boolean visibleBackgroundUserOnDefaultDisplayAllowed, Handler handler) {
        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
        mVisibleBackgroundUserOnDefaultDisplayAllowed =
                visibleBackgroundUserOnDefaultDisplayAllowed;
        if (mVisibleBackgroundUsersEnabled) {
            mUsersAssignedToDisplayOnStart = new SparseIntArray();
            mExtraDisplaysAssignedToUsers = new SparseIntArray();
@@ -203,7 +211,12 @@ public final class UserVisibilityMediator implements Dumpable {
                return result;
            }

            int mappingResult = canAssignUserToDisplayLocked(userId, profileGroupId, displayId);
            int mappingResult = canAssignUserToDisplayLocked(userId, profileGroupId, userStartMode,
                    displayId);
            if (DBG) {
                Slogf.d(TAG, "mapping result: %s",
                        secondaryDisplayMappingStatusToString(mappingResult));
            }
            if (mappingResult == SECONDARY_DISPLAY_MAPPING_FAILED) {
                return USER_ASSIGNMENT_RESULT_FAILURE;
            }
@@ -263,14 +276,16 @@ public final class UserVisibilityMediator implements Dumpable {
                    + "(it should be BACKGROUND_USER_VISIBLE", userId, displayId);
            return USER_ASSIGNMENT_RESULT_FAILURE;
        }
        if (userStartMode == USER_START_MODE_BACKGROUND_VISIBLE
                && displayId == DEFAULT_DISPLAY && !isProfile(userId, profileGroupId)) {

        boolean visibleBackground = userStartMode == USER_START_MODE_BACKGROUND_VISIBLE;
        if (displayId == DEFAULT_DISPLAY && visibleBackground
                && !mVisibleBackgroundUserOnDefaultDisplayAllowed
                && !isProfile(userId, profileGroupId)) {
            Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
            return USER_ASSIGNMENT_RESULT_FAILURE;
        }

        boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;

        if (displayId != DEFAULT_DISPLAY) {
            if (foreground) {
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
@@ -309,6 +324,7 @@ public final class UserVisibilityMediator implements Dumpable {
        }

        return foreground || displayId != DEFAULT_DISPLAY
                || (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayAllowed)
                        ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
                        : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
    }
@@ -316,20 +332,40 @@ public final class UserVisibilityMediator implements Dumpable {
    @GuardedBy("mLock")
    @SecondaryDisplayMappingStatus
    private int canAssignUserToDisplayLocked(@UserIdInt int userId,
            @UserIdInt int profileGroupId, int displayId) {
        if (displayId == DEFAULT_DISPLAY
                && (!mVisibleBackgroundUsersEnabled || !isProfile(userId, profileGroupId))) {
            @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
        if (displayId == DEFAULT_DISPLAY) {
            boolean mappingNeeded = false;
            if (mVisibleBackgroundUserOnDefaultDisplayAllowed
                    && userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
                int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
                if (userStartedOnDefaultDisplay != USER_NULL) {
                    Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
                            + " default display because user %d already did so", userId,
                            userStartedOnDefaultDisplay);
                    return SECONDARY_DISPLAY_MAPPING_FAILED;
                }
                mappingNeeded = true;
            }
            if (!mappingNeeded && mVisibleBackgroundUsersEnabled
                    && isProfile(userId, profileGroupId)) {
                mappingNeeded = true;
            }

            if (!mappingNeeded) {
                // Don't need to do anything because methods (such as isUserVisible()) already
                // know that the current user (and its profiles) is assigned to the default display.
                // But on MUMD devices, profiles are only supported in the default display, so it
                // cannot return yet as it needs to check if the parent is also assigned to the
            // DEFAULT_DISPLAY (this is done indirectly below when it checks that the profile parent
            // is the current user, as the current user is always assigned to the DEFAULT_DISPLAY).
                // DEFAULT_DISPLAY (this is done indirectly below when it checks that the profile
                // parent is the current user, as the current user is always assigned to the
                // DEFAULT_DISPLAY).
                if (DBG) {
                Slogf.d(TAG, "ignoring mapping for default display");
                    Slogf.d(TAG, "ignoring mapping for default display for user %d starting as %s",
                            userId, userStartModeToString(userStartMode));
                }
                return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
            }
        }

        if (userId == UserHandle.USER_SYSTEM) {
            Slogf.w(TAG, "Cannot assign system user to secondary display (%d)", displayId);
@@ -421,13 +457,14 @@ public final class UserVisibilityMediator implements Dumpable {
                return false;
            }

            int userAssignedToDisplay = getUserAssignedToDisplay(displayId,
                    /* returnCurrentUserByDefault= */ false);
            // First check if the user started on display
            int userAssignedToDisplay = getUserStartedOnDisplay(displayId);
            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;
            }
            // Then if was assigned extra
            userAssignedToDisplay = mExtraDisplaysAssignedToUsers.get(userId, USER_NULL);
            if (userAssignedToDisplay != USER_NULL) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user %d was already "
@@ -435,7 +472,8 @@ public final class UserVisibilityMediator implements Dumpable {
                return false;
            }
            if (DBG) {
                Slogf.d(TAG, "addding %d -> %d to map", displayId, userId);
                Slogf.d(TAG, "addding %d -> %d to mExtraDisplaysAssignedToUsers", displayId,
                        userId);
            }
            mExtraDisplaysAssignedToUsers.put(displayId, userId);
        }
@@ -501,7 +539,7 @@ public final class UserVisibilityMediator implements Dumpable {
        mStartedProfileGroupIds.delete(userId);

        if (!mVisibleBackgroundUsersEnabled) {
            // Don't need to do update mUsersOnSecondaryDisplays because methods (such as
            // Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
            // isUserVisible()) already know that the current user (and their profiles) is
            // assigned to the default display.
            return;
@@ -536,11 +574,10 @@ public final class UserVisibilityMediator implements Dumpable {
            return true;
        }

        // Device doesn't support multiple users on multiple displays, so only users checked above
        // can be visible
        if (!mVisibleBackgroundUsersEnabled) {
            if (DBG) {
                Slogf.d(TAG, "isUserVisible(%d): false for non-current user on MUMD", userId);
                Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
                        + " device doesn't support visible background users", userId);
            }
            return false;
        }
@@ -559,15 +596,29 @@ public final class UserVisibilityMediator implements Dumpable {
     * See {@link UserManagerInternal#isUserVisible(int, int)}.
     */
    public boolean isUserVisible(@UserIdInt int userId, int displayId) {
        if (displayId == Display.INVALID_DISPLAY) {
        if (displayId == INVALID_DISPLAY) {
            return false;
        }

        if (!mVisibleBackgroundUsersEnabled || displayId == Display.DEFAULT_DISPLAY) {
            // TODO(b/245939659): will need to move the displayId == Display.DEFAULT_DISPLAY outside
            // once it supports background users on DEFAULT_DISPLAY (for example, passengers in a
            // no-driver configuration)
            return isCurrentUserOrRunningProfileOfCurrentUser(userId);
        // Current user is always visible on:
        // - Default display
        // - Secondary displays when device doesn't support visible bg users
        //   - Or when explicitly added (which is checked below)
        if (isCurrentUserOrRunningProfileOfCurrentUser(userId)
                && (displayId == DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
            if (VERBOSE) {
                Slogf.v(TAG, "isUserVisible(%d, %d): returning true for current user/profile",
                        userId, displayId);
            }
            return true;
        }

        if (!mVisibleBackgroundUsersEnabled) {
            if (DBG) {
                Slogf.d(TAG, "isUserVisible(%d, %d): returning false as device does not support"
                        + " visible background users", userId, displayId);
            }
            return false;
        }

        synchronized (mLock) {
@@ -575,7 +626,8 @@ public final class UserVisibilityMediator implements Dumpable {
                // User assigned to display on start
                return true;
            }
            // Check for extra assignment

            // Check for extra display assignment
            return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
        }
    }
@@ -585,15 +637,31 @@ public final class UserVisibilityMediator implements Dumpable {
     */
    public int getDisplayAssignedToUser(@UserIdInt int userId) {
        if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
            return Display.DEFAULT_DISPLAY;
            if (mVisibleBackgroundUserOnDefaultDisplayAllowed) {
                // When device supports visible bg users on default display, the default display is
                // assigned to the current user, unless a user is started visible on it
                int userStartedOnDefaultDisplay;
                synchronized (mLock) {
                    userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
                }
                if (userStartedOnDefaultDisplay != USER_NULL) {
                    if (DBG) {
                        Slogf.d(TAG, "getDisplayAssignedToUser(%d): returning INVALID_DISPLAY for "
                                + "current user user %d was started on DEFAULT_DISPLAY",
                                userId, userStartedOnDefaultDisplay);
                    }
                    return INVALID_DISPLAY;
                }
            }
            return DEFAULT_DISPLAY;
        }

        if (!mVisibleBackgroundUsersEnabled) {
            return Display.INVALID_DISPLAY;
            return INVALID_DISPLAY;
        }

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

@@ -604,6 +672,13 @@ public final class UserVisibilityMediator implements Dumpable {
        return getUserAssignedToDisplay(displayId, /* returnCurrentUserByDefault= */ true);
    }

    /**
     * Gets the user explicitly assigned to a display.
     */
    private @UserIdInt int getUserStartedOnDisplay(@UserIdInt int displayId) {
        return getUserAssignedToDisplay(displayId, /* returnCurrentUserByDefault= */ false);
    }

    /**
     * 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}).
@@ -611,7 +686,8 @@ public final class UserVisibilityMediator implements Dumpable {
    private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
            boolean returnCurrentUserByDefault) {
        if (returnCurrentUserByDefault
                && (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
                && ((displayId == DEFAULT_DISPLAY && !mVisibleBackgroundUserOnDefaultDisplayAllowed
                || !mVisibleBackgroundUsersEnabled))) {
            return getCurrentUserId();
        }

@@ -763,8 +839,10 @@ public final class UserVisibilityMediator implements Dumpable {
            ipw.print("Supports visible background users on displays: ");
            ipw.println(mVisibleBackgroundUsersEnabled);

            dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
            ipw.print("Allows visible background users on default display: ");
            ipw.println(mVisibleBackgroundUserOnDefaultDisplayAllowed);

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

@@ -872,4 +950,10 @@ public final class UserVisibilityMediator implements Dumpable {
            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
        }
    }

    private static String secondaryDisplayMappingStatusToString(
            @SecondaryDisplayMappingStatus int status) {
        return DebugUtils.constantToString(UserVisibilityMediator.class,
                PREFIX_SECONDARY_DISPLAY_MAPPING, status);
    }
}
+9 −2
Original line number Diff line number Diff line
@@ -62,14 +62,21 @@ public final class DumpableDumperRule implements TestRule {
        };
    }

    private void dumpOnFailure(String testName) throws IOException {
    /**
     * Logs all dumpables.
     */
    public void dump(String reason) {
        if (mDumpables.isEmpty()) {
            return;
        }
        Log.w(TAG, "Dumping " + mDumpables.size() + " dumpables on failure of " + testName);
        Log.w(TAG, "Dumping " + mDumpables.size() + " dumpable(s). Reason: " + reason);
        mDumpables.forEach(d -> logDumpable(d));
    }

    private void dumpOnFailure(String testName) throws IOException {
        dump("failure of " + testName);
    }

    private void logDumpable(Dumpable dumpable) {
        try {
            try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+16 −1
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.pm;

import org.junit.Test;

/**
 * Tests for {@link UserVisibilityMediator} tests for devices that support concurrent Multiple
 * Users on Multiple Displays (A.K.A {@code MUMD}).
@@ -26,6 +28,19 @@ public final class UserVisibilityMediatorMUMDTest
        extends UserVisibilityMediatorVisibleBackgroundUserTestCase {

    public UserVisibilityMediatorMUMDTest() throws Exception {
        super(/* usersOnSecondaryDisplaysEnabled= */ true);
        super(/* backgroundUsersOnDisplaysEnabled= */ true,
                /* backgroundUserOnDefaultDisplayAllowed= */ false);
    }

    @Test
    public void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
        int userId = visibleBgUserCannotBeStartedOnDefaultDisplayTest();

        assertInvisibleUserCannotBeAssignedExtraDisplay(userId, SECONDARY_DISPLAY_ID);
    }

    @Test
    public void testStartBgUser_onDefaultDisplay_visible() throws Exception {
        visibleBgUserCannotBeStartedOnDefaultDisplayTest();
    }
}
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm;

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_SUCCESS_VISIBLE;
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
import static com.android.server.pm.UserVisibilityMediator.INITIAL_CURRENT_USER_ID;

import org.junit.Test;

/**
 * Tests for {@link UserVisibilityMediator} tests for devices that support not only concurrent
 * Multiple Users on Multiple Displays, but also let background users to be visible in the default
 * display (A.K.A {@code MUPAND} - MUltiple Passengers, No Driver).
 *
 * <p> Run as {@code
* atest FrameworksMockingServicesTests:com.android.server.pm.UserVisibilityMediatorMUPANDTest}
 */
public final class UserVisibilityMediatorMUPANDTest
        extends UserVisibilityMediatorVisibleBackgroundUserTestCase {

    public UserVisibilityMediatorMUPANDTest() throws Exception {
        super(/* backgroundUsersOnDisplaysEnabled= */ true,
                /* backgroundUserOnDefaultDisplayAllowed= */ true);
    }

    @Test
    public void testStartVisibleBgUser_onDefaultDisplay_initialCurrentUserId()
            throws Exception {
        int currentUserId = INITIAL_CURRENT_USER_ID;
        int visibleBgUserId = USER_ID;
        int otherUserId = OTHER_USER_ID;

        AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(visibleBgUserId));

        int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        expectVisibleUsers(currentUserId, visibleBgUserId);

        // Assert bg user visibility
        expectUserIsVisible(visibleBgUserId);
        expectUserIsVisibleOnDisplay(visibleBgUserId, DEFAULT_DISPLAY);
        expectUserIsNotVisibleOnDisplay(visibleBgUserId, INVALID_DISPLAY);
        expectDisplayAssignedToUser(visibleBgUserId, DEFAULT_DISPLAY);
        expectUserAssignedToDisplay(DEFAULT_DISPLAY, visibleBgUserId);

        // Assert current user visibility
        expectUserIsVisible(currentUserId);
        expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
        expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
        expectDisplayAssignedToUser(currentUserId, INVALID_DISPLAY);

        assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);

        // Make sure another user cannot be started on default display
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                "when user (%d) is starting on default display after it was started by user %d",
                otherUserId, visibleBgUserId);
        expectVisibleUsers(currentUserId, visibleBgUserId);

        listener.verify();
    }

    @Test
    public void testStartVisibleBgUser_onDefaultDisplay_nonInitialCurrentUserId()
            throws Exception {
        int currentUserId = OTHER_USER_ID;
        int visibleBgUserId = USER_ID;
        int otherUserId = YET_ANOTHER_USER_ID;

        AsyncUserVisibilityListener listener = addListenerForEvents(
                onInvisible(INITIAL_CURRENT_USER_ID),
                onVisible(currentUserId),
                onVisible(visibleBgUserId));
        startForegroundUser(currentUserId);

        int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
        expectVisibleUsers(currentUserId, visibleBgUserId);

        // Assert bg user visibility
        expectUserIsVisible(visibleBgUserId);
        expectUserIsVisibleOnDisplay(visibleBgUserId, DEFAULT_DISPLAY);
        expectUserIsNotVisibleOnDisplay(visibleBgUserId, INVALID_DISPLAY);
        expectDisplayAssignedToUser(visibleBgUserId, DEFAULT_DISPLAY);
        expectUserAssignedToDisplay(DEFAULT_DISPLAY, visibleBgUserId);

        // Assert current user visibility
        expectUserIsVisible(currentUserId);
        expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
        expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
        expectDisplayAssignedToUser(currentUserId, INVALID_DISPLAY);

        assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);

        // Make sure another user cannot be started on default display
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                "when user (%d) is starting on default display after it was started by user %d",
                otherUserId, visibleBgUserId);
        expectVisibleUsers(currentUserId, visibleBgUserId);

        listener.verify();
    }
}
+14 −1
Original line number Diff line number Diff line
@@ -37,7 +37,15 @@ import org.junit.Test;
public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediatorTestCase {

    public UserVisibilityMediatorSUSDTest() {
        super(/* usersOnSecondaryDisplaysEnabled= */ false);
        super(/* backgroundUsersOnDisplaysEnabled= */ false,
                /* backgroundUserOnDefaultDisplayAllowed= */ false);
    }

    @Test
    public void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
        int userId = visibleBgUserCannotBeStartedOnDefaultDisplayTest();

        assertInvisibleUserCannotBeAssignedExtraDisplay(userId, SECONDARY_DISPLAY_ID);
    }

    @Test
@@ -100,6 +108,11 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
        listener.verify();
    }

    @Test
    public void testStartBgUser_onDefaultDisplay_visible() throws Exception {
        visibleBgUserCannotBeStartedOnDefaultDisplayTest();
    }

    @Test
    public void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
            throws Exception {
Loading