summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2014-08-11 17:09:26 -0700
committerAmith Yamasani <yamasani@google.com>2014-08-13 20:09:20 +0000
commit95ab7849444125387dc88088bb5197ee463d8c17 (patch)
treec5747585a3e3e2dd8aed2475767eaf91c9376ff5 /services
parent437e61d5adc81b57c11f56b94ecc75239708fbb1 (diff)
downloadframeworks_base-95ab7849444125387dc88088bb5197ee463d8c17.zip
frameworks_base-95ab7849444125387dc88088bb5197ee463d8c17.tar.gz
frameworks_base-95ab7849444125387dc88088bb5197ee463d8c17.tar.bz2
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
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java37
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java35
2 files changed, 70 insertions, 2 deletions
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 @@ public class UserManagerService extends IUserManager.Stub {
// 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 @@ public class UserManagerService extends IUserManager.Stub {
// 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 @@ public class UserManagerService extends IUserManager.Stub {
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 @@ public class UserManagerService extends IUserManager.Stub {
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 @@ public class UserManagerService extends IUserManager.Stub {
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.
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 2e309be..6e13732 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -47,6 +47,18 @@ public class UserManagerTest extends AndroidTestCase {
}
}
}, filter);
+
+ removeExistingUsers();
+ }
+
+ private void removeExistingUsers() {
+ List<UserInfo> list = mUserManager.getUsers();
+ boolean found = false;
+ for (UserInfo user : list) {
+ if (user.id != UserHandle.USER_OWNER) {
+ removeUser(user.id);
+ }
+ }
}
public void testHasPrimary() throws Exception {
@@ -95,6 +107,29 @@ public class UserManagerTest extends AndroidTestCase {
assertFalse(findUser(userInfo.id));
}
+ public void testAddGuest() throws Exception {
+ UserInfo userInfo1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+ UserInfo userInfo2 = mUserManager.createUser("Guest 2", UserInfo.FLAG_GUEST);
+ assertNotNull(userInfo1);
+ assertNull(userInfo2);
+
+ // Cleanup
+ removeUser(userInfo1.id);
+ }
+
+ // Make sure only one managed profile can be created
+ public void testAddManagedProfile() throws Exception {
+ UserInfo userInfo1 = mUserManager.createProfileForUser("Managed 1",
+ UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+ UserInfo userInfo2 = mUserManager.createProfileForUser("Managed 2",
+ UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+ assertNotNull(userInfo1);
+ assertNull(userInfo2);
+
+ // Cleanup
+ removeUser(userInfo1.id);
+ }
+
private boolean findUser(int id) {
List<UserInfo> list = mUserManager.getUsers();