Loading services/core/java/com/android/server/pm/UserManagerService.java +38 −7 Original line number Diff line number Diff line Loading @@ -341,6 +341,10 @@ public class UserManagerService extends IUserManager.Stub { private static final String TRON_USER_CREATED = "users_user_created"; private static final String TRON_DEMO_CREATED = "users_demo_created"; // The boot user strategy for HSUM. private static final int BOOT_TO_PREVIOUS_OR_FIRST_SWITCHABLE_USER = 0; private static final int BOOT_TO_HSU_FOR_PROVISIONED_DEVICE = 1; private final Context mContext; private final PackageManagerService mPm; Loading Loading @@ -1391,16 +1395,42 @@ public class UserManagerService extends IUserManager.Stub { } if (isHeadlessSystemUserMode()) { if (mContext.getResources() .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser)) { return UserHandle.USER_SYSTEM; } final int bootStrategy = mContext.getResources() .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); switch (bootStrategy) { case BOOT_TO_PREVIOUS_OR_FIRST_SWITCHABLE_USER: return getPreviousOrFirstSwitchableUser(); case BOOT_TO_HSU_FOR_PROVISIONED_DEVICE: return getBootUserBasedOnProvisioning(); default: Slogf.w(LOG_TAG, "Unknown HSUM boot strategy: %d", bootStrategy); return getPreviousOrFirstSwitchableUser(); } } // Not HSUM, return system user. return UserHandle.USER_SYSTEM; } private @UserIdInt int getBootUserBasedOnProvisioning() throws UserManager.CheckedUserOperationException { final boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; if (provisioned) { return UserHandle.USER_SYSTEM; } else { final int firstSwitchableFullUser = getFirstSwitchableUser(true); if (firstSwitchableFullUser != UserHandle.USER_NULL) { Slogf.i(LOG_TAG, "Boot user is first switchable full user %d", firstSwitchableFullUser); return firstSwitchableFullUser; } // No switchable full user found. Uh oh! throw new UserManager.CheckedUserOperationException( "No switchable full user found", USER_OPERATION_ERROR_UNKNOWN); } } private @UserIdInt int getPreviousOrFirstSwitchableUser() throws UserManager.CheckedUserOperationException { // Return the previous foreground user, if there is one. Loading @@ -1410,7 +1440,7 @@ public class UserManagerService extends IUserManager.Stub { return previousUser; } // No previous user. Return the first switchable user if there is one. final int firstSwitchableUser = getFirstSwitchableUser(); final int firstSwitchableUser = getFirstSwitchableUser(false); if (firstSwitchableUser != UserHandle.USER_NULL) { Slogf.i(LOG_TAG, "Boot user is first switchable user %d", firstSwitchableUser); Loading @@ -1421,12 +1451,13 @@ public class UserManagerService extends IUserManager.Stub { "No switchable users found", USER_OPERATION_ERROR_UNKNOWN); } private @UserIdInt int getFirstSwitchableUser() { private @UserIdInt int getFirstSwitchableUser(boolean fullUserOnly) { synchronized (mUsersLock) { final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { final UserData userData = mUsers.valueAt(i); if (userData.info.supportsSwitchToByUser()) { if (userData.info.supportsSwitchToByUser() && (!fullUserOnly || userData.info.isFull())) { int firstSwitchable = userData.info.id; return firstSwitchable; } Loading services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +46 −6 Original line number Diff line number Diff line Loading @@ -195,12 +195,12 @@ public final class UserManagerServiceTest { doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any()); mockIsLowRamDevice(false); // Called when getting boot user. config_bootToHeadlessSystemUser is false by default. // Called when getting boot user. config_bootToHeadlessSystemUser is 0 by default. mSpyResources = spy(mSpiedContext.getResources()); when(mSpiedContext.getResources()).thenReturn(mSpyResources); doReturn(false) doReturn(0) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser); .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); // Must construct UserManagerService in the UiThread mTestDir = new File(mRealContext.getDataDir(), "umstest"); Loading Loading @@ -859,15 +859,50 @@ public final class UserManagerServiceTest { } @Test public void testGetBootUser_enableBootToHeadlessSystemUser() { public void testGetBootUser_Headless_BootToSystemUserWhenDeviceIsProvisioned() { setSystemUserHeadless(true); doReturn(true) addUser(USER_ID); addUser(OTHER_USER_ID); mockProvisionedDevice(true); doReturn(1) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser); .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); assertThat(mUms.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM); } @Test public void testGetBootUser_Headless_BootToFirstSwitchableFullUserWhenDeviceNotProvisioned() { setSystemUserHeadless(true); addUser(USER_ID); addUser(OTHER_USER_ID); mockProvisionedDevice(false); doReturn(1) .when(mSpyResources) .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); // Even if the headless system user switchable flag is true, the boot user should be the // first switchable full user. doReturn(true) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_canSwitchToHeadlessSystemUser); assertThat(mUms.getBootUser()).isEqualTo(USER_ID); } @Test public void testGetBootUser_Headless_ThrowsIfBootFailsNoFullUserWhenDeviceNotProvisioned() throws Exception { setSystemUserHeadless(true); removeNonSystemUsers(); mockProvisionedDevice(false); doReturn(1) .when(mSpyResources) .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); assertThrows(ServiceSpecificException.class, () -> mUms.getBootUser()); } /** * Returns true if the user's XML file has Default restrictions * @param userId Id of the user. Loading Loading @@ -935,6 +970,11 @@ public final class UserManagerServiceTest { any(), eq(android.provider.Settings.Global.USER_SWITCHER_ENABLED), anyInt())); } private void mockProvisionedDevice(boolean isProvisionedDevice) { doReturn(isProvisionedDevice ? 1 : 0).when(() -> Settings.Global.getInt( any(), eq(android.provider.Settings.Global.DEVICE_PROVISIONED), anyInt())); } private void mockIsLowRamDevice(boolean isLowRamDevice) { doReturn(isLowRamDevice).when(ActivityManager::isLowRamDeviceStatic); } Loading Loading
services/core/java/com/android/server/pm/UserManagerService.java +38 −7 Original line number Diff line number Diff line Loading @@ -341,6 +341,10 @@ public class UserManagerService extends IUserManager.Stub { private static final String TRON_USER_CREATED = "users_user_created"; private static final String TRON_DEMO_CREATED = "users_demo_created"; // The boot user strategy for HSUM. private static final int BOOT_TO_PREVIOUS_OR_FIRST_SWITCHABLE_USER = 0; private static final int BOOT_TO_HSU_FOR_PROVISIONED_DEVICE = 1; private final Context mContext; private final PackageManagerService mPm; Loading Loading @@ -1391,16 +1395,42 @@ public class UserManagerService extends IUserManager.Stub { } if (isHeadlessSystemUserMode()) { if (mContext.getResources() .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser)) { return UserHandle.USER_SYSTEM; } final int bootStrategy = mContext.getResources() .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); switch (bootStrategy) { case BOOT_TO_PREVIOUS_OR_FIRST_SWITCHABLE_USER: return getPreviousOrFirstSwitchableUser(); case BOOT_TO_HSU_FOR_PROVISIONED_DEVICE: return getBootUserBasedOnProvisioning(); default: Slogf.w(LOG_TAG, "Unknown HSUM boot strategy: %d", bootStrategy); return getPreviousOrFirstSwitchableUser(); } } // Not HSUM, return system user. return UserHandle.USER_SYSTEM; } private @UserIdInt int getBootUserBasedOnProvisioning() throws UserManager.CheckedUserOperationException { final boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; if (provisioned) { return UserHandle.USER_SYSTEM; } else { final int firstSwitchableFullUser = getFirstSwitchableUser(true); if (firstSwitchableFullUser != UserHandle.USER_NULL) { Slogf.i(LOG_TAG, "Boot user is first switchable full user %d", firstSwitchableFullUser); return firstSwitchableFullUser; } // No switchable full user found. Uh oh! throw new UserManager.CheckedUserOperationException( "No switchable full user found", USER_OPERATION_ERROR_UNKNOWN); } } private @UserIdInt int getPreviousOrFirstSwitchableUser() throws UserManager.CheckedUserOperationException { // Return the previous foreground user, if there is one. Loading @@ -1410,7 +1440,7 @@ public class UserManagerService extends IUserManager.Stub { return previousUser; } // No previous user. Return the first switchable user if there is one. final int firstSwitchableUser = getFirstSwitchableUser(); final int firstSwitchableUser = getFirstSwitchableUser(false); if (firstSwitchableUser != UserHandle.USER_NULL) { Slogf.i(LOG_TAG, "Boot user is first switchable user %d", firstSwitchableUser); Loading @@ -1421,12 +1451,13 @@ public class UserManagerService extends IUserManager.Stub { "No switchable users found", USER_OPERATION_ERROR_UNKNOWN); } private @UserIdInt int getFirstSwitchableUser() { private @UserIdInt int getFirstSwitchableUser(boolean fullUserOnly) { synchronized (mUsersLock) { final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { final UserData userData = mUsers.valueAt(i); if (userData.info.supportsSwitchToByUser()) { if (userData.info.supportsSwitchToByUser() && (!fullUserOnly || userData.info.isFull())) { int firstSwitchable = userData.info.id; return firstSwitchable; } Loading
services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +46 −6 Original line number Diff line number Diff line Loading @@ -195,12 +195,12 @@ public final class UserManagerServiceTest { doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any()); mockIsLowRamDevice(false); // Called when getting boot user. config_bootToHeadlessSystemUser is false by default. // Called when getting boot user. config_bootToHeadlessSystemUser is 0 by default. mSpyResources = spy(mSpiedContext.getResources()); when(mSpiedContext.getResources()).thenReturn(mSpyResources); doReturn(false) doReturn(0) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser); .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); // Must construct UserManagerService in the UiThread mTestDir = new File(mRealContext.getDataDir(), "umstest"); Loading Loading @@ -859,15 +859,50 @@ public final class UserManagerServiceTest { } @Test public void testGetBootUser_enableBootToHeadlessSystemUser() { public void testGetBootUser_Headless_BootToSystemUserWhenDeviceIsProvisioned() { setSystemUserHeadless(true); doReturn(true) addUser(USER_ID); addUser(OTHER_USER_ID); mockProvisionedDevice(true); doReturn(1) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_bootToHeadlessSystemUser); .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); assertThat(mUms.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM); } @Test public void testGetBootUser_Headless_BootToFirstSwitchableFullUserWhenDeviceNotProvisioned() { setSystemUserHeadless(true); addUser(USER_ID); addUser(OTHER_USER_ID); mockProvisionedDevice(false); doReturn(1) .when(mSpyResources) .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); // Even if the headless system user switchable flag is true, the boot user should be the // first switchable full user. doReturn(true) .when(mSpyResources) .getBoolean(com.android.internal.R.bool.config_canSwitchToHeadlessSystemUser); assertThat(mUms.getBootUser()).isEqualTo(USER_ID); } @Test public void testGetBootUser_Headless_ThrowsIfBootFailsNoFullUserWhenDeviceNotProvisioned() throws Exception { setSystemUserHeadless(true); removeNonSystemUsers(); mockProvisionedDevice(false); doReturn(1) .when(mSpyResources) .getInteger(com.android.internal.R.integer.config_hsumBootStrategy); assertThrows(ServiceSpecificException.class, () -> mUms.getBootUser()); } /** * Returns true if the user's XML file has Default restrictions * @param userId Id of the user. Loading Loading @@ -935,6 +970,11 @@ public final class UserManagerServiceTest { any(), eq(android.provider.Settings.Global.USER_SWITCHER_ENABLED), anyInt())); } private void mockProvisionedDevice(boolean isProvisionedDevice) { doReturn(isProvisionedDevice ? 1 : 0).when(() -> Settings.Global.getInt( any(), eq(android.provider.Settings.Global.DEVICE_PROVISIONED), anyInt())); } private void mockIsLowRamDevice(boolean isLowRamDevice) { doReturn(isLowRamDevice).when(ActivityManager::isLowRamDeviceStatic); } Loading