diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b8703eb5bad5b..83963fd2141dc 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 1420cbf3ae451..1027f4c031277 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 9f84ab030cefd..c5212a16c3edd 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1645,8 +1645,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); } }