Make UserManager enforce user restrictions, not DPM.

- Now even if a user restriction is set via UserManager, it'll be correctly
enforced.

- Changed the way AudioService enforces the OP_MUTE_MICROPHONE and
OP_AUDIO_MASTER_VOLUME app ops -- previously, when they're set, even a muting
call would be rejected.  This was why DPMS.setUserRestriction() used different
calling orders for DISALLOW_UNMUTE_MICROPHONE/DISALLOW_ADJUST_VOLUME depending
on setting them or clearing them.
Now, even when the app ops are set, we still allow muting calls.

Bug 23902097
Bug 24981972

Change-Id: I865b5de43e15f5955f94006475a5ec6254904d31
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c1f827f..62ced52 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -199,6 +199,14 @@
     @GuardedBy("mRestrictionsLock")
     private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
 
+    /**
+     * User restrictions that have already been applied in {@link #applyUserRestrictionsRL}.  We
+     * use it to detect restrictions that have changed since the last
+     * {@link #applyUserRestrictionsRL} call.
+     */
+    @GuardedBy("mRestrictionsLock")
+    private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
+
     private final Bundle mGuestRestrictions = new Bundle();
 
     /**
@@ -727,8 +735,6 @@
             Log.d(LOG_TAG, "updateUserRestrictionsInternalLocked userId=" + userId
                     + " bundle=" + newRestrictions);
         }
-        final Bundle prevRestrictions = getEffectiveUserRestrictions(userId);
-
         // Update system restrictions.
         if (newRestrictions != null) {
             // If newRestrictions == the current one, it's probably a bug.
@@ -742,12 +748,18 @@
 
         mCachedEffectiveUserRestrictions.put(userId, effective);
 
-        applyUserRestrictionsRL(userId, effective, prevRestrictions);
+        applyUserRestrictionsRL(userId, effective);
     }
 
     @GuardedBy("mRestrictionsLock")
-    private void applyUserRestrictionsRL(int userId,
-            Bundle newRestrictions, Bundle prevRestrictions) {
+    private void applyUserRestrictionsRL(int userId, Bundle newRestrictions) {
+        final Bundle prevRestrictions = mAppliedUserRestrictions.get(userId);
+
+        if (DBG) {
+            Log.d(LOG_TAG, "applyUserRestrictionsRL userId=" + userId
+                    + " new=" + newRestrictions + " prev=" + prevRestrictions);
+        }
+
         final long token = Binder.clearCallingIdentity();
         try {
             mAppOpsService.setUserRestrictions(newRestrictions, userId);
@@ -757,7 +769,10 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        // TODO Move the code from DPMS.setUserRestriction().
+        UserRestrictionsUtils.applyUserRestrictions(
+                mContext, userId, newRestrictions, prevRestrictions);
+
+        mAppliedUserRestrictions.put(userId, new Bundle(newRestrictions));
     }
 
     @GuardedBy("mRestrictionsLock")
@@ -768,9 +783,8 @@
     @GuardedBy("mRestrictionsLock")
     private void updateEffectiveUserRestrictionsForAllUsersRL() {
         // First, invalidate all cached values.
-        synchronized (mRestrictionsLock) {
-            mCachedEffectiveUserRestrictions.clear();
-        }
+        mCachedEffectiveUserRestrictions.clear();
+
         // We don't want to call into ActivityManagerNative while taking a lock, so we'll call
         // it on a handler.
         final Runnable r = new Runnable() {