Add APIs to UserManager for getting remaining user/profile counts.
Add UM.getRemainingCreatableUserCount(userType) method as a system API. Add UM.getRemainingCreatableProfileCount(userType, allowedToRemoveOne) method as a system API. Bug: 208842920 Bug: 142482943 Test: atest android.multiuser.cts.UserManagerTest Change-Id: I286fe10b2c8448aeb03ee6c791d415ef62f50451
This commit is contained in:
@@ -9637,6 +9637,8 @@ package android.os {
|
||||
method @NonNull public java.util.List<android.os.UserHandle> getAllProfiles();
|
||||
method @NonNull public java.util.List<android.os.UserHandle> getEnabledProfiles();
|
||||
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableProfileCount(@NonNull String, boolean);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public int getRemainingCreatableUserCount(@NonNull String);
|
||||
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public android.os.UserHandle getRestrictedProfileParent();
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
|
||||
|
||||
@@ -62,6 +62,8 @@ interface IUserManager {
|
||||
int[] getProfileIds(int userId, boolean enabledOnly);
|
||||
boolean isUserTypeEnabled(in String userType);
|
||||
boolean canAddMoreUsersOfType(in String userType);
|
||||
int getRemainingCreatableUserCount(in String userType);
|
||||
int getRemainingCreatableProfileCount(in String userType, int userId, boolean allowedToRemoveOne);
|
||||
boolean canAddMoreProfilesToUser(in String userType, int userId, boolean allowedToRemoveOne);
|
||||
boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
|
||||
UserInfo getProfileParent(int userId);
|
||||
|
||||
@@ -4028,6 +4028,58 @@ public class UserManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining number of users of the given type that can be created.
|
||||
*
|
||||
* @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_SECONDARY}.
|
||||
* @return how many additional users can be created.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.MANAGE_USERS,
|
||||
android.Manifest.permission.CREATE_USERS,
|
||||
android.Manifest.permission.QUERY_USERS
|
||||
})
|
||||
public int getRemainingCreatableUserCount(@NonNull String userType) {
|
||||
Objects.requireNonNull(userType, "userType must not be null");
|
||||
try {
|
||||
return mService.getRemainingCreatableUserCount(userType);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining number of profiles that can be added to the context user.
|
||||
* <p>Note that is applicable to any profile type (currently not including Restricted profiles).
|
||||
*
|
||||
* @param userType the type of profile, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
|
||||
* @param allowedToRemoveOne whether removing an existing profile of given type -if there is-
|
||||
* from the context user to make up space should be taken into account
|
||||
* for the calculation.
|
||||
* @return how many additional profiles can be created.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.MANAGE_USERS,
|
||||
android.Manifest.permission.CREATE_USERS,
|
||||
android.Manifest.permission.QUERY_USERS
|
||||
})
|
||||
@UserHandleAware
|
||||
public int getRemainingCreatableProfileCount(@NonNull String userType,
|
||||
boolean allowedToRemoveOne) {
|
||||
Objects.requireNonNull(userType, "userType must not be null");
|
||||
try {
|
||||
// TODO(b/142482943): Perhaps let the following code apply to restricted users too.
|
||||
return mService.getRemainingCreatableProfileCount(userType, mUserId,
|
||||
allowedToRemoveOne);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether it's possible to add more managed profiles.
|
||||
* if allowedToRemoveOne is true and if the user already has a managed profile, then return if
|
||||
@@ -4038,6 +4090,7 @@ public class UserManager {
|
||||
*/
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.MANAGE_USERS,
|
||||
android.Manifest.permission.CREATE_USERS,
|
||||
android.Manifest.permission.QUERY_USERS
|
||||
})
|
||||
public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
|
||||
@@ -4057,6 +4110,7 @@ public class UserManager {
|
||||
*/
|
||||
@RequiresPermission(anyOf = {
|
||||
android.Manifest.permission.MANAGE_USERS,
|
||||
android.Manifest.permission.CREATE_USERS,
|
||||
android.Manifest.permission.QUERY_USERS
|
||||
})
|
||||
public boolean canAddMoreProfilesToUser(@NonNull String userType, @UserIdInt int userId) {
|
||||
@@ -4931,8 +4985,8 @@ public class UserManager {
|
||||
public static int getMaxSupportedUsers() {
|
||||
// Don't allow multiple users on certain builds
|
||||
if (android.os.Build.ID.startsWith("JVP")) return 1;
|
||||
return SystemProperties.getInt("fw.max_users",
|
||||
Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers));
|
||||
return Math.max(1, SystemProperties.getInt("fw.max_users",
|
||||
Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2417,6 +2417,51 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return getNumberOfUsersOfType(userTypeDetails.getName()) < max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining number of users of the given type that can be created. (taking into
|
||||
* account the total number of users on the device as well as how many exist of that type)
|
||||
*/
|
||||
@Override
|
||||
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()) {
|
||||
return 0;
|
||||
}
|
||||
synchronized (mUsersLock) {
|
||||
final int userCount = getAliveUsersExcludingGuestsCountLU();
|
||||
|
||||
// Limit total number of users that can be created (except for guest and demo)
|
||||
int result =
|
||||
UserManager.isUserTypeGuest(userType) || UserManager.isUserTypeDemo(userType)
|
||||
? Integer.MAX_VALUE
|
||||
: (UserManager.getMaxSupportedUsers() - userCount);
|
||||
|
||||
// Managed profiles have their own specific rules.
|
||||
if (type.isManagedProfile()) {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(
|
||||
PackageManager.FEATURE_MANAGED_USERS)) {
|
||||
return 0;
|
||||
}
|
||||
// Special case: Allow creating a managed profile anyway if there's only 1 user
|
||||
if (result <= 0 & userCount == 1) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
if (result <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Limit against max allowed for type
|
||||
result = Math.min(result,
|
||||
type.getMaxAllowed() == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS
|
||||
? Integer.MAX_VALUE
|
||||
: (type.getMaxAllowed() - getNumberOfUsersOfType(userType)));
|
||||
|
||||
return Math.max(0, result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of users of the given user type.
|
||||
* Does not include users that are about to die.
|
||||
@@ -2467,24 +2512,36 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
@Override
|
||||
public boolean canAddMoreProfilesToUser(String userType, @UserIdInt int userId,
|
||||
boolean allowedToRemoveOne) {
|
||||
checkQueryUsersPermission("check if more profiles can be added.");
|
||||
return 0 < getRemainingCreatableProfileCount(userType, userId, allowedToRemoveOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remaining number of profiles of the given type that can be added to the given
|
||||
* user. (taking into account the total number of users on the device as well as how many
|
||||
* profiles exist of that type both in general and for the given user)
|
||||
*/
|
||||
@Override
|
||||
public int getRemainingCreatableProfileCount(@NonNull String userType, @UserIdInt int userId,
|
||||
boolean allowedToRemoveOne) {
|
||||
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()) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
// Managed profiles have their own specific rules.
|
||||
final boolean isManagedProfile = type.isManagedProfile();
|
||||
if (isManagedProfile) {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(
|
||||
PackageManager.FEATURE_MANAGED_USERS)) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
synchronized (mUsersLock) {
|
||||
// Check if the parent exists and its type is even allowed to have a profile.
|
||||
UserInfo userInfo = getUserInfoLU(userId);
|
||||
if (userInfo == null || !userInfo.canHaveProfile()) {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int userTypeCount = getProfileIds(userId, userType, false).length;
|
||||
@@ -2493,23 +2550,30 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
- profilesRemovedCount;
|
||||
|
||||
// Limit total number of users that can be created
|
||||
if (usersCountAfterRemoving >= UserManager.getMaxSupportedUsers()) {
|
||||
// Special case: Allow creating a managed profile anyway if there's only 1 user
|
||||
// Otherwise, disallow.
|
||||
if (!(isManagedProfile && usersCountAfterRemoving == 1)) {
|
||||
return false;
|
||||
}
|
||||
int result = UserManager.getMaxSupportedUsers() - usersCountAfterRemoving;
|
||||
|
||||
// Special case: Allow creating a managed profile anyway if there's only 1 user
|
||||
if (result <= 0 && isManagedProfile && usersCountAfterRemoving == 1) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
// Limit the number of profiles of this type that can be created.
|
||||
final int maxUsersOfType = getMaxUsersOfTypePerParent(type);
|
||||
if (maxUsersOfType != UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) {
|
||||
if (userTypeCount - profilesRemovedCount >= maxUsersOfType) {
|
||||
return false;
|
||||
}
|
||||
result = Math.min(result, maxUsersOfType - (userTypeCount - profilesRemovedCount));
|
||||
}
|
||||
if (result <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Limit against max allowed for type (beyond max allowed per parent)
|
||||
if (type.getMaxAllowed() != UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) {
|
||||
result = Math.min(result, type.getMaxAllowed()
|
||||
- (getNumberOfUsersOfType(userType) - profilesRemovedCount));
|
||||
}
|
||||
|
||||
return Math.max(0, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@GuardedBy("mUsersLock")
|
||||
@@ -3791,6 +3855,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
+ ". Maximum number of that type already exists.",
|
||||
UserManager.USER_OPERATION_ERROR_MAX_USERS);
|
||||
}
|
||||
// Keep logic in sync with getRemainingCreatableUserCount()
|
||||
if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
|
||||
// If the user limit has been reached, we cannot add a user (except guest/demo).
|
||||
// Note that managed profiles can bypass it in certain circumstances (taken
|
||||
|
||||
Reference in New Issue
Block a user