From e6aa1016beabdf5fc2bf8aa93fb7028fc939b263 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Fri, 28 Oct 2022 15:01:07 -0700 Subject: [PATCH] UserVisibilityMediator refactoring, step 3. This CL improves startUser() so it does all checks before setting the state (atomically). It also "fixes" 2 issues in that method: - Return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE when the profile is started but its parent is not visible (this could happen when the profile is started in the background for maintenance purposes, like garage mode). - Don't throw RuntimeExceptions in case of error (but rather USER_ASSIGNMENT_RESULT_FAILURE). This is the last refactoring per se - further changes will either modify the behavior of the class (for example, to allow background users starting in the main display) or improve the test cases (for example, to make sure subclasses of UserVisibilityMediatorTestCase test all use case scenarios). Test: atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest UserVisibilityMediatorMUMDTest UserVisibilityMediatorSUSDTest UserControllerTest Test: atest CtsMultiUserTestCases:android.multiuser.cts.MultipleUsersOnMultipleDisplaysTest Test: adb shell dumpsys user --visibility-mediator Bug: 244644281 Change-Id: Ia09b58607f93c4dd02a7a646da9359af58e3d0e7 --- core/java/android/app/ActivityManager.java | 2 - .../server/pm/UserManagerInternal.java | 2 +- .../android/server/pm/UserManagerService.java | 3 +- .../server/pm/UserVisibilityMediator.java | 342 ++++++++++-------- .../pm/UserVisibilityMediatorMUMDTest.java | 171 ++++----- .../pm/UserVisibilityMediatorSUSDTest.java | 33 -- .../pm/UserVisibilityMediatorTestCase.java | 182 ++++------ 7 files changed, 340 insertions(+), 395 deletions(-) diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index d6c10ae264066..4ee2a067a75f2 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -4398,8 +4398,6 @@ public class ActivityManager { * * @throws UnsupportedOperationException if the device does not support background users on * secondary displays. - * @throws IllegalArgumentException if the display doesn't exist or is not a valid display to - * start secondary users on. * * @hide */ diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 9dafcceefdd00..fa8a29199465b 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -51,7 +51,7 @@ public abstract class UserManagerInternal { public static final int USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE = 2; public static final int USER_ASSIGNMENT_RESULT_FAILURE = -1; - private static final String PREFIX_USER_ASSIGNMENT_RESULT = "USER_ASSIGNMENT_RESULT"; + private static final String PREFIX_USER_ASSIGNMENT_RESULT = "USER_ASSIGNMENT_RESULT_"; @IntDef(flag = false, prefix = {PREFIX_USER_ASSIGNMENT_RESULT}, value = { USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE, diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 44b5ba242f915..e5b1ee54c1952 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1644,8 +1644,7 @@ public class UserManagerService extends IUserManager.Stub { return isProfileUnchecked(userId); } - // TODO(b/244644281): make it private once UserVisibilityMediator don't use it anymore - boolean isProfileUnchecked(@UserIdInt int userId) { + private boolean isProfileUnchecked(@UserIdInt int userId) { synchronized (mUsersLock) { UserInfo userInfo = getUserInfoLU(userId); return userInfo != null && userInfo.isProfile(); diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java index cbf7dfe77ca6f..2cc7fca45426f 100644 --- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java +++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java @@ -25,6 +25,7 @@ import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_S import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE; import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.UserHandle; @@ -36,26 +37,50 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.server.pm.UserManagerInternal.UserAssignmentResult; import com.android.server.utils.Slogf; import java.io.PrintWriter; -import java.util.LinkedHashMap; -import java.util.Map; /** * Class responsible for deciding whether a user is visible (or visible for a given display). * + *

Currently, it has 2 "modes" (set on constructor), which defines the class behavior (i.e, the + * logic that dictates the result of methods such as {@link #isUserVisible(int)} and + * {@link #isUserVisible(int, int)}): + * + *

+ * *

This class is thread safe. */ -// TODO(b/244644281): improve javadoc (for example, explain all cases / modes) public final class UserVisibilityMediator implements Dumpable { private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE private static final String TAG = UserVisibilityMediator.class.getSimpleName(); + 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; + + /** + * Whether a user / display assignment requires adding an entry to the + * {@code mUsersOnSecondaryDisplays} map. + */ + @IntDef(flag = false, prefix = {"SECONDARY_DISPLAY_MAPPING_"}, value = { + SECONDARY_DISPLAY_MAPPING_NEEDED, + SECONDARY_DISPLAY_MAPPING_NOT_NEEDED, + SECONDARY_DISPLAY_MAPPING_FAILED + }) + public @interface SecondaryDisplayMappingStatus {} + // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices @VisibleForTesting static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM; @@ -68,9 +93,14 @@ public final class UserVisibilityMediator implements Dumpable { @GuardedBy("mLock") private int mCurrentUserId = INITIAL_CURRENT_USER_ID; + /** + * Map of background users started on secondary displays. + * + *

Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}. + */ @Nullable @GuardedBy("mLock") - private final SparseIntArray mUsersOnSecondaryDisplays = new SparseIntArray(); + private final SparseIntArray mUsersOnSecondaryDisplays; /** * Mapping from each started user to its profile group. @@ -85,171 +115,199 @@ public final class UserVisibilityMediator implements Dumpable { @VisibleForTesting UserVisibilityMediator(boolean usersOnSecondaryDisplaysEnabled) { mUsersOnSecondaryDisplaysEnabled = usersOnSecondaryDisplaysEnabled; + mUsersOnSecondaryDisplays = mUsersOnSecondaryDisplaysEnabled ? new SparseIntArray() : null; } /** * See {@link UserManagerInternal#assignUserToDisplayOnStart(int, int, boolean, int)}. */ - public @UserAssignmentResult int startUser(@UserIdInt int userId, @UserIdInt int profileGroupId, - boolean foreground, int displayId) { - // TODO(b/244644281): this method need to perform 4 actions: + public @UserAssignmentResult int startUser(@UserIdInt int userId, + @UserIdInt int unResolvedProfileGroupId, boolean foreground, int displayId) { + // This method needs to perform 4 actions: // // 1. Check if the user can be started given the provided arguments // 2. If it can, decide whether it's visible or not (which is the return value) // 3. Update the current user / profiles state // 4. Update the users on secondary display state (if applicable) // - // Ideally, they should be done "atomically" (i.e, only changing state while holding the - // mLock), but the initial implementation is just calling the existing methods, as the - // focus is to change the UserController startUser() workflow (so it relies on this class - // for the logic above). - // - // The next CL will refactor it (and the unit tests) to achieve that atomicity. - int result = startOnly(userId, profileGroupId, foreground, displayId); - if (result != USER_ASSIGNMENT_RESULT_FAILURE) { - assignUserToDisplay(userId, profileGroupId, displayId); + // Notice that steps 3 and 4 should be done atomically (i.e., while holding mLock), so the + // previous steps are delegated to other methods (canAssignUserToDisplayLocked() and + // getUserVisibilityOnStartLocked() respectively). + + + int profileGroupId = unResolvedProfileGroupId == NO_PROFILE_GROUP_ID + ? userId + : unResolvedProfileGroupId; + if (DBG) { + Slogf.d(TAG, "startUser(%d, %d, %b, %d): actualProfileGroupId=%d", + userId, unResolvedProfileGroupId, foreground, displayId, profileGroupId); } + + int result; + synchronized (mLock) { + result = getUserVisibilityOnStartLocked(userId, profileGroupId, foreground, displayId); + if (DBG) { + Slogf.d(TAG, "result of getUserVisibilityOnStartLocked(%s)", + userAssignmentResultToString(result)); + } + if (result == USER_ASSIGNMENT_RESULT_FAILURE) { + return result; + } + + int mappingResult = canAssignUserToDisplayLocked(userId, profileGroupId, displayId); + if (mappingResult == SECONDARY_DISPLAY_MAPPING_FAILED) { + return USER_ASSIGNMENT_RESULT_FAILURE; + } + + // Set current user / profiles state + if (foreground) { + mCurrentUserId = userId; + } + if (DBG) { + Slogf.d(TAG, "adding user / profile mapping (%d -> %d)", userId, profileGroupId); + } + mStartedProfileGroupIds.put(userId, profileGroupId); + + // Set user / display state + switch (mappingResult) { + case SECONDARY_DISPLAY_MAPPING_NEEDED: + if (DBG) { + Slogf.d(TAG, "adding user / display mapping (%d -> %d)", userId, displayId); + } + mUsersOnSecondaryDisplays.put(userId, displayId); + break; + case SECONDARY_DISPLAY_MAPPING_NOT_NEEDED: + if (DBG) { + // Don't need to do set state because methods (such as isUserVisible()) + // already know that the current user (and their profiles) is assigned to + // the default display. + Slogf.d(TAG, "Don't need to update mUsersOnSecondaryDisplays"); + } + break; + default: + Slogf.wtf(TAG, "Invalid resut from canAssignUserToDisplayLocked: %d", + mappingResult); + } + } + + if (DBG) { + Slogf.d(TAG, "returning %s", userAssignmentResultToString(result)); + } + return result; } - /** - * @deprecated - see comment inside {@link #startUser(int, int, boolean, int)} - */ - @Deprecated - @VisibleForTesting - @UserAssignmentResult int startOnly(@UserIdInt int userId, + @GuardedBy("mLock") + @UserAssignmentResult + private int getUserVisibilityOnStartLocked(@UserIdInt int userId, @UserIdInt int profileGroupId, boolean foreground, int displayId) { - int actualProfileGroupId = profileGroupId == NO_PROFILE_GROUP_ID - ? userId - : profileGroupId; - if (DBG) { - Slogf.d(TAG, "startUser(%d, %d, %b, %d): actualProfileGroupId=%d", - userId, profileGroupId, foreground, displayId, actualProfileGroupId); - } - if (foreground && displayId != DEFAULT_DISPLAY) { - Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start foreground user on " - + "secondary display", userId, actualProfileGroupId, foreground, displayId); - return USER_ASSIGNMENT_RESULT_FAILURE; + if (displayId != DEFAULT_DISPLAY) { + if (foreground) { + Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start " + + "foreground user on secondary display", userId, profileGroupId, + foreground, displayId); + return USER_ASSIGNMENT_RESULT_FAILURE; + } + if (!mUsersOnSecondaryDisplaysEnabled) { + Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on " + + "device that doesn't support multiple users on multiple displays", + userId, profileGroupId, foreground, displayId); + return USER_ASSIGNMENT_RESULT_FAILURE; + } } - int visibility; - synchronized (mLock) { - if (isProfile(userId, actualProfileGroupId)) { - if (displayId != DEFAULT_DISPLAY) { - Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user on " - + "secondary display", userId, actualProfileGroupId, foreground, - displayId); - return USER_ASSIGNMENT_RESULT_FAILURE; - } - if (foreground) { - Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in " - + "foreground", userId, actualProfileGroupId, foreground, displayId); - return USER_ASSIGNMENT_RESULT_FAILURE; - } else { - boolean isParentRunning = mStartedProfileGroupIds - .get(actualProfileGroupId) == actualProfileGroupId; - if (DBG) { - Slogf.d(TAG, "profile parent running: %b", isParentRunning); - } - visibility = isParentRunning - ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE - : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE; - } - } else if (foreground) { - mCurrentUserId = userId; - visibility = USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE; + if (isProfile(userId, profileGroupId)) { + if (displayId != DEFAULT_DISPLAY) { + Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user " + + "on secondary display", userId, profileGroupId, foreground, + displayId); + return USER_ASSIGNMENT_RESULT_FAILURE; + } + if (foreground) { + Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in " + + "foreground", userId, profileGroupId, foreground, displayId); + return USER_ASSIGNMENT_RESULT_FAILURE; } else { - visibility = USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE; + boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId); + if (DBG) { + Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay); + } + return isParentVisibleOnDisplay + ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE + : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE; } - if (DBG) { - Slogf.d(TAG, "adding user / profile mapping (%d -> %d) and returning %s", - userId, actualProfileGroupId, userAssignmentResultToString(visibility)); - } - mStartedProfileGroupIds.put(userId, actualProfileGroupId); } - return visibility; + + return foreground || displayId != DEFAULT_DISPLAY + ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE + : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE; } - /** - * @deprecated - see comment inside {@link #startUser(int, int, boolean, int)} - */ - @Deprecated - @VisibleForTesting - void assignUserToDisplay(int userId, int profileGroupId, int displayId) { - if (DBG) { - Slogf.d(TAG, "assignUserToDisplay(%d, %d): mUsersOnSecondaryDisplaysEnabled=%b", - userId, displayId, mUsersOnSecondaryDisplaysEnabled); - } - + @GuardedBy("mLock") + @SecondaryDisplayMappingStatus + private int canAssignUserToDisplayLocked(@UserIdInt int userId, + @UserIdInt int profileGroupId, int displayId) { if (displayId == DEFAULT_DISPLAY && (!mUsersOnSecondaryDisplaysEnabled || !isProfile(userId, profileGroupId))) { // Don't need to do anything because methods (such as isUserVisible()) already - // know that the current user (and their profiles) is assigned to the default display. - // But on MUMD devices, it profiles are only supported in the default display, so it + // 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 on default display"); + Slogf.d(TAG, "ignoring mapping for default display"); } - return; + return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED; } - if (!mUsersOnSecondaryDisplaysEnabled) { - throw new UnsupportedOperationException("assignUserToDisplay(" + userId + ", " - + displayId + ") called on device that doesn't support multiple " - + "users on multiple displays"); + if (userId == UserHandle.USER_SYSTEM) { + Slogf.w(TAG, "Cannot assign system user to secondary display (%d)", displayId); + return SECONDARY_DISPLAY_MAPPING_FAILED; + } + if (displayId == Display.INVALID_DISPLAY) { + Slogf.w(TAG, "Cannot assign to INVALID_DISPLAY (%d)", displayId); + return SECONDARY_DISPLAY_MAPPING_FAILED; + } + if (userId == mCurrentUserId) { + Slogf.w(TAG, "Cannot assign current user (%d) to other displays", userId); + return SECONDARY_DISPLAY_MAPPING_FAILED; } - - Preconditions.checkArgument(userId != UserHandle.USER_SYSTEM, "Cannot assign system " - + "user to secondary display (%d)", displayId); - Preconditions.checkArgument(displayId != Display.INVALID_DISPLAY, - "Cannot assign to INVALID_DISPLAY (%d)", displayId); - - int currentUserId = getCurrentUserId(); - Preconditions.checkArgument(userId != currentUserId, - "Cannot assign current user (%d) to other displays", currentUserId); if (isProfile(userId, profileGroupId)) { // Profile can only start in the same display as parent. And for simplicity, // that display must be the DEFAULT_DISPLAY. - Preconditions.checkArgument(displayId == Display.DEFAULT_DISPLAY, - "Profile user can only be started in the default display"); - int parentUserId = getStartedProfileGroupId(userId); - Preconditions.checkArgument(parentUserId == currentUserId, - "Only profile of current user can be assigned to a display"); - if (DBG) { - Slogf.d(TAG, "Ignoring profile user %d on default display", userId); + if (displayId != Display.DEFAULT_DISPLAY) { + Slogf.w(TAG, "Profile user can only be started in the default display"); + return SECONDARY_DISPLAY_MAPPING_FAILED; + } - return; + if (DBG) { + Slogf.d(TAG, "Don't need to map profile user %d to default display", userId); + } + return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED; } - synchronized (mLock) { - // Check if display is available - for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) { - int assignedUserId = mUsersOnSecondaryDisplays.keyAt(i); - int assignedDisplayId = mUsersOnSecondaryDisplays.valueAt(i); - if (DBG) { - Slogf.d(TAG, "%d: assignedUserId=%d, assignedDisplayId=%d", - i, assignedUserId, assignedDisplayId); - } - if (displayId == assignedDisplayId) { - throw new IllegalStateException("Cannot assign user " + userId + " to " - + "display " + displayId + " because such display is already " - + "assigned to user " + assignedUserId); - } - if (userId == assignedUserId) { - throw new IllegalStateException("Cannot assign user " + userId + " to " - + "display " + displayId + " because such user is as already " - + "assigned to display " + assignedDisplayId); - } - } - + // Check if display is available + for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) { + int assignedUserId = mUsersOnSecondaryDisplays.keyAt(i); + int assignedDisplayId = mUsersOnSecondaryDisplays.valueAt(i); if (DBG) { - Slogf.d(TAG, "Adding full user %d -> display %d", userId, displayId); + Slogf.d(TAG, "%d: assignedUserId=%d, assignedDisplayId=%d", + i, assignedUserId, assignedDisplayId); + } + if (displayId == assignedDisplayId) { + Slogf.w(TAG, "Cannot assign user %d to display %d because such display is already " + + "assigned to user %d", userId, displayId, assignedUserId); + return SECONDARY_DISPLAY_MAPPING_FAILED; + } + if (userId == assignedUserId) { + Slogf.w(TAG, "Cannot assign user %d to display %d because such user is as already " + + "assigned to display %d", userId, displayId, assignedUserId); + return SECONDARY_DISPLAY_MAPPING_FAILED; } - mUsersOnSecondaryDisplays.put(userId, displayId); } + return SECONDARY_DISPLAY_MAPPING_NEEDED; } /** @@ -311,12 +369,12 @@ public final class UserVisibilityMediator implements Dumpable { return isCurrentUserOrRunningProfileOfCurrentUser(userId); } - // TODO(b/244644281): temporary workaround to let WM use this API without breaking current + // TODO(b/256242848): temporary workaround to let WM use this API without breaking current // behavior - return true for current user / profile for any display (other than those // explicitly assigned to another users), otherwise they wouldn't be able to launch - // activities on other non-passenger displays, like cluster, display, or virtual displays). + // activities on other non-passenger displays, like cluster). // In the long-term, it should rely just on mUsersOnSecondaryDisplays, which - // would be updated by DisplayManagerService when displays are created / initialized. + // would be updated by CarService to allow additional mappings. if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) { synchronized (mLock) { boolean assignedToUser = false; @@ -410,7 +468,7 @@ public final class UserVisibilityMediator implements Dumpable { ipw.print("Supports background users on secondary displays: "); ipw.println(mUsersOnSecondaryDisplaysEnabled); - if (mUsersOnSecondaryDisplaysEnabled) { + if (mUsersOnSecondaryDisplays != null) { dumpIntArray(ipw, mUsersOnSecondaryDisplays, "background user / secondary display", "u", "d"); } @@ -448,23 +506,13 @@ public final class UserVisibilityMediator implements Dumpable { dump(new IndentingPrintWriter(pw)); } - @VisibleForTesting - Map getUsersOnSecondaryDisplays() { - Map map; - synchronized (mLock) { - int size = mUsersOnSecondaryDisplays.size(); - map = new LinkedHashMap<>(size); - for (int i = 0; i < size; i++) { - map.put(mUsersOnSecondaryDisplays.keyAt(i), mUsersOnSecondaryDisplays.valueAt(i)); - } - } - Slogf.v(TAG, "getUsersOnSecondaryDisplays(): returning %s", map); - return map; + private static boolean isProfile(@UserIdInt int userId, @UserIdInt int profileGroupId) { + return profileGroupId != NO_PROFILE_GROUP_ID && profileGroupId != userId; } - // TODO(b/244644281): methods below are needed because some APIs use the current users (full and - // profiles) state to decide whether a user is visible or not. If we decide to always store that - // info into intermediate maps, we should remove them. + // NOTE: methods below are needed because some APIs use the current users (full and profiles) + // state to decide whether a user is visible or not. If we decide to always store that info into + // mUsersOnSecondaryDisplays, we should remove them. @VisibleForTesting @UserIdInt int getCurrentUserId() { @@ -487,10 +535,6 @@ public final class UserVisibilityMediator implements Dumpable { } } - private static boolean isProfile(@UserIdInt int userId, @UserIdInt int profileGroupId) { - return profileGroupId != NO_PROFILE_GROUP_ID && profileGroupId != userId; - } - @VisibleForTesting boolean isStartedUser(@UserIdInt int userId) { synchronized (mLock) { 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 9be370fe3045c..6b340205ceda3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java @@ -19,12 +19,12 @@ import static android.os.UserHandle.USER_SYSTEM; 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_INVISIBLE; +import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE; + import static com.google.common.truth.Truth.assertWithMessage; -import static org.junit.Assert.assertThrows; - -import android.util.Log; - import org.junit.Test; /** @@ -36,130 +36,94 @@ import org.junit.Test; */ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediatorTestCase { - private static final String TAG = UserVisibilityMediatorMUMDTest.class.getSimpleName(); - public UserVisibilityMediatorMUMDTest() { super(/* usersOnSecondaryDisplaysEnabled= */ true); } @Test - public void testAssignUserToDisplay_systemUser() { - assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(USER_SYSTEM, USER_SYSTEM, SECONDARY_DISPLAY_ID)); + public void testStartUser_systemUser() { + int result = mMediator.startUser(USER_SYSTEM, USER_SYSTEM, FG, SECONDARY_DISPLAY_ID); + + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); } @Test - public void testAssignUserToDisplay_invalidDisplay() { - assertThrows(IllegalArgumentException.class, - () -> mMediator.assignUserToDisplay(USER_ID, USER_ID, INVALID_DISPLAY)); + public void testStartUser_invalidDisplay() { + int result = mMediator.startUser(USER_ID, USER_ID, FG, INVALID_DISPLAY); + + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); } @Test - public void testAssignUserToDisplay_currentUser() { - mockCurrentUser(USER_ID); + public void testStartUser_displayAvailable() { + int result = mMediator.startUser(USER_ID, USER_ID, BG, SECONDARY_DISPLAY_ID); - assertThrows(IllegalArgumentException.class, - () -> mMediator.assignUserToDisplay(USER_ID, USER_ID, SECONDARY_DISPLAY_ID)); + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE); - assertNoUserAssignedToDisplay(); + assertIsNotCurrentUserOrRunningProfileOfCurrentUser(USER_ID); + assertStartedProfileGroupIdOf(USER_ID, USER_ID); + + stopUserAndAssertState(USER_ID); } @Test - public void testAssignUserToDisplay_startedProfileOfCurrentUser() { - mockCurrentUser(PARENT_USER_ID); - startDefaultProfile(); + public void testStartUser_displayAlreadyAssigned() { + startUserInSecondaryDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID)); + int result = mMediator.startUser(USER_ID, USER_ID, BG, SECONDARY_DISPLAY_ID); - Log.v(TAG, "Exception: " + e); - assertNoUserAssignedToDisplay(); + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); + + stopUserAndAssertState(PROFILE_USER_ID); } @Test - public void testAssignUserToDisplay_stoppedProfileOfCurrentUser() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); + public void testStartUser_userAlreadyAssigned() { + startUserInSecondaryDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID); - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID)); + int result = mMediator.startUser(USER_ID, USER_ID, BG, SECONDARY_DISPLAY_ID); - Log.v(TAG, "Exception: " + e); - assertNoUserAssignedToDisplay(); + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); } @Test - public void testAssignUserToDisplay_displayAvailable() { - mMediator.assignUserToDisplay(USER_ID, USER_ID, SECONDARY_DISPLAY_ID); + public void testStartUser_profileOnSameDisplayAsParent() { + startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID); - assertUserAssignedToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, SECONDARY_DISPLAY_ID); + + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); + + stopUserAndAssertState(PROFILE_USER_ID); } @Test - public void testAssignUserToDisplay_displayAlreadyAssigned() { - mMediator.assignUserToDisplay(USER_ID, USER_ID, SECONDARY_DISPLAY_ID); + public void testStartUser_profileOnDifferentDisplayAsParent() { + startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID); - IllegalStateException e = assertThrows(IllegalStateException.class, () -> mMediator - .assignUserToDisplay(OTHER_USER_ID, OTHER_USER_ID, SECONDARY_DISPLAY_ID)); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, + OTHER_SECONDARY_DISPLAY_ID); - Log.v(TAG, "Exception: " + e); - assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() - .matches("Cannot.*" + OTHER_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*already.*" - + USER_ID + ".*"); + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); + + stopUserAndAssertState(PROFILE_USER_ID); } @Test - public void testAssignUserToDisplay_userAlreadyAssigned() { - mMediator.assignUserToDisplay(USER_ID, USER_ID, SECONDARY_DISPLAY_ID); + public void testStartUser_profileDefaultDisplayParentOnSecondaryDisplay() { + startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID); - IllegalStateException e = assertThrows(IllegalStateException.class, - () -> mMediator.assignUserToDisplay(USER_ID, USER_ID, OTHER_SECONDARY_DISPLAY_ID)); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); - Log.v(TAG, "Exception: " + e); - assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() - .matches("Cannot.*" + USER_ID + ".*" + OTHER_SECONDARY_DISPLAY_ID + ".*already.*" - + SECONDARY_DISPLAY_ID + ".*"); + assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE); - assertUserAssignedToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + stopUserAndAssertState(PROFILE_USER_ID); } - @Test - public void testAssignUserToDisplay_profileOnSameDisplayAsParent() { - mMediator.assignUserToDisplay(PARENT_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID); - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID)); - - Log.v(TAG, "Exception: " + e); - assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); - } - - @Test - public void testAssignUserToDisplay_profileOnDifferentDisplayAsParent() { - mMediator.assignUserToDisplay(PARENT_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID); - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID)); - - Log.v(TAG, "Exception: " + e); - assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); - } - - @Test - public void testAssignUserToDisplay_profileDefaultDisplayParentOnSecondaryDisplay() { - mMediator.assignUserToDisplay(PARENT_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID); - IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, DEFAULT_DISPLAY)); - - Log.v(TAG, "Exception: " + e); - assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); - } - - // TODO(b/244644281): when start & assign are merged, rename tests above and also call - // stopUserAndAssertState() at the end of them - @Test public void testIsUserVisible_bgUserOnSecondaryDisplay() { - mockCurrentUser(OTHER_USER_ID); - assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(OTHER_USER_ID); + startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s)", USER_ID) .that(mMediator.isUserVisible(USER_ID)).isTrue(); @@ -170,7 +134,7 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_currentUserUnassignedSecondaryDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(USER_ID, SECONDARY_DISPLAY_ID)).isTrue(); @@ -178,8 +142,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_currentUserSecondaryDisplayAssignedToAnotherUser() { - mockCurrentUser(USER_ID); - assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(USER_ID); + startUserInSecondaryDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(USER_ID, SECONDARY_DISPLAY_ID)).isFalse(); @@ -188,8 +152,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_startedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() { startDefaultProfile(); - mockCurrentUser(PARENT_USER_ID); - assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(PARENT_USER_ID); + startUserInSecondaryDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse(); @@ -197,9 +161,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_stoppedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() { - stopDefaultProfile(); - mockCurrentUser(PARENT_USER_ID); - assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(PARENT_USER_ID); + startUserInSecondaryDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse(); @@ -208,7 +171,7 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_startedProfileOfCurrentUserOnUnassignedSecondaryDisplay() { startDefaultProfile(); - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); // TODO(b/244644281): change it to isFalse() once isUserVisible() is fixed (see note there) assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID) @@ -217,8 +180,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_bgUserOnSecondaryDisplay() { - mockCurrentUser(OTHER_USER_ID); - assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(OTHER_USER_ID); + startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(USER_ID, SECONDARY_DISPLAY_ID)).isTrue(); @@ -226,8 +189,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testIsUserVisibleOnDisplay_bgUserOnAnotherSecondaryDisplay() { - mockCurrentUser(OTHER_USER_ID); - assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(OTHER_USER_ID); + startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(USER_ID, OTHER_SECONDARY_DISPLAY_ID)).isFalse(); @@ -240,8 +203,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testGetDisplayAssignedToUser_bgUserOnSecondaryDisplay() { - mockCurrentUser(OTHER_USER_ID); - assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(OTHER_USER_ID); + startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("getDisplayAssignedToUser(%s)", USER_ID) .that(mMediator.getDisplayAssignedToUser(USER_ID)) @@ -253,8 +216,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testGetUserAssignedToDisplay_bgUserOnSecondaryDisplay() { - mockCurrentUser(OTHER_USER_ID); - assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID); + startForegroundUser(OTHER_USER_ID); + startUserInSecondaryDisplay(USER_ID, SECONDARY_DISPLAY_ID); assertWithMessage("getUserAssignedToDisplay(%s)", SECONDARY_DISPLAY_ID) .that(mMediator.getUserAssignedToDisplay(SECONDARY_DISPLAY_ID)).isEqualTo(USER_ID); @@ -262,7 +225,7 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator @Test public void testGetUserAssignedToDisplay_noUserOnSecondaryDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getUserAssignedToDisplay(%s)", SECONDARY_DISPLAY_ID) .that(mMediator.getUserAssignedToDisplay(SECONDARY_DISPLAY_ID)).isEqualTo(USER_ID); 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 7abdd9e7bbafd..ef04c282b7eea 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java @@ -15,10 +15,6 @@ */ package com.android.server.pm; -import static org.junit.Assert.assertThrows; - -import org.junit.Test; - /** * Tests for {@link UserVisibilityMediator} tests for devices that DO NOT support concurrent * multiple users on multiple displays (A.K.A {@code SUSD} - Single User on Single Device). @@ -31,33 +27,4 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator public UserVisibilityMediatorSUSDTest() { super(/* usersOnSecondaryDisplaysEnabled= */ false); } - - // TODO(b/244644281): when start & assign are merged, rename tests below and also call - // stopUserAndAssertState() at the end of them - - @Test - public void testAssignUserToDisplay_otherDisplay_currentUser() { - mockCurrentUser(USER_ID); - - assertThrows(UnsupportedOperationException.class, - () -> mMediator.assignUserToDisplay(USER_ID, USER_ID, SECONDARY_DISPLAY_ID)); - } - - @Test - public void testAssignUserToDisplay_otherDisplay_startProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); - startDefaultProfile(); - - assertThrows(UnsupportedOperationException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID)); - } - - @Test - public void testAssignUserToDisplay_otherDisplay_stoppedProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - - assertThrows(UnsupportedOperationException.class, () -> mMediator - .assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID)); - } } 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 e8be97db717db..9c6cbd9e3b2ab 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java @@ -31,6 +31,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import android.annotation.UserIdInt; import android.util.Log; +import com.android.internal.util.Preconditions; import com.android.server.ExtendedMockitoTestCase; import org.junit.Before; @@ -81,8 +82,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { */ protected static final int OTHER_SECONDARY_DISPLAY_ID = 108; - private static final boolean FG = true; - private static final boolean BG = false; + protected static final boolean FG = true; + protected static final boolean BG = false; private final boolean mUsersOnSecondaryDisplaysEnabled; @@ -100,7 +101,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testStartUser_currentUser() { - int result = mMediator.startOnly(USER_ID, USER_ID, FG, DEFAULT_DISPLAY); + int result = mMediator.startUser(USER_ID, USER_ID, FG, DEFAULT_DISPLAY); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE); assertCurrentUser(USER_ID); @@ -111,8 +112,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { } @Test - public final void testStartUser_currentUserSecondaryDisplay() { - int result = mMediator.startOnly(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID); + public final void testStartUser_currentUserOnSecondaryDisplay() { + int result = mMediator.startUser(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); assertCurrentUser(INITIAL_CURRENT_USER_ID); @@ -124,9 +125,9 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testStartUser_profileBg_parentStarted() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE); assertCurrentUser(PARENT_USER_ID); @@ -139,7 +140,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testStartUser_profileBg_parentNotStarted() { - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE); assertCurrentUser(INITIAL_CURRENT_USER_ID); @@ -152,7 +153,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testStartUser_profileBg_secondaryDisplay() { - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, SECONDARY_DISPLAY_ID); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, SECONDARY_DISPLAY_ID); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); assertCurrentUser(INITIAL_CURRENT_USER_ID); @@ -163,7 +164,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testStartUser_profileFg() { - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, FG, DEFAULT_DISPLAY); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, FG, DEFAULT_DISPLAY); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); assertCurrentUser(INITIAL_CURRENT_USER_ID); @@ -173,8 +174,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { } @Test - public final void testStartUser_profileFgSecondaryDisplay() { - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, FG, SECONDARY_DISPLAY_ID); + public final void testStartUser_profileFg_secondaryDisplay() { + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, FG, SECONDARY_DISPLAY_ID); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE); assertCurrentUser(INITIAL_CURRENT_USER_ID); @@ -182,25 +183,19 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { stopUserAndAssertState(USER_ID); } + @Test public final void testGetStartedProfileGroupId_whenStartedWithNoProfileGroupId() { - int result = mMediator.startOnly(USER_ID, NO_PROFILE_GROUP_ID, FG, DEFAULT_DISPLAY); + int result = mMediator.startUser(USER_ID, NO_PROFILE_GROUP_ID, FG, DEFAULT_DISPLAY); assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE); - assertWithMessage("shit").that(mMediator.getStartedProfileGroupId(USER_ID)) - .isEqualTo(USER_ID); - } - - @Test - public final void testAssignUserToDisplay_defaultDisplayIgnored() { - mMediator.assignUserToDisplay(USER_ID, USER_ID, DEFAULT_DISPLAY); - - assertNoUserAssignedToDisplay(); + assertWithMessage("getStartedProfileGroupId(%s)", USER_ID) + .that(mMediator.getStartedProfileGroupId(USER_ID)).isEqualTo(USER_ID); } @Test public final void testIsUserVisible_invalidUser() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s)", USER_NULL) .that(mMediator.isUserVisible(USER_NULL)).isFalse(); @@ -208,7 +203,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisible_currentUser() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s)", USER_ID) .that(mMediator.isUserVisible(USER_ID)).isTrue(); @@ -216,7 +211,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisible_nonCurrentUser() { - mockCurrentUser(OTHER_USER_ID); + startForegroundUser(OTHER_USER_ID); assertWithMessage("isUserVisible(%s)", USER_ID) .that(mMediator.isUserVisible(USER_ID)).isFalse(); @@ -224,7 +219,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisible_startedProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); startDefaultProfile(); assertWithMessage("isUserVisible(%s)", PROFILE_USER_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID)).isTrue(); @@ -232,16 +227,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisible_stoppedProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - + startForegroundUser(PARENT_USER_ID); assertWithMessage("isUserVisible(%s)", PROFILE_USER_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID)).isFalse(); } @Test public final void testIsUserVisibleOnDisplay_invalidUser() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_NULL, DEFAULT_DISPLAY) .that(mMediator.isUserVisible(USER_NULL, DEFAULT_DISPLAY)).isFalse(); @@ -249,7 +242,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_currentUserInvalidDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, INVALID_DISPLAY) .that(mMediator.isUserVisible(USER_ID, INVALID_DISPLAY)).isFalse(); @@ -257,7 +250,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_currentUserDefaultDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, DEFAULT_DISPLAY) .that(mMediator.isUserVisible(USER_ID, DEFAULT_DISPLAY)).isTrue(); @@ -265,7 +258,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_currentUserSecondaryDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(USER_ID, SECONDARY_DISPLAY_ID)).isTrue(); @@ -273,7 +266,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_nonCurrentUserDefaultDisplay() { - mockCurrentUser(OTHER_USER_ID); + startForegroundUser(OTHER_USER_ID); assertWithMessage("isUserVisible(%s, %s)", USER_ID, DEFAULT_DISPLAY) .that(mMediator.isUserVisible(USER_ID, DEFAULT_DISPLAY)).isFalse(); @@ -281,7 +274,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_startedProfileOfcurrentUserInvalidDisplay() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); startDefaultProfile(); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, INVALID_DISPLAY) @@ -290,16 +283,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_stoppedProfileOfcurrentUserInvalidDisplay() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - + startForegroundUser(PARENT_USER_ID); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, INVALID_DISPLAY) .that(mMediator.isUserVisible(PROFILE_USER_ID, DEFAULT_DISPLAY)).isFalse(); } @Test public final void testIsUserVisibleOnDisplay_startedProfileOfcurrentUserDefaultDisplay() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); startDefaultProfile(); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, DEFAULT_DISPLAY) .that(mMediator.isUserVisible(PROFILE_USER_ID, DEFAULT_DISPLAY)).isTrue(); @@ -307,16 +298,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testIsUserVisibleOnDisplay_stoppedProfileOfcurrentUserDefaultDisplay() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - + startForegroundUser(PARENT_USER_ID); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, DEFAULT_DISPLAY) .that(mMediator.isUserVisible(PROFILE_USER_ID, DEFAULT_DISPLAY)).isFalse(); } @Test public final void testIsUserVisibleOnDisplay_startedProfileOfCurrentUserSecondaryDisplay() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); startDefaultProfile(); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isTrue(); @@ -324,16 +313,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public void testIsUserVisibleOnDisplay_stoppedProfileOfcurrentUserSecondaryDisplay() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - + startForegroundUser(PARENT_USER_ID); assertWithMessage("isUserVisible(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID) .that(mMediator.isUserVisible(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse(); } @Test public void testGetDisplayAssignedToUser_invalidUser() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getDisplayAssignedToUser(%s)", USER_NULL) .that(mMediator.getDisplayAssignedToUser(USER_NULL)).isEqualTo(INVALID_DISPLAY); @@ -341,7 +328,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public void testGetDisplayAssignedToUser_currentUser() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getDisplayAssignedToUser(%s)", USER_ID) .that(mMediator.getDisplayAssignedToUser(USER_ID)).isEqualTo(DEFAULT_DISPLAY); @@ -349,7 +336,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testGetDisplayAssignedToUser_nonCurrentUser() { - mockCurrentUser(OTHER_USER_ID); + startForegroundUser(OTHER_USER_ID); assertWithMessage("getDisplayAssignedToUser(%s)", USER_ID) .that(mMediator.getDisplayAssignedToUser(USER_ID)).isEqualTo(INVALID_DISPLAY); @@ -357,7 +344,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testGetDisplayAssignedToUser_startedProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); startDefaultProfile(); assertWithMessage("getDisplayAssignedToUser(%s)", PROFILE_USER_ID) .that(mMediator.getDisplayAssignedToUser(PROFILE_USER_ID)) @@ -366,9 +353,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testGetDisplayAssignedToUser_stoppedProfileOfcurrentUser() { - mockCurrentUser(PARENT_USER_ID); - stopDefaultProfile(); - + startForegroundUser(PARENT_USER_ID); assertWithMessage("getDisplayAssignedToUser(%s)", PROFILE_USER_ID) .that(mMediator.getDisplayAssignedToUser(PROFILE_USER_ID)) .isEqualTo(INVALID_DISPLAY); @@ -376,7 +361,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public void testGetUserAssignedToDisplay_invalidDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getUserAssignedToDisplay(%s)", INVALID_DISPLAY) .that(mMediator.getUserAssignedToDisplay(INVALID_DISPLAY)).isEqualTo(USER_ID); @@ -384,7 +369,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testGetUserAssignedToDisplay_defaultDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getUserAssignedToDisplay(%s)", DEFAULT_DISPLAY) .that(mMediator.getUserAssignedToDisplay(DEFAULT_DISPLAY)).isEqualTo(USER_ID); @@ -392,7 +377,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { @Test public final void testGetUserAssignedToDisplay_secondaryDisplay() { - mockCurrentUser(USER_ID); + startForegroundUser(USER_ID); assertWithMessage("getUserAssignedToDisplay(%s)", SECONDARY_DISPLAY_ID) .that(mMediator.getUserAssignedToDisplay(SECONDARY_DISPLAY_ID)) @@ -407,72 +392,61 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { * own methods, but it depends on the user being started at first place, so pragmatically * speaking, it's better to "reuse" such tests for both (start and stop) */ - private void stopUserAndAssertState(@UserIdInt int userId) { + protected void stopUserAndAssertState(@UserIdInt int userId) { mMediator.stopUser(userId); assertUserIsStopped(userId); - assertNoUserAssignedToDisplay(); } - // TODO(b/244644281): remove if start & assign are merged; if they aren't, add a note explaining - // it's not meant to be used to test startUser() itself. - protected void mockCurrentUser(@UserIdInt int userId) { - Log.d(TAG, "mockCurrentUser(" + userId + ")"); - int result = mMediator.startOnly(userId, userId, FG, DEFAULT_DISPLAY); + /** + * Starts a user in foreground on the main display, asserting it was properly started. + * + *

NOTE: should only be used as a helper method, not to test the behavior of the + * {@link UserVisibilityMediator#startUser(int, int, boolean, int)} method per se. + */ + protected void startForegroundUser(@UserIdInt int userId) { + Log.d(TAG, "startForegroundUSer(" + userId + ")"); + int result = mMediator.startUser(userId, userId, FG, DEFAULT_DISPLAY); if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) { - throw new IllegalStateException("Failed to mock current user " + userId + throw new IllegalStateException("Failed to start foreground user " + userId + ": mediator returned " + userAssignmentResultToString(result)); } } - // TODO(b/244644281): remove when start & assign are merged; or add a note explaining - // it's not meant to be used to test startUser() itself. + /** + * Starts the {@link #PROFILE_USER_ID default profile } in foreground on the main display, + * asserting it was properly started. + * + *

NOTE: should only be used as a helper method, not to test the behavior of the + * {@link UserVisibilityMediator#startUser(int, int, boolean, int)} method per se. + */ protected void startDefaultProfile() { - mockCurrentUser(PARENT_USER_ID); + startForegroundUser(PARENT_USER_ID); Log.d(TAG, "starting default profile (" + PROFILE_USER_ID + ") in background after starting" + " its parent (" + PARENT_USER_ID + ") on foreground"); - int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); + int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY); if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) { throw new IllegalStateException("Failed to start profile user " + PROFILE_USER_ID + ": mediator returned " + userAssignmentResultToString(result)); } } - // TODO(b/244644281): remove when start & assign are merged; or add a note explaining - // it's not meant to be used to test stopUser() itself. - protected void stopDefaultProfile() { - Log.d(TAG, "stopping default profile"); - mMediator.stopUser(PROFILE_USER_ID); - } - - // TODO(b/244644281): remove when start & assign are merged; or add a note explaining - // it's not meant to be used to test assignUserToDisplay() itself. - protected final void assignUserToDisplay(@UserIdInt int userId, int displayId) { - Log.d(TAG, "assignUserToDisplay(" + userId + ", " + displayId + ")"); - int result = mMediator.startOnly(userId, userId, BG, displayId); - if (result != USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE) { + /** + * Starts a user in background on the secondary display, asserting it was properly started. + * + *

NOTE: should only be used as a helper method, not to test the behavior of the + * {@link UserVisibilityMediator#startUser(int, int, boolean, int)} method per se. + */ + protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) { + Preconditions.checkArgument(displayId != INVALID_DISPLAY && displayId != DEFAULT_DISPLAY, + "must pass a secondary display, not %d", displayId); + Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")"); + int result = mMediator.startUser(userId, userId, BG, displayId); + if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) { throw new IllegalStateException("Failed to startuser " + userId + " on background: mediator returned " + userAssignmentResultToString(result)); } - mMediator.assignUserToDisplay(userId, userId, displayId); - - } - - // TODO(b/244644281): remove when start & assign are merged; or rename to - // assertNoUserAssignedToSecondaryDisplays - protected final void assertNoUserAssignedToDisplay() { - assertWithMessage("users on secondary displays") - .that(mMediator.getUsersOnSecondaryDisplays()) - .isEmpty(); - } - - // TODO(b/244644281): remove when start & assign are merged; or rename to - // assertUserAssignedToSecondaryDisplay - protected final void assertUserAssignedToDisplay(@UserIdInt int userId, int displayId) { - assertWithMessage("users on secondary displays") - .that(mMediator.getUsersOnSecondaryDisplays()) - .containsExactly(userId, displayId); } private void assertCurrentUser(@UserIdInt int userId) { @@ -500,7 +474,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { assertUserIsStarted(userId); } - private void assertStartedProfileGroupIdOf(@UserIdInt int userId, + protected void assertStartedProfileGroupIdOf(@UserIdInt int userId, @UserIdInt int profileGroupId) { assertWithMessage("mediator.getStartedProfileGroupId(%s)", userId) .that(mMediator.getStartedProfileGroupId(userId)) @@ -518,16 +492,16 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase { } } - private void assertIsNotCurrentUserOrRunningProfileOfCurrentUser(int userId) { + protected void assertIsNotCurrentUserOrRunningProfileOfCurrentUser(int userId) { assertWithMessage("mediator.isCurrentUserOrRunningProfileOfCurrentUser(%s)", userId) .that(mMediator.isCurrentUserOrRunningProfileOfCurrentUser(userId)) .isFalse(); } - private void assertStartUserResult(int actualResult, int expectedResult) { + protected void assertStartUserResult(int actualResult, int expectedResult) { assertWithMessage("startUser() result (where %s=%s and %s=%s)", - actualResult, userAssignmentResultToString(actualResult), - expectedResult, userAssignmentResultToString(expectedResult)) + expectedResult, userAssignmentResultToString(expectedResult), + actualResult, userAssignmentResultToString(actualResult)) .that(actualResult).isEqualTo(expectedResult); } }