From aceef919807a7a3205d09470f23b91c0aa41aa7b Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Thu, 30 Mar 2017 03:05:06 +0900 Subject: [PATCH] MediaSessionService: Cache active sessions per an user This fixes an issue that MediaSessionManager.getActiveSessions() may return media sessions of the wrong user. This had been an issue since the Android M. Bug: 36227938 Test: Run the CtsMediaTest (MediaSessionTest and MediaSessionManagerTest) and CtsMediaHostTestCases Change-Id: I8a8297e4d182f52c84f654bdb0ba78bc16a1c058 --- .../server/media/MediaSessionStack.java | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index b0d8adcc122e2..2f82915a459bc 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -23,6 +23,7 @@ import android.os.Debug; import android.os.UserHandle; import android.util.IntArray; import android.util.Log; +import android.util.SparseArray; import java.io.PrintWriter; import java.util.ArrayList; @@ -38,7 +39,7 @@ class MediaSessionStack { private static final String TAG = "MediaSessionStack"; /** - * Listens the change in the media button session. + * Listen the change in the media button session. */ interface OnMediaButtonSessionChangedListener { /** @@ -85,7 +86,12 @@ class MediaSessionStack { private MediaSessionRecord mCachedDefault; private MediaSessionRecord mCachedVolumeDefault; - private ArrayList mCachedActiveList; + + /** + * Cache the result of the {@link #getActiveSessions} per user. + */ + private final SparseArray> mCachedActiveLists = + new SparseArray<>(); MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) { mAudioPlaybackMonitor = monitor; @@ -99,7 +105,7 @@ class MediaSessionStack { */ public void addSession(MediaSessionRecord record) { mSessions.add(record); - clearCache(); + clearCache(record.getUserId()); // Update the media button session. // The added session could be the session from the package with the audio playback. @@ -119,7 +125,7 @@ class MediaSessionStack { // in the media button session app. onMediaSessionChangeInMediaButtonSessionApp(); } - clearCache(); + clearCache(record.getUserId()); } /** @@ -140,7 +146,7 @@ class MediaSessionStack { if (shouldUpdatePriority(oldState, newState)) { mSessions.remove(record); mSessions.add(0, record); - clearCache(); + clearCache(record.getUserId()); } else if (!MediaSession.isActiveState(newState)) { // Just clear the volume cache when a state goes inactive mCachedVolumeDefault = null; @@ -163,7 +169,7 @@ class MediaSessionStack { public void onSessionStateChange(MediaSessionRecord record) { // For now just clear the cache. Eventually we'll selectively clear // depending on what changed. - clearCache(); + clearCache(record.getUserId()); } /** @@ -245,14 +251,17 @@ class MediaSessionStack { * Get the current priority sorted list of active sessions. The most * important session is at index 0 and the least important at size - 1. * - * @param userId The user to check. + * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all sessions + * for all users in this {@link MediaSessionStack}. * @return All the active sessions in priority order. */ public ArrayList getActiveSessions(int userId) { - if (mCachedActiveList == null) { - mCachedActiveList = getPriorityList(true, userId); + ArrayList cachedActiveList = mCachedActiveLists.get(userId); + if (cachedActiveList == null) { + cachedActiveList = getPriorityList(true, userId); + mCachedActiveLists.put(userId, cachedActiveList); } - return mCachedActiveList; + return cachedActiveList; } /** @@ -382,9 +391,12 @@ class MediaSessionStack { return false; } - private void clearCache() { + private void clearCache(int userId) { mCachedDefault = null; mCachedVolumeDefault = null; - mCachedActiveList = null; + mCachedActiveLists.remove(userId); + // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL, + // so they also need to be cleared. + mCachedActiveLists.remove(UserHandle.USER_ALL); } }