Decouple user limit from guest creation
Allow Guest to be created even if there are N users.
Allow N users to be created even if there are N-1 users
and a Guest.
Limit number of guests and managed profiles that can
be added.
Added unit tests.
Bug: 15934700
Change-Id: I1a8f0fa38a91d71ef7b2980e05c974244dfc337a
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 33ecc4d..ad87993 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -125,6 +125,10 @@
// Number of attempts before jumping to the next BACKOFF_TIMES slot
private static final int BACKOFF_INC_INTERVAL = 5;
+ // Maximum number of managed profiles permitted is 1. This cannot be increased
+ // without first making sure that the rest of the framework is prepared for it.
+ private static final int MAX_MANAGED_PROFILES = 1;
+
// Amount of time to force the user to wait before entering the PIN again, after failing
// BACKOFF_INC_INTERVAL times.
private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
@@ -510,7 +514,8 @@
// Skip over users being removed
for (int i = 0; i < totalUserCount; i++) {
UserInfo user = mUsers.valueAt(i);
- if (!mRemovingUserIds.get(user.id)) {
+ if (!mRemovingUserIds.get(user.id)
+ && !user.isGuest()) {
aliveUserCount++;
}
}
@@ -1093,6 +1098,7 @@
Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
return null;
}
+ final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo = null;
try {
@@ -1103,7 +1109,21 @@
parent = getUserInfoLocked(parentId);
if (parent == null) return null;
}
- if (isUserLimitReachedLocked()) return null;
+ // If we're not adding a guest user and the limit has been reached,
+ // cannot add a user.
+ if (!isGuest && isUserLimitReachedLocked()) {
+ return null;
+ }
+ // If we're adding a guest and there already exists one, bail.
+ if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) {
+ 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));
@@ -1142,6 +1162,19 @@
return userInfo;
}
+ private int numberOfUsersOfTypeLocked(int flags, boolean excludeDying) {
+ int count = 0;
+ for (int i = mUsers.size() - 1; i >= 0; i--) {
+ UserInfo user = mUsers.valueAt(i);
+ if (!excludeDying || !mRemovingUserIds.get(user.id)) {
+ if ((user.flags & flags) != 0) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
/**
* Removes a user and all data directories created for that user. This method should be called
* after the user's processes have been terminated.