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

Commit 18341301 authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Fix overactive media routing

For MediaRouterService,
- Delay route restoration to BT for 0.5s in case the app plays
  more audio

For AudioPlaybackMonitor,
- Rename to AudioPlayerStateMonitor.
- Combine two listeners into one.
- Take a handler for the looper of the callback methods.
- Move the registration of playback callback into audio service
  from the constructor to the caller.

Bug: 65376604
Test: manual tests as follows
1. Checked that the lastly played app receives the media key events
although the app's media session doesn't report its playback state.
2. Checked that the lastly played app receives the media key events
although the app's media session is released.
3. Confirmed that this mitigates the issue.
Change-Id: I52e3719cd962f5d92c2f0e547309ce1314cc0926
parent e439d721
Loading
Loading
Loading
Loading
+324 −0
Original line number Diff line number Diff line
@@ -16,20 +16,23 @@

package com.android.server.media;

import android.annotation.Nullable;
import android.content.Context;
import android.media.AudioManager.AudioPlaybackCallback;
import android.media.AudioPlaybackConfiguration;
import android.media.IAudioService;
import android.media.IPlaybackConfigDispatcher;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
@@ -37,58 +40,70 @@ import java.util.Map;
import java.util.Set;

/**
 * Monitors changes in audio playback, and notify the newly started audio playback through the
 * {@link OnAudioPlaybackStartedListener} and the activeness change through the
 * {@link OnAudioPlaybackActiveStateListener}.
 * Monitors the state changes of audio players.
 */
class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub {
    private static boolean DEBUG = MediaSessionService.DEBUG;
    private static String TAG = "AudioPlaybackMonitor";
    private static String TAG = "AudioPlayerStateMonitor";

    private static AudioPlaybackMonitor sInstance;
    private static AudioPlayerStateMonitor sInstance = new AudioPlayerStateMonitor();

    /**
     * Called when audio playback is started for a given UID.
     * Called when the state of audio player is changed.
     */
    interface OnAudioPlaybackStartedListener {
        void onAudioPlaybackStarted(int uid);
    interface OnAudioPlayerStateChangedListener {
        void onAudioPlayerStateChanged(
                int uid, int prevState, @Nullable AudioPlaybackConfiguration config);
    }

    /**
     * Called when audio player state is changed.
     */
    interface OnAudioPlayerActiveStateChangedListener {
        void onAudioPlayerActiveStateChanged(int uid, boolean active);
    private final static class MessageHandler extends Handler {
        private static final int MSG_AUDIO_PLAYER_STATE_CHANGED = 1;

        private final OnAudioPlayerStateChangedListener mListsner;

        public MessageHandler(Looper looper, OnAudioPlayerStateChangedListener listener) {
            super(looper);
            mListsner = listener;
        }

    private final Object mLock = new Object();
    private final Context mContext;
    private final List<OnAudioPlaybackStartedListener> mAudioPlaybackStartedListeners
            = new ArrayList<>();
    private final List<OnAudioPlayerActiveStateChangedListener>
            mAudioPlayerActiveStateChangedListeners = new ArrayList<>();
    private final Map<Integer, Integer> mAudioPlaybackStates = new HashMap<>();
    private final Set<Integer> mActiveAudioPlaybackClientUids = new HashSet<>();
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_AUDIO_PLAYER_STATE_CHANGED:
                    mListsner.onAudioPlayerStateChanged(
                            msg.arg1, msg.arg2, (AudioPlaybackConfiguration) msg.obj);
                    break;
            }
        }

        public void sendAudioPlayerStateChangedMessage(int uid, int prevState,
                AudioPlaybackConfiguration config) {
            obtainMessage(MSG_AUDIO_PLAYER_STATE_CHANGED, uid, prevState, config).sendToTarget();
        }
    }

    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private final Map<OnAudioPlayerStateChangedListener, MessageHandler> mListenerMap =
            new HashMap<>();
    @GuardedBy("mLock")
    private final Map<Integer, Integer> mAudioPlayerStates = new HashMap<>();
    @GuardedBy("mLock")
    private final Map<Integer, HashSet<Integer>> mAudioPlayersForUid = new HashMap<>();
    // Sorted array of UIDs that had active audio playback. (i.e. playing an audio/video)
    // The UID whose audio playback becomes active at the last comes first.
    // TODO(b/35278867): Find and use unique identifier for apps because apps may share the UID.
    @GuardedBy("mLock")
    private final IntArray mSortedAudioPlaybackClientUids = new IntArray();

