diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index f212daff29f05..aa4b0514c02d8 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -36,6 +36,7 @@ interface IUserManager { ParcelFileDescriptor getUserIcon(int userHandle); List getUsers(boolean excludeDying); List getProfiles(int userHandle, boolean enabledOnly); + boolean canAddMoreManagedProfiles(); UserInfo getProfileParent(int userHandle); UserInfo getUserInfo(int userHandle); long getUserCreationTime(int userHandle); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 3dee68c1e756e..11043b33a36b9 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -932,6 +932,22 @@ public class UserManager { return aliveUserCount < getMaxSupportedUsers(); } + /** + * Checks whether it's possible to add more managed profiles. Caller must hold the MANAGE_USERS + * permission. + * + * @return true if more managed profiles can be added, false if limit has been reached. + * @hide + */ + public boolean canAddMoreManagedProfiles() { + try { + return mService.canAddMoreManagedProfiles(); + } catch (RemoteException re) { + Log.w(TAG, "Could not check if we can add more managed profiles", re); + return false; + } + } + /** * Returns list of the profiles of userHandle including * userHandle itself. diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 40c8ca32d205f..15d1535a2eb14 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -580,6 +580,28 @@ public class UserManagerService extends IUserManager.Stub { * Check if we've hit the limit of how many users can be created. */ private boolean isUserLimitReachedLocked() { + return getAliveUsersExcludingGuestsCountLocked() >= UserManager.getMaxSupportedUsers(); + } + + @Override + public boolean canAddMoreManagedProfiles() { + checkManageUsersPermission("check if more managed profiles can be added."); + if (ActivityManager.isLowRamDeviceStatic()) { + return false; + } + synchronized(mPackagesLock) { + // Limit number of managed profiles that can be created + if (numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true) + >= MAX_MANAGED_PROFILES) { + return false; + } + int usersCount = getAliveUsersExcludingGuestsCountLocked(); + // We allow creating a managed profile in the special case where there is only one user. + return usersCount == 1 || usersCount < UserManager.getMaxSupportedUsers(); + } + } + + private int getAliveUsersExcludingGuestsCountLocked() { int aliveUserCount = 0; final int totalUserCount = mUsers.size(); // Skip over users being removed @@ -590,7 +612,7 @@ public class UserManagerService extends IUserManager.Stub { aliveUserCount++; } } - return aliveUserCount >= UserManager.getMaxSupportedUsers(); + return aliveUserCount; } /** @@ -1176,7 +1198,11 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); return null; } + if (ActivityManager.isLowRamDeviceStatic()) { + return null; + } final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0; + final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0; final long ident = Binder.clearCallingIdentity(); UserInfo userInfo = null; try { @@ -1187,21 +1213,18 @@ public class UserManagerService extends IUserManager.Stub { parent = getUserInfoLocked(parentId); if (parent == null) return null; } - // If we're not adding a guest user and the limit has been reached, - // cannot add a user. - if (!isGuest && isUserLimitReachedLocked()) { + if (isManagedProfile && !canAddMoreManagedProfiles()) { + return null; + } + if (!isGuest && !isManagedProfile && isUserLimitReachedLocked()) { + // If we're not adding a guest user or a managed profile and the limit has + // been reached, cannot add a user. return null; } // If we're adding a guest and there already exists one, bail. if (isGuest && findCurrentGuestUserLocked() != null) { return null; } - // Limit number of managed profiles that can be created - if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0 - && numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true) - >= MAX_MANAGED_PROFILES) { - return null; - } int userId = getNextAvailableIdLocked(); userInfo = new UserInfo(userId, name, null, flags); File userPath = new File(mBaseUserPath, Integer.toString(userId));