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 {