Loading core/java/android/content/pm/UserInfo.java +5 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class UserInfo implements Parcelable { public static final int FLAG_DISABLED = 0x00000040; public static final int NO_PROFILE_GROUP_ID = -1; public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL; public int id; public int serialNumber; Loading @@ -87,6 +87,7 @@ public class UserInfo implements Parcelable { public long creationTime; public long lastLoggedInTime; public int profileGroupId; public int restrictedProfileParentId; /** User is only partially created. */ public boolean partial; Loading @@ -102,6 +103,7 @@ public class UserInfo implements Parcelable { this.flags = flags; this.iconPath = iconPath; this.profileGroupId = NO_PROFILE_GROUP_ID; this.restrictedProfileParentId = NO_PROFILE_GROUP_ID; } public boolean isPrimary() { Loading Loading @@ -206,6 +208,7 @@ public class UserInfo implements Parcelable { dest.writeInt(partial ? 1 : 0); dest.writeInt(profileGroupId); dest.writeInt(guestToRemove ? 1 : 0); dest.writeInt(restrictedProfileParentId); } public static final Parcelable.Creator<UserInfo> CREATOR Loading @@ -229,5 +232,6 @@ public class UserInfo implements Parcelable { partial = source.readInt() != 0; profileGroupId = source.readInt(); guestToRemove = source.readInt() != 0; restrictedProfileParentId = source.readInt(); } } core/java/android/os/UserManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -926,6 +926,28 @@ public class UserManager { } } /** * Creates a restricted profile with the specified name. * * @param name profile's name * @return UserInfo object for the created user, or null if the user could not be created. * @hide */ public UserInfo createRestrictedProfile(String name) { try { if (isSplitSystemUser()) { return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, UserHandle.getCallingUserId()); } else { return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, UserHandle.USER_SYSTEM); } } catch (RemoteException e) { Log.w(TAG, "Could not create a restricted profile", e); } return null; } /** * @hide * Marks the guest user for deletion to allow a new guest to be created before deleting Loading services/core/java/com/android/server/accounts/AccountManagerService.java +44 −30 Original line number Diff line number Diff line Loading @@ -511,10 +511,17 @@ public class AccountManagerService Account[] sharedAccounts = getSharedAccountsAsUser(userId); if (sharedAccounts == null || sharedAccounts.length == 0) return; Account[] accounts = getAccountsAsUser(null, userId); int parentUserId = UserManager.isSplitSystemUser() ? mUserManager.getUserInfo(userId).restrictedProfileParentId : UserHandle.USER_SYSTEM; if (parentUserId < 0) { Log.w(TAG, "User " + userId + " has shared accounts, but no parent user"); return; } for (Account sa : sharedAccounts) { if (ArrayUtils.contains(accounts, sa)) continue; // Account doesn't exist. Copy it now. copyAccountToUser(null /*no response*/, sa, UserHandle.USER_OWNER, userId); copyAccountToUser(null /*no response*/, sa, parentUserId, userId); } } Loading Loading @@ -740,7 +747,7 @@ public class AccountManagerService @Override public void copyAccountToUser(final IAccountManagerResponse response, final Account account, int userFrom, int userTo) { final int userFrom, int userTo) { int callingUid = Binder.getCallingUid(); if (isCrossUser(callingUid, UserHandle.USER_ALL)) { throw new SecurityException("Calling copyAccountToUser requires " Loading Loading @@ -784,7 +791,7 @@ public class AccountManagerService if (result != null && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { // Create a Session for the target user and pass in the bundle completeCloningAccount(response, result, account, toAccounts); completeCloningAccount(response, result, account, toAccounts, userFrom); } else { super.onResult(result); } Loading Loading @@ -851,7 +858,8 @@ public class AccountManagerService } private void completeCloningAccount(IAccountManagerResponse response, final Bundle accountCredentials, final Account account, final UserAccounts targetUser) { final Bundle accountCredentials, final Account account, final UserAccounts targetUser, final int parentUserId){ long id = clearCallingIdentity(); try { new Session(targetUser, response, account.type, false, Loading @@ -866,9 +874,9 @@ public class AccountManagerService @Override public void run() throws RemoteException { // Confirm that the owner's account still exists before this step. UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER); UserAccounts owner = getUserAccounts(parentUserId); synchronized (owner.cacheLock) { for (Account acc : getAccounts(UserHandle.USER_OWNER)) { for (Account acc : getAccounts(parentUserId)) { if (acc.equals(account)) { mAuthenticator.addAccountFromCredentials( this, account, accountCredentials); Loading Loading @@ -949,27 +957,27 @@ public class AccountManagerService } sendAccountsChangedBroadcast(accounts.userId); } if (accounts.userId == UserHandle.USER_OWNER) { addAccountToLimitedUsers(account); if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) { addAccountToLinkedRestrictedUsers(account, accounts.userId); } return true; } /** * Adds the account to all limited users as shared accounts. If the user is currently * Adds the account to all linked restricted users as shared accounts. If the user is currently * running, then clone the account too. * @param account the account to share with limited users * */ private void addAccountToLimitedUsers(Account account) { private void addAccountToLinkedRestrictedUsers(Account account, int parentUserId) { List<UserInfo> users = getUserManager().getUsers(); for (UserInfo user : users) { if (user.isRestricted()) { if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) { addSharedAccountAsUser(account, user.id); try { if (ActivityManagerNative.getDefault().isUserRunning(user.id, false)) { mMessageHandler.sendMessage(mMessageHandler.obtainMessage( MESSAGE_COPY_SHARED_ACCOUNT, UserHandle.USER_OWNER, user.id, account)); MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account)); } } catch (RemoteException re) { // Shouldn't happen Loading Loading @@ -1172,14 +1180,16 @@ public class AccountManagerService new AtomicReference<String>(accountToRename.name)); resultAccount = renamedAccount; if (accounts.userId == UserHandle.USER_OWNER) { int parentUserId = accounts.userId; if (canHaveProfile(parentUserId)) { /* * Owner's account was renamed, rename the account for * Owner or system user account was renamed, rename the account for * those users with which the account was shared. */ List<UserInfo> users = mUserManager.getUsers(true); for (UserInfo user : users) { if (!user.isPrimary() && user.isRestricted()) { if (user.isRestricted() && (user.restrictedProfileParentId == parentUserId)) { renameSharedAccountAsUser(accountToRename, newName, user.id); } } Loading @@ -1191,6 +1201,11 @@ public class AccountManagerService return resultAccount; } private boolean canHaveProfile(final int parentUserId) { final UserInfo userInfo = mUserManager.getUserInfo(parentUserId); return userInfo != null && userInfo.canHaveProfile(); } @Override public void removeAccount(IAccountManagerResponse response, Account account, boolean expectActivityLaunch) { Loading Loading @@ -1304,7 +1319,7 @@ public class AccountManagerService logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); long identityToken = clearCallingIdentity(); try { return removeAccountInternal(accounts, account); return removeAccountInternal(accounts, account, callingUid); } finally { restoreCallingIdentity(identityToken); } Loading Loading @@ -1337,7 +1352,7 @@ public class AccountManagerService && !result.containsKey(AccountManager.KEY_INTENT)) { final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); if (removalAllowed) { removeAccountInternal(mAccounts, mAccount); removeAccountInternal(mAccounts, mAccount, getCallingUid()); } IAccountManagerResponse response = getResponseAndClose(); if (response != null) { Loading @@ -1360,10 +1375,10 @@ public class AccountManagerService /* For testing */ protected void removeAccountInternal(Account account) { removeAccountInternal(getUserAccountsForCaller(), account); removeAccountInternal(getUserAccountsForCaller(), account, getCallingUid()); } private boolean removeAccountInternal(UserAccounts accounts, Account account) { private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) { int deleted; synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); Loading @@ -1376,22 +1391,21 @@ public class AccountManagerService logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_ACCOUNTS, accountId, accounts); } if (accounts.userId == UserHandle.USER_OWNER) { // Owner's account was removed, remove from any users that are sharing // this account. int callingUid = getCallingUid(); long id = Binder.clearCallingIdentity(); try { int parentUserId = accounts.userId; if (canHaveProfile(parentUserId)) { // Remove from any restricted profiles that are sharing this account. List<UserInfo> users = mUserManager.getUsers(true); for (UserInfo user : users) { if (!user.isPrimary() && user.isRestricted()) { if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) { removeSharedAccountAsUser(account, user.id, callingUid); } } } } finally { Binder.restoreCallingIdentity(id); } } return (deleted > 0); } Loading Loading @@ -2707,7 +2721,7 @@ public class AccountManagerService if (r > 0) { logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_SHARED_ACCOUNTS, sharedTableAccountId, accounts, callingUid); removeAccountInternal(accounts, account); removeAccountInternal(accounts, account, callingUid); } return r > 0; } Loading services/core/java/com/android/server/pm/UserManagerService.java +43 −21 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import com.google.android.collect.Sets; 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; Loading Loading @@ -102,6 +101,7 @@ public class UserManagerService extends IUserManager.Stub { 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"; Loading Loading @@ -927,7 +927,10 @@ public class UserManagerService extends IUserManager.Stub { 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); Loading Loading @@ -1037,6 +1040,7 @@ public class UserManagerService extends IUserManager.Stub { 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(); Loading Loading @@ -1072,6 +1076,8 @@ public class UserManagerService extends IUserManager.Stub { 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; Loading Loading @@ -1106,6 +1112,7 @@ public class UserManagerService extends IUserManager.Stub { userInfo.partial = partial; userInfo.guestToRemove = guestToRemove; userInfo.profileGroupId = profileGroupId; userInfo.restrictedProfileParentId = restrictedProfileParentId; mUserRestrictions.append(id, restrictions); return userInfo; Loading Loading @@ -1262,6 +1269,7 @@ public class UserManagerService extends IUserManager.Stub { } 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; Loading @@ -1286,6 +1294,24 @@ public class UserManagerService extends IUserManager.Stub { 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. Loading @@ -1309,11 +1335,22 @@ public class UserManagerService extends IUserManager.Stub { mUsers.put(userId, userInfo); writeUserListLocked(); if (parent != null) { 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; } } final StorageManager storage = mContext.getSystemService(StorageManager.class); for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { Loading Loading @@ -1348,24 +1385,9 @@ 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; } /** * 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(); Loading Loading
core/java/android/content/pm/UserInfo.java +5 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class UserInfo implements Parcelable { public static final int FLAG_DISABLED = 0x00000040; public static final int NO_PROFILE_GROUP_ID = -1; public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL; public int id; public int serialNumber; Loading @@ -87,6 +87,7 @@ public class UserInfo implements Parcelable { public long creationTime; public long lastLoggedInTime; public int profileGroupId; public int restrictedProfileParentId; /** User is only partially created. */ public boolean partial; Loading @@ -102,6 +103,7 @@ public class UserInfo implements Parcelable { this.flags = flags; this.iconPath = iconPath; this.profileGroupId = NO_PROFILE_GROUP_ID; this.restrictedProfileParentId = NO_PROFILE_GROUP_ID; } public boolean isPrimary() { Loading Loading @@ -206,6 +208,7 @@ public class UserInfo implements Parcelable { dest.writeInt(partial ? 1 : 0); dest.writeInt(profileGroupId); dest.writeInt(guestToRemove ? 1 : 0); dest.writeInt(restrictedProfileParentId); } public static final Parcelable.Creator<UserInfo> CREATOR Loading @@ -229,5 +232,6 @@ public class UserInfo implements Parcelable { partial = source.readInt() != 0; profileGroupId = source.readInt(); guestToRemove = source.readInt() != 0; restrictedProfileParentId = source.readInt(); } }
core/java/android/os/UserManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -926,6 +926,28 @@ public class UserManager { } } /** * Creates a restricted profile with the specified name. * * @param name profile's name * @return UserInfo object for the created user, or null if the user could not be created. * @hide */ public UserInfo createRestrictedProfile(String name) { try { if (isSplitSystemUser()) { return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, UserHandle.getCallingUserId()); } else { return mService.createProfileForUser(name, UserInfo.FLAG_RESTRICTED, UserHandle.USER_SYSTEM); } } catch (RemoteException e) { Log.w(TAG, "Could not create a restricted profile", e); } return null; } /** * @hide * Marks the guest user for deletion to allow a new guest to be created before deleting Loading
services/core/java/com/android/server/accounts/AccountManagerService.java +44 −30 Original line number Diff line number Diff line Loading @@ -511,10 +511,17 @@ public class AccountManagerService Account[] sharedAccounts = getSharedAccountsAsUser(userId); if (sharedAccounts == null || sharedAccounts.length == 0) return; Account[] accounts = getAccountsAsUser(null, userId); int parentUserId = UserManager.isSplitSystemUser() ? mUserManager.getUserInfo(userId).restrictedProfileParentId : UserHandle.USER_SYSTEM; if (parentUserId < 0) { Log.w(TAG, "User " + userId + " has shared accounts, but no parent user"); return; } for (Account sa : sharedAccounts) { if (ArrayUtils.contains(accounts, sa)) continue; // Account doesn't exist. Copy it now. copyAccountToUser(null /*no response*/, sa, UserHandle.USER_OWNER, userId); copyAccountToUser(null /*no response*/, sa, parentUserId, userId); } } Loading Loading @@ -740,7 +747,7 @@ public class AccountManagerService @Override public void copyAccountToUser(final IAccountManagerResponse response, final Account account, int userFrom, int userTo) { final int userFrom, int userTo) { int callingUid = Binder.getCallingUid(); if (isCrossUser(callingUid, UserHandle.USER_ALL)) { throw new SecurityException("Calling copyAccountToUser requires " Loading Loading @@ -784,7 +791,7 @@ public class AccountManagerService if (result != null && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { // Create a Session for the target user and pass in the bundle completeCloningAccount(response, result, account, toAccounts); completeCloningAccount(response, result, account, toAccounts, userFrom); } else { super.onResult(result); } Loading Loading @@ -851,7 +858,8 @@ public class AccountManagerService } private void completeCloningAccount(IAccountManagerResponse response, final Bundle accountCredentials, final Account account, final UserAccounts targetUser) { final Bundle accountCredentials, final Account account, final UserAccounts targetUser, final int parentUserId){ long id = clearCallingIdentity(); try { new Session(targetUser, response, account.type, false, Loading @@ -866,9 +874,9 @@ public class AccountManagerService @Override public void run() throws RemoteException { // Confirm that the owner's account still exists before this step. UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER); UserAccounts owner = getUserAccounts(parentUserId); synchronized (owner.cacheLock) { for (Account acc : getAccounts(UserHandle.USER_OWNER)) { for (Account acc : getAccounts(parentUserId)) { if (acc.equals(account)) { mAuthenticator.addAccountFromCredentials( this, account, accountCredentials); Loading Loading @@ -949,27 +957,27 @@ public class AccountManagerService } sendAccountsChangedBroadcast(accounts.userId); } if (accounts.userId == UserHandle.USER_OWNER) { addAccountToLimitedUsers(account); if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) { addAccountToLinkedRestrictedUsers(account, accounts.userId); } return true; } /** * Adds the account to all limited users as shared accounts. If the user is currently * Adds the account to all linked restricted users as shared accounts. If the user is currently * running, then clone the account too. * @param account the account to share with limited users * */ private void addAccountToLimitedUsers(Account account) { private void addAccountToLinkedRestrictedUsers(Account account, int parentUserId) { List<UserInfo> users = getUserManager().getUsers(); for (UserInfo user : users) { if (user.isRestricted()) { if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) { addSharedAccountAsUser(account, user.id); try { if (ActivityManagerNative.getDefault().isUserRunning(user.id, false)) { mMessageHandler.sendMessage(mMessageHandler.obtainMessage( MESSAGE_COPY_SHARED_ACCOUNT, UserHandle.USER_OWNER, user.id, account)); MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account)); } } catch (RemoteException re) { // Shouldn't happen Loading Loading @@ -1172,14 +1180,16 @@ public class AccountManagerService new AtomicReference<String>(accountToRename.name)); resultAccount = renamedAccount; if (accounts.userId == UserHandle.USER_OWNER) { int parentUserId = accounts.userId; if (canHaveProfile(parentUserId)) { /* * Owner's account was renamed, rename the account for * Owner or system user account was renamed, rename the account for * those users with which the account was shared. */ List<UserInfo> users = mUserManager.getUsers(true); for (UserInfo user : users) { if (!user.isPrimary() && user.isRestricted()) { if (user.isRestricted() && (user.restrictedProfileParentId == parentUserId)) { renameSharedAccountAsUser(accountToRename, newName, user.id); } } Loading @@ -1191,6 +1201,11 @@ public class AccountManagerService return resultAccount; } private boolean canHaveProfile(final int parentUserId) { final UserInfo userInfo = mUserManager.getUserInfo(parentUserId); return userInfo != null && userInfo.canHaveProfile(); } @Override public void removeAccount(IAccountManagerResponse response, Account account, boolean expectActivityLaunch) { Loading Loading @@ -1304,7 +1319,7 @@ public class AccountManagerService logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); long identityToken = clearCallingIdentity(); try { return removeAccountInternal(accounts, account); return removeAccountInternal(accounts, account, callingUid); } finally { restoreCallingIdentity(identityToken); } Loading Loading @@ -1337,7 +1352,7 @@ public class AccountManagerService && !result.containsKey(AccountManager.KEY_INTENT)) { final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); if (removalAllowed) { removeAccountInternal(mAccounts, mAccount); removeAccountInternal(mAccounts, mAccount, getCallingUid()); } IAccountManagerResponse response = getResponseAndClose(); if (response != null) { Loading @@ -1360,10 +1375,10 @@ public class AccountManagerService /* For testing */ protected void removeAccountInternal(Account account) { removeAccountInternal(getUserAccountsForCaller(), account); removeAccountInternal(getUserAccountsForCaller(), account, getCallingUid()); } private boolean removeAccountInternal(UserAccounts accounts, Account account) { private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) { int deleted; synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); Loading @@ -1376,22 +1391,21 @@ public class AccountManagerService logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_ACCOUNTS, accountId, accounts); } if (accounts.userId == UserHandle.USER_OWNER) { // Owner's account was removed, remove from any users that are sharing // this account. int callingUid = getCallingUid(); long id = Binder.clearCallingIdentity(); try { int parentUserId = accounts.userId; if (canHaveProfile(parentUserId)) { // Remove from any restricted profiles that are sharing this account. List<UserInfo> users = mUserManager.getUsers(true); for (UserInfo user : users) { if (!user.isPrimary() && user.isRestricted()) { if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) { removeSharedAccountAsUser(account, user.id, callingUid); } } } } finally { Binder.restoreCallingIdentity(id); } } return (deleted > 0); } Loading Loading @@ -2707,7 +2721,7 @@ public class AccountManagerService if (r > 0) { logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_SHARED_ACCOUNTS, sharedTableAccountId, accounts, callingUid); removeAccountInternal(accounts, account); removeAccountInternal(accounts, account, callingUid); } return r > 0; } Loading
services/core/java/com/android/server/pm/UserManagerService.java +43 −21 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import com.google.android.collect.Sets; 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; Loading Loading @@ -102,6 +101,7 @@ public class UserManagerService extends IUserManager.Stub { 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"; Loading Loading @@ -927,7 +927,10 @@ public class UserManagerService extends IUserManager.Stub { 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); Loading Loading @@ -1037,6 +1040,7 @@ public class UserManagerService extends IUserManager.Stub { 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(); Loading Loading @@ -1072,6 +1076,8 @@ public class UserManagerService extends IUserManager.Stub { 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; Loading Loading @@ -1106,6 +1112,7 @@ public class UserManagerService extends IUserManager.Stub { userInfo.partial = partial; userInfo.guestToRemove = guestToRemove; userInfo.profileGroupId = profileGroupId; userInfo.restrictedProfileParentId = restrictedProfileParentId; mUserRestrictions.append(id, restrictions); return userInfo; Loading Loading @@ -1262,6 +1269,7 @@ public class UserManagerService extends IUserManager.Stub { } 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; Loading @@ -1286,6 +1294,24 @@ public class UserManagerService extends IUserManager.Stub { 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. Loading @@ -1309,11 +1335,22 @@ public class UserManagerService extends IUserManager.Stub { mUsers.put(userId, userInfo); writeUserListLocked(); if (parent != null) { 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; } } final StorageManager storage = mContext.getSystemService(StorageManager.class); for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { Loading Loading @@ -1348,24 +1385,9 @@ 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; } /** * 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(); Loading