Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89743430 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[audio] Add volume hardening metrics and logs" into main

parents be243604 878817ab
Loading
Loading
Loading
Loading
+37 −24
Original line number Diff line number Diff line
@@ -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) {
@@ -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,
@@ -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);
    }
@@ -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()) {
@@ -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,
@@ -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)
@@ -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,
@@ -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);
@@ -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);
        }
    }
}
+50 −12
Original line number Diff line number Diff line
@@ -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;
    }

    /**