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

Commit 9c05037d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "AudioService: mute music during BT A2DP device switch" into rvc-dev am:...

Merge "AudioService: mute music during BT A2DP device switch" into rvc-dev am: 82938719 am: 24983e2d am: 20836716 am: 32db5c4e

Change-Id: Iffb94081db0263d24b96aeb80a8e6b39d18dc3de
parents 0f15d2ab 32db5c4e
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -45,7 +45,10 @@ import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;


/** @hide */
@@ -59,6 +62,9 @@ import java.util.NoSuchElementException;
    // Timeout for connection to bluetooth headset service
    /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;

    // Delay before checking it music should be unmuted after processing an A2DP message
    private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 50;

    private final @NonNull AudioService mAudioService;
    private final @NonNull Context mContext;

@@ -1050,9 +1056,19 @@ import java.util.NoSuchElementException;
                    final int strategy = msg.arg1;
                    mDeviceInventory.onSaveRemovePreferredDevice(strategy);
                } break;
                case MSG_CHECK_MUTE_MUSIC:
                    checkMessagesMuteMusic();
                    break;
                default:
                    Log.wtf(TAG, "Invalid message " + msg.what);
            }

            // Give some time to Bluetooth service to post a connection message
            // in case of active device switch
            if (MESSAGES_MUTE_MUSIC.contains(msg.what)) {
                sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS);
            }

            if (isMessageHandledUnderWakelock(msg.what)) {
                try {
                    mBrokerEventWakeLock.release();
@@ -1116,6 +1132,7 @@ import java.util.NoSuchElementException;
    private static final int MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY = 34;

    private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35;
    private static final int MSG_CHECK_MUTE_MUSIC = 36;


    private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -1132,6 +1149,7 @@ import java.util.NoSuchElementException;
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
            case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
            case MSG_CHECK_MUTE_MUSIC:
                return true;
            default:
                return false;
@@ -1231,6 +1249,37 @@ import java.util.NoSuchElementException;
            mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
                    time);
        }
        if (MESSAGES_MUTE_MUSIC.contains(msg)) {
            checkMessagesMuteMusic();
        }
    }

    /** List of messages for which music is muted while processing is pending */
    private static final Set<Integer> MESSAGES_MUTE_MUSIC;
    static {
        MESSAGES_MUTE_MUSIC = new HashSet<>();
        MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED);
        MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
    }

    private AtomicBoolean mMusicMuted = new AtomicBoolean(false);

    /** Mutes or unmutes music according to pending A2DP messages */
    private void checkMessagesMuteMusic() {
        boolean mute = false;
        for (int msg : MESSAGES_MUTE_MUSIC) {
            if (mBrokerHandler.hasMessages(msg)) {
                mute = true;
                break;
            }
        }
        if (mute != mMusicMuted.getAndSet(mute)) {
            mAudioService.setMusicMute(mute);
        }
    }

    private class SpeakerphoneClient implements IBinder.DeathRecipient {
+47 −4
Original line number Diff line number Diff line
@@ -5061,6 +5061,10 @@ public class AudioService extends IAudioService.Stub
                profile, suppressNoisyIntent, a2dpVolume);
    }

    /*package*/ void setMusicMute(boolean mute) {
        mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
    }

    /**
     * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
     * @param device
@@ -5487,6 +5491,7 @@ public class AudioService extends IAudioService.Stub
        private int mIndexMax;

        private boolean mIsMuted;
        private boolean mIsMutedInternally;
        private String mVolumeIndexSettingName;
        private int mObservedDevices;

@@ -5660,7 +5665,8 @@ public class AudioService extends IAudioService.Stub
            // Only set audio policy BT SCO stream volume to 0 when the stream is actually muted.
            // This allows RX path muting by the audio HAL only when explicitly muted but not when
            // index is just set to 0 to repect BT requirements
            if (mStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0 && !mIsMuted) {
            if (mStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0
                    && !isFullyMuted()) {
                index = 1;
            }
            AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
@@ -5669,7 +5675,7 @@ public class AudioService extends IAudioService.Stub
        // must be called while synchronized VolumeStreamState.class
        /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
            int index;
            if (mIsMuted) {
            if (isFullyMuted()) {
                index = 0;
            } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                    && isAvrcpAbsVolSupported) {
@@ -5692,7 +5698,7 @@ public class AudioService extends IAudioService.Stub
                for (int i = 0; i < mIndexMap.size(); i++) {
                    final int device = mIndexMap.keyAt(i);
                    if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                        if (mIsMuted) {
                        if (isFullyMuted()) {
                            index = 0;
                        } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                                && isAvrcpAbsVolSupported) {
@@ -5709,7 +5715,7 @@ public class AudioService extends IAudioService.Stub
                }
                // apply default volume last: by convention , default device volume will be used
                // by audio policy manager if no explicit volume is present for a given device type
                if (mIsMuted) {
                if (isFullyMuted()) {
                    index = 0;
                } else {
                    index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -5891,6 +5897,41 @@ public class AudioService extends IAudioService.Stub
            return changed;
        }

        /**
         * Mute/unmute the stream by AudioService
         * @param state the new mute state
         * @return true if the mute state was changed
         */
        public boolean muteInternally(boolean state) {
            boolean changed = false;
            synchronized (VolumeStreamState.class) {
                if (state != mIsMutedInternally) {
                    changed = true;
                    mIsMutedInternally = state;

                    // Set the new mute volume. This propagates the values to
                    // the audio system, otherwise the volume won't be changed
                    // at the lower level.
                    sendMsg(mAudioHandler,
                            MSG_SET_ALL_VOLUMES,
                            SENDMSG_QUEUE,
                            0,
                            0,
                            this, 0);
                }
            }
            if (changed) {
                sVolumeLogger.log(new VolumeEvent(
                        VolumeEvent.VOL_MUTE_STREAM_INT, mStreamType, state));
            }
            return changed;
        }

        @GuardedBy("VolumeStreamState.class")
        public boolean isFullyMuted() {
            return mIsMuted || mIsMutedInternally;
        }

        public int getStreamType() {
            return mStreamType;
        }
