diff options
| author | 2025-02-20 16:20:58 -0800 | |
|---|---|---|
| committer | 2025-02-20 16:20:58 -0800 | |
| commit | 878817ab6767fa16dedeb254c0ae3e609b92ec59 (patch) | |
| tree | a5275f93780f0af59e12a6c25e657b0adef8db9a | |
| parent | 789cc0d07435800580f56a36b13b1845fed00792 (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.java | 61 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/HardeningEnforcer.java | 62 |
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; } /** |