    static AudioPlaybackMonitor getInstance(Context context, IAudioService audioService) {
        if (sInstance == null) {
            sInstance = new AudioPlaybackMonitor(context, audioService);
        }
    @GuardedBy("mLock")
    private boolean mRegisteredToAudioService;

    static AudioPlayerStateMonitor getInstance() {
        return sInstance;
    }

    private AudioPlaybackMonitor(Context context, IAudioService audioService) {
        mContext = context;
        try {
            audioService.registerPlaybackCallback(this);
        } catch (RemoteException e) {
            Log.wtf(TAG, "Failed to register playback callback", e);
        }
    private AudioPlayerStateMonitor() {
    }

    /**
@@ -107,69 +122,78 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
        }
        final long token = Binder.clearCallingIdentity();
        try {
            List<Integer> newActiveAudioPlaybackClientUids = new ArrayList<>();
            List<OnAudioPlayerActiveStateChangedListener> audioPlayerActiveStateChangedListeners;
            List<OnAudioPlaybackStartedListener> audioPlaybackStartedListeners;
            final Map<Integer, Integer> prevAudioPlayerStates = new HashMap<>(mAudioPlayerStates);
            final Map<Integer, HashSet<Integer>> prevAudioPlayersForUid =
                    new HashMap<>(mAudioPlayersForUid);
            synchronized (mLock) {
                // Update mActiveAudioPlaybackClientUids and mSortedAudioPlaybackClientUids,
                // and find newly activated audio playbacks.
                mActiveAudioPlaybackClientUids.clear();
                mAudioPlayerStates.clear();
                mAudioPlayersForUid.clear();
                for (AudioPlaybackConfiguration config : configs) {
                    // Ignore inactive (i.e. not playing) or PLAYER_TYPE_JAM_SOUNDPOOL
                    // (i.e. playback from the SoundPool class which is only for sound effects)
                    // playback.
                    // Note that we shouldn't ignore PLAYER_TYPE_UNKNOWN because it might be OEM
                    // specific audio/video players.
                    if (!config.isActive() || config.getPlayerType()
                            == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
                    int pii = config.getPlayerInterfaceId();
                    int uid = config.getClientUid();
                    mAudioPlayerStates.put(pii, config.getPlayerState());
                    HashSet<Integer> players = mAudioPlayersForUid.get(uid);
                    if (players == null) {
                        players = new HashSet<Integer>();
                        players.add(pii);
                        mAudioPlayersForUid.put(uid, players);
                    } else {
                        players.add(pii);
                    }
                }
                for (AudioPlaybackConfiguration config : configs) {
                    if (!config.isActive()) {
                        continue;
                    }

                    mActiveAudioPlaybackClientUids.add(config.getClientUid());
                    Integer oldState = mAudioPlaybackStates.get(config.getPlayerInterfaceId());
                    if (!isActiveState(oldState)) {
                    int uid = config.getClientUid();
                    if (!isActiveState(prevAudioPlayerStates.get(config.getPlayerInterfaceId()))) {
                        if (DEBUG) {
                            Log.d(TAG, "Found a new active media playback. " +
                                    AudioPlaybackConfiguration.toLogFriendlyString(config));
                        }
                        // New active audio playback.
                        newActiveAudioPlaybackClientUids.add(config.getClientUid());
                        int index = mSortedAudioPlaybackClientUids.indexOf(config.getClientUid());
                        int index = mSortedAudioPlaybackClientUids.indexOf(uid);
                        if (index == 0) {
                            // It's the lastly played music app already. Skip updating.
                            continue;
                        } else if (index > 0) {
                            mSortedAudioPlaybackClientUids.remove(index);
                        }
                        mSortedAudioPlaybackClientUids.add(0, config.getClientUid());
                    }
                        mSortedAudioPlaybackClientUids.add(0, uid);
                    }
                audioPlayerActiveStateChangedListeners = new ArrayList<>(
                        mAudioPlayerActiveStateChangedListeners);
                audioPlaybackStartedListeners = new ArrayList<>(mAudioPlaybackStartedListeners);
                }
            // Notify the change of audio playback states.
                // Notify the change of audio player states.
                for (AudioPlaybackConfiguration config : configs) {
                boolean wasActive = isActiveState(
                        mAudioPlaybackStates.get(config.getPlayerInterfaceId()));
                boolean isActive = config.isActive();
                if (wasActive != isActive) {
                    for (OnAudioPlayerActiveStateChangedListener listener
                            : audioPlayerActiveStateChangedListeners) {
                        listener.onAudioPlayerActiveStateChanged(config.getClientUid(),
                                isActive);
                    Integer prevState = prevAudioPlayerStates.get(config.getPlayerInterfaceId());
                    if (prevState == null || prevState != config.getPlayerState()) {
                        sendAudioPlayerStateChangedMessageLocked(
                                config.getClientUid(), prevState, config);
                    }
                }
                for (Integer prevUid : prevAudioPlayersForUid.keySet()) {
                    // If all players for prevUid is removed, notify the prev state was
                    // PLAYER_STATE_STARTED only when there were a player whose state was
                    // PLAYER_STATE_STARTED, otherwise any inactive state is okay to notify.
                    if (!mAudioPlayersForUid.containsKey(prevUid)) {
                        Set<Integer> players = mAudioPlayersForUid.get(prevUid);
                        int prevState = AudioPlaybackConfiguration.PLAYER_STATE_UNKNOWN;
                        for (int pii : players) {
                            Integer state = prevAudioPlayerStates.get(pii);
                            if (state == null) {
                                continue;
                            }
                            if (state == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                                prevState = state;
                                break;
                            } else if (prevState
                                    == AudioPlaybackConfiguration.PLAYER_STATE_UNKNOWN) {
                                prevState = state;
                            }
                        }
            // Notify the start of audio playback
            for (int uid : newActiveAudioPlaybackClientUids) {
                for (OnAudioPlaybackStartedListener listener : audioPlaybackStartedListeners) {
                    listener.onAudioPlaybackStarted(uid);
                        sendAudioPlayerStateChangedMessageLocked(prevUid, prevState, null);
                    }
                }
            mAudioPlaybackStates.clear();
            for (AudioPlaybackConfiguration config : configs) {
                mAudioPlaybackStates.put(config.getPlayerInterfaceId(), config.getPlayerState());
            }
        } finally {
            Binder.restoreCallingIdentity(token);
@@ -177,40 +201,21 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
    }

    /**
     * Registers OnAudioPlaybackStartedListener.
     * Registers OnAudioPlayerStateChangedListener.
     */
    public void registerOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) {
    public void registerListener(OnAudioPlayerStateChangedListener listener, Handler handler) {
        synchronized (mLock) {
            mAudioPlaybackStartedListeners.add(listener);
            mListenerMap.put(listener, new MessageHandler((handler == null) ?
                    Looper.myLooper() : handler.getLooper(), listener));
        }
    }

    /**
     * Unregisters OnAudioPlaybackStartedListener.
     * Unregisters OnAudioPlayerStateChangedListener.
     */
    public void unregisterOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) {
    public void unregisterListener(OnAudioPlayerStateChangedListener listener) {
        synchronized (mLock) {
            mAudioPlaybackStartedListeners.remove(listener);
        }
    }

    /**
     * Registers OnAudioPlayerActiveStateChangedListener.
     */
    public void registerOnAudioPlayerActiveStateChangedListener(
            OnAudioPlayerActiveStateChangedListener listener) {
        synchronized (mLock) {
            mAudioPlayerActiveStateChangedListeners.add(listener);
        }
    }

    /**
     * Unregisters OnAudioPlayerActiveStateChangedListener.
     */
    public void unregisterOnAudioPlayerActiveStateChangedListener(
            OnAudioPlayerActiveStateChangedListener listener) {
        synchronized (mLock) {
            mAudioPlayerActiveStateChangedListeners.remove(listener);
            mListenerMap.remove(listener);
        }
    }

@@ -231,15 +236,24 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
     */
    public boolean isPlaybackActive(int uid) {
        synchronized (mLock) {
            return mActiveAudioPlaybackClientUids.contains(uid);
            Set<Integer> players = mAudioPlayersForUid.get(uid);
            if (players == null) {
                return false;
            }
            for (Integer pii : players) {
                if (isActiveState(mAudioPlayerStates.get(pii))) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Cleans up the sorted list of audio playback client UIDs with given {@param
     * mediaButtonSessionUid}.
     * <p>UIDs whose audio playback started after the media button session's audio playback
     * cannot be the lastly played media app. So they won't needed anymore.
     * <p>UIDs whose audio playback are inactive and have started before the media button session's
     * audio playback cannot be the lastly played media app. So they won't needed anymore.
     *
     * @param mediaButtonSessionUid UID of the media button session.
     */
@@ -263,16 +277,16 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
    }

    /**
     * Dumps {@link AudioPlaybackMonitor}.
     * Dumps {@link AudioPlayerStateMonitor}.
     */
    public void dump(PrintWriter pw, String prefix) {
    public void dump(Context context, PrintWriter pw, String prefix) {
        synchronized (mLock) {
            pw.println(prefix + "Audio playback (lastly played comes first)");
            String indent = prefix + "  ";
            for (int i = 0; i < mSortedAudioPlaybackClientUids.size(); i++) {
                int uid = mSortedAudioPlaybackClientUids.get(i);
                pw.print(indent + "uid=" + uid + " packages=");
                String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
                String[] packages = context.getPackageManager().getPackagesForUid(uid);
                if (packages != null && packages.length > 0) {
                    for (int j = 0; j < packages.length; j++) {
                        pw.print(packages[j] + " ");
@@ -283,7 +297,28 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
        }
    }

    private boolean isActiveState(Integer state) {
    public void registerSelfIntoAudioServiceIfNeeded(IAudioService audioService) {
        synchronized (mLock) {
            try {
                if (!mRegisteredToAudioService) {
                    audioService.registerPlaybackCallback(this);
                    mRegisteredToAudioService = true;
                }
            } catch (RemoteException e) {
                Log.wtf(TAG, "Failed to register playback callback", e);
                mRegisteredToAudioService = false;
            }
        }
    }

    private void sendAudioPlayerStateChangedMessageLocked(
            final int uid, final int prevState, final AudioPlaybackConfiguration config) {
        for (MessageHandler messageHandler : mListenerMap.values()) {
            messageHandler.sendAudioPlayerStateChangedMessage(uid, prevState, config);
        }
    }

    private static boolean isActiveState(Integer state) {
        return state != null && state.equals(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
    }
}
+50 −24
Original line number Diff line number Diff line
@@ -19,12 +19,14 @@ package com.android.server.media;
import com.android.internal.util.DumpUtils;
import com.android.server.Watchdog;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
@@ -96,7 +98,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
    private int mCurrentUserId = -1;
    private boolean mGlobalBluetoothA2dpOn = false;
    private final IAudioService mAudioService;
    private final AudioPlaybackMonitor mAudioPlaybackMonitor;
    private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
    private final Handler mHandler = new Handler();
    private final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();

    public MediaRouterService(Context context) {
@@ -106,31 +109,57 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        mAudioService = IAudioService.Stub.asInterface(
                ServiceManager.getService(Context.AUDIO_SERVICE));

        mAudioPlaybackMonitor = AudioPlaybackMonitor.getInstance(context, mAudioService);
        mAudioPlaybackMonitor.registerOnAudioPlayerActiveStateChangedListener(
                new AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener() {
        mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance();
        mAudioPlayerStateMonitor.registerListener(
                new AudioPlayerStateMonitor.OnAudioPlayerStateChangedListener() {
            static final long WAIT_MS = 500;
            final Runnable mRestoreBluetoothA2dpRunnable = new Runnable() {
                @Override
            public void onAudioPlayerActiveStateChanged(int uid, boolean active) {
                public void run() {
                    restoreBluetoothA2dp();
                }
            };

            @Override
            public void onAudioPlayerStateChanged(
                    int uid, int prevState, @Nullable AudioPlaybackConfiguration config) {
                int restoreUid = -1;
                boolean active = config == null ? false : config.isActive();
                if (active) {
                    restoreRoute(uid);
                    restoreUid = uid;
                } else if (prevState != AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    // Noting to do if the prev state is not an active state.
                    return;
                } else {
                    IntArray sortedAudioPlaybackClientUids =
                            mAudioPlaybackMonitor.getSortedAudioPlaybackClientUids();
                    boolean restored = false;
                    for (int i = 0; i < sortedAudioPlaybackClientUids.size(); i++) {
                        if (mAudioPlaybackMonitor.isPlaybackActive(
                            mAudioPlayerStateMonitor.getSortedAudioPlaybackClientUids();
                    for (int i = 0; i < sortedAudioPlaybackClientUids.size(); ++i) {
                        if (mAudioPlayerStateMonitor.isPlaybackActive(
                                sortedAudioPlaybackClientUids.get(i))) {
                            restoreRoute(sortedAudioPlaybackClientUids.get(i));
                            restored = true;
                            restoreUid = sortedAudioPlaybackClientUids.get(i);
                            break;
                        }
                    }
                    if (!restored) {
                        restoreBluetoothA2dp();
                }

                mHandler.removeCallbacks(mRestoreBluetoothA2dpRunnable);
                if (restoreUid >= 0) {
                    restoreRoute(restoreUid);
                    if (DEBUG) {
                        Slog.d(TAG, "onAudioPlayerStateChanged: " + "uid " + uid
                                + " active " + active + " restoring " + restoreUid);
                    }
                } else {
                    mHandler.postDelayed(mRestoreBluetoothA2dpRunnable, WAIT_MS);
                    if (DEBUG) {
                        Slog.d(TAG, "onAudioPlayerStateChanged: " + "uid " + uid
                                + " active " + active + " delaying");
                    }
        });
                }
            }
        }, mHandler);
        mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);

        AudioRoutesInfo audioRoutes = null;
        try {
            audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() {
@@ -261,9 +290,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub

        final long token = Binder.clearCallingIdentity();
        try {
            ClientRecord clientRecord;
            synchronized (mLock) {
                return isPlaybackActiveLocked(client);
                clientRecord = mAllClientRecords.get(client.asBinder());
            }
            if (clientRecord != null) {
                return mAudioPlayerStateMonitor.isPlaybackActive(clientRecord.mUid);
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
@@ -480,14 +514,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        return null;
    }

    private boolean isPlaybackActiveLocked(IMediaRouterClient client) {
        ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
        if (clientRecord != null) {
            return mAudioPlaybackMonitor.isPlaybackActive(clientRecord.mUid);
        }
        return false;
    }

    private void setDiscoveryRequestLocked(IMediaRouterClient client,
            int routeTypes, boolean activeScan) {
        final IBinder binder = client.asBinder();
+16 −12

File changed.

Preview size limit exceeded, changes collapsed.

+6 −8
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ class MediaSessionStack {
     */
    private final List<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();

    private final AudioPlaybackMonitor mAudioPlaybackMonitor;
    private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
    private final OnMediaButtonSessionChangedListener mOnMediaButtonSessionChangedListener;

    /**
@@ -84,7 +84,6 @@ class MediaSessionStack {
     */
    private MediaSessionRecord mMediaButtonSession;

    private MediaSessionRecord mCachedDefault;
    private MediaSessionRecord mCachedVolumeDefault;

    /**
@@ -93,8 +92,8 @@ class MediaSessionStack {
    private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists =
            new SparseArray<>();

    MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) {
        mAudioPlaybackMonitor = monitor;
    MediaSessionStack(AudioPlayerStateMonitor monitor, OnMediaButtonSessionChangedListener listener) {
        mAudioPlayerStateMonitor = monitor;
        mOnMediaButtonSessionChangedListener = listener;
    }

@@ -187,13 +186,13 @@ class MediaSessionStack {
        if (DEBUG) {
            Log.d(TAG, "updateMediaButtonSessionIfNeeded, callers=" + Debug.getCallers(2));
        }
        IntArray audioPlaybackUids = mAudioPlaybackMonitor.getSortedAudioPlaybackClientUids();
        IntArray audioPlaybackUids = mAudioPlayerStateMonitor.getSortedAudioPlaybackClientUids();
        for (int i = 0; i < audioPlaybackUids.size(); i++) {
            MediaSessionRecord mediaButtonSession =
                    findMediaButtonSession(audioPlaybackUids.get(i));
            if (mediaButtonSession != null) {
                // Found the media button session.
                mAudioPlaybackMonitor.cleanUpAudioPlaybackUids(mediaButtonSession.getUid());
                mAudioPlayerStateMonitor.cleanUpAudioPlaybackUids(mediaButtonSession.getUid());
                if (mMediaButtonSession != mediaButtonSession) {
                    updateMediaButtonSession(mediaButtonSession);
                }
@@ -216,7 +215,7 @@ class MediaSessionStack {
        for (MediaSessionRecord session : mSessions) {
            if (uid == session.getUid()) {
                if (session.getPlaybackState() != null && session.isPlaybackActive() ==
                        mAudioPlaybackMonitor.isPlaybackActive(session.getUid())) {
                        mAudioPlayerStateMonitor.isPlaybackActive(session.getUid())) {
                    // If there's a media session whose PlaybackState matches
                    // the audio playback state, return it immediately.
                    return session;
@@ -376,7 +375,6 @@ class MediaSessionStack {
    }

    private void clearCache(int userId) {
        mCachedDefault = null;
        mCachedVolumeDefault = null;
        mCachedActiveLists.remove(userId);
        // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL,