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

Commit 6916df53 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "mediarouter_fix"

* changes:
  AudioPlayerStateMonitor: fix NPE
  Revert "Revert "Fix overactive media routing""
parents 0eaf5eef 46be72ed
Loading
Loading
Loading
Loading
+327 −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,81 @@ 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);
                    final Integer prevState = prevAudioPlayerStates.get(config.getPlayerInterfaceId());
                    final int prevStateInt =
                            (prevState == null) ? AudioPlaybackConfiguration.PLAYER_STATE_UNKNOWN :
                                prevState.intValue();
                    if (prevStateInt != config.getPlayerState()) {
                        sendAudioPlayerStateChangedMessageLocked(
                                config.getClientUid(), prevStateInt, 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> prevPlayers = prevAudioPlayersForUid.get(prevUid);
                        int prevState = AudioPlaybackConfiguration.PLAYER_STATE_UNKNOWN;
                        for (int pii : prevPlayers) {
                            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 +204,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 +239,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 +280,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 +300,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,