Merge "UserVisibilityMediator refactoring, step 3."

This commit is contained in:
Felipe Leme
2022-11-17 22:51:36 +00:00
committed by Android (Google) Code Review
7 changed files with 340 additions and 395 deletions

View File

@@ -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
*/

View File

@@ -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,

View File

@@ -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();

View File

@@ -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).
*
* <p>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)}):
*
* <ul>
* <li>default: this is the most common mode (used by phones, tablets, foldables, automotives with
* just cluster and driver displayes, etc...), where the logic is based solely on the current
* foreground user (and its started profiles)
* <li>{@code MUMD}: mode for "(concurrent) Multiple Users on Multiple Displays", which is used on
* automotives with passenger display. In this mode, users started in background on the secondary
* display are stored in map.
* </ul>
*
* <p>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.
*
* <p>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<Integer, Integer> getUsersOnSecondaryDisplays() {
Map<Integer, Integer> 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) {

View File

@@ -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);

View File

@@ -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));
}
}

View File

@@ -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.
*
* <p><b>NOTE: </b>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.
*
* <p><b>NOTE: </b>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.
*
* <p><b>NOTE: </b>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);
}
}