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
This commit is contained in:
Jaewan Kim
2017-03-30 03:05:06 +09:00
parent 307bec8572
commit aceef91980

View File

@@ -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<MediaSessionRecord> mCachedActiveList;
/**
* Cache the result of the {@link #getActiveSessions} per user.
*/
private final SparseArray<ArrayList<MediaSessionRecord>> 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<MediaSessionRecord> getActiveSessions(int userId) {
if (mCachedActiveList == null) {
mCachedActiveList = getPriorityList(true, userId);
ArrayList<MediaSessionRecord> 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);
}
}