Reduce excessive locking in UserManager
Bug: 24979571
Change-Id: I1cfbe48712ae26ec134354d109d2538d566b92d7
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bb805c1..be7a795 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1917,8 +1917,7 @@
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
- sUserManager = new UserManagerService(context, this,
- mInstallLock, mPackages);
+ sUserManager = new UserManagerService(context, this, mPackages);
// Propagate permission configuration in to package manager.
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
@@ -16314,23 +16313,26 @@
}
/** Called by UserManagerService */
- void cleanUpUserLILPw(UserManagerService userManager, int userHandle) {
- mDirtyUsers.remove(userHandle);
- mSettings.removeUserLPw(userHandle);
- mPendingBroadcasts.remove(userHandle);
- if (mInstaller != null) {
- // Technically, we shouldn't be doing this with the package lock
- // held. However, this is very rare, and there is already so much
- // other disk I/O going on, that we'll let it slide for now.
- final StorageManager storage = mContext.getSystemService(StorageManager.class);
- for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
- final String volumeUuid = vol.getFsUuid();
- if (DEBUG_INSTALL) Slog.d(TAG, "Removing user data on volume " + volumeUuid);
- mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ void cleanUpUser(UserManagerService userManager, int userHandle) {
+ synchronized (mPackages) {
+ mDirtyUsers.remove(userHandle);
+ mUserNeedsBadging.delete(userHandle);
+ mSettings.removeUserLPw(userHandle);
+ mPendingBroadcasts.remove(userHandle);
+ }
+ synchronized (mInstallLock) {
+ if (mInstaller != null) {
+ final StorageManager storage = mContext.getSystemService(StorageManager.class);
+ for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+ final String volumeUuid = vol.getFsUuid();
+ if (DEBUG_INSTALL) Slog.d(TAG, "Removing user data on volume " + volumeUuid);
+ mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ }
+ }
+ synchronized (mPackages) {
+ removeUnusedPackagesLILPw(userManager, userHandle);
}
}
- mUserNeedsBadging.delete(userHandle);
- removeUnusedPackagesLILPw(userManager, userHandle);
}
/**
@@ -16380,12 +16382,18 @@
}
/** Called by UserManagerService */
- void createNewUserLILPw(int userHandle) {
+ void createNewUser(int userHandle) {
if (mInstaller != null) {
- mInstaller.createUserConfig(userHandle);
- mSettings.createNewUserLILPw(this, mInstaller, userHandle);
- applyFactoryDefaultBrowserLPw(userHandle);
- primeDomainVerificationsLPw(userHandle);
+ synchronized (mInstallLock) {
+ synchronized (mPackages) {
+ mInstaller.createUserConfig(userHandle);
+ mSettings.createNewUserLILPw(this, mInstaller, userHandle);
+ }
+ }
+ synchronized (mPackages) {
+ applyFactoryDefaultBrowserLPw(userHandle);
+ primeDomainVerificationsLPw(userHandle);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3a1d2de..ab0b182 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -97,8 +97,7 @@
*
* Method naming convention:
* <ul>
- * <li> Methods suffixed with "LILP" should be called within {@link #mInstallLock} and
- * {@link #mPackagesLock} locks obtained in the respective order.
+ * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
* <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
* <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
* </ul>
@@ -164,7 +163,6 @@
private final Context mContext;
private final PackageManagerService mPm;
- private final Object mInstallLock;
private final Object mPackagesLock;
// Short-term lock for internal state, when interaction/sync with PM is not required
private final Object mUsersLock = new Object();
@@ -215,6 +213,7 @@
@GuardedBy("mRestrictionsLock")
private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
+ @GuardedBy("mGuestRestrictions")
private final Bundle mGuestRestrictions = new Bundle();
/**
@@ -226,6 +225,7 @@
@GuardedBy("mUsersLock")
private int[] mUserIds;
+ @GuardedBy("mPackagesLock")
private int mNextSerialNumber;
private int mUserVersion = 0;
@@ -245,11 +245,9 @@
}
}
- /**
- * Available for testing purposes.
- */
- UserManagerService(File dataDir, File baseUserPath) {
- this(null, null, new Object(), new Object(), dataDir, baseUserPath);
+ @VisibleForTesting
+ UserManagerService(File dataDir) {
+ this(null, null, new Object(), dataDir);
}
/**
@@ -257,68 +255,53 @@
* associated with the package manager, and the given lock is the
* package manager's own lock.
*/
- UserManagerService(Context context, PackageManagerService pm,
- Object installLock, Object packagesLock) {
- this(context, pm, installLock, packagesLock,
- Environment.getDataDirectory(),
- new File(Environment.getDataDirectory(), "user"));
+ UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
+ this(context, pm, packagesLock, Environment.getDataDirectory());
}
- /**
- * Available for testing purposes.
- */
private UserManagerService(Context context, PackageManagerService pm,
- Object installLock, Object packagesLock,
- File dataDir, File baseUserPath) {
+ Object packagesLock, File dataDir) {
mContext = context;
mPm = pm;
- mInstallLock = installLock;
mPackagesLock = packagesLock;
mHandler = new MainHandler();
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- mUsersDir = new File(dataDir, USER_INFO_DIR);
- mUsersDir.mkdirs();
- // Make zeroth user directory, for services to migrate their files to that location
- File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
- userZeroDir.mkdirs();
- FileUtils.setPermissions(mUsersDir.toString(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG
- |FileUtils.S_IROTH|FileUtils.S_IXOTH,
- -1, -1);
- mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
- initDefaultGuestRestrictions();
- readUserListLILP();
- sInstance = this;
- }
+ synchronized (mPackagesLock) {
+ mUsersDir = new File(dataDir, USER_INFO_DIR);
+ mUsersDir.mkdirs();
+ // Make zeroth user directory, for services to migrate their files to that location
+ File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
+ userZeroDir.mkdirs();
+ FileUtils.setPermissions(mUsersDir.toString(),
+ FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
+ -1, -1);
+ mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
+ initDefaultGuestRestrictions();
+ readUserListLP();
+ sInstance = this;
}
mLocalService = new LocalService();
LocalServices.addService(UserManagerInternal.class, mLocalService);
}
void systemReady() {
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- synchronized (mUsersLock) {
- // Prune out any partially created/partially removed users.
- ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
- final int userSize = mUsers.size();
- for (int i = 0; i < userSize; i++) {
- UserInfo ui = mUsers.valueAt(i);
- if ((ui.partial || ui.guestToRemove) && i != 0) {
- partials.add(ui);
- }
- }
- final int partialsSize = partials.size();
- for (int i = 0; i < partialsSize; i++) {
- UserInfo ui = partials.get(i);
- Slog.w(LOG_TAG, "Removing partially created user " + ui.id
- + " (name=" + ui.name + ")");
- removeUserStateLILP(ui.id);
- }
+ // Prune out any partially created/partially removed users.
+ ArrayList<UserInfo> partials = new ArrayList<>();
+ synchronized (mUsersLock) {
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ UserInfo ui = mUsers.valueAt(i);
+ if ((ui.partial || ui.guestToRemove) && i != 0) {
+ partials.add(ui);
}
}
}
+ final int partialsSize = partials.size();
+ for (int i = 0; i < partialsSize; i++) {
+ UserInfo ui = partials.get(i);
+ Slog.w(LOG_TAG, "Removing partially created user " + ui.id
+ + " (name=" + ui.name + ")");
+ removeUserState(ui.id);
+ }
onUserForeground(UserHandle.USER_SYSTEM);
mAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -627,17 +610,22 @@
public void makeInitialized(int userId) {
checkManageUsersPermission("makeInitialized");
- synchronized (mPackagesLock) {
- UserInfo info = getUserInfoNoChecks(userId);
+ boolean scheduleWriteUser = false;
+ UserInfo info;
+ synchronized (mUsersLock) {
+ info = mUsers.get(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
- // TODO Check if we should return here instead of a null check below
+ return;
}
- if (info != null && (info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
+ if ((info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
info.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUser(info);
+ scheduleWriteUser = true;
}
}
+ if (scheduleWriteUser) {
+ scheduleWriteUser(info);
+ }
}
/**
@@ -645,17 +633,18 @@
* restrictions.
*/
private void initDefaultGuestRestrictions() {
- if (mGuestRestrictions.isEmpty()) {
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
+ synchronized (mGuestRestrictions) {
+ if (mGuestRestrictions.isEmpty()) {
+ mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
+ mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
+ }
}
}
@Override
public Bundle getDefaultGuestRestrictions() {
checkManageUsersPermission("getDefaultGuestRestrictions");
- // TODO Switch to mGuestRestrictions for locking
- synchronized (mPackagesLock) {
+ synchronized (mGuestRestrictions) {
return new Bundle(mGuestRestrictions);
}
}
@@ -663,12 +652,12 @@
@Override
public void setDefaultGuestRestrictions(Bundle restrictions) {
checkManageUsersPermission("setDefaultGuestRestrictions");
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- mGuestRestrictions.clear();
- mGuestRestrictions.putAll(restrictions);
- writeUserListLILP();
- }
+ synchronized (mGuestRestrictions) {
+ mGuestRestrictions.clear();
+ mGuestRestrictions.putAll(restrictions);
+ }
+ synchronized (mPackagesLock) {
+ writeUserListLP();
}
}
@@ -775,7 +764,7 @@
Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
!= newRestrictions);
mBaseUserRestrictions.put(userId, newRestrictions);
- scheduleWriteUser(mUsers.get(userId));
+ scheduleWriteUser(getUserInfoNoChecks(userId));
}
final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
@@ -996,9 +985,9 @@
}
}
- private void readUserListLILP() {
+ private void readUserListLP() {
if (!mUserListFile.exists()) {
- fallbackToSingleUserLILP();
+ fallbackToSingleUserLP();
return;
}
FileInputStream fis = null;
@@ -1015,7 +1004,7 @@
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
- fallbackToSingleUserLILP();
+ fallbackToSingleUserLP();
return;
}
@@ -1036,7 +1025,7 @@
final String name = parser.getName();
if (name.equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
- UserInfo user = readUserLILP(Integer.parseInt(id));
+ UserInfo user = readUserLP(Integer.parseInt(id));
if (user != null) {
synchronized (mUsersLock) {
@@ -1051,8 +1040,10 @@
&& type != XmlPullParser.END_TAG) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
- UserRestrictionsUtils
- .readRestrictions(parser, mGuestRestrictions);
+ synchronized (mGuestRestrictions) {
+ UserRestrictionsUtils
+ .readRestrictions(parser, mGuestRestrictions);
+ }
}
break;
}
@@ -1061,25 +1052,18 @@
}
}
updateUserIds();
- upgradeIfNecessaryLILP();
- } catch (IOException ioe) {
- fallbackToSingleUserLILP();
- } catch (XmlPullParserException pe) {
- fallbackToSingleUserLILP();
+ upgradeIfNecessaryLP();
+ } catch (IOException | XmlPullParserException e) {
+ fallbackToSingleUserLP();
} finally {
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException e) {
- }
- }
+ IoUtils.closeQuietly(fis);
}
}
/**
* Upgrade steps between versions, either for fixing bugs or changing the data format.
*/
- private void upgradeIfNecessaryLILP() {
+ private void upgradeIfNecessaryLP() {
int userVersion = mUserVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
@@ -1132,11 +1116,11 @@
+ USER_VERSION);
} else {
mUserVersion = userVersion;
- writeUserListLILP();
+ writeUserListLP();
}
}
- private void fallbackToSingleUserLILP() {
+ private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_INITIALIZED;
// In split system user mode, the admin and primary flags are assigned to the first human
// user.
@@ -1161,7 +1145,7 @@
updateUserIds();
initDefaultGuestRestrictions();
- writeUserListLILP();
+ writeUserListLP();
writeUserLP(system);
}
@@ -1247,8 +1231,7 @@
* <user id="2"></user>
* </users>
*/
- private void writeUserListLILP() {
- // TODO Investigate removing a dependency on mInstallLock
+ private void writeUserListLP() {
FileOutputStream fos = null;
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
@@ -1266,8 +1249,10 @@
serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
- UserRestrictionsUtils
- .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
+ synchronized (mGuestRestrictions) {
+ UserRestrictionsUtils
+ .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
+ }
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
int[] userIdsToWrite;
synchronized (mUsersLock) {
@@ -1293,7 +1278,7 @@
}
}
- private UserInfo readUserLILP(int id) {
+ private UserInfo readUserLP(int id) {
int flags = 0;
int serialNumber = id;
String name = null;
@@ -1468,8 +1453,7 @@
}
private UserInfo createUserInternal(String name, int flags, int parentId) {
- if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
- UserManager.DISALLOW_ADD_USER, false)) {
+ if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
return null;
}
@@ -1480,120 +1464,114 @@
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;
+ UserInfo userInfo;
final int userId;
try {
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- UserInfo parent = null;
- if (parentId != UserHandle.USER_NULL) {
- synchronized (mUsersLock) {
- parent = getUserInfoLU(parentId);
- }
- if (parent == null) return null;
+ synchronized (mPackagesLock) {
+ UserInfo parent = null;
+ if (parentId != UserHandle.USER_NULL) {
+ synchronized (mUsersLock) {
+ parent = getUserInfoLU(parentId);
}
- if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
- Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
+ if (parent == null) return null;
+ }
+ if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
+ Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
+ return null;
+ }
+ if (!isGuest && !isManagedProfile && isUserLimitReached()) {
+ // If we're not adding a guest user or a managed profile and the limit has
+ // been reached, cannot add a user.
+ return null;
+ }
+ // If we're adding a guest and there already exists one, bail.
+ if (isGuest && findCurrentGuestUser() != 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 (!isGuest && !isManagedProfile && isUserLimitReached()) {
- // If we're not adding a guest user or a managed profile and the limit has
- // been reached, cannot add a user.
+ if (!parent.canHaveProfile()) {
+ Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
+ + "created for the specified parent user id " + parentId);
return null;
}
- // If we're adding a guest and there already exists one, bail.
- if (isGuest && findCurrentGuestUser() != null) {
- 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.
+ if (UserManager.isSplitSystemUser()
+ && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
+ flags |= UserInfo.FLAG_PRIMARY;
+ DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (devicePolicyManager == null
+ || devicePolicyManager.getDeviceOwner() == null) {
+ flags |= UserInfo.FLAG_ADMIN;
}
- // 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.
- if (UserManager.isSplitSystemUser()
- && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
- flags |= UserInfo.FLAG_PRIMARY;
- DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
- mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- if (devicePolicyManager == null
- || devicePolicyManager.getDeviceOwner() == null) {
- flags |= UserInfo.FLAG_ADMIN;
- }
- }
- userId = getNextAvailableId();
- userInfo = new UserInfo(userId, name, null, flags);
- userInfo.serialNumber = mNextSerialNumber++;
- long now = System.currentTimeMillis();
- userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
- userInfo.partial = true;
- Environment.getUserSystemDirectory(userInfo.id).mkdirs();
+ }
+ userId = getNextAvailableId();
+ userInfo = new UserInfo(userId, name, null, flags);
+ userInfo.serialNumber = mNextSerialNumber++;
+ long now = System.currentTimeMillis();
+ userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+ userInfo.partial = true;
+ Environment.getUserSystemDirectory(userInfo.id).mkdirs();
+ synchronized (mUsersLock) {
mUsers.put(userId, userInfo);
- writeUserListLILP();
- if (parent != null) {
- if (isManagedProfile) {
- if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- parent.profileGroupId = parent.id;
- scheduleWriteUser(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;
- scheduleWriteUser(parent);
- }
- userInfo.restrictedProfileParentId = parent.restrictedProfileParentId;
+ }
+ writeUserListLP();
+ if (parent != null) {
+ if (isManagedProfile) {
+ if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ parent.profileGroupId = parent.id;
+ writeUserLP(parent);
}
- }
-
- final StorageManager storage = mContext.getSystemService(StorageManager.class);
- storage.createUserKey(userId, userInfo.serialNumber);
- for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
- final String volumeUuid = vol.getFsUuid();
- try {
- final File userDir = Environment.getDataUserDirectory(volumeUuid,
- userId);
- storage.prepareUserStorage(volumeUuid, userId, userInfo.serialNumber);
- enforceSerialNumber(userDir, userInfo.serialNumber);
- } catch (IOException e) {
- Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e);
+ userInfo.profileGroupId = parent.profileGroupId;
+ } else if (isRestricted) {
+ if (parent.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
+ parent.restrictedProfileParentId = parent.id;
+ writeUserLP(parent);
}
- }
- mPm.createNewUserLILPw(userId);
- userInfo.partial = false;
- scheduleWriteUser(userInfo);
- updateUserIds();
- Bundle restrictions = new Bundle();
- synchronized (mRestrictionsLock) {
- mBaseUserRestrictions.append(userId, restrictions);
+ userInfo.restrictedProfileParentId = parent.restrictedProfileParentId;
}
}
}
- mPm.newUserCreated(userId);
- if (userInfo != null) {
- Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
- addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
- mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
- android.Manifest.permission.MANAGE_USERS);
+ final StorageManager storage = mContext.getSystemService(StorageManager.class);
+ storage.createUserKey(userId, userInfo.serialNumber);
+ for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+ final String volumeUuid = vol.getFsUuid();
+ try {
+ final File userDir = Environment.getDataUserDirectory(volumeUuid, userId);
+ storage.prepareUserStorage(volumeUuid, userId, userInfo.serialNumber);
+ enforceSerialNumber(userDir, userInfo.serialNumber);
+ } catch (IOException e) {
+ Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e);
+ }
}
+ mPm.createNewUser(userId);
+ userInfo.partial = false;
+ synchronized (mPackagesLock) {
+ writeUserLP(userInfo);
+ }
+ updateUserIds();
+ Bundle restrictions = new Bundle();
+ synchronized (mRestrictionsLock) {
+ mBaseUserRestrictions.append(userId, restrictions);
+ }
+ mPm.newUserCreated(userId);
+ Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
+ addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
+ android.Manifest.permission.MANAGE_USERS);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1782,11 +1760,7 @@
// Clean up any ActivityManager state
LocalServices.getService(ActivityManagerInternal.class)
.onUserRemoved(userHandle);
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- removeUserStateLILP(userHandle);
- }
- }
+ removeUserState(userHandle);
}
}.start();
}
@@ -1798,10 +1772,10 @@
}
}
- private void removeUserStateLILP(final int userHandle) {
+ private void removeUserState(final int userHandle) {
mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
// Cleanup package manager settings
- mPm.cleanUpUserLILPw(this, userHandle);
+ mPm.cleanUpUser(this, userHandle);
// Remove this user from the list
synchronized (mUsersLock) {
@@ -1811,7 +1785,9 @@
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
userFile.delete();
// Update the user list
- writeUserListLILP();
+ synchronized (mPackagesLock) {
+ writeUserListLP();
+ }
updateUserIds();
removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
}
@@ -2146,17 +2122,15 @@
* @param userId the user that was just foregrounded
*/
public void onUserForeground(int userId) {
- synchronized (mPackagesLock) {
- UserInfo user = getUserInfoNoChecks(userId);
- long now = System.currentTimeMillis();
- if (user == null || user.partial) {
- Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
- return;
- }
- if (now > EPOCH_PLUS_30_YEARS) {
- user.lastLoggedInTime = now;
- scheduleWriteUser(user);
- }
+ UserInfo user = getUserInfoNoChecks(userId);
+ if (user == null || user.partial) {
+ Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
+ return;
+ }
+ long now = System.currentTimeMillis();
+ if (now > EPOCH_PLUS_30_YEARS) {
+ user.lastLoggedInTime = now;
+ scheduleWriteUser(user);
}
}
@@ -2164,7 +2138,6 @@
* Returns the next available user id, filling in any holes in the ids.
* TODO: May not be a good idea to recycle ids, in case it results in confusion
* for data and battery stats collection, or unexpected cross-talk.
- * @return
*/
private int getNextAvailableId() {
synchronized (mUsersLock) {
@@ -2348,7 +2321,9 @@
}
pw.println();
pw.println("Guest restrictions:");
- UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
+ synchronized (mGuestRestrictions) {
+ UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
+ }
}
}