Loading services/core/java/com/android/server/am/ActivityManagerService.java +1 −2 Original line number Diff line number Diff line Loading @@ -16145,8 +16145,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean startUserInBackgroundOnSecondaryDisplay(int userId, int displayId) { // Permission check done inside UserController. return mUserController.startUserOnSecondaryDisplay(userId, displayId, /* unlockListener= */ null); return mUserController.startUserOnSecondaryDisplay(userId, displayId); } /** services/core/java/com/android/server/am/UserController.java +13 −6 Original line number Diff line number Diff line Loading @@ -1375,8 +1375,9 @@ class UserController implements Handler.Callback { } final int profilesToStartSize = profilesToStart.size(); int i = 0; // TODO(b/239982558): pass displayId for (; i < profilesToStartSize && i < (getMaxRunningUsers() - 1); ++i) { // NOTE: this method is setting the profiles of the current user - which is always // assigned to the default display - so there's no need to pass PARENT_DISPLAY startUser(profilesToStart.get(i).id, /* foreground= */ false); } if (i < profilesToStartSize) { Loading Loading @@ -1419,8 +1420,10 @@ class UserController implements Handler.Callback { return false; } // TODO(b/239982558): pass proper displayId return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, /* foreground= */ false, int displayId = mInjector.isUsersOnSecondaryDisplaysEnabled() ? UserManagerInternal.PARENT_DISPLAY : Display.DEFAULT_DISPLAY; return startUserNoChecks(userId, displayId, /* foreground= */ false, /* unlockListener= */ null); } Loading Loading @@ -1472,8 +1475,7 @@ class UserController implements Handler.Callback { // TODO(b/239982558): add javadoc (need to wait until the intents / SystemService callbacks are // defined boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId, @Nullable IProgressListener unlockListener) { boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId) { checkCallingHasOneOfThosePermissions("startUserOnSecondaryDisplay", MANAGE_USERS, CREATE_USERS); Loading @@ -1482,7 +1484,8 @@ class UserController implements Handler.Callback { "Cannot use DEFAULT_DISPLAY"); try { return startUserNoChecks(userId, displayId, /* foreground= */ false, unlockListener); return startUserNoChecks(userId, displayId, /* foreground= */ false, /* unlockListener= */ null); } catch (RuntimeException e) { Slogf.w(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e); return false; Loading Loading @@ -3484,5 +3487,9 @@ class UserController implements Handler.Callback { } }, reason); } boolean isUsersOnSecondaryDisplaysEnabled() { return UserManager.isUsersOnSecondaryDisplaysEnabled(); } } } services/core/java/com/android/server/pm/UserManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,15 @@ public abstract class UserManagerInternal { public @interface OwnerType { } // TODO(b/245963156): move to Display.java (and @hide) if we decide to support profiles on MUMD /** * Used only when starting a profile (on systems that * {@link android.os.UserManager#isUsersOnSecondaryDisplaysSupported() support users running on * secondary displays}), to indicate the profile should be started in the same display as its * parent user. */ public static final int PARENT_DISPLAY = -2; public interface UserRestrictionsListener { /** * Called when a user restriction changes. Loading services/core/java/com/android/server/pm/UserManagerService.java +29 −38 Original line number Diff line number Diff line Loading @@ -6825,34 +6825,23 @@ public class UserManagerService extends IUserManager.Stub { int currentUserId = getCurrentUserId(); Preconditions.checkArgument(userId != currentUserId, "Cannot assign current user to other displays"); boolean isProfile = isProfileUnchecked(userId); Preconditions.checkArgument(userId != currentUserId, "Cannot assign current user to other displays"); Preconditions.checkArgument( !isProfile || getProfileParentIdUnchecked(userId) != currentUserId, "Cannot assign profile user %d to display %d when its parent is the current " + "user (%d)", userId, displayId, currentUserId); "Cannot assign current user (%d) to other displays", currentUserId); synchronized (mUsersOnSecondaryDisplays) { if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding %d->%d to mUsersOnSecondaryDisplays", userId, displayId); } if (isProfile) { if (isProfileUnchecked(userId)) { // Profile can only start in the same display as parent Preconditions.checkArgument(displayId == UserManagerInternal.PARENT_DISPLAY, "Profile user can only be started in the same display as parent"); int parentUserId = getProfileParentId(userId); int parentDisplayId = mUsersOnSecondaryDisplays.get(parentUserId); if (displayId != parentDisplayId) { throw new IllegalStateException("Cannot assign profile " + userId + " to " + "display " + displayId + " as its parent (user " + parentUserId + ") is assigned to display " + parentDisplayId); if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding profile user %d -> display %d", userId, parentDisplayId); } } else { mUsersOnSecondaryDisplays.put(userId, parentDisplayId); return; } // Check if display is available for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) { // Make sure display is not used by other users... Loading @@ -6870,8 +6859,10 @@ public class UserManagerService extends IUserManager.Stub { // (for example, would need to add a new AM method to start user in bg on // main display), so it's better to test on unit tests } } if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding full user %d -> display %d", userId, displayId); } mUsersOnSecondaryDisplays.put(userId, displayId); } } Loading services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java +5 −13 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ 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.PARENT_DISPLAY; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; Loading Loading @@ -119,9 +121,6 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*parent.*current.*" + PARENT_USER_ID + ".*"); assertNoUserAssignedToDisplay(); } Loading @@ -136,10 +135,6 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*parent.*current.*" + PARENT_USER_ID + ".*"); assertNoUserAssignedToDisplay(); } Loading Loading @@ -173,7 +168,7 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT addDefaultProfileAndParent(); mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID); mUmi.assignUserToDisplay(PROFILE_USER_ID, PARENT_DISPLAY); assertUsersAssignedToDisplays(PARENT_USER_ID, SECONDARY_DISPLAY_ID, pair(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Loading @@ -185,13 +180,10 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT addDefaultProfileAndParent(); mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); IllegalStateException e = assertThrows(IllegalStateException.class, () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, OTHER_SECONDARY_DISPLAY_ID)); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + OTHER_SECONDARY_DISPLAY_ID + ".*parent.*" + PARENT_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*"); assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); } Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +1 −2 Original line number Diff line number Diff line Loading @@ -16145,8 +16145,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean startUserInBackgroundOnSecondaryDisplay(int userId, int displayId) { // Permission check done inside UserController. return mUserController.startUserOnSecondaryDisplay(userId, displayId, /* unlockListener= */ null); return mUserController.startUserOnSecondaryDisplay(userId, displayId); } /**
services/core/java/com/android/server/am/UserController.java +13 −6 Original line number Diff line number Diff line Loading @@ -1375,8 +1375,9 @@ class UserController implements Handler.Callback { } final int profilesToStartSize = profilesToStart.size(); int i = 0; // TODO(b/239982558): pass displayId for (; i < profilesToStartSize && i < (getMaxRunningUsers() - 1); ++i) { // NOTE: this method is setting the profiles of the current user - which is always // assigned to the default display - so there's no need to pass PARENT_DISPLAY startUser(profilesToStart.get(i).id, /* foreground= */ false); } if (i < profilesToStartSize) { Loading Loading @@ -1419,8 +1420,10 @@ class UserController implements Handler.Callback { return false; } // TODO(b/239982558): pass proper displayId return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, /* foreground= */ false, int displayId = mInjector.isUsersOnSecondaryDisplaysEnabled() ? UserManagerInternal.PARENT_DISPLAY : Display.DEFAULT_DISPLAY; return startUserNoChecks(userId, displayId, /* foreground= */ false, /* unlockListener= */ null); } Loading Loading @@ -1472,8 +1475,7 @@ class UserController implements Handler.Callback { // TODO(b/239982558): add javadoc (need to wait until the intents / SystemService callbacks are // defined boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId, @Nullable IProgressListener unlockListener) { boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId) { checkCallingHasOneOfThosePermissions("startUserOnSecondaryDisplay", MANAGE_USERS, CREATE_USERS); Loading @@ -1482,7 +1484,8 @@ class UserController implements Handler.Callback { "Cannot use DEFAULT_DISPLAY"); try { return startUserNoChecks(userId, displayId, /* foreground= */ false, unlockListener); return startUserNoChecks(userId, displayId, /* foreground= */ false, /* unlockListener= */ null); } catch (RuntimeException e) { Slogf.w(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e); return false; Loading Loading @@ -3484,5 +3487,9 @@ class UserController implements Handler.Callback { } }, reason); } boolean isUsersOnSecondaryDisplaysEnabled() { return UserManager.isUsersOnSecondaryDisplaysEnabled(); } } }
services/core/java/com/android/server/pm/UserManagerInternal.java +9 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,15 @@ public abstract class UserManagerInternal { public @interface OwnerType { } // TODO(b/245963156): move to Display.java (and @hide) if we decide to support profiles on MUMD /** * Used only when starting a profile (on systems that * {@link android.os.UserManager#isUsersOnSecondaryDisplaysSupported() support users running on * secondary displays}), to indicate the profile should be started in the same display as its * parent user. */ public static final int PARENT_DISPLAY = -2; public interface UserRestrictionsListener { /** * Called when a user restriction changes. Loading
services/core/java/com/android/server/pm/UserManagerService.java +29 −38 Original line number Diff line number Diff line Loading @@ -6825,34 +6825,23 @@ public class UserManagerService extends IUserManager.Stub { int currentUserId = getCurrentUserId(); Preconditions.checkArgument(userId != currentUserId, "Cannot assign current user to other displays"); boolean isProfile = isProfileUnchecked(userId); Preconditions.checkArgument(userId != currentUserId, "Cannot assign current user to other displays"); Preconditions.checkArgument( !isProfile || getProfileParentIdUnchecked(userId) != currentUserId, "Cannot assign profile user %d to display %d when its parent is the current " + "user (%d)", userId, displayId, currentUserId); "Cannot assign current user (%d) to other displays", currentUserId); synchronized (mUsersOnSecondaryDisplays) { if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding %d->%d to mUsersOnSecondaryDisplays", userId, displayId); } if (isProfile) { if (isProfileUnchecked(userId)) { // Profile can only start in the same display as parent Preconditions.checkArgument(displayId == UserManagerInternal.PARENT_DISPLAY, "Profile user can only be started in the same display as parent"); int parentUserId = getProfileParentId(userId); int parentDisplayId = mUsersOnSecondaryDisplays.get(parentUserId); if (displayId != parentDisplayId) { throw new IllegalStateException("Cannot assign profile " + userId + " to " + "display " + displayId + " as its parent (user " + parentUserId + ") is assigned to display " + parentDisplayId); if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding profile user %d -> display %d", userId, parentDisplayId); } } else { mUsersOnSecondaryDisplays.put(userId, parentDisplayId); return; } // Check if display is available for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) { // Make sure display is not used by other users... Loading @@ -6870,8 +6859,10 @@ public class UserManagerService extends IUserManager.Stub { // (for example, would need to add a new AM method to start user in bg on // main display), so it's better to test on unit tests } } if (DBG_MUMD) { Slogf.d(LOG_TAG, "Adding full user %d -> display %d", userId, displayId); } mUsersOnSecondaryDisplays.put(userId, displayId); } } Loading
services/tests/mockingservicestests/src/com/android/server/pm/UserManagerInternalTest.java +5 −13 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ 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.PARENT_DISPLAY; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; Loading Loading @@ -119,9 +121,6 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*parent.*current.*" + PARENT_USER_ID + ".*"); assertNoUserAssignedToDisplay(); } Loading @@ -136,10 +135,6 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*parent.*current.*" + PARENT_USER_ID + ".*"); assertNoUserAssignedToDisplay(); } Loading Loading @@ -173,7 +168,7 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT addDefaultProfileAndParent(); mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID); mUmi.assignUserToDisplay(PROFILE_USER_ID, PARENT_DISPLAY); assertUsersAssignedToDisplays(PARENT_USER_ID, SECONDARY_DISPLAY_ID, pair(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Loading @@ -185,13 +180,10 @@ public final class UserManagerInternalTest extends UserManagerServiceOrInternalT addDefaultProfileAndParent(); mUmi.assignUserToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); IllegalStateException e = assertThrows(IllegalStateException.class, () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, OTHER_SECONDARY_DISPLAY_ID)); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> mUmi.assignUserToDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)); Log.v(TAG, "Exception: " + e); assertWithMessage("exception (%s) message", e).that(e).hasMessageThat() .matches("Cannot.*" + PROFILE_USER_ID + ".*" + OTHER_SECONDARY_DISPLAY_ID + ".*parent.*" + PARENT_USER_ID + ".*" + SECONDARY_DISPLAY_ID + ".*"); assertUserAssignedToDisplay(PARENT_USER_ID, SECONDARY_DISPLAY_ID); } Loading