summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Atneya Nair <atneya@google.com> 2025-02-20 16:20:58 -0800
committer Atneya Nair <atneya@google.com> 2025-02-20 16:20:58 -0800
commit878817ab6767fa16dedeb254c0ae3e609b92ec59 (patch)
treea5275f93780f0af59e12a6c25e657b0adef8db9a
parent789cc0d07435800580f56a36b13b1845fed00792 (diff)
[audio] Add volume hardening metrics and logs
Prepare for hardening enforcement for volume APIs by logging express metrics on volume api usage and the potential affect of levels of hardening. Add logging to hardening enforcer for consistency with playback hardening. Integrate enforcement shell cmd to test enforcement even with flags disabled. Note, this CL does not yet include any flags, so by default no restriction is enabled. Test: atest AudioManagerTest Bug: 376481063 Flag: EXEMPT logging only Change-Id: If7bad31b121bf52d7dd2e2e33930f44f2365e8f6
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java61
-rw-r--r--services/core/java/com/android/server/audio/HardeningEnforcer.java62
2 files changed, 87 insertions, 36 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6b16b131ce0d..54b33c3f6c69 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -844,23 +844,6 @@ public class AudioService extends IAudioService.Stub
"media_audio.value_audio_playback_hardening_partial_restriction";
static final String METRIC_COUNTERS_PLAYBACK_STRICT =
"media_audio.value_audio_playback_hardening_strict_would_restrict";
-
- String getPackNameForUid(int uid) {
- final long token = Binder.clearCallingIdentity();
- try {
- final String[] names = AudioService.this.mContext.
- getPackageManager().getPackagesForUid(uid);
- if (names == null
- || names.length == 0
- || TextUtils.isEmpty(names[0])) {
- return "[" + uid + "]";
- }
- return names[0];
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
// oneway
@Override
public void playbackHardeningEvent(int uid, byte type, boolean bypassed) {
@@ -878,7 +861,7 @@ public class AudioService extends IAudioService.Stub
String msg = "AudioHardening background playback "
+ (bypassed ? "would be " : "")
+ "muted for "
- + getPackNameForUid(uid) + " (" + uid + "), "
+ + getPackageNameForUid(uid) + " (" + uid + "), "
+ "level: " + (type == HardeningType.PARTIAL ? "partial" : "full");
AudioService.this.mHardeningLogger.enqueueAndSlog(msg,
@@ -1604,7 +1587,9 @@ public class AudioService extends IAudioService.Stub
mMusicFxHelper = new MusicFxHelper(mContext, mAudioHandler);
- mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive(), mAppOps,
+ mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive(),
+ mShouldEnableAllHardening,
+ mAppOps,
context.getPackageManager(),
mHardeningLogger);
}
@@ -3898,7 +3883,9 @@ public class AudioService extends IAudioService.Stub
public void adjustStreamVolumeWithAttribution(int streamType, int direction, int flags,
String callingPackage, String attributionTag) {
if (mHardeningEnforcer.blockVolumeMethod(
- HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_STREAM_VOLUME)) {
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_STREAM_VOLUME,
+ callingPackage,
+ Binder.getCallingUid())) {
return;
}
if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
@@ -4659,7 +4646,9 @@ public class AudioService extends IAudioService.Stub
public void setStreamVolumeWithAttribution(int streamType, int index, int flags,
String callingPackage, String attributionTag) {
if (mHardeningEnforcer.blockVolumeMethod(
- HardeningEnforcer.METHOD_AUDIO_MANAGER_SET_STREAM_VOLUME)) {
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_SET_STREAM_VOLUME,
+ callingPackage,
+ Binder.getCallingUid())) {
return;
}
setStreamVolumeWithAttributionInt(streamType, index, flags, /*device*/ null,
@@ -6106,7 +6095,9 @@ public class AudioService extends IAudioService.Stub
public void setRingerModeExternal(int ringerMode, String caller) {
if (mHardeningEnforcer.blockVolumeMethod(
- HardeningEnforcer.METHOD_AUDIO_MANAGER_SET_RINGER_MODE)) {
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_SET_RINGER_MODE,
+ getPackageNameForUid(Binder.getCallingUid()),
+ Binder.getCallingUid())) {
return;
}
if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
@@ -6875,7 +6866,9 @@ public class AudioService extends IAudioService.Stub
@Override
public void adjustVolume(int direction, int flags) {
if (mHardeningEnforcer.blockVolumeMethod(
- HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_VOLUME)) {
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_VOLUME,
+ getPackageNameForUid(Binder.getCallingUid()),
+ Binder.getCallingUid())) {
return;
}
getMediaSessionManager().dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
@@ -6890,7 +6883,9 @@ public class AudioService extends IAudioService.Stub
@Override
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
if (mHardeningEnforcer.blockVolumeMethod(
- HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_SUGGESTED_STREAM_VOLUME)) {
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_ADJUST_SUGGESTED_STREAM_VOLUME,
+ getPackageNameForUid(Binder.getCallingUid()),
+ Binder.getCallingUid())) {
return;
}
getMediaSessionManager().dispatchAdjustVolume(suggestedStreamType, direction, flags);
@@ -15448,4 +15443,22 @@ public class AudioService extends IAudioService.Stub
}
return true;
}
+
+ private String getPackageNameForUid(int uid) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final String[] names = AudioService.this.mContext.
+ getPackageManager().getPackagesForUid(uid);
+ if (names == null
+ || names.length == 0
+ || TextUtils.isEmpty(names[0])) {
+ return "[" + uid + "]";
+ }
+ return names[0];
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+
}
diff --git a/services/core/java/com/android/server/audio/HardeningEnforcer.java b/services/core/java/com/android/server/audio/HardeningEnforcer.java
index f69a810b314f..9bb5160f108a 100644
--- a/services/core/java/com/android/server/audio/HardeningEnforcer.java
+++ b/services/core/java/com/android/server/audio/HardeningEnforcer.java
@@ -37,6 +37,7 @@ import com.android.modules.expresslog.Counter;
import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Class to encapsulate all audio API hardening operations
@@ -49,6 +50,7 @@ public class HardeningEnforcer {
final Context mContext;
final AppOpsManager mAppOps;
+ final AtomicBoolean mShouldEnableAllHardening;
final boolean mIsAutomotive;
final ActivityManager mActivityManager;
@@ -106,10 +108,16 @@ public class HardeningEnforcer {
*/
public static final int METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS = 300;
- public HardeningEnforcer(Context ctxt, boolean isAutomotive, AppOpsManager appOps,
- PackageManager pm, EventLogger logger) {
+ private static final int ALLOWED = 0;
+ private static final int DENIED_IF_PARTIAL = 1;
+ private static final int DENIED_IF_FULL = 2;
+
+ public HardeningEnforcer(Context ctxt, boolean isAutomotive,
+ AtomicBoolean shouldEnableHardening, AppOpsManager appOps, PackageManager pm,
+ EventLogger logger) {
mContext = ctxt;
mIsAutomotive = isAutomotive;
+ mShouldEnableAllHardening = shouldEnableHardening;
mAppOps = appOps;
mActivityManager = ctxt.getSystemService(ActivityManager.class);
mPackageManager = pm;
@@ -121,29 +129,59 @@ public class HardeningEnforcer {
* @param volumeMethod name of the method to check, for logging purposes
* @return false if the method call is allowed, true if it should be a no-op
*/
- protected boolean blockVolumeMethod(int volumeMethod) {
+ protected boolean blockVolumeMethod(int volumeMethod, String packageName, int uid) {
+ // Regardless of flag state, always permit callers with MODIFY_AUDIO_SETTINGS_PRIVILEGED
+ // Prevent them from showing up in metrics as well
+ if (mContext.checkCallingOrSelfPermission(
+ Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+ == PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
// for Auto, volume methods require MODIFY_AUDIO_SETTINGS_PRIVILEGED
if (mIsAutomotive) {
if (!autoPublicVolumeApiHardening()) {
// automotive hardening flag disabled, no blocking on auto
return false;
}
- if (mContext.checkCallingOrSelfPermission(
- Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
- == PackageManager.PERMISSION_GRANTED) {
- return false;
- }
- if (Binder.getCallingUid() < UserHandle.AID_APP_START) {
+ if (uid < UserHandle.AID_APP_START) {
return false;
}
// TODO metrics?
// TODO log for audio dumpsys?
Slog.e(TAG, "Preventing volume method " + volumeMethod + " for "
- + getPackNameForUid(Binder.getCallingUid()));
+ + packageName);
return true;
+ } else {
+ int allowed;
+ // No flags controlling restriction yet
+ boolean enforced = mShouldEnableAllHardening.get();
+ if (!noteOp(AppOpsManager.OP_CONTROL_AUDIO_PARTIAL, uid, packageName, null)) {
+ // blocked by partial
+ Counter.logIncrementWithUid(
+ "media_audio.value_audio_volume_hardening_partial_restriction", uid);
+ allowed = DENIED_IF_PARTIAL;
+ } else if (!noteOp(AppOpsManager.OP_CONTROL_AUDIO, uid, packageName, null)) {
+ // blocked by full, permitted by partial
+ Counter.logIncrementWithUid(
+ "media_audio.value_audio_volume_hardening_strict_restriction", uid);
+ allowed = DENIED_IF_FULL;
+ } else {
+ // permitted with strict hardening, log anyway for API metrics
+ Counter.logIncrementWithUid(
+ "media_audio.value_audio_volume_hardening_allowed", uid);
+ allowed = ALLOWED;
+ }
+ if (allowed != ALLOWED) {
+ String msg = "AudioHardening volume control for api "
+ + volumeMethod
+ + (!enforced ? " would be " : " ")
+ + "ignored for "
+ + getPackNameForUid(uid) + " (" + uid + "), "
+ + "level: " + (allowed == DENIED_IF_PARTIAL ? "partial" : "full");
+ mEventLogger.enqueueAndSlog(msg, EventLogger.Event.ALOGW, TAG);
+ }
+ return enforced && allowed != ALLOWED;
}
- // not blocking
- return false;
}
/**