@@ -5927,6 +5968,8 @@ public class AudioService extends IAudioService.Stub
        private void dump(PrintWriter pw) {
            pw.print("   Muted: ");
            pw.println(mIsMuted);
            pw.print("   Muted Internally: ");
            pw.println(mIsMutedInternally);
            pw.print("   Min: ");
            pw.print((mIndexMin + 5) / 10);
            if (mIndexMin != mIndexMinNoPerm) {
+21 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ public class AudioServiceEvents {
        static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6;
        static final int VOL_MODE_CHANGE_HEARING_AID = 7;
        static final int VOL_SET_GROUP_VOL = 8;
        static final int VOL_MUTE_STREAM_INT = 9;

        final int mOp;
        final int mStream;
@@ -188,6 +189,18 @@ public class AudioServiceEvents {
            logMetricEvent();
        }

        /** used for VOL_MUTE_STREAM_INT */
        VolumeEvent(int op, int stream, boolean state) {
            mOp = op;
            mStream = stream;
            mVal1 = state ? 1 : 0;
            mVal2 = 0;
            mCaller = null;
            mGroupName = null;
            mAudioAttributes = null;
            logMetricEvent();
        }


        /**
         * Audio Analytics unique Id.
@@ -278,6 +291,9 @@ public class AudioServiceEvents {
                            .set(MediaMetrics.Property.INDEX, mVal1)
                            .record();
                    return;
                case VOL_MUTE_STREAM_INT:
                    // No value in logging metrics for this internal event
                    return;
                default:
                    return;
            }
@@ -343,6 +359,11 @@ public class AudioServiceEvents {
                            .append(" flags:0x").append(Integer.toHexString(mVal2))
                            .append(") from ").append(mCaller)
                            .toString();
                case VOL_MUTE_STREAM_INT:
                    return new StringBuilder("VolumeStreamState.muteInternally(stream:")
                            .append(AudioSystem.streamToString(mStream))
                            .append(mVal1 == 1 ? ", muted)" : ", unmuted)")
                            .toString();
                default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
            }
        }