Loading services/core/java/com/android/server/am/UserController.java +7 −0 Original line number Diff line number Diff line Loading @@ -993,6 +993,13 @@ class UserController implements Handler.Callback { if (isCurrentUserLU(userId)) { return USER_OP_IS_CURRENT; } // TODO(b/324647580): Refactor the idea of "force" and clean up. In the meantime... final int parentId = mUserProfileGroupIds.get(userId, UserInfo.NO_PROFILE_GROUP_ID); if (parentId != UserInfo.NO_PROFILE_GROUP_ID && parentId != userId) { if ((UserHandle.USER_SYSTEM == parentId || isCurrentUserLU(parentId)) && !force) { return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; } } TimingsTraceAndSlog t = new TimingsTraceAndSlog(); int[] usersToStop = getUsersToStopLU(userId); // If one of related users is system or current, no related users should be stopped Loading services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +82 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; Loading Loading @@ -677,6 +678,87 @@ public class UserControllerTest { .lockCeStorage(TEST_USER_ID); } /** * Test that, when exceeding the maximum number of running users, a profile of the current user * is not stopped. */ @Test public void testStoppingExcessRunningUsersAfterSwitch_currentProfileNotStopped() throws Exception { mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false); final int PARENT_ID = 200; final int PROFILE1_ID = 201; final int PROFILE2_ID = 202; final int FG_USER_ID = 300; final int BG_USER_ID = 400; setUpUser(PARENT_ID, 0).profileGroupId = PARENT_ID; setUpUser(PROFILE1_ID, UserInfo.FLAG_PROFILE).profileGroupId = PARENT_ID; setUpUser(PROFILE2_ID, UserInfo.FLAG_PROFILE).profileGroupId = PARENT_ID; setUpUser(FG_USER_ID, 0).profileGroupId = FG_USER_ID; setUpUser(BG_USER_ID, 0).profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; mUserController.onSystemReady(); // To set the profileGroupIds in UserController. assertEquals(newHashSet( SYSTEM_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); int numberOfUserSwitches = 1; addForegroundUserAndContinueUserSwitch(PARENT_ID, UserHandle.USER_SYSTEM, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(PARENT_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); assertTrue(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); assertThat(mUserController.startProfile(PROFILE1_ID, true, null)).isTrue(); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); numberOfUserSwitches++; addForegroundUserAndContinueUserSwitch(FG_USER_ID, PARENT_ID, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(FG_USER_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); assertTrue(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID, FG_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); mUserController.startUser(BG_USER_ID, USER_START_MODE_BACKGROUND); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID, BG_USER_ID, FG_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); // Now we exceed the maxRunningUsers parameter (of 5): assertThat(mUserController.startProfile(PROFILE2_ID, true, null)).isTrue(); // Currently, starting a profile doesn't trigger evaluating whether we've exceeded max, so // we expect no users to be stopped. This policy may change in the future. Log but no fail. if (!newHashSet(SYSTEM_USER_ID, PROFILE1_ID, BG_USER_ID, PROFILE2_ID, PARENT_ID, FG_USER_ID) .equals(new HashSet<>(mUserController.getRunningUsersLU()))) { Log.w(TAG, "Starting a profile that exceeded max running users didn't lead to " + "expectations: " + mUserController.getRunningUsersLU()); } numberOfUserSwitches++; addForegroundUserAndContinueUserSwitch(PARENT_ID, FG_USER_ID, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(PARENT_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); // We've now done a user switch and should notice that we've exceeded the maximum number of // users. The oldest background user should be stopped (BG_USER); even though PROFILE1 was // older, it should not be stopped since it's a profile of the (new) current user. assertFalse(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PROFILE2_ID, FG_USER_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); } /** * Test that, in getRunningUsersLU, parents come after their profile, even if the profile was * started afterwards. Loading Loading
services/core/java/com/android/server/am/UserController.java +7 −0 Original line number Diff line number Diff line Loading @@ -993,6 +993,13 @@ class UserController implements Handler.Callback { if (isCurrentUserLU(userId)) { return USER_OP_IS_CURRENT; } // TODO(b/324647580): Refactor the idea of "force" and clean up. In the meantime... final int parentId = mUserProfileGroupIds.get(userId, UserInfo.NO_PROFILE_GROUP_ID); if (parentId != UserInfo.NO_PROFILE_GROUP_ID && parentId != userId) { if ((UserHandle.USER_SYSTEM == parentId || isCurrentUserLU(parentId)) && !force) { return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; } } TimingsTraceAndSlog t = new TimingsTraceAndSlog(); int[] usersToStop = getUsersToStopLU(userId); // If one of related users is system or current, no related users should be stopped Loading
services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +82 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; Loading Loading @@ -677,6 +678,87 @@ public class UserControllerTest { .lockCeStorage(TEST_USER_ID); } /** * Test that, when exceeding the maximum number of running users, a profile of the current user * is not stopped. */ @Test public void testStoppingExcessRunningUsersAfterSwitch_currentProfileNotStopped() throws Exception { mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, /* maxRunningUsers= */ 5, /* delayUserDataLocking= */ false); final int PARENT_ID = 200; final int PROFILE1_ID = 201; final int PROFILE2_ID = 202; final int FG_USER_ID = 300; final int BG_USER_ID = 400; setUpUser(PARENT_ID, 0).profileGroupId = PARENT_ID; setUpUser(PROFILE1_ID, UserInfo.FLAG_PROFILE).profileGroupId = PARENT_ID; setUpUser(PROFILE2_ID, UserInfo.FLAG_PROFILE).profileGroupId = PARENT_ID; setUpUser(FG_USER_ID, 0).profileGroupId = FG_USER_ID; setUpUser(BG_USER_ID, 0).profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; mUserController.onSystemReady(); // To set the profileGroupIds in UserController. assertEquals(newHashSet( SYSTEM_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); int numberOfUserSwitches = 1; addForegroundUserAndContinueUserSwitch(PARENT_ID, UserHandle.USER_SYSTEM, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(PARENT_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); assertTrue(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); assertThat(mUserController.startProfile(PROFILE1_ID, true, null)).isTrue(); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); numberOfUserSwitches++; addForegroundUserAndContinueUserSwitch(FG_USER_ID, PARENT_ID, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(FG_USER_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); assertTrue(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID, FG_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); mUserController.startUser(BG_USER_ID, USER_START_MODE_BACKGROUND); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PARENT_ID, BG_USER_ID, FG_USER_ID), new HashSet<>(mUserController.getRunningUsersLU())); // Now we exceed the maxRunningUsers parameter (of 5): assertThat(mUserController.startProfile(PROFILE2_ID, true, null)).isTrue(); // Currently, starting a profile doesn't trigger evaluating whether we've exceeded max, so // we expect no users to be stopped. This policy may change in the future. Log but no fail. if (!newHashSet(SYSTEM_USER_ID, PROFILE1_ID, BG_USER_ID, PROFILE2_ID, PARENT_ID, FG_USER_ID) .equals(new HashSet<>(mUserController.getRunningUsersLU()))) { Log.w(TAG, "Starting a profile that exceeded max running users didn't lead to " + "expectations: " + mUserController.getRunningUsersLU()); } numberOfUserSwitches++; addForegroundUserAndContinueUserSwitch(PARENT_ID, FG_USER_ID, numberOfUserSwitches, false); mUserController.finishUserSwitch(mUserStates.get(PARENT_ID)); waitForHandlerToComplete(mInjector.mHandler, HANDLER_WAIT_TIME_MS); // We've now done a user switch and should notice that we've exceeded the maximum number of // users. The oldest background user should be stopped (BG_USER); even though PROFILE1 was // older, it should not be stopped since it's a profile of the (new) current user. assertFalse(mUserController.canStartMoreUsers()); assertEquals(newHashSet( SYSTEM_USER_ID, PROFILE1_ID, PROFILE2_ID, FG_USER_ID, PARENT_ID), new HashSet<>(mUserController.getRunningUsersLU())); } /** * Test that, in getRunningUsersLU, parents come after their profile, even if the profile was * started afterwards. Loading