Loading services/core/java/com/android/server/audio/AudioService.java +37 −24 Original line number Diff line number Diff line Loading @@ -848,23 +848,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) { Loading @@ -882,7 +865,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, Loading Loading @@ -1638,7 +1621,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); } Loading Loading @@ -3934,7 +3919,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()) { Loading Loading @@ -4695,7 +4682,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, Loading Loading @@ -6144,7 +6133,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) Loading Loading @@ -6913,7 +6904,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, Loading @@ -6928,7 +6921,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); Loading Loading @@ -15489,4 +15484,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); } } } services/core/java/com/android/server/audio/HardeningEnforcer.java +50 −12 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -49,6 +50,7 @@ public class HardeningEnforcer { final Context mContext; final AppOpsManager mAppOps; final AtomicBoolean mShouldEnableAllHardening; final boolean mIsAutomotive; final ActivityManager mActivityManager; Loading Loading @@ -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; Loading @@ -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; } /** Loading Loading
services/core/java/com/android/server/audio/AudioService.java +37 −24 Original line number Diff line number Diff line Loading @@ -848,23 +848,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) { Loading @@ -882,7 +865,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, Loading Loading @@ -1638,7 +1621,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); } Loading Loading @@ -3934,7 +3919,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()) { Loading Loading @@ -4695,7 +4682,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, Loading Loading @@ -6144,7 +6133,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) Loading Loading @@ -6913,7 +6904,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, Loading @@ -6928,7 +6921,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); Loading Loading @@ -15489,4 +15484,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); } } }
services/core/java/com/android/server/audio/HardeningEnforcer.java +50 −12 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -49,6 +50,7 @@ public class HardeningEnforcer { final Context mContext; final AppOpsManager mAppOps; final AtomicBoolean mShouldEnableAllHardening; final boolean mIsAutomotive; final ActivityManager mActivityManager; Loading Loading @@ -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; Loading @@ -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; } /** Loading