Allow profile and device owners to change and get the master volume mute state.
Also protect muting master volume with op code OP_AUDIO_MASTER_VOLUME.
Bug: 13585918
Change-Id: I91fe7ee60cd291cca15966b3127c0bb8a4828f6a
diff --git a/api/current.txt b/api/current.txt
index da75946..ece7b13 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5205,6 +5205,7 @@
method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String);
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isLockTaskPermitted(android.content.ComponentName);
+ method public boolean isMasterVolumeMuted(android.content.ComponentName);
method public boolean isProfileOwnerApp(java.lang.String);
method public void lockNow();
method public void removeActiveAdmin(android.content.ComponentName);
@@ -5218,6 +5219,7 @@
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
+ method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5579470..4aa4294 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.RestrictionsManager;
+import android.media.AudioService;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.Handler;
@@ -2406,4 +2407,37 @@
}
}
}
+
+ /**
+ * Called by profile or device owners to set the master volume mute on or off.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param on {@code true} to mute master volume, {@code false} to turn mute off.
+ */
+ public void setMasterVolumeMuted(ComponentName admin, boolean on) {
+ if (mService != null) {
+ try {
+ mService.setMasterVolumeMuted(admin, on);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to setMasterMute on device policy service");
+ }
+ }
+ }
+
+ /**
+ * Called by profile or device owners to check whether the master volume mute is on or off.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return {@code true} if master volume is muted, {@code false} if it's not.
+ */
+ public boolean isMasterVolumeMuted(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.isMasterVolumeMuted(admin);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to get isMasterMute on device policy service");
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 4935ddc..f8df780 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -147,4 +147,7 @@
void setGlobalSetting(in ComponentName who, in String setting, in String value);
void setSecureSetting(in ComponentName who, in String setting, in String value);
+
+ void setMasterVolumeMuted(in ComponentName admin, boolean on);
+ boolean isMasterVolumeMuted(in ComponentName admin);
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 88756d7..c3d5d94 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1017,7 +1017,7 @@
public void setMasterMute(boolean state, int flags) {
IAudioService service = getService();
try {
- service.setMasterMute(state, flags, mICallBack);
+ service.setMasterMute(state, flags, mContext.getOpPackageName(), mICallBack);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setMasterMute", e);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 74f39b7..2f782cc 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1321,11 +1321,16 @@
}
/** @see AudioManager#setMasterMute(boolean, int) */
- public void setMasterMute(boolean state, int flags, IBinder cb) {
+ public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) {
if (mUseFixedVolume) {
return;
}
+ if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return;
+ }
+
if (state != AudioSystem.getMasterMute()) {
AudioSystem.setMasterMute(state);
// Post a persist master volume msg
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index e59623b..ba3cfb6 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -62,7 +62,7 @@
boolean isStreamMute(int streamType);
- void setMasterMute(boolean state, int flags, IBinder cb);
+ void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb);
boolean isMasterMute();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 14f14f4..5cfe0f1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,8 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.media.AudioManager;
+import android.media.IAudioService;
import android.net.ConnectivityManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ProxyInfo;
@@ -3775,4 +3777,40 @@
}
}
}
+
+ @Override
+ public void setMasterVolumeMuted(ComponentName who, boolean on) {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ IAudioService iAudioService = IAudioService.Stub.asInterface(
+ ServiceManager.getService(Context.AUDIO_SERVICE));
+ try{
+ iAudioService.setMasterMute(on, 0, who.getPackageName(), null);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Failed to setMasterMute", re);
+ }
+ }
+ }
+
+ @Override
+ public boolean isMasterVolumeMuted(ComponentName who) {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ AudioManager audioManager =
+ (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ return audioManager.isMasterMute();
+ }
+ }
}