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

Commit e5a351cb authored by Eric Laurent's avatar Eric Laurent
Browse files

Fix Cell broadcast sound in total silence

PlayerBase:
 Update player volume when the audio attributes are updated in case
we need to unmute
PlaybackActivityMonitor:
 Unmute alarm stream if needed when an alarm with flag
 FLAG_BYPASS_INTERRUPTION_POLICY starts from an app with
 privileged permission MODIFY_PHONE_STATE.

Bug: 63617557
Test: check sound with cell broadcast in total silence
Change-Id: Ifacb1d96a2d8d44047d9f9642d1e672fcf756cda
parent 4de7ab5c
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -127,8 +127,9 @@ public abstract class PlayerBase {
            Log.e(TAG, "Error talking to audio service, STARTED state will not be tracked", e);
        }
        synchronized (mLock) {
            boolean attributesChanged = (mAttributes != attr);
            mAttributes = attr;
            updateAppOpsPlayAudio_sync();
            updateAppOpsPlayAudio_sync(attributesChanged);
        }
    }

@@ -200,16 +201,13 @@ public abstract class PlayerBase {
    }

    void baseSetVolume(float leftVolume, float rightVolume) {
        final boolean hasAppOpsPlayAudio;
        final boolean isRestricted;
        synchronized (mLock) {
            mLeftVolume = leftVolume;
            mRightVolume = rightVolume;
            hasAppOpsPlayAudio = mHasAppOpsPlayAudio;
            if (isRestricted_sync()) {
                return;
            }
            isRestricted = isRestricted_sync();
        }
        playerSetVolume(!hasAppOpsPlayAudio/*muting*/,
        playerSetVolume(isRestricted/*muting*/,
                leftVolume * mPanMultiplierL, rightVolume * mPanMultiplierR);
    }

@@ -250,7 +248,7 @@ public abstract class PlayerBase {

    private void updateAppOpsPlayAudio() {
        synchronized (mLock) {
            updateAppOpsPlayAudio_sync();
            updateAppOpsPlayAudio_sync(false);
        }
    }

@@ -258,7 +256,7 @@ public abstract class PlayerBase {
     * To be called whenever a condition that might affect audibility of this player is updated.
     * Must be called synchronized on mLock.
     */
    void updateAppOpsPlayAudio_sync() {
    void updateAppOpsPlayAudio_sync(boolean attributesChanged) {
        boolean oldHasAppOpsPlayAudio = mHasAppOpsPlayAudio;
        try {
            int mode = AppOpsManager.MODE_IGNORED;
@@ -275,9 +273,10 @@ public abstract class PlayerBase {
        // AppsOps alters a player's volume; when the restriction changes, reflect it on the actual
        // volume used by the player
        try {
            if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio) {
            if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio ||
                    attributesChanged) {
                getService().playerHasOpPlayAudio(mPlayerIId, mHasAppOpsPlayAudio);
                if (mHasAppOpsPlayAudio) {
                if (!isRestricted_sync()) {
                    if (DEBUG_APP_OPS) {
                        Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume
                                + "/" + mRightVolume);
+4 −1
Original line number Diff line number Diff line
@@ -751,6 +751,9 @@ public class AudioService extends IAudioService.Stub
        // relies on audio policy having correct ranges for volume indexes.
        mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();

        mPlaybackMonitor =
                new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);

        mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);

        mRecordMonitor = new RecordingActivityMonitor(mContext);
@@ -6972,7 +6975,7 @@ public class AudioService extends IAudioService.Stub
    //======================
    // Audio playback notification
    //======================
    private final PlaybackActivityMonitor mPlaybackMonitor = new PlaybackActivityMonitor();
    private final PlaybackActivityMonitor mPlaybackMonitor;

    public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
        final boolean isPrivileged =
+44 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.audio;

import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
@@ -90,7 +92,14 @@ public final class PlaybackActivityMonitor
    private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
            new HashMap<Integer, AudioPlaybackConfiguration>();

    PlaybackActivityMonitor() {
    private final Context mContext;
    private int mSavedAlarmVolume = -1;
    private final int mMaxAlarmVolume;
    private int mPrivilegedAlarmActiveCount = 0;

    PlaybackActivityMonitor(Context context, int maxAlarmVolume) {
        mContext = context;
        mMaxAlarmVolume = maxAlarmVolume;
        PlayMonitorClient.sListenerDeathMonitor = this;
        AudioPlaybackConfiguration.sPlayerDeathMonitor = this;
    }
@@ -175,6 +184,38 @@ public final class PlaybackActivityMonitor
        }
    }

    private void checkVolumeForPrivilegedAlarm(AudioPlaybackConfiguration apc, int event) {
        if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED ||
                apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
            if ((apc.getAudioAttributes().getAllFlags() &
                    AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0 &&
                    apc.getAudioAttributes().getUsage() == AudioAttributes.USAGE_ALARM &&
                    mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
                            apc.getClientPid(), apc.getClientUid()) ==
                            PackageManager.PERMISSION_GRANTED) {
                if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED &&
                        apc.getPlayerState() != AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (mPrivilegedAlarmActiveCount++ == 0) {
                        mSavedAlarmVolume = AudioSystem.getStreamVolumeIndex(
                                AudioSystem.STREAM_ALARM, AudioSystem.DEVICE_OUT_SPEAKER);
                        AudioSystem.setStreamVolumeIndex(AudioSystem.STREAM_ALARM,
                                mMaxAlarmVolume, AudioSystem.DEVICE_OUT_SPEAKER);
                    }
                } else if (event != AudioPlaybackConfiguration.PLAYER_STATE_STARTED &&
                        apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (--mPrivilegedAlarmActiveCount == 0) {
                        if (AudioSystem.getStreamVolumeIndex(
                                AudioSystem.STREAM_ALARM, AudioSystem.DEVICE_OUT_SPEAKER) ==
                                mMaxAlarmVolume) {
                            AudioSystem.setStreamVolumeIndex(AudioSystem.STREAM_ALARM,
                                    mSavedAlarmVolume, AudioSystem.DEVICE_OUT_SPEAKER);
                        }
                    }
                }
            }
        }
    }

    public void playerEvent(int piid, int event, int binderUid) {
        if (DEBUG) { Log.v(TAG, String.format("playerEvent(piid=%d, event=%d)", piid, event)); }
        final boolean change;
@@ -200,6 +241,7 @@ public final class PlaybackActivityMonitor
            }
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                //TODO add generation counter to only update to the latest state
                checkVolumeForPrivilegedAlarm(apc, event);
                change = apc.handleStateEvent(event);
            } else {
                Log.e(TAG, "Error handling event " + event);
@@ -228,6 +270,7 @@ public final class PlaybackActivityMonitor
                        "releasing player piid:" + piid));
                mPlayers.remove(new Integer(piid));
                mDuckingManager.removeReleased(apc);
                checkVolumeForPrivilegedAlarm(apc, AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
                apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
            }
        }