Non-system users can now have restricted profiles
In the non split system user, only USER_OWNER is allowed to have restricted
profiles. This is now changed in split user mode, where multiple secondary
users can have restricted profiles.
Added UserInfo.restrictedProfileGroupId field, which defines parent/child
relationship between secondary users and linked restricted profiles. Adjusted
shared accounts handling logic to not assume that USER_OWNER is the only owner.
Bug: 23191995
Change-Id: I5f3fc2aa4f229103d6e75ec2c3dfce866b8007de
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4bfcb90..1924bab 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -61,7 +61,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -102,6 +101,7 @@
private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
private static final String ATTR_USER_VERSION = "version";
private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
+ private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId";
private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
private static final String TAG_USERS = "users";
private static final String TAG_USER = "user";
@@ -927,7 +927,10 @@
serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
Integer.toString(userInfo.profileGroupId));
}
-
+ if (userInfo.restrictedProfileParentId != UserInfo.NO_PROFILE_GROUP_ID) {
+ serializer.attribute(null, ATTR_RESTRICTED_PROFILE_PARENT_ID,
+ Integer.toString(userInfo.restrictedProfileParentId));
+ }
serializer.startTag(null, TAG_NAME);
serializer.text(userInfo.name);
serializer.endTag(null, TAG_NAME);
@@ -1037,6 +1040,7 @@
long creationTime = 0L;
long lastLoggedInTime = 0L;
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
+ int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
boolean partial = false;
boolean guestToRemove = false;
Bundle restrictions = new Bundle();
@@ -1072,6 +1076,8 @@
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
UserInfo.NO_PROFILE_GROUP_ID);
+ restrictedProfileParentId = readIntAttribute(parser,
+ ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID);
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
if ("true".equals(valueString)) {
partial = true;
@@ -1106,6 +1112,7 @@
userInfo.partial = partial;
userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
+ userInfo.restrictedProfileParentId = restrictedProfileParentId;
mUserRestrictions.append(id, restrictions);
return userInfo;
@@ -1262,6 +1269,7 @@
}
final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
+ final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo = null;
final int userId;
@@ -1286,6 +1294,24 @@
if (isGuest && findCurrentGuestUserLocked() != null) {
return null;
}
+ // In legacy mode, restricted profile's parent can only be the owner user
+ if (isRestricted && !UserManager.isSplitSystemUser()
+ && (parentId != UserHandle.USER_SYSTEM)) {
+ Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
+ return null;
+ }
+ if (isRestricted && UserManager.isSplitSystemUser()) {
+ if (parent == null) {
+ Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
+ + "specified");
+ return null;
+ }
+ if (!parent.canHaveProfile()) {
+ Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
+ + "created for the specified parent user id " + parentId);
+ return null;
+ }
+ }
// In split system user mode, we assign the first human user the primary flag.
// And if there is no device owner, we also assign the admin flag to primary
// user.
@@ -1309,11 +1335,22 @@
mUsers.put(userId, userInfo);
writeUserListLocked();
if (parent != null) {
- if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- parent.profileGroupId = parent.id;
- scheduleWriteUserLocked(parent);
+ if (isManagedProfile) {
+ if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ parent.profileGroupId = parent.id;
+ scheduleWriteUserLocked(parent);
+ }
+ userInfo.profileGroupId = parent.profileGroupId;
+ } else if (isRestricted) {
+ if (!parent.canHaveProfile()) {
+ Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
+ }
+ if (parent.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
+ parent.restrictedProfileParentId = parent.id;
+ scheduleWriteUserLocked(parent);
+ }
+ userInfo.restrictedProfileParentId = parent.restrictedProfileParentId;
}
- userInfo.profileGroupId = parent.profileGroupId;
}
final StorageManager storage = mContext.getSystemService(StorageManager.class);
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
@@ -1348,24 +1385,9 @@
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;
- }
-
/**
* Find the current guest user. If the Guest user is partial,
* then do not include it in the results as it is about to die.
- * This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to
- * the special handling of Guests being removed.
*/
private UserInfo findCurrentGuestUserLocked() {
final int size = mUsers.size();