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 Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import android.annotation.UserIdInt;
import android.os.Handler;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.util.DebugUtils;
import android.util.Dumpable;
import android.util.Dumpable;
import android.util.EventLog;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
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 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_NEEDED = 1;
    public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
    public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
    public static final int SECONDARY_DISPLAY_MAPPING_FAILED = -1;
    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
     * Whether a user / display assignment requires adding an entry to the
     * {@code mUsersOnSecondaryDisplays} map.
     * {@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_NEEDED,
            SECONDARY_DISPLAY_MAPPING_NOT_NEEDED,
            SECONDARY_DISPLAY_MAPPING_NOT_NEEDED,
            SECONDARY_DISPLAY_MAPPING_FAILED
            SECONDARY_DISPLAY_MAPPING_FAILED
@@ -102,6 +104,7 @@ public final class UserVisibilityMediator implements Dumpable {
    private final Object mLock = new Object();
    private final Object mLock = new Object();


    private final boolean mVisibleBackgroundUsersEnabled;
    private final boolean mVisibleBackgroundUsersEnabled;
    private final boolean mVisibleBackgroundUserOnDefaultDisplayAllowed;


    @UserIdInt
    @UserIdInt
    @GuardedBy("mLock")
    @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).
     * 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
    @Nullable
    @GuardedBy("mLock")
    @GuardedBy("mLock")
@@ -121,7 +124,7 @@ public final class UserVisibilityMediator implements Dumpable {
     * {@link #assignUserToExtraDisplay(int, int)}) displays assigned to user (key is display id,
     * {@link #assignUserToExtraDisplay(int, int)}) displays assigned to user (key is display id,
     * value is user id).
     * value is user id).
     *
     *
     * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
     * <p>Only set when {@code mVisibleBackgroundUsersEnabled} is {@code true}.
     */
     */
    @Nullable
    @Nullable
    @GuardedBy("mLock")
    @GuardedBy("mLock")
@@ -143,12 +146,17 @@ public final class UserVisibilityMediator implements Dumpable {
            new CopyOnWriteArrayList<>();
            new CopyOnWriteArrayList<>();


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


    @VisibleForTesting
    @VisibleForTesting
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled,
            boolean visibleBackgroundUserOnDefaultDisplayAllowed, Handler handler) {
        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
        mVisibleBackgroundUserOnDefaultDisplayAllowed =
                visibleBackgroundUserOnDefaultDisplayAllowed;
        if (mVisibleBackgroundUsersEnabled) {
        if (mVisibleBackgroundUsersEnabled) {
            mUsersAssignedToDisplayOnStart = new SparseIntArray();
            mUsersAssignedToDisplayOnStart = new SparseIntArray();
            mExtraDisplaysAssignedToUsers = new SparseIntArray();
            mExtraDisplaysAssignedToUsers = new SparseIntArray();
@@ -203,7 +211,12 @@ public final class UserVisibilityMediator implements Dumpable {
                return result;
                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) {
            if (mappingResult == SECONDARY_DISPLAY_MAPPING_FAILED) {
                return USER_ASSIGNMENT_RESULT_FAILURE;
                return USER_ASSIGNMENT_RESULT_FAILURE;
            }
            }
@@ -263,14 +276,16 @@ public final class UserVisibilityMediator implements Dumpable {
                    + "(it should be BACKGROUND_USER_VISIBLE", userId, displayId);
                    + "(it should be BACKGROUND_USER_VISIBLE", userId, displayId);
            return USER_ASSIGNMENT_RESULT_FAILURE;
            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);
            Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
            return USER_ASSIGNMENT_RESULT_FAILURE;
            return USER_ASSIGNMENT_RESULT_FAILURE;
        }
        }


        boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
        boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;

        if (displayId != DEFAULT_DISPLAY) {
        if (displayId != DEFAULT_DISPLAY) {
            if (foreground) {
            if (foreground) {
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
                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
        return foreground || displayId != DEFAULT_DISPLAY
                || (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayAllowed)
                        ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
                        ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
                        : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
                        : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
    }
    }
@@ -316,20 +332,40 @@ public final class UserVisibilityMediator implements Dumpable {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    @SecondaryDisplayMappingStatus
    @SecondaryDisplayMappingStatus
    private int canAssignUserToDisplayLocked(@UserIdInt int userId,
    private int canAssignUserToDisplayLocked(@UserIdInt int userId,
            @UserIdInt int profileGroupId, int displayId) {
            @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
        if (displayId == DEFAULT_DISPLAY
        if (displayId == DEFAULT_DISPLAY) {
                && (!mVisibleBackgroundUsersEnabled || !isProfile(userId, profileGroupId))) {
            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
                // 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.
                // 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
                // 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
                // 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
                // DEFAULT_DISPLAY (this is done indirectly below when it checks that the profile
            // is the current user, as the current user is always assigned to the DEFAULT_DISPLAY).
                // parent is the current user, as the current user is always assigned to the
                // DEFAULT_DISPLAY).
                if (DBG) {
                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;
                return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
            }
            }
        }


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


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


        if (!mVisibleBackgroundUsersEnabled) {
        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
            // isUserVisible()) already know that the current user (and their profiles) is
            // assigned to the default display.
            // assigned to the default display.
            return;
            return;
@@ -536,11 +574,10 @@ public final class UserVisibilityMediator implements Dumpable {
            return true;
            return true;
        }
        }


        // Device doesn't support multiple users on multiple displays, so only users checked above
        // can be visible
        if (!mVisibleBackgroundUsersEnabled) {
        if (!mVisibleBackgroundUsersEnabled) {
            if (DBG) {
            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;
            return false;
        }
        }
@@ -559,15 +596,29 @@ public final class UserVisibilityMediator implements Dumpable {
     * See {@link UserManagerInternal#isUserVisible(int, int)}.
     * See {@link UserManagerInternal#isUserVisible(int, int)}.
     */
     */
    public boolean isUserVisible(@UserIdInt int userId, int displayId) {
    public boolean isUserVisible(@UserIdInt int userId, int displayId) {
        if (displayId == Display.INVALID_DISPLAY) {
        if (displayId == INVALID_DISPLAY) {
            return false;
            return false;
        }
        }


        if (!mVisibleBackgroundUsersEnabled || displayId == Display.DEFAULT_DISPLAY) {
        // Current user is always visible on:
            // TODO(b/245939659): will need to move the displayId == Display.DEFAULT_DISPLAY outside
        // - Default display
            // once it supports background users on DEFAULT_DISPLAY (for example, passengers in a
        // - Secondary displays when device doesn't support visible bg users
            // no-driver configuration)
        //   - Or when explicitly added (which is checked below)
            return isCurrentUserOrRunningProfileOfCurrentUser(userId);
        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) {
        synchronized (mLock) {
@@ -575,7 +626,8 @@ public final class UserVisibilityMediator implements Dumpable {
                // User assigned to display on start
                // User assigned to display on start
                return true;
                return true;
            }
            }
            // Check for extra assignment

            // Check for extra display assignment
            return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
            return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
        }
        }
    }
    }
@@ -585,15 +637,31 @@ public final class UserVisibilityMediator implements Dumpable {
     */
     */
    public int getDisplayAssignedToUser(@UserIdInt int userId) {
    public int getDisplayAssignedToUser(@UserIdInt int userId) {
        if (isCurrentUserOrRunningProfileOfCurrentUser(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) {
        if (!mVisibleBackgroundUsersEnabled) {
            return Display.INVALID_DISPLAY;
            return INVALID_DISPLAY;
        }
        }


        synchronized (mLock) {
        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);
        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
     * 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}).
     * 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,
    private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
            boolean returnCurrentUserByDefault) {
            boolean returnCurrentUserByDefault) {
        if (returnCurrentUserByDefault
        if (returnCurrentUserByDefault
                && (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
                && ((displayId == DEFAULT_DISPLAY && !mVisibleBackgroundUserOnDefaultDisplayAllowed
                || !mVisibleBackgroundUsersEnabled))) {
            return getCurrentUserId();
            return getCurrentUserId();
        }
        }


@@ -763,8 +839,10 @@ 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);


            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",
            dumpSparseIntArray(ipw, mExtraDisplaysAssignedToUsers, "extra display / user",
                    "d", "u");
                    "d", "u");


@@ -872,4 +950,10 @@ public final class UserVisibilityMediator implements Dumpable {
            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
            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 Original line 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()) {
        if (mDumpables.isEmpty()) {
            return;
            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));
        mDumpables.forEach(d -> logDumpable(d));
    }
    }


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

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


import org.junit.Test;

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


    public UserVisibilityMediatorMUMDTest() throws Exception {
    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 Original line 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 Original line Diff line number Diff line
@@ -37,7 +37,15 @@ import org.junit.Test;
public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediatorTestCase {
public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediatorTestCase {


    public UserVisibilityMediatorSUSDTest() {
    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
    @Test
@@ -100,6 +108,11 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
        listener.verify();
        listener.verify();
    }
    }


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

    @Test
    @Test
    public void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
    public void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
            throws Exception {
            throws Exception {
Loading