FileDocCategorySizeDatePackage
MediaSessionStack.javaAPI DocAndroid 5.1 API13647Thu Mar 12 22:22:42 GMT 2015com.android.server.media

MediaSessionStack

public class MediaSessionStack extends Object
Keeps track of media sessions and their priority for notifications, media button dispatch, etc.

Fields Summary
private static final int[]
ALWAYS_PRIORITY_STATES
These are states that usually indicate the user took an action and should bump priority regardless of the old state.
private static final int[]
TRANSITION_PRIORITY_STATES
These are states that usually indicate the user took an action if they were entered from a non-priority state.
private final ArrayList
mSessions
private MediaSessionRecord
mGlobalPrioritySession
private MediaSessionRecord
mLastInterestingRecord
private MediaSessionRecord
mCachedButtonReceiver
private MediaSessionRecord
mCachedDefault
private MediaSessionRecord
mCachedVolumeDefault
private ArrayList
mCachedActiveList
private ArrayList
mCachedTransportControlList
Constructors Summary
Methods Summary
public voidaddSession(MediaSessionRecord record)
Add a record to the priority tracker.

param
record The record to add.


                      
        
        mSessions.add(record);
        clearCache();
        mLastInterestingRecord = record;
    
private voidclearCache()

        mCachedDefault = null;
        mCachedVolumeDefault = null;
        mCachedButtonReceiver = null;
        mCachedActiveList = null;
        mCachedTransportControlList = null;
    
private booleancontainsState(int state, int[] states)

        for (int i = 0; i < states.length; i++) {
            if (states[i] == state) {
                return true;
            }
        }
        return false;
    
public voiddump(java.io.PrintWriter pw, java.lang.String prefix)

        ArrayList<MediaSessionRecord> sortedSessions = getPriorityListLocked(false, 0,
                UserHandle.USER_ALL);
        int count = sortedSessions.size();
        pw.println(prefix + "Global priority session is " + mGlobalPrioritySession);
        pw.println(prefix + "Sessions Stack - have " + count + " sessions:");
        String indent = prefix + "  ";
        for (int i = 0; i < count; i++) {
            MediaSessionRecord record = sortedSessions.get(i);
            record.dump(pw, indent);
            pw.println();
        }
    
public java.util.ArrayListgetActiveSessions(int userId)
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.
return
All the active sessions in priority order.

        if (mCachedActiveList == null) {
            mCachedActiveList = getPriorityListLocked(true, 0, userId);
        }
        return mCachedActiveList;
    
public MediaSessionRecordgetDefaultMediaButtonSession(int userId, boolean includeNotPlaying)
Get the highest priority session that can handle media buttons.

param
userId The user to check.
param
includeNotPlaying Return a non-playing session if nothing else is available
return
The default media button session or null.

        if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
            return mGlobalPrioritySession;
        }
        if (mCachedButtonReceiver != null) {
            return mCachedButtonReceiver;
        }
        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true,
                MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userId);
        if (records.size() > 0) {
            MediaSessionRecord record = records.get(0);
            if (record.isPlaybackActive(false)) {
                // Since we're going to send a button event to this record make
                // it the last interesting one.
                mLastInterestingRecord = record;
                mCachedButtonReceiver = record;
            } else if (mLastInterestingRecord != null) {
                if (records.contains(mLastInterestingRecord)) {
                    mCachedButtonReceiver = mLastInterestingRecord;
                } else {
                    // That record is no longer used. Clear its reference.
                    mLastInterestingRecord = null;
                }
            }
            if (includeNotPlaying && mCachedButtonReceiver == null) {
                // If we really want a record and we didn't find one yet use the
                // highest priority session even if it's not playing.
                mCachedButtonReceiver = record;
            }
        }
        return mCachedButtonReceiver;
    
public MediaSessionRecordgetDefaultRemoteSession(int userId)

        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);

        int size = records.size();
        for (int i = 0; i < size; i++) {
            MediaSessionRecord record = records.get(i);
            if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
                return record;
            }
        }
        return null;
    
public MediaSessionRecordgetDefaultSession(int userId)
Get the highest priority active session.

param
userId The user to check.
return
The current highest priority session or null.

        if (mCachedDefault != null) {
            return mCachedDefault;
        }
        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
        if (records.size() > 0) {
            return records.get(0);
        }
        return null;
    
