From a0cbc982a9cb1d7c2fce8dd84a8eb45fbbfae5ea Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Fri, 3 Feb 2023 12:42:34 -0800 Subject: [PATCH] Fixed UserVisibilityMediator so user can start visible on same display again. Test: atest UserVisibilityMediatorMUPANDTest UserVisibilityMediatorMUMDTest Fixes: 267788387 Change-Id: I3cc1ad1513ef818ed2ddb50da386c2b6a4481a0c --- .../server/pm/UserVisibilityMediator.java | 33 ++++++++++++++++++- ...MediatorVisibleBackgroundUserTestCase.java | 33 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java index d5cc7caffa902..3f7502bfa613a 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 @@ public final class UserVisibilityMediator implements Dumpable { ? 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 @@ public final class UserVisibilityMediator implements Dumpable { 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 @@ public final class UserVisibilityMediator implements Dumpable { 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 49c6a8854c49a..af85ef4b6b878 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.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_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; @@ -233,6 +234,38 @@ abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase listener.verify(); } + @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 {