From 82c53f0c8569c254e983ea601d5806f0b9251eab Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Wed, 9 Nov 2022 13:13:02 -0800 Subject: [PATCH] SystemProperty to create disabled usertypes For development, it helps to be able to create users whose usertype is disabled or their limit has been reached. We therefore introduce a system property for this. It can only be used on debug builds. Bug: 255793314 Bug: 137101239 Test: adb shell setprop debug.user.creation_override 1 && try to create disabled users Change-Id: I6ab2aa80b0387b32f1b5fe5e9c8dd0096ed7bcd7 --- core/java/android/os/UserManager.java | 10 ++++ .../android/server/pm/UserManagerService.java | 57 ++++++++++--------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 3d20d6373ae29..c2793c3d58e68 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1612,6 +1612,16 @@ public class UserManager { /** @hide */ public static final String SYSTEM_USER_MODE_EMULATION_HEADLESS = "headless"; + /** + * System Property used to override whether users can be created even if their type is disabled + * or their limit is reached. Set value to 1 to enable. + * + *

Only used on non-user builds. + * + * @hide + */ + public static final String DEV_CREATE_OVERRIDE_PROPERTY = "debug.user.creation_override"; + private static final String ACTION_CREATE_USER = "android.os.action.CREATE_USER"; /** diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index f85b11da252ea..4a53e278e32fa 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.UserManager.DEV_CREATE_OVERRIDE_PROPERTY; import static android.os.UserManager.DISALLOW_USER_SWITCH; import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY; @@ -2807,7 +2808,8 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUsersLock) { count = getAliveUsersExcludingGuestsCountLU(); } - return count >= UserManager.getMaxSupportedUsers(); + return count >= UserManager.getMaxSupportedUsers() + && !isCreationOverrideEnabled(); } /** @@ -2817,15 +2819,16 @@ public class UserManagerService extends IUserManager.Stub { *

For checking whether more profiles can be added to a particular parent use * {@link #canAddMoreProfilesToUser}. */ - private boolean canAddMoreUsersOfType(UserTypeDetails userTypeDetails) { - if (!userTypeDetails.isEnabled()) { + private boolean canAddMoreUsersOfType(@NonNull UserTypeDetails userTypeDetails) { + if (!isUserTypeEnabled(userTypeDetails)) { return false; } final int max = userTypeDetails.getMaxAllowed(); if (max == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) { return true; // Indicates that there is no max. } - return getNumberOfUsersOfType(userTypeDetails.getName()) < max; + return getNumberOfUsersOfType(userTypeDetails.getName()) < max + || isCreationOverrideEnabled(); } /** @@ -2836,7 +2839,7 @@ public class UserManagerService extends IUserManager.Stub { public int getRemainingCreatableUserCount(String userType) { checkQueryOrCreateUsersPermission("get the remaining number of users that can be added."); final UserTypeDetails type = mUserTypes.get(userType); - if (type == null || !type.isEnabled()) { + if (type == null || !isUserTypeEnabled(type)) { return 0; } synchronized (mUsersLock) { @@ -2910,7 +2913,21 @@ public class UserManagerService extends IUserManager.Stub { public boolean isUserTypeEnabled(String userType) { checkCreateUsersPermission("check if user type is enabled."); final UserTypeDetails userTypeDetails = mUserTypes.get(userType); - return userTypeDetails != null && userTypeDetails.isEnabled(); + return userTypeDetails != null && isUserTypeEnabled(userTypeDetails); + } + + /** Returns whether the creation of users of the given user type is enabled on this device. */ + private boolean isUserTypeEnabled(@NonNull UserTypeDetails userTypeDetails) { + return userTypeDetails.isEnabled() || isCreationOverrideEnabled(); + } + + /** + * Returns whether to almost-always allow creating users even beyond their limit or if disabled. + * For Debug builds only. + */ + private boolean isCreationOverrideEnabled() { + return Build.isDebuggable() + && SystemProperties.getBoolean(DEV_CREATE_OVERRIDE_PROPERTY, false); } @Override @@ -2923,7 +2940,8 @@ public class UserManagerService extends IUserManager.Stub { @Override public boolean canAddMoreProfilesToUser(String userType, @UserIdInt int userId, boolean allowedToRemoveOne) { - return 0 < getRemainingCreatableProfileCount(userType, userId, allowedToRemoveOne); + return 0 < getRemainingCreatableProfileCount(userType, userId, allowedToRemoveOne) + || isCreationOverrideEnabled(); } @Override @@ -2941,7 +2959,7 @@ public class UserManagerService extends IUserManager.Stub { checkQueryOrCreateUsersPermission( "get the remaining number of profiles that can be added to the given user."); final UserTypeDetails type = mUserTypes.get(userType); - if (type == null || !type.isEnabled()) { + if (type == null || !isUserTypeEnabled(type)) { return 0; } // Managed profiles have their own specific rules. @@ -4400,7 +4418,7 @@ public class UserManagerService extends IUserManager.Stub { + ") indicated SYSTEM user, which cannot be created."); return null; } - if (!userTypeDetails.isEnabled()) { + if (!isUserTypeEnabled(userTypeDetails)) { throwCheckedUserOperationException( "Cannot add a user of disabled type " + userType + ".", UserManager.USER_OPERATION_ERROR_MAX_USERS); @@ -4472,27 +4490,12 @@ public class UserManagerService extends IUserManager.Stub { + " for user " + parentId, UserManager.USER_OPERATION_ERROR_MAX_USERS); } - // In legacy mode, restricted profile's parent can only be the owner user - if (isRestricted && !UserManager.isSplitSystemUser() - && (parentId != UserHandle.USER_SYSTEM)) { + if (isRestricted && (parentId != UserHandle.USER_SYSTEM) + && !isCreationOverrideEnabled()) { throwCheckedUserOperationException( - "Cannot add restricted profile - parent user must be owner", + "Cannot add restricted profile - parent user must be system", UserManager.USER_OPERATION_ERROR_UNKNOWN); } - if (isRestricted && UserManager.isSplitSystemUser()) { - if (parent == null) { - throwCheckedUserOperationException( - "Cannot add restricted profile - parent user must be specified", - UserManager.USER_OPERATION_ERROR_UNKNOWN); - } - if (!parent.info.canHaveProfile()) { - throwCheckedUserOperationException( - "Cannot add restricted profile - profiles cannot be created for " - + "the specified parent user id " - + parentId, - UserManager.USER_OPERATION_ERROR_UNKNOWN); - } - } userId = getNextAvailableId(); Slog.i(LOG_TAG, "Creating user " + userId + " of type " + userType);