Merge "UserVisibilityMediator: allow visible bg users on default display."

This commit is contained in:
Felipe Leme
2023-01-18 03:51:44 +00:00
committed by Android (Google) Code Review
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