Merge "UserVisibilityMediator: allow visible bg users on default display."
This commit is contained in:
@@ -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,26 +324,47 @@ public final class UserVisibilityMediator implements Dumpable {
|
||||
}
|
||||
|
||||
return foreground || displayId != DEFAULT_DISPLAY
|
||||
? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
|
||||
: USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
|
||||
|| (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayAllowed)
|
||||
? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
|
||||
: USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@SecondaryDisplayMappingStatus
|
||||
private int canAssignUserToDisplayLocked(@UserIdInt int userId,
|
||||
@UserIdInt int profileGroupId, int displayId) {
|
||||
if (displayId == DEFAULT_DISPLAY
|
||||
&& (!mVisibleBackgroundUsersEnabled || !isProfile(userId, profileGroupId))) {
|
||||
// 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).
|
||||
if (DBG) {
|
||||
Slogf.d(TAG, "ignoring mapping for default display");
|
||||
@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).
|
||||
if (DBG) {
|
||||
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) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -78,6 +78,11 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
*/
|
||||
protected static final int OTHER_USER_ID = 666;
|
||||
|
||||
/**
|
||||
* Id for yeat another simple user.
|
||||
*/
|
||||
protected static final int YET_ANOTHER_USER_ID = 700;
|
||||
|
||||
/**
|
||||
* Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
|
||||
*
|
||||
@@ -110,11 +115,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
protected AsyncUserVisibilityListener.Factory mListenerFactory;
|
||||
|
||||
private final boolean mBackgroundUsersOnDisplaysEnabled;
|
||||
private final boolean mBackgroundUserOnDefaultDisplayAllowed;
|
||||
|
||||
protected UserVisibilityMediator mMediator;
|
||||
|
||||
protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled) {
|
||||
protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled,
|
||||
boolean backgroundUserOnDefaultDisplayAllowed) {
|
||||
mBackgroundUsersOnDisplaysEnabled = backgroundUsersOnDisplaysEnabled;
|
||||
mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed;
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -123,7 +131,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
Thread thread = mHandler.getLooper().getThread();
|
||||
Log.i(TAG, "setFixtures(): using thread " + thread + " (from handler " + mHandler + ")");
|
||||
mListenerFactory = new AsyncUserVisibilityListener.Factory(mExpect, thread);
|
||||
mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled, mHandler);
|
||||
mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled,
|
||||
mBackgroundUserOnDefaultDisplayAllowed, mHandler);
|
||||
mDumpableDumperRule.addDumpable(mMediator);
|
||||
}
|
||||
|
||||
@@ -170,14 +179,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
listener.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
|
||||
visibleBgUserCannotBeStartedOnDefaultDisplayTest();
|
||||
|
||||
assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
|
||||
}
|
||||
|
||||
protected final void visibleBgUserCannotBeStartedOnDefaultDisplayTest() throws Exception {
|
||||
protected final @UserIdInt int visibleBgUserCannotBeStartedOnDefaultDisplayTest()
|
||||
throws Exception {
|
||||
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
||||
|
||||
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
|
||||
@@ -188,6 +191,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
expectNoDisplayAssignedToUser(USER_ID);
|
||||
|
||||
listener.verify();
|
||||
|
||||
return USER_ID;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -504,7 +509,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
|
||||
}
|
||||
|
||||
protected void assertStartUserResult(int actualResult, int expectedResult) {
|
||||
assertWithMessage("startUser() result (where %s=%s and %s=%s)",
|
||||
assertStartUserResult(actualResult, expectedResult, "");
|
||||
}
|
||||
|
||||
@SuppressWarnings("AnnotateFormatMethod")
|
||||
protected void assertStartUserResult(int actualResult, int expectedResult,
|
||||
String extraMessageFormat, Object... extraMessageArguments) {
|
||||
String extraMessage = String.format(extraMessageFormat, extraMessageArguments);
|
||||
assertWithMessage("startUser() result %s(where %s=%s and %s=%s)", extraMessage,
|
||||
expectedResult, userAssignmentResultToString(expectedResult),
|
||||
actualResult, userAssignmentResultToString(actualResult))
|
||||
.that(actualResult).isEqualTo(expectedResult);
|
||||
|
||||
@@ -38,9 +38,9 @@ import org.junit.Test;
|
||||
abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
|
||||
extends UserVisibilityMediatorTestCase {
|
||||
|
||||
UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled)
|
||||
throws Exception {
|
||||
super(backgroundUsersOnDisplaysEnabled);
|
||||
UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled,
|
||||
boolean backgroundUserOnDefaultDisplayAllowed) throws Exception {
|
||||
super(backgroundUsersOnDisplaysEnabled, backgroundUserOnDefaultDisplayAllowed);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user