Merge "Mute correct user from device policy manager." into mnc-dev
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 2c28d8e..3bf8129 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -40,6 +40,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -872,7 +873,8 @@
     public void setMasterMute(boolean mute, int flags) {
         IAudioService service = getService();
         try {
-            service.setMasterMute(mute, flags, getContext().getOpPackageName());
+            service.setMasterMute(mute, flags, getContext().getOpPackageName(),
+                    UserHandle.getCallingUserId());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setMasterMute", e);
         }
@@ -1551,10 +1553,11 @@
      * @param on set <var>true</var> to mute the microphone;
      *           <var>false</var> to turn mute off
      */
-    public void setMicrophoneMute(boolean on){
+    public void setMicrophoneMute(boolean on) {
         IAudioService service = getService();
         try {
-            service.setMicrophoneMute(on, getContext().getOpPackageName());
+            service.setMicrophoneMute(on, getContext().getOpPackageName(),
+                    UserHandle.getCallingUserId());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setMicrophoneMute", e);
         }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c75c7e5..8aebe11 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -55,7 +55,7 @@
 
     boolean isMasterMute();
 
-    void setMasterMute(boolean mute, int flags, String callingPackage);
+    void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
 
     int getStreamVolume(int streamType);
 
@@ -65,7 +65,7 @@
 
     int getLastAudibleStreamVolume(int streamType);
 
-    void setMicrophoneMute(boolean on, String callingPackage);
+    void setMicrophoneMute(boolean on, String callingPackage, int userId);
 
     void setRingerModeExternal(int ringerMode, String caller);
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index dd4111d..eef3d63 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1166,6 +1166,11 @@
             return;
         }
 
+        // If we are being called by the system (e.g. hardware keys) check for current user
+        // so we handle user restrictions correctly.
+        if (uid == android.os.Process.SYSTEM_UID) {
+            uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
+        }
         if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
                 != AppOpsManager.MODE_ALLOWED) {
             return;
@@ -1412,7 +1417,11 @@
             (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
-
+        // If we are being called by the system (e.g. hardware keys) check for current user
+        // so we handle user restrictions correctly.
+        if (uid == android.os.Process.SYSTEM_UID) {
+            uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
+        }
         if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
                 != AppOpsManager.MODE_ALLOWED) {
             return;
@@ -1540,6 +1549,19 @@
         }
     }
 
+    private int getCurrentUserId() {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            UserInfo currentUser = ActivityManagerNative.getDefault().getCurrentUser();
+            return currentUser.id;
+        } catch (RemoteException e) {
+            // Activity manager not running, nothing we can do assume user 0.
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        return UserHandle.USER_OWNER;
+    }
+
     // UI update and Broadcast Intent
     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
         streamType = mStreamVolumeAlias[streamType];
@@ -1733,22 +1755,41 @@
         }
     }
 
-    private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid) {
+    private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
+            int userId) {
+        // If we are being called by the system check for user we are going to change
+        // so we handle user restrictions correctly.
+        if (uid == android.os.Process.SYSTEM_UID) {
+            uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
+        }
         if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
                 != AppOpsManager.MODE_ALLOWED) {
             return;
         }
-        if (mute != AudioSystem.getMasterMute()) {
-            setSystemAudioMute(mute);
-            AudioSystem.setMasterMute(mute);
-            // Post a persist master volume msg
-            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                    : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
-            sendMasterMuteUpdate(mute, flags);
+        if (userId != UserHandle.getCallingUserId() &&
+                mContext.checkCallingOrSelfPermission(
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+        if (getCurrentUserId() == userId) {
+            if (mute != AudioSystem.getMasterMute()) {
+                setSystemAudioMute(mute);
+                AudioSystem.setMasterMute(mute);
+                // Post a persist master volume msg
+                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
+                        : 0, userId, null, PERSIST_DELAY);
+                sendMasterMuteUpdate(mute, flags);
 
-            Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
-            intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
-            sendBroadcastToAll(intent);
+                Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
+                intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
+                sendBroadcastToAll(intent);
+            }
+        } else {
+            // If not the current user just persist the setting which will be loaded
+            // on user switch.
+            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
+                    : 0, userId, null, PERSIST_DELAY);
         }
     }
 