public MediaSessionRecordgetDefaultVolumeSession(int userId)

        if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
            return mGlobalPrioritySession;
        }
        if (mCachedVolumeDefault != null) {
            return mCachedVolumeDefault;
        }
        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
        int size = records.size();
        for (int i = 0; i < size; i++) {
            MediaSessionRecord record = records.get(i);
            if (record.isPlaybackActive(false)) {
                mCachedVolumeDefault = record;
                return record;
            }
        }
        return null;
    
private java.util.ArrayListgetPriorityListLocked(boolean activeOnly, int withFlags, int userId)
Get a priority sorted list of sessions. Can filter to only return active sessions or sessions with specific flags.

param
activeOnly True to only return active sessions, false to return all sessions.
param
withFlags Only return sessions with all the specified flags set. 0 returns all sessions.
param
userId The user to get sessions for. {@link UserHandle#USER_ALL} will return sessions for all users.
return
The priority sorted list of sessions.

        ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>();
        int lastLocalIndex = 0;
        int lastActiveIndex = 0;
        int lastPublishedIndex = 0;

        int size = mSessions.size();
        for (int i = 0; i < size; i++) {
            final MediaSessionRecord session = mSessions.get(i);

            if (userId != UserHandle.USER_ALL && userId != session.getUserId()) {
                // Filter out sessions for the wrong user
                continue;
            }
            if ((session.getFlags() & withFlags) != withFlags) {
                // Filter out sessions with the wrong flags
                continue;
            }
            if (!session.isActive()) {
                if (!activeOnly) {
                    // If we're getting unpublished as well always put them at
                    // the end
                    result.add(session);
                }
                continue;
            }

            if (session.isSystemPriority()) {
                // System priority sessions are special and always go at the
                // front. We expect there to only be one of these at a time.
                result.add(0, session);
                lastLocalIndex++;
                lastActiveIndex++;
                lastPublishedIndex++;
            } else if (session.isPlaybackActive(true)) {
                // TODO this with real local route check
                if (true) {
                    // Active local sessions get top priority
                    result.add(lastLocalIndex, session);
                    lastLocalIndex++;
                    lastActiveIndex++;
                    lastPublishedIndex++;
                } else {
                    // Then active remote sessions
                    result.add(lastActiveIndex, session);
                    lastActiveIndex++;
                    lastPublishedIndex++;
                }
            } else {
                // inactive sessions go at the end in order of whoever last did
                // something.
                result.add(lastPublishedIndex, session);
                lastPublishedIndex++;
            }
        }

        return result;
    
public java.util.ArrayListgetTransportControlSessions(int userId)
Get the current priority sorted list of active sessions that use transport controls. The most important session is at index 0 and the least important at size -1.

param
userId The user to check.
return
All the active sessions that handle transport controls in priority order.

        if (mCachedTransportControlList == null) {
            mCachedTransportControlList = getPriorityListLocked(true,
                    MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS, userId);
        }
        return mCachedTransportControlList;
    
public booleanisGlobalPriorityActive()

        return mGlobalPrioritySession == null ? false : mGlobalPrioritySession.isActive();
    
public booleanonPlaystateChange(MediaSessionRecord record, int oldState, int newState)
Notify the priority tracker that a session's state changed.

param
record The record that changed.
param
oldState Its old playback state.
param
newState Its new playback state.
return
true if the priority order was updated, false otherwise.

        if (shouldUpdatePriority(oldState, newState)) {
            mSessions.remove(record);
            mSessions.add(0, record);
            clearCache();
            // This becomes the last interesting record since it entered a
            // playing state
            mLastInterestingRecord = record;
            return true;
        } else if (!MediaSession.isActiveState(newState)) {
            // Just clear the volume cache when a state goes inactive
            mCachedVolumeDefault = null;
        }
        return false;
    
public voidonSessionStateChange(MediaSessionRecord record)
Handle any stack changes that need to occur in response to a session state change. TODO add the old and new session state as params

param
record The record that changed.

        if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
            mGlobalPrioritySession = record;
        }
        // For now just clear the cache. Eventually we'll selectively clear
        // depending on what changed.
        clearCache();
    
public voidremoveSession(MediaSessionRecord record)
Remove a record from the priority tracker.

param
record The record to remove.

        mSessions.remove(record);
        if (record == mGlobalPrioritySession) {
            mGlobalPrioritySession = null;
        }
        clearCache();
    
private booleanshouldUpdatePriority(int oldState, int newState)

        if (containsState(newState, ALWAYS_PRIORITY_STATES)) {
            return true;
        }
        if (!containsState(oldState, TRANSITION_PRIORITY_STATES)
                && containsState(newState, TRANSITION_PRIORITY_STATES)) {
            return true;
        }
        return false;