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

Commit d80f46a1 authored by Atneya Nair's avatar Atneya Nair
Browse files

Batch zen audio restrictions across usages

Migrate Zen audio restrictions to new API which batches across usages.

New applyRestriction logic partitions usages across those which should
be muted, and those which shouldn't be, with a single appops call for
each (both directions are needed since the restriction state is never
implicitly cleared).

Modify mocking tests to handle the refactored call, additionally
verifying the restriction state across all usages in the process. In
doing so, a few redundant tests can be eliminated.

Test: atest ZenModeHelperTest
Flag: EXEMPT mechanical refactor
Bug: 415378815
Change-Id: I5c8435fcff1a90bb61d0dbfad8a35cb54cf76d40
parent 5c1799e5
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -375,6 +375,13 @@ public final class AudioAttributes implements Parcelable {
        return SDK_USAGES.toArray();
        return SDK_USAGES.toArray();
    }
    }


    /**
     * @hide
     */
    public static int getSuppressibleUsage(@AttributeSdkUsage int usage) {
        return SUPPRESSIBLE_USAGES.get(usage);
    }

    /**
    /**
     * Flag defining a behavior where the audibility of the sound will be ensured by the system.
     * Flag defining a behavior where the audibility of the sound will be ensured by the system.
     * To ensure sound audibility, the system only uses built-in speakers or wired headphones
     * To ensure sound audibility, the system only uses built-in speakers or wired headphones
+51 −49
Original line number Original line Diff line number Diff line
@@ -107,6 +107,7 @@ import android.service.notification.ZenPolicy;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArray;
@@ -131,6 +132,7 @@ import java.io.PrintWriter;
import java.time.Clock;
import java.time.Clock;
import java.time.Duration;
import java.time.Duration;
import java.time.Instant;
import java.time.Instant;
import java.util.function.IntPredicate;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
@@ -2283,75 +2285,75 @@ public class ZenModeHelper {
        final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
        final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
        final boolean allowCalls = mConsolidatedPolicy.allowCalls()
        final boolean allowCalls = mConsolidatedPolicy.allowCalls()
                && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY;
                && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY;
        final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
        final boolean allowSystem = mConsolidatedPolicy.allowSystem();
        final boolean allowMedia = mConsolidatedPolicy.allowMedia();
        final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();


        // notification restrictions
        // notification restrictions
        final boolean muteNotifications = zenOn
        final boolean muteNotifications =
                || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
                zenOn || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
        // call restrictions
        // call restrictions
        final boolean muteCalls = zenAlarmsOnly
        final boolean muteCalls = zenAlarmsOnly
                || (zenPriorityOnly && (!allowCalls || !allowRepeatCallers))
                || (zenPriorityOnly && (!allowCalls || !mConsolidatedPolicy.allowRepeatCallers()))
                || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
                || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
        // alarm restrictions
        // alarm restrictions
        final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
        final boolean muteAlarms = zenPriorityOnly && !mConsolidatedPolicy.allowAlarms();
        // media restrictions
        // media restrictions
        final boolean muteMedia = zenPriorityOnly && !allowMedia;
        final boolean muteMedia = zenPriorityOnly && !mConsolidatedPolicy.allowMedia();
        // system restrictions
        // system restrictions
        final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
        final boolean muteSystem =
                zenAlarmsOnly || (zenPriorityOnly && !mConsolidatedPolicy.allowSystem());
        // total silence restrictions
        // total silence restrictions
        final boolean muteEverything = zenSilence || (zenPriorityOnly
        final boolean muteEverything = zenSilence
                || (zenPriorityOnly
                        && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
                        && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));


        for (int usage : AudioAttributes.SDK_USAGES.toArray()) {
        final IntPredicate shouldMute = (usage) ->
            final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
        switch (AudioAttributes.getSuppressibleUsage(usage)) {
            if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
            case AudioAttributes.SUPPRESSIBLE_NEVER -> false;
                applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
            case AudioAttributes.SUPPRESSIBLE_NOTIFICATION -> muteNotifications || muteEverything;
            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
            case AudioAttributes.SUPPRESSIBLE_CALL -> muteCalls || muteEverything;
                applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
            case AudioAttributes.SUPPRESSIBLE_ALARM -> muteAlarms || muteEverything;
            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
            case AudioAttributes.SUPPRESSIBLE_MEDIA -> muteMedia || muteEverything;
                applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
            case AudioAttributes.SUPPRESSIBLE_SYSTEM -> muteSystem || muteEverything;
            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
            default -> muteEverything; // TODO BUG!
                applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
        };
            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {

                applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
        // special case: touch sounds should still vibrate during DND
            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
        final IntPredicate shouldMuteForVibrate = (usage)
                if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
                -> usage != AudioAttributes.USAGE_ASSISTANCE_SONIFICATION && shouldMute.test(usage);
                    // normally DND will only restrict touch sounds, not haptic feedback/vibrations
                    applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
                            AppOpsManager.OP_PLAY_AUDIO);
                    applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
                } else {
                    applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
                }
            } else {
                applyRestrictions(zenPriorityOnly, muteEverything, usage);
            }
        }
    }


        applyRestrictions(zenPriorityOnly, shouldMute, AppOpsManager.OP_PLAY_AUDIO);
        applyRestrictions(zenPriorityOnly, shouldMuteForVibrate, AppOpsManager.OP_VIBRATE);
    }


    @VisibleForTesting
    @VisibleForTesting
    protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
    protected void applyRestrictions(
            boolean zenPriorityOnly, IntPredicate shouldMuteForUsage, int code) {
        final long ident = Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        try {
        try {
            mAppOps.setRestriction(code, usage,
            final var unmutedUsages = new IntArray();
                    mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
            final var mutedUsages = new IntArray();

            for (int usage : AudioAttributes.getSdkUsages()) {
                if (shouldMuteForUsage.test(usage)) {
                    mutedUsages.add(usage);
                } else {
                    unmutedUsages.add(usage);
                }
            }
            // MODE_IGNORED for muted usages
            mAppOps.setAudioRestriction(code, mutedUsages.toArray(),
                    AppOpsManager.MODE_IGNORED,
                    zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
                    zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);

            // MODE_ALLOWED for unmuted usages
            mAppOps.setAudioRestriction(code, unmutedUsages.toArray(),
                    AppOpsManager.MODE_ALLOWED,
                    zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);

        } finally {
        } finally {
            Binder.restoreCallingIdentity(ident);
            Binder.restoreCallingIdentity(ident);
        }
        }
    }
    }


    @VisibleForTesting
    protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
        applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
        applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
    }


    @VisibleForTesting
    @VisibleForTesting
    protected void applyZenToRingerMode() {
    protected void applyZenToRingerMode() {
        if (mAudioManager == null) return;
        if (mAudioManager == null) return;
+199 −130

File changed.

Preview size limit exceeded, changes collapsed.