Fixed UserVisibilityMediator so user can start visible on same display again.
Test: atest UserVisibilityMediatorMUPANDTest UserVisibilityMediatorMUMDTest
Fixes: 267788387
Change-Id: I3cc1ad1513ef818ed2ddb50da386c2b6a4481a0c
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index d5cc7ca..3f7502b 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -330,6 +330,12 @@
? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
: USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
+ } else if (mUsersAssignedToDisplayOnStart != null
+ && isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
+ if (DBG) {
+ Slogf.d(TAG, "full user %d is already visible on display %d", userId, displayId);
+ }
+ return USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
}
return foreground || displayId != DEFAULT_DISPLAY
@@ -403,7 +409,15 @@
return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
}
- // Check if display is available
+ if (mUsersAssignedToDisplayOnStart == null) {
+ // Should never have reached this point
+ Slogf.wtf(TAG, "canAssignUserToDisplayLocked(%d, %d, %d, %d) is trying to check "
+ + "mUsersAssignedToDisplayOnStart when it's not set",
+ userId, profileGroupId, userStartMode, displayId);
+ return SECONDARY_DISPLAY_MAPPING_FAILED;
+ }
+
+ // Check if display is available and user is not assigned to any display
for (int i = 0; i < mUsersAssignedToDisplayOnStart.size(); i++) {
int assignedUserId = mUsersAssignedToDisplayOnStart.keyAt(i);
int assignedDisplayId = mUsersAssignedToDisplayOnStart.valueAt(i);
@@ -601,6 +615,23 @@
return visible;
}
+ @GuardedBy("mLock")
+ private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId, int displayId) {
+ if (mUsersAssignedToDisplayOnStart == null) {
+ // Shouldn't have been called in this case
+ Slogf.wtf(TAG, "isUserAssignedToDisplayOnStartLocked(%d, %d): called when "
+ + "mUsersAssignedToDisplayOnStart is null", userId, displayId);
+ return false;
+ }
+ boolean isIt = displayId != INVALID_DISPLAY
+ && mUsersAssignedToDisplayOnStart.get(userId, INVALID_DISPLAY) == displayId;
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d, %d): %b", userId, displayId,
+ isIt);
+ }
+ return isIt;
+ }
+
/**
* See {@link UserManagerInternal#isUserVisible(int, int)}.
*/
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 49c6a88..af85ef4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -20,6 +20,7 @@
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_ALREADY_VISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
@@ -234,6 +235,38 @@
}
@Test
+ public final void testStartVisibleBgUser_onSecondaryDisplay_displayAlreadyAssignedToSameUser()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(USER_ID));
+ startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
+ expectUserIsVisible(USER_ID);
+ expectUserIsVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserIsNotVisibleOnDisplay(USER_ID, INVALID_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(USER_ID, DEFAULT_DISPLAY);
+ expectVisibleUsers(INITIAL_CURRENT_USER_ID, USER_ID);
+ expectDisplayAssignedToUser(USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
+ SECONDARY_DISPLAY_ID);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE);
+
+ // Run same assertions above
+ expectUserIsVisible(USER_ID);
+ expectUserIsVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserIsNotVisibleOnDisplay(USER_ID, INVALID_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(USER_ID, DEFAULT_DISPLAY);
+ expectVisibleUsers(INITIAL_CURRENT_USER_ID, USER_ID);
+ expectDisplayAssignedToUser(USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
public final void testStartVisibleBgUser_onSecondaryDisplay_userAlreadyAssigned()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(USER_ID));