Don't call DPM from UserManager to avoid lock inversion
- Also make sure DPMS.mOwners is always guarded with DPMS.this.
(and remove synchronization from Owners.)
Bug 25796840
Change-Id: I83f7b78e7b437d9c2a2b1d6e714346cd15f95330
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ff829ff..424b902 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -24,7 +24,6 @@
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
-import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -216,14 +215,15 @@
private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
/**
- * User restrictions set by {@link DevicePolicyManager} that should be applied to all users,
- * including guests.
+ * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
+ * that should be applied to all users, including guests.
*/
@GuardedBy("mRestrictionsLock")
private Bundle mDevicePolicyGlobalUserRestrictions;
/**
- * User restrictions set by {@link DevicePolicyManager} for each user.
+ * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
+ * for each user.
*/
@GuardedBy("mRestrictionsLock")
private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
@@ -248,6 +248,12 @@
private final LocalService mLocalService;
+ @GuardedBy("mUsersLock")
+ private boolean mIsDeviceManaged;
+
+ @GuardedBy("mUsersLock")
+ private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray();
+
@GuardedBy("mUserRestrictionsListeners")
private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
new ArrayList<>();
@@ -509,11 +515,9 @@
if (!userInfo.isAdmin()) {
return false;
}
+ // restricted profile can be created if there is no DO set and the admin user has no PO;
+ return !mIsDeviceManaged && !mIsUserManaged.get(userId);
}
- DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- // restricted profile can be created if there is no DO set and the admin user has no PO
- return !dpm.isDeviceManaged() && dpm.getProfileOwnerAsUser(userId) == null;
}
/*
@@ -1596,11 +1600,10 @@
if (UserManager.isSplitSystemUser()
&& !isGuest && !isManagedProfile && getPrimaryUser() == null) {
flags |= UserInfo.FLAG_PRIMARY;
- DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
- mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- if (devicePolicyManager == null
- || !devicePolicyManager.isDeviceManaged()) {
- flags |= UserInfo.FLAG_ADMIN;
+ synchronized (mUsersLock) {
+ if (!mIsDeviceManaged) {
+ flags |= UserInfo.FLAG_ADMIN;
+ }
}
}
userId = getNextAvailableId();
@@ -1865,6 +1868,13 @@
// Remove this user from the list
synchronized (mUsersLock) {
mUsers.remove(userHandle);
+ mIsUserManaged.delete(userHandle);
+ }
+ synchronized (mRestrictionsLock) {
+ mBaseUserRestrictions.remove(userHandle);
+ mAppliedUserRestrictions.remove(userHandle);
+ mCachedEffectiveUserRestrictions.remove(userHandle);
+ mDevicePolicyLocalUserRestrictions.remove(userHandle);
}
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
@@ -2376,9 +2386,10 @@
if (user == null) {
continue;
}
+ final int userId = user.id;
pw.print(" "); pw.print(user);
pw.print(" serialNo="); pw.print(user.serialNumber);
- if (mRemovingUserIds.get(mUsers.keyAt(i))) {
+ if (mRemovingUserIds.get(userId)) {
pw.print(" <removing> ");
}
if (user.partial) {
@@ -2403,6 +2414,8 @@
sb.append(" ago");
pw.println(sb);
}
+ pw.print(" Has profile owner: ");
+ pw.println(mIsUserManaged.get(userId));
pw.println(" Restrictions:");
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.dumpRestrictions(
@@ -2427,6 +2440,10 @@
synchronized (mGuestRestrictions) {
UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
}
+ synchronized (mUsersLock) {
+ pw.println();
+ pw.println(" Device managed: " + mIsDeviceManaged);
+ }
}
}
@@ -2507,6 +2524,20 @@
mUserRestrictionsListeners.remove(listener);
}
}
+
+ @Override
+ public void setDeviceManaged(boolean isManaged) {
+ synchronized (mUsersLock) {
+ mIsDeviceManaged = isManaged;
+ }
+ }
+
+ @Override
+ public void setUserManaged(int userId, boolean isManaged) {
+ synchronized (mUsersLock) {
+ mIsUserManaged.put(userId, isManaged);
+ }
+ }
}
private class Shell extends ShellCommand {