@@ -1757,8 +1798,9 @@
         return AudioSystem.getMasterMute();
     }
 
-    public void setMasterMute(boolean mute, int flags, String callingPackage) {
-        setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid());
+    public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
+        setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
+                userId);
     }
 
     /** @see AudioManager#getStreamVolume(int) */
@@ -1804,20 +1846,36 @@
         return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
     }
 
-    /** @see AudioManager#setMicrophoneMute(boolean) */
-    public void setMicrophoneMute(boolean on, String callingPackage) {
-        if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(),
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+    /** @see AudioManager#setMicrophoneMute(boolean, int) */
+    public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
+        // If we are being called by the system check for user we are going to change
+        // so we handle user restrictions correctly.
+        int uid = Binder.getCallingUid();
+        if (uid == android.os.Process.SYSTEM_UID) {
+            uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
+        }
+        if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
             return;
         }
         if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
             return;
         }
+        if (userId != UserHandle.getCallingUserId() &&
+                mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
 
-        AudioSystem.muteMicrophone(on);
+        // If mute is for current user actually mute, else just persist the setting
+        // which will be loaded on user switch.
+        if (getCurrentUserId() == userId) {
+            AudioSystem.muteMicrophone(on);
+        }
         // Post a persist microphone msg.
         sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
-                : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
+                : 0, userId, null, PERSIST_DELAY);
     }
 
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5040bd0..ed4fe24 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4407,15 +4407,25 @@
 
 
     private void clearUserRestrictions(UserHandle userHandle) {
-        AudioManager audioManager =
-                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         Bundle userRestrictions = mUserManager.getUserRestrictions();
         mUserManager.setUserRestrictions(new Bundle(), userHandle);
+        IAudioService iAudioService = IAudioService.Stub.asInterface(
+                ServiceManager.getService(Context.AUDIO_SERVICE));
         if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
-            audioManager.setMasterMute(false, 0);
+            try {
+                iAudioService.setMasterMute(true, 0, mContext.getPackageName(),
+                        userHandle.getIdentifier());
+            } catch (RemoteException e) {
+                // Not much we can do here.
+            }
         }
         if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
-            audioManager.setMicrophoneMute(false);
+            try {
+                iAudioService.setMicrophoneMute(true, mContext.getPackageName(),
+                        userHandle.getIdentifier());
+            } catch (RemoteException e) {
+                // Not much we can do here.
+            }
         }
     }
 
@@ -5426,9 +5436,11 @@
             try {
                 if (enabled && !alreadyRestricted) {
                     if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        iAudioService.setMicrophoneMute(true, mContext.getPackageName());
+                        iAudioService.setMicrophoneMute(true, mContext.getPackageName(),
+                                userHandle);
                     } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        iAudioService.setMasterMute(true, 0, mContext.getPackageName());
+                        iAudioService.setMasterMute(true, 0, mContext.getPackageName(),
+                                userHandle);
                     }
                     if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
                         Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -5480,9 +5492,11 @@
                 }
                 if (!enabled && alreadyRestricted) {
                     if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        iAudioService.setMicrophoneMute(false, mContext.getPackageName());
+                        iAudioService.setMicrophoneMute(false, mContext.getPackageName(),
+                                userHandle);
                     } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        iAudioService.setMasterMute(false, 0, mContext.getPackageName());
+                        iAudioService.setMasterMute(false, 0, mContext.getPackageName(),
+                                userHandle);
                     }
                 }
             } catch (RemoteException re) {
@@ -6031,13 +6045,16 @@
         Preconditions.checkNotNull(who, "ComponentName is null");
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
-            IAudioService iAudioService = IAudioService.Stub.asInterface(
-                    ServiceManager.getService(Context.AUDIO_SERVICE));
+            int userId = UserHandle.getCallingUserId();
+            long identity = Binder.clearCallingIdentity();
             try {
-                iAudioService.setMasterMute(on, 0, who.getPackageName());
+                IAudioService iAudioService = IAudioService.Stub.asInterface(
+                        ServiceManager.getService(Context.AUDIO_SERVICE));
+                iAudioService.setMasterMute(on, 0, mContext.getPackageName(), userId);
             } catch (RemoteException re) {
                 Slog.e(LOG_TAG, "Failed to setMasterMute", re);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
     }