summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Felipe Leme <felipeal@google.com> 2022-10-28 11:06:49 -0700
committer Felipe Leme <felipeal@google.com> 2022-11-14 10:53:47 -0800
commitd16bc3eea37fb20ea5114a2b4307c5ee5cf87ca5 (patch)
treefd02c8ccde579299f9b3228a7fbda44f8abb10f2
parent90e81227d9857041b6fdbc8d6ed411504bcf3602 (diff)
UserVisibilityMediator refactoring, step 2.
The previous refactoring introduced a startUser() on UserVisibilityMediator and changed UserManagerInternal to call both startUser() and assignUserToDisplay(); this CL "merges" these two methods into just startUser(), and changed UserController.startUser() workflow so the logic of whether the user is visible is handled by UserVisibilityMediator. Test: atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest UserVisibilityMediatorMUMDTest UserVisibilityMediatorSUSDTest UserControllerTest # unit Test: atest CtsMultiUserTestCases:android.multiuser.cts.MultipleUsersOnMultipleDisplaysTest # CTS Test: adb shell dumpsys user --visibility-mediator Bug: 244644281 Change-Id: Ide7b62c1ab3bb119dde7dc2790919ad3c864b3e9
-rw-r--r--services/core/java/com/android/server/am/UserController.java46
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java50
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java9
-rw-r--r--services/core/java/com/android/server/pm/UserVisibilityMediator.java169
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java10
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java16
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java142
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java69
8 files changed, 312 insertions, 199 deletions
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 92133274c0cc..4d86140816ea 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1090,7 +1090,7 @@ class UserController implements Handler.Callback {
// TODO(b/239982558): for now we're just updating the user's visibility, but most likely
// we'll need to remove this call and handle that as part of the user state workflow
// instead.
- userManagerInternal.unassignUserFromDisplay(userId);
+ userManagerInternal.unassignUserFromDisplayOnStop(userId);
final boolean visibilityChanged;
boolean visibleBefore;
@@ -1650,13 +1650,30 @@ class UserController implements Handler.Callback {
return false;
}
- if (!userInfo.preCreated) {
- // TODO(b/244644281): UMI should return whether the user is visible. And if fails,
- // the user should not be in the mediator's started users structure
- mInjector.getUserManagerInternal().assignUserToDisplay(userId,
- userInfo.profileGroupId, foreground, displayId);
+ t.traceBegin("assignUserToDisplayOnStart");
+ int result = mInjector.getUserManagerInternal().assignUserToDisplayOnStart(userId,
+ userInfo.profileGroupId, foreground, displayId);
+ t.traceEnd();
+
+ boolean visible;
+ switch (result) {
+ case UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE:
+ visible = true;
+ break;
+ case UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE:
+ visible = false;
+ break;
+ default:
+ Slogf.wtf(TAG, "Wrong result from assignUserToDisplayOnStart(): %d", result);
+ // Fall through
+ case UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE:
+ Slogf.e(TAG, "%s user(%d) / display (%d) assignment failed: %s",
+ (foreground ? "fg" : "bg"), userId, displayId,
+ UserManagerInternal.userAssignmentResultToString(result));
+ return false;
}
+
// TODO(b/239982558): might need something similar for bg users on secondary display
if (foreground && isUserSwitchUiEnabled()) {
t.traceBegin("startFreezingScreen");
@@ -1751,19 +1768,6 @@ class UserController implements Handler.Callback {
}
t.traceEnd();
- // Need to call UM when user is on background, as there are some cases where the user
- // cannot be started in background on a secondary display (for example, if user is a
- // profile).
- // TODO(b/253103846): it's also explicitly checking if the user is the USER_SYSTEM, as
- // the UM call would return true during boot (when CarService / BootUserInitializer
- // calls AM.startUserInBackground() because the system user is still the current user.
- // TODO(b/244644281): another fragility of this check is that it must wait to call
- // UMI.isUserVisible() until the user state is check, as that method checks if the
- // profile of the current user is started. We should fix that dependency so the logic
- // belongs to just one place (like UserDisplayAssigner)
- boolean visible = foreground
- || userId != UserHandle.USER_SYSTEM
- && mInjector.getUserManagerInternal().isUserVisible(userId);
if (visible) {
synchronized (mLock) {
addVisibleUserLocked(userId);
@@ -1816,8 +1820,8 @@ class UserController implements Handler.Callback {
// user that was started in the background before), so it's necessary to explicitly
// notify the services (while when the user starts from BOOTING, USER_START_MSG
// takes care of that.
- mHandler.sendMessage(mHandler.obtainMessage(USER_VISIBILITY_CHANGED_MSG, userId,
- visible ? 1 : 0));
+ mHandler.sendMessage(
+ mHandler.obtainMessage(USER_VISIBILITY_CHANGED_MSG, userId, 1));
}
t.traceBegin("sendMessages");
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 91558308e305..9dafcceefdd0 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -25,6 +25,7 @@ import android.content.pm.UserProperties;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.UserManager;
+import android.util.DebugUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,6 +47,18 @@ public abstract class UserManagerInternal {
public @interface OwnerType {
}
+ public static final int USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE = 1;
+ 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";
+ @IntDef(flag = false, prefix = {PREFIX_USER_ASSIGNMENT_RESULT}, value = {
+ USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE,
+ USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE,
+ USER_ASSIGNMENT_RESULT_FAILURE
+ })
+ public @interface UserAssignmentResult {}
+
public interface UserRestrictionsListener {
/**
* Called when a user restriction changes.
@@ -343,34 +356,28 @@ public abstract class UserManagerInternal {
public abstract @Nullable UserProperties getUserProperties(@UserIdInt int userId);
/**
- * Assigns a user to a display.
- *
- * <p>On most devices this call will be a no-op, but it will be used on devices that support
- * multiple users on multiple displays (like automotives with passenger displays).
+ * Assigns a user to a display when it's starting, returning whether the assignment succeeded
+ * and the user is {@link UserManager#isUserVisible() visible}.
*
* <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
- * is started)
+ * is started). If other clients (like {@code CarService} need to explicitly change the user /
+ * display assignment, we'll need to provide other APIs.
*
* <p><b>NOTE: </b>this method doesn't validate if the display exists, it's up to the caller to
- * check it. In fact, one of the intended clients for this method is
- * {@code DisplayManagerService}, which will call it when a virtual display is created (another
- * client is {@code UserController}, which will call it when a user is started).
+ * pass a valid display id.
*/
- // TODO(b/244644281): rename to assignUserToDisplayOnStart() and make sure it's called on boot
- // as well
- public abstract void assignUserToDisplay(@UserIdInt int userId, @UserIdInt int profileGroupId,
+ public abstract @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
+ @UserIdInt int profileGroupId,
boolean foreground, int displayId);
/**
- * Unassigns a user from its current display.
- *
- * <p>On most devices this call will be a no-op, but it will be used on devices that support
- * multiple users on multiple displays (like automotives with passenger displays).
+ * Unassigns a user from its current display when it's stopping.
*
* <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
- * is stopped).
+ * is stopped). If other clients (like {@code CarService} need to explicitly change the user /
+ * display assignment, we'll need to provide other APIs.
*/
- public abstract void unassignUserFromDisplay(@UserIdInt int userId);
+ public abstract void unassignUserFromDisplayOnStop(@UserIdInt int userId);
/**
* Returns {@code true} if the user is visible (as defined by
@@ -413,6 +420,15 @@ public abstract class UserManagerInternal {
*/
public abstract @UserIdInt int getUserAssignedToDisplay(int displayId);
+ /**
+ * Gets the user-friendly representation of the {@code result} of a
+ * {@link #assignUserToDisplayOnStart(int, int, boolean, int)} call.
+ */
+ public static String userAssignmentResultToString(@UserAssignmentResult int result) {
+ return DebugUtils.constantToString(UserManagerInternal.class, PREFIX_USER_ASSIGNMENT_RESULT,
+ result);
+ }
+
/** Adds a {@link UserVisibilityListener}. */
public abstract void addUserVisibilityListener(UserVisibilityListener listener);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d25566980fbb..44b5ba242f91 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -6799,15 +6799,14 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public void assignUserToDisplay(@UserIdInt int userId, @UserIdInt int profileGroupId,
+ public int assignUserToDisplayOnStart(@UserIdInt int userId, @UserIdInt int profileGroupId,
boolean foreground, int displayId) {
- mUserVisibilityMediator.startUser(userId, profileGroupId, foreground, displayId);
- mUserVisibilityMediator.assignUserToDisplay(userId, profileGroupId, displayId);
+ return mUserVisibilityMediator.startUser(userId, profileGroupId, foreground,
+ displayId);
}
@Override
- public void unassignUserFromDisplay(@UserIdInt int userId) {
- mUserVisibilityMediator.unassignUserFromDisplay(userId);
+ public void unassignUserFromDisplayOnStop(@UserIdInt int userId) {
mUserVisibilityMediator.stopUser(userId);
}
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index bd81062b0ff1..cbf7dfe77ca6 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -20,12 +20,15 @@ import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
-import android.annotation.IntDef;
+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.android.server.pm.UserManagerInternal.userAssignmentResultToString;
+
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.UserHandle;
import android.os.UserManager;
-import android.util.DebugUtils;
import android.util.Dumpable;
import android.util.IndentingPrintWriter;
import android.util.SparseIntArray;
@@ -34,6 +37,7 @@ 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;
@@ -52,23 +56,10 @@ public final class UserVisibilityMediator implements Dumpable {
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
- private static final String PREFIX_START_USER_RESULT = "START_USER_";
-
// 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;
- public static final int START_USER_RESULT_SUCCESS_VISIBLE = 1;
- public static final int START_USER_RESULT_SUCCESS_INVISIBLE = 2;
- public static final int START_USER_RESULT_FAILURE = -1;
-
- @IntDef(flag = false, prefix = {PREFIX_START_USER_RESULT}, value = {
- START_USER_RESULT_SUCCESS_VISIBLE,
- START_USER_RESULT_SUCCESS_INVISIBLE,
- START_USER_RESULT_FAILURE
- })
- public @interface StartUserResult {}
-
private final Object mLock = new Object();
private final boolean mUsersOnSecondaryDisplaysEnabled;
@@ -97,10 +88,37 @@ public final class UserVisibilityMediator implements Dumpable {
}
/**
- * TODO(b/244644281): merge with assignUserToDisplay() or add javadoc.
+ * See {@link UserManagerInternal#assignUserToDisplayOnStart(int, int, boolean, int)}.
*/
- public @StartUserResult int startUser(@UserIdInt int userId, @UserIdInt int profileGroupId,
+ public @UserAssignmentResult int startUser(@UserIdInt int userId, @UserIdInt int profileGroupId,
boolean foreground, int displayId) {
+ // TODO(b/244644281): this method need 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);
+ }
+ return result;
+ }
+
+ /**
+ * @deprecated - see comment inside {@link #startUser(int, int, boolean, int)}
+ */
+ @Deprecated
+ @VisibleForTesting
+ @UserAssignmentResult int startOnly(@UserIdInt int userId,
+ @UserIdInt int profileGroupId, boolean foreground, int displayId) {
int actualProfileGroupId = profileGroupId == NO_PROFILE_GROUP_ID
? userId
: profileGroupId;
@@ -111,7 +129,7 @@ public final class UserVisibilityMediator implements Dumpable {
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 START_USER_RESULT_FAILURE;
+ return USER_ASSIGNMENT_RESULT_FAILURE;
}
int visibility;
@@ -121,13 +139,12 @@ public final class UserVisibilityMediator implements Dumpable {
Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user on "
+ "secondary display", userId, actualProfileGroupId, foreground,
displayId);
- return START_USER_RESULT_FAILURE;
+ 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 START_USER_RESULT_FAILURE;
+ + "foreground", userId, actualProfileGroupId, foreground, displayId);
+ return USER_ASSIGNMENT_RESULT_FAILURE;
} else {
boolean isParentRunning = mStartedProfileGroupIds
.get(actualProfileGroupId) == actualProfileGroupId;
@@ -135,18 +152,18 @@ public final class UserVisibilityMediator implements Dumpable {
Slogf.d(TAG, "profile parent running: %b", isParentRunning);
}
visibility = isParentRunning
- ? START_USER_RESULT_SUCCESS_VISIBLE
- : START_USER_RESULT_SUCCESS_INVISIBLE;
+ ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
+ : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
} else if (foreground) {
mCurrentUserId = userId;
- visibility = START_USER_RESULT_SUCCESS_VISIBLE;
+ visibility = USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
} else {
- visibility = START_USER_RESULT_SUCCESS_INVISIBLE;
+ visibility = USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
if (DBG) {
Slogf.d(TAG, "adding user / profile mapping (%d -> %d) and returning %s",
- userId, actualProfileGroupId, startUserResultToString(visibility));
+ userId, actualProfileGroupId, userAssignmentResultToString(visibility));
}
mStartedProfileGroupIds.put(userId, actualProfileGroupId);
}
@@ -154,21 +171,11 @@ public final class UserVisibilityMediator implements Dumpable {
}
/**
- * TODO(b/244644281): merge with unassignUserFromDisplay() or add javadoc (and unit tests)
- */
- public void stopUser(@UserIdInt int userId) {
- if (DBG) {
- Slogf.d(TAG, "stopUser(%d)", userId);
- }
- synchronized (mLock) {
- mStartedProfileGroupIds.delete(userId);
- }
- }
-
- /**
- * See {@link UserManagerInternal#assignUserToDisplay(int, int)}.
+ * @deprecated - see comment inside {@link #startUser(int, int, boolean, int)}
*/
- public void assignUserToDisplay(int userId, int profileGroupId, int displayId) {
+ @Deprecated
+ @VisibleForTesting
+ void assignUserToDisplay(int userId, int profileGroupId, int displayId) {
if (DBG) {
Slogf.d(TAG, "assignUserToDisplay(%d, %d): mUsersOnSecondaryDisplaysEnabled=%b",
userId, displayId, mUsersOnSecondaryDisplaysEnabled);
@@ -246,22 +253,25 @@ public final class UserVisibilityMediator implements Dumpable {
}
/**
- * See {@link UserManagerInternal#unassignUserFromDisplay(int)}.
+ * See {@link UserManagerInternal#unassignUserFromDisplayOnStop(int)}.
*/
- public void unassignUserFromDisplay(int userId) {
+ public void stopUser(int userId) {
if (DBG) {
- Slogf.d(TAG, "unassignUserFromDisplay(%d)", userId);
+ Slogf.d(TAG, "stopUser(%d)", userId);
}
- if (!mUsersOnSecondaryDisplaysEnabled) {
- // 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.
+ synchronized (mLock) {
if (DBG) {
- Slogf.d(TAG, "ignoring when device doesn't support MUMD");
+ Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
+ mStartedProfileGroupIds);
}
- return;
- }
+ mStartedProfileGroupIds.delete(userId);
- synchronized (mLock) {
+ if (!mUsersOnSecondaryDisplaysEnabled) {
+ // Don't need to do update mUsersOnSecondaryDisplays because methods (such as
+ // isUserVisible()) already know that the current user (and their profiles) is
+ // assigned to the default display.
+ return;
+ }
if (DBG) {
Slogf.d(TAG, "Removing %d from mUsersOnSecondaryDisplays (%s)", userId,
mUsersOnSecondaryDisplays);
@@ -395,33 +405,40 @@ public final class UserVisibilityMediator implements Dumpable {
ipw.print("Current user id: ");
ipw.println(mCurrentUserId);
- ipw.print("Number of started user / profile group mappings: ");
- ipw.println(mStartedProfileGroupIds.size());
- if (mStartedProfileGroupIds.size() > 0) {
- ipw.increaseIndent();
- for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
- ipw.print("User #");
- ipw.print(mStartedProfileGroupIds.keyAt(i));
- ipw.print(" -> profile #");
- ipw.println(mStartedProfileGroupIds.valueAt(i));
- }
- ipw.decreaseIndent();
- }
+ dumpIntArray(ipw, mStartedProfileGroupIds, "started user / profile group", "u", "pg");
- ipw.print("Supports users on secondary displays: ");
+ ipw.print("Supports background users on secondary displays: ");
ipw.println(mUsersOnSecondaryDisplaysEnabled);
if (mUsersOnSecondaryDisplaysEnabled) {
- ipw.print("Users on secondary displays: ");
- synchronized (mLock) {
- ipw.println(mUsersOnSecondaryDisplays);
- }
+ dumpIntArray(ipw, mUsersOnSecondaryDisplays, "background user / secondary display",
+ "u", "d");
}
}
ipw.decreaseIndent();
}
+ private static void dumpIntArray(IndentingPrintWriter ipw, SparseIntArray array,
+ String arrayDescription, String keyName, String valueName) {
+ ipw.print("Number of ");
+ ipw.print(arrayDescription);
+ ipw.print(" mappings: ");
+ ipw.println(array.size());
+ if (array.size() <= 0) {
+ return;
+ }
+ ipw.increaseIndent();
+ for (int i = 0; i < array.size(); i++) {
+ ipw.print(keyName); ipw.print(':');
+ ipw.print(array.keyAt(i));
+ ipw.print(" -> ");
+ ipw.print(valueName); ipw.print(':');
+ ipw.println(array.valueAt(i));
+ }
+ ipw.decreaseIndent();
+ }
+
@Override
public void dump(PrintWriter pw, String[] args) {
if (pw instanceof IndentingPrintWriter) {
@@ -445,14 +462,6 @@ public final class UserVisibilityMediator implements Dumpable {
return map;
}
- /**
- * Gets the user-friendly representation of the {@code result}.
- */
- public static String startUserResultToString(@StartUserResult int result) {
- return DebugUtils.constantToString(UserVisibilityMediator.class, PREFIX_START_USER_RESULT,
- result);
- }
-
// 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.
@@ -483,6 +492,14 @@ public final class UserVisibilityMediator implements Dumpable {
}
@VisibleForTesting
+ boolean isStartedUser(@UserIdInt int userId) {
+ synchronized (mLock) {
+ return mStartedProfileGroupIds.get(userId,
+ INITIAL_CURRENT_USER_ID) != INITIAL_CURRENT_USER_ID;
+ }
+ }
+
+ @VisibleForTesting
boolean isStartedProfile(@UserIdInt int userId) {
int profileGroupId;
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 923c3e385b5e..9be370fe3045 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
@@ -153,14 +153,8 @@ public final class UserVisibilityMediatorMUMDTest extends UserVisibilityMediator
assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID);
}
- @Test
- public void testUnassignUserFromDisplay() {
- testAssignUserToDisplay_displayAvailable();
-
- mMediator.unassignUserFromDisplay(USER_ID);
-
- assertNoUserAssignedToDisplay();
- }
+ // 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() {
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 7af5f5d6b2fe..7abdd9e7bbaf 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
@@ -15,8 +15,6 @@
*/
package com.android.server.pm;
-import static android.os.UserHandle.USER_SYSTEM;
-
import static org.junit.Assert.assertThrows;
import org.junit.Test;
@@ -34,6 +32,9 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
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);
@@ -59,15 +60,4 @@ public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediator
assertThrows(UnsupportedOperationException.class, () -> mMediator
.assignUserToDisplay(PROFILE_USER_ID, PARENT_USER_ID, SECONDARY_DISPLAY_ID));
}
-
- @Test
- public void testUnassignUserFromDisplay_ignored() {
- mockCurrentUser(USER_ID);
-
- mMediator.unassignUserFromDisplay(USER_SYSTEM);
- mMediator.unassignUserFromDisplay(USER_ID);
- mMediator.unassignUserFromDisplay(OTHER_USER_ID);
-
- assertNoUserAssignedToDisplay();
- }
}
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 7b20092b503a..e8be97db717d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -20,11 +20,11 @@ import static android.os.UserHandle.USER_NULL;
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.android.server.pm.UserManagerInternal.userAssignmentResultToString;
import static com.android.server.pm.UserVisibilityMediator.INITIAL_CURRENT_USER_ID;
-import static com.android.server.pm.UserVisibilityMediator.START_USER_RESULT_FAILURE;
-import static com.android.server.pm.UserVisibilityMediator.START_USER_RESULT_SUCCESS_INVISIBLE;
-import static com.android.server.pm.UserVisibilityMediator.START_USER_RESULT_SUCCESS_VISIBLE;
-import static com.android.server.pm.UserVisibilityMediator.startUserResultToString;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -100,79 +100,92 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
@Test
public final void testStartUser_currentUser() {
- int result = mMediator.startUser(USER_ID, USER_ID, FG, DEFAULT_DISPLAY);
- assertStartUserResult(result, START_USER_RESULT_SUCCESS_VISIBLE);
+ int result = mMediator.startOnly(USER_ID, USER_ID, FG, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
assertCurrentUser(USER_ID);
assertIsCurrentUserOrRunningProfileOfCurrentUser(USER_ID);
assertStartedProfileGroupIdOf(USER_ID, USER_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_currentUserSecondaryDisplay() {
- int result = mMediator.startUser(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID);
- assertStartUserResult(result, START_USER_RESULT_FAILURE);
+ int result = mMediator.startOnly(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
assertCurrentUser(INITIAL_CURRENT_USER_ID);
assertIsNotCurrentUserOrRunningProfileOfCurrentUser(USER_ID);
assertStartedProfileGroupIdOf(USER_ID, NO_PROFILE_GROUP_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_profileBg_parentStarted() {
mockCurrentUser(PARENT_USER_ID);
- int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY);
- assertStartUserResult(result, START_USER_RESULT_SUCCESS_VISIBLE);
+ int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
assertCurrentUser(PARENT_USER_ID);
assertIsCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID);
assertStartedProfileGroupIdOf(PROFILE_USER_ID, PARENT_USER_ID);
- assertIsStartedProfile(PROFILE_USER_ID);
+ assertProfileIsStarted(PROFILE_USER_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_profileBg_parentNotStarted() {
- int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY);
- assertStartUserResult(result, START_USER_RESULT_SUCCESS_INVISIBLE);
+ int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
assertCurrentUser(INITIAL_CURRENT_USER_ID);
assertIsNotCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID);
assertStartedProfileGroupIdOf(PROFILE_USER_ID, PARENT_USER_ID);
- assertIsStartedProfile(PROFILE_USER_ID);
+ assertProfileIsStarted(PROFILE_USER_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_profileBg_secondaryDisplay() {
- int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, SECONDARY_DISPLAY_ID);
- assertStartUserResult(result, START_USER_RESULT_FAILURE);
+ int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, BG, SECONDARY_DISPLAY_ID);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
assertCurrentUser(INITIAL_CURRENT_USER_ID);
assertIsNotCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_profileFg() {
- int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, FG, DEFAULT_DISPLAY);
- assertStartUserResult(result, START_USER_RESULT_FAILURE);
+ int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, FG, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
assertCurrentUser(INITIAL_CURRENT_USER_ID);
assertIsNotCurrentUserOrRunningProfileOfCurrentUser(PROFILE_USER_ID);
- assertStartedProfileGroupIdOf(PROFILE_USER_ID, NO_PROFILE_GROUP_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testStartUser_profileFgSecondaryDisplay() {
- int result = mMediator.startUser(PROFILE_USER_ID, PARENT_USER_ID, FG, SECONDARY_DISPLAY_ID);
+ int result = mMediator.startOnly(PROFILE_USER_ID, PARENT_USER_ID, FG, SECONDARY_DISPLAY_ID);
- assertStartUserResult(result, START_USER_RESULT_FAILURE);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
assertCurrentUser(INITIAL_CURRENT_USER_ID);
+
+ stopUserAndAssertState(USER_ID);
}
@Test
public final void testGetStartedProfileGroupId_whenStartedWithNoProfileGroupId() {
- int result = mMediator.startUser(USER_ID, NO_PROFILE_GROUP_ID, FG, DEFAULT_DISPLAY);
- assertStartUserResult(result, START_USER_RESULT_SUCCESS_VISIBLE);
+ int result = mMediator.startOnly(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);
@@ -386,59 +399,78 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
.isEqualTo(USER_ID);
}
+ /**
+ * Stops the given user and assert the proper state is set.
+ *
+ * <p>This method should be called at the end of tests that starts a user, so it can test
+ * {@code stopUser()} as well (technically speaking, {@code stopUser()} should be tested on its
+ * 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) {
+ 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.startUser(userId, userId, FG, DEFAULT_DISPLAY);
- if (result != START_USER_RESULT_SUCCESS_VISIBLE) {
+ int result = mMediator.startOnly(userId, userId, FG, DEFAULT_DISPLAY);
+ if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
throw new IllegalStateException("Failed to mock current user " + userId
- + ": mediator returned " + startUserResultToString(result));
+ + ": mediator returned " + userAssignmentResultToString(result));
}
}
- // TODO(b/244644281): remove if start & assign are merged; if they aren't, add a note explaining
+ // 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.
protected void startDefaultProfile() {
mockCurrentUser(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.startUser(PROFILE_USER_ID, PARENT_USER_ID, BG, DEFAULT_DISPLAY);
- if (result != START_USER_RESULT_SUCCESS_VISIBLE) {
+ int result = mMediator.startOnly(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 " + startUserResultToString(result));
+ + ": mediator returned " + userAssignmentResultToString(result));
}
}
- // TODO(b/244644281): remove if start & assign are merged; if they aren't, add a note explaining
+ // 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 if start & assign are merged; if they aren't, add a note explaining
+ // 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.startUser(userId, userId, BG, displayId);
- if (result != START_USER_RESULT_SUCCESS_INVISIBLE) {
+ int result = mMediator.startOnly(userId, userId, BG, displayId);
+ if (result != USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE) {
throw new IllegalStateException("Failed to startuser " + userId
- + " on background: mediator returned " + startUserResultToString(result));
+ + " 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("uses on secondary displays")
+ 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("uses on secondary displays")
+ assertWithMessage("users on secondary displays")
.that(mMediator.getUsersOnSecondaryDisplays())
.containsExactly(userId, displayId);
}
@@ -446,24 +478,44 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
private void assertCurrentUser(@UserIdInt int userId) {
assertWithMessage("mediator.getCurrentUserId()").that(mMediator.getCurrentUserId())
.isEqualTo(userId);
+ if (userId != INITIAL_CURRENT_USER_ID) {
+ assertUserIsStarted(userId);
+ }
+ }
+
+ private void assertUserIsStarted(@UserIdInt int userId) {
+ assertWithMessage("mediator.isStarted(%s)", userId).that(mMediator.isStartedUser(userId))
+ .isTrue();
+ }
+
+ private void assertUserIsStopped(@UserIdInt int userId) {
+ assertWithMessage("mediator.isStarted(%s)", userId).that(mMediator.isStartedUser(userId))
+ .isFalse();
}
- private void assertIsStartedProfile(@UserIdInt int userId) {
+ private void assertProfileIsStarted(@UserIdInt int userId) {
assertWithMessage("mediator.isStartedProfile(%s)", userId)
.that(mMediator.isStartedProfile(userId))
.isTrue();
+ assertUserIsStarted(userId);
}
- private void assertStartedProfileGroupIdOf(@UserIdInt int profileId, @UserIdInt int parentId) {
- assertWithMessage("mediator.getStartedProfileGroupId(%s)", profileId)
- .that(mMediator.getStartedProfileGroupId(profileId))
- .isEqualTo(parentId);
+ private void assertStartedProfileGroupIdOf(@UserIdInt int userId,
+ @UserIdInt int profileGroupId) {
+ assertWithMessage("mediator.getStartedProfileGroupId(%s)", userId)
+ .that(mMediator.getStartedProfileGroupId(userId))
+ .isEqualTo(profileGroupId);
}
- private void assertIsCurrentUserOrRunningProfileOfCurrentUser(int userId) {
+ private void assertIsCurrentUserOrRunningProfileOfCurrentUser(@UserIdInt int userId) {
assertWithMessage("mediator.isCurrentUserOrRunningProfileOfCurrentUser(%s)", userId)
.that(mMediator.isCurrentUserOrRunningProfileOfCurrentUser(userId))
.isTrue();
+ if (mMediator.getCurrentUserId() == userId) {
+ assertUserIsStarted(userId);
+ } else {
+ assertProfileIsStarted(userId);
+ }
}
private void assertIsNotCurrentUserOrRunningProfileOfCurrentUser(int userId) {
@@ -474,8 +526,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
private void assertStartUserResult(int actualResult, int expectedResult) {
assertWithMessage("startUser() result (where %s=%s and %s=%s)",
- actualResult, startUserResultToString(actualResult),
- expectedResult, startUserResultToString(expectedResult))
+ actualResult, userAssignmentResultToString(actualResult),
+ expectedResult, userAssignmentResultToString(expectedResult))
.that(actualResult).isEqualTo(expectedResult);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 80cee50cef79..a49214f9b4f5 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -39,6 +39,8 @@ import static com.android.server.am.UserController.USER_CURRENT_MSG;
import static com.android.server.am.UserController.USER_START_MSG;
import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
import static com.android.server.am.UserController.USER_VISIBILITY_CHANGED_MSG;
+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.android.collect.Lists.newArrayList;
import static com.google.android.collect.Sets.newHashSet;
@@ -100,6 +102,7 @@ import com.android.server.FgThread;
import com.android.server.SystemService;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerInternal;
+import com.android.server.pm.UserManagerInternal.UserAssignmentResult;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
@@ -162,10 +165,15 @@ public class UserControllerTest {
USER_VISIBILITY_CHANGED_MSG,
USER_CURRENT_MSG);
- private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
+ private static final Set<Integer> START_INVISIBLE_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
USER_START_MSG,
REPORT_LOCKED_BOOT_COMPLETE_MSG);
+ private static final Set<Integer> START_VISIBLE_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
+ USER_START_MSG,
+ USER_VISIBILITY_CHANGED_MSG,
+ REPORT_LOCKED_BOOT_COMPLETE_MSG);
+
@Before
public void setUp() throws Exception {
runWithDexmakerShareClassLoader(() -> {
@@ -184,6 +192,12 @@ public class UserControllerTest {
mockIsUsersOnSecondaryDisplaysEnabled(false);
// All UserController params are set to default.
+ // Starts with a generic assumption that the user starts visible, but on tests where
+ // that's not the case, the test should call mockAssignUserToMainDisplay()
+ doReturn(UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE)
+ .when(mInjector.mUserManagerInternalMock)
+ .assignUserToDisplayOnStart(anyInt(), anyInt(), anyBoolean(), anyInt());
+
mUserController = new UserController(mInjector);
mUserController.setAllowUserUnlocking(true);
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
@@ -211,16 +225,29 @@ public class UserControllerTest {
@Test
public void testStartUser_background() {
+ mockAssignUserToMainDisplay(TEST_USER_ID, /* foreground= */ false,
+ USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
boolean started = mUserController.startUser(TEST_USER_ID, /* foreground= */ false);
assertWithMessage("startUser(%s, foreground=false)", TEST_USER_ID).that(started).isTrue();
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
- startBackgroundUserAssertions();
+ startBackgroundUserAssertions(/*visible= */ false);
verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY);
}
@Test
+ public void testStartUser_displayAssignmentFailed() {
+ doReturn(UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE)
+ .when(mInjector.mUserManagerInternalMock)
+ .assignUserToDisplayOnStart(eq(TEST_USER_ID), anyInt(), eq(true), anyInt());
+
+ boolean started = mUserController.startUser(TEST_USER_ID, /* foreground= */ true);
+
+ assertWithMessage("startUser(%s, foreground=true)", TEST_USER_ID).that(started).isFalse();
+ }
+
+ @Test
public void testStartUserOnSecondaryDisplay_defaultDisplay() {
assertThrows(IllegalArgumentException.class, () -> mUserController
.startUserOnSecondaryDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY));
@@ -240,7 +267,7 @@ public class UserControllerTest {
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
- startBackgroundUserAssertions();
+ startBackgroundUserAssertions(/*visible= */ true);
}
@Test
@@ -266,6 +293,8 @@ public class UserControllerTest {
@Test
public void testStartPreCreatedUser_background() throws Exception {
+ mockAssignUserToMainDisplay(TEST_PRE_CREATED_USER_ID, /* foreground= */ false,
+ USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
assertTrue(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ false));
// Make sure no intents have been fired for pre-created users.
assertTrue(mInjector.mSentIntents.isEmpty());
@@ -284,8 +313,6 @@ public class UserControllerTest {
// binder calls, but their side effects (in this case, that the user is stopped right away)
assertWithMessage("wrong binder message calls").that(mInjector.mHandler.getMessageCodes())
.containsExactly(USER_START_MSG);
-
- verifyUserNeverAssignedToDisplay();
}
private void startUserAssertions(
@@ -295,8 +322,10 @@ public class UserControllerTest {
assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes);
}
- private void startBackgroundUserAssertions() {
- startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES);
+ private void startBackgroundUserAssertions(boolean visible) {
+ startUserAssertions(START_BACKGROUND_USER_ACTIONS,
+ visible ? START_VISIBLE_BACKGROUND_USER_MESSAGE_CODES
+ : START_INVISIBLE_BACKGROUND_USER_MESSAGE_CODES);
}
private void startForegroundUserAssertions() {
@@ -680,19 +709,24 @@ public class UserControllerTest {
@Test
public void testStartProfile() throws Exception {
+ mockAssignUserToMainDisplay(TEST_PRE_CREATED_USER_ID, /* foreground= */ false,
+ USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
setUpAndStartProfileInBackground(TEST_USER_ID1);
- startBackgroundUserAssertions();
+ startBackgroundUserAssertions(/*visible= */ true);
verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
}
@Test
public void testStartProfile_whenUsersOnSecondaryDisplaysIsEnabled() throws Exception {
+ mockAssignUserToMainDisplay(TEST_USER_ID1, /* foreground= */ false,
+ USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+
mockIsUsersOnSecondaryDisplaysEnabled(true);
setUpAndStartProfileInBackground(TEST_USER_ID1);
- startBackgroundUserAssertions();
+ startBackgroundUserAssertions(/*visible= */ true);
verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
}
@@ -949,22 +983,29 @@ public class UserControllerTest {
when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value);
}
+ private void mockAssignUserToMainDisplay(@UserIdInt int userId, boolean foreground,
+ @UserAssignmentResult int result) {
+ when(mInjector.mUserManagerInternalMock.assignUserToDisplayOnStart(eq(userId),
+ /* profileGroupId= */ anyInt(), eq(foreground), eq(Display.DEFAULT_DISPLAY)))
+ .thenReturn(result);
+ }
+
private void verifyUserAssignedToDisplay(@UserIdInt int userId, int displayId) {
- verify(mInjector.getUserManagerInternal()).assignUserToDisplay(eq(userId), anyInt(),
+ verify(mInjector.getUserManagerInternal()).assignUserToDisplayOnStart(eq(userId), anyInt(),
anyBoolean(), eq(displayId));
}
private void verifyUserNeverAssignedToDisplay() {
- verify(mInjector.getUserManagerInternal(), never()).assignUserToDisplay(anyInt(), anyInt(),
- anyBoolean(), anyInt());
+ verify(mInjector.getUserManagerInternal(), never()).assignUserToDisplayOnStart(anyInt(),
+ anyInt(), anyBoolean(), anyInt());
}
private void verifyUserUnassignedFromDisplay(@UserIdInt int userId) {
- verify(mInjector.getUserManagerInternal()).unassignUserFromDisplay(userId);
+ verify(mInjector.getUserManagerInternal()).unassignUserFromDisplayOnStop(userId);
}
private void verifyUserUnassignedFromDisplayNeverCalled(@UserIdInt int userId) {
- verify(mInjector.getUserManagerInternal(), never()).unassignUserFromDisplay(userId);
+ verify(mInjector.getUserManagerInternal(), never()).unassignUserFromDisplayOnStop(userId);
}
private void verifySystemUserVisibilityChangedNotified(boolean visible) {