diff options
4 files changed, 115 insertions, 37 deletions
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.Process; 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 class AudioManager { 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 @@ public class AudioManager { * @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 @@ interface IAudioService { 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 @@ interface IAudioService { 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { (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 @@ public class AudioService extends IAudioService.Stub { } } + 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 @@ public class AudioService extends IAudioService.Stub { } } - 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 + 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); + } + } 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, UserHandle.getCallingUserId(), 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); + : 0, userId, null, PERSIST_DELAY); } } @@ -1757,8 +1798,9 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class AudioService extends IAudioService.Stub { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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); } } } |