Merge "UserVisibilityMediator: allow visible bg users on default display."
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 66d390f..1f935f90 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -36,6 +36,7 @@
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 @@
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 @@
* 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 @@
private final Object mLock = new Object();
private final boolean mVisibleBackgroundUsersEnabled;
+ private final boolean mVisibleBackgroundUserOnDefaultDisplayAllowed;
@UserIdInt
@GuardedBy("mLock")
@@ -110,7 +113,7 @@
/**
* 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 @@
* {@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 @@
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 @@
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 @@
+ "(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 @@
}
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;
}
- return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
+ 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;
+ }
}
if (userId == UserHandle.USER_SYSTEM) {
@@ -421,13 +457,14 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
// 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 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);
}
}
@@ -605,13 +673,21 @@
}
/**
+ * 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}).
*/
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 @@
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 @@
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);
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
index 33275bd..a0687f6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
@@ -62,14 +62,21 @@
};
}
- 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)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
index 579621c..36c9f2e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
@@ -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 @@
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();
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
new file mode 100644
index 0000000..01ce696
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -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();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
index b9ba780..c195064 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
@@ -37,7 +37,15 @@
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
@@ -101,6 +109,11 @@
}
@Test
+ public void testStartBgUser_onDefaultDisplay_visible() throws Exception {
+ visibleBgUserCannotBeStartedOnDefaultDisplayTest();
+ }
+
+ @Test
public void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index c59834b..5176d68 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -79,6 +79,11 @@
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}.
*
* <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
@@ -110,11 +115,14 @@
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 @@
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 @@
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 @@
expectNoDisplayAssignedToUser(USER_ID);
listener.verify();
+
+ return USER_ID;
}
@Test
@@ -504,7 +509,14 @@
}
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);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index 627553b..49c6a88 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -38,9 +38,9 @@
abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
extends UserVisibilityMediatorTestCase {
- UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled)
- throws Exception {
- super(backgroundUsersOnDisplaysEnabled);
+ UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled,
+ boolean backgroundUserOnDefaultDisplayAllowed) throws Exception {
+ super(backgroundUsersOnDisplaysEnabled, backgroundUserOnDefaultDisplayAllowed);
}
@Test