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
This commit is contained in:
Felipe Leme
2022-12-22 07:20:02 +00:00
parent 843cd7b139
commit 2c4a5939e7
7 changed files with 320 additions and 60 deletions

View File

@@ -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);
}
}

View File

@@ -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)) {

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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