MediaSessionStack.java revision b69ffd4dc2c8fa85e0064151141ebeee90de471e
1a8f951462791a16f47e8c07e552232f31dcefac5RoboErik/* 2a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Copyright (C) 2014 The Android Open Source Project 3a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 4a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Licensed under the Apache License, Version 2.0 (the "License"); 5a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * you may not use this file except in compliance with the License. 6a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * You may obtain a copy of the License at 7a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 8a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * http://www.apache.org/licenses/LICENSE-2.0 9a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 10a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Unless required by applicable law or agreed to in writing, software 11a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * distributed under the License is distributed on an "AS IS" BASIS, 12a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * See the License for the specific language governing permissions and 14a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * limitations under the License. 15a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 16a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 17a8f951462791a16f47e8c07e552232f31dcefac5RoboErikpackage com.android.server.media; 18a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 19a8f951462791a16f47e8c07e552232f31dcefac5RoboErikimport android.media.session.PlaybackState; 2042ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSession; 21a5b02329209be355eafadbdf9ee685ffa58d3148RoboErikimport android.os.UserHandle; 22a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 23a8f951462791a16f47e8c07e552232f31dcefac5RoboErikimport java.io.PrintWriter; 24a8f951462791a16f47e8c07e552232f31dcefac5RoboErikimport java.util.ArrayList; 25a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 26a8f951462791a16f47e8c07e552232f31dcefac5RoboErik/** 27a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Keeps track of media sessions and their priority for notifications, media 28a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * button routing, etc. 29a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 30a8f951462791a16f47e8c07e552232f31dcefac5RoboErikpublic class MediaSessionStack { 31a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 32a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * These are states that usually indicate the user took an action and should 33a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * bump priority regardless of the old state. 34a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 35a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private static final int[] ALWAYS_PRIORITY_STATES = { 3679fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_FAST_FORWARDING, 3779fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_REWINDING, 3879fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_SKIPPING_TO_PREVIOUS, 3979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_SKIPPING_TO_NEXT }; 40a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 41a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * These are states that usually indicate the user took an action if they 42a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * were entered from a non-priority state. 43a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 44a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private static final int[] TRANSITION_PRIORITY_STATES = { 4579fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_BUFFERING, 4679fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_CONNECTING, 4779fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik PlaybackState.STATE_PLAYING }; 48a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 49a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>(); 50a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 514646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik private MediaSessionRecord mGlobalPrioritySession; 524646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik 53a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private MediaSessionRecord mCachedButtonReceiver; 54a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private MediaSessionRecord mCachedDefault; 55b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik private MediaSessionRecord mCachedVolumeDefault; 56a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private ArrayList<MediaSessionRecord> mCachedActiveList; 57a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private ArrayList<MediaSessionRecord> mCachedTransportControlList; 58a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 59a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 60a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Add a record to the priority tracker. 61a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 62a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record to add. 63a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 64a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void addSession(MediaSessionRecord record) { 65a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.add(record); 6642ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) { 674646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik mGlobalPrioritySession = record; 684646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 69a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 70a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 71a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 72a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 73a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Remove a record from the priority tracker. 74a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 75a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record to remove. 76a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 77a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void removeSession(MediaSessionRecord record) { 78a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.remove(record); 794646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (record == mGlobalPrioritySession) { 804646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik mGlobalPrioritySession = null; 814646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 82a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 83a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 84a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 85a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 86a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Notify the priority tracker that a session's state changed. 87a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 88a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record that changed. 89a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param oldState Its old playback state. 90a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param newState Its new playback state. 91a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 92a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void onPlaystateChange(MediaSessionRecord record, int oldState, int newState) { 93a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (shouldUpdatePriority(oldState, newState)) { 94a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.remove(record); 95a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.add(0, record); 96a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 97b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } else if (newState == PlaybackState.STATE_PAUSED) { 98b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik // Just clear the volume cache in this case 99b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik mCachedVolumeDefault = null; 100a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 101a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 102a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 103a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 104a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Handle any stack changes that need to occur in response to a session 105a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * state change. TODO add the old and new session state as params 106a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 107a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record that changed. 108a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 109a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void onSessionStateChange(MediaSessionRecord record) { 110a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // For now just clear the cache. Eventually we'll selectively clear 111a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // depending on what changed. 112a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 113a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 114a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 115a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 116a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the current priority sorted list of active sessions. The most 117a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * important session is at index 0 and the least important at size - 1. 118a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 119a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @param userId The user to check. 120a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return All the active sessions in priority order. 121a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 122a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public ArrayList<MediaSessionRecord> getActiveSessions(int userId) { 123a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedActiveList == null) { 124a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik mCachedActiveList = getPriorityListLocked(true, 0, userId); 125a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 126a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedActiveList; 127a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 128a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 129a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 130a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the current priority sorted list of active sessions that use 131a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * transport controls. The most important session is at index 0 and the 132a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * least important at size -1. 133a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 134a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @param userId The user to check. 135a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return All the active sessions that handle transport controls in 136a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * priority order. 137a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 138a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public ArrayList<MediaSessionRecord> getTransportControlSessions(int userId) { 139a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedTransportControlList == null) { 140a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedTransportControlList = getPriorityListLocked(true, 14142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS, userId); 142a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 143a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedTransportControlList; 144a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 145a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 146a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 147a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the highest priority active session. 148a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 149a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @param userId The user to check. 150a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The current highest priority session or null. 151a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 152a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public MediaSessionRecord getDefaultSession(int userId) { 153a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedDefault != null) { 154a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedDefault; 155a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 156a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId); 157a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (records.size() > 0) { 158a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return records.get(0); 159a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 160a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return null; 161a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 162a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 163a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 164a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the highest priority session that can handle media buttons. 165a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 166a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @param userId The user to check. 167a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The default media button session or null. 168a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 169a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public MediaSessionRecord getDefaultMediaButtonSession(int userId) { 1704646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) { 1714646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return mGlobalPrioritySession; 1724646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 173a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedButtonReceiver != null) { 174a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedButtonReceiver; 175a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 176a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 17742ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userId); 178a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (records.size() > 0) { 179a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedButtonReceiver = records.get(0); 180a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 181a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedButtonReceiver; 182a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 183a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 184b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public MediaSessionRecord getDefaultVolumeSession(int userId) { 185b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) { 186b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return mGlobalPrioritySession; 187b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 188b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik if (mCachedVolumeDefault != null) { 189b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return mCachedVolumeDefault; 190b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 191b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId); 192b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik int size = records.size(); 193b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik for (int i = 0; i < size; i++) { 194b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik MediaSessionRecord record = records.get(i); 195b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik if (record.isPlaybackActive(false)) { 196b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik mCachedVolumeDefault = record; 197b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return record; 198b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 199b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 200b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return null; 201b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 202b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 203a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public void dump(PrintWriter pw, String prefix) { 204a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik ArrayList<MediaSessionRecord> sortedSessions = getPriorityListLocked(false, 0, 205a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik UserHandle.USER_ALL); 206a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int count = sortedSessions.size(); 207a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(prefix + "Sessions Stack - have " + count + " sessions:"); 208a8f951462791a16f47e8c07e552232f31dcefac5RoboErik String indent = prefix + " "; 209a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < count; i++) { 210a8f951462791a16f47e8c07e552232f31dcefac5RoboErik MediaSessionRecord record = sortedSessions.get(i); 211a8f951462791a16f47e8c07e552232f31dcefac5RoboErik record.dump(pw, indent); 212a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(); 213a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 214a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 215a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 216a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 217a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get a priority sorted list of sessions. Can filter to only return active 218a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * sessions or sessions with specific flags. 219a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 220a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param activeOnly True to only return active sessions, false to return 221a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * all sessions. 222a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param withFlags Only return sessions with all the specified flags set. 0 223a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * returns all sessions. 224a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @param userId The user to get sessions for. {@link UserHandle#USER_ALL} 225a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * will return sessions for all users. 226a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The priority sorted list of sessions. 227a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 228a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags, 229a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik int userId) { 230a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>(); 231a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastLocalIndex = 0; 232a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastActiveIndex = 0; 233a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastPublishedIndex = 0; 234a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 235a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int size = mSessions.size(); 236a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < size; i++) { 237a8f951462791a16f47e8c07e552232f31dcefac5RoboErik final MediaSessionRecord session = mSessions.get(i); 238a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 239a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik if (userId != UserHandle.USER_ALL && userId != session.getUserId()) { 240a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik // Filter out sessions for the wrong user 241a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik continue; 242a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik } 243a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if ((session.getFlags() & withFlags) != withFlags) { 244a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik // Filter out sessions with the wrong flags 245a8f951462791a16f47e8c07e552232f31dcefac5RoboErik continue; 246a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 247a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!session.isActive()) { 248a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!activeOnly) { 249a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // If we're getting unpublished as well always put them at 250a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // the end 251a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(session); 252a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 253a8f951462791a16f47e8c07e552232f31dcefac5RoboErik continue; 254a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 255a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 256a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (session.isSystemPriority()) { 257a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // System priority sessions are special and always go at the 258a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // front. We expect there to only be one of these at a time. 259a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(0, session); 260a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastLocalIndex++; 261a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 262a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 263b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } else if (session.isPlaybackActive(true)) { 264a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // TODO replace getRoute() == null with real local route check 265a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if(session.getRoute() == null) { 266a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // Active local sessions get top priority 267a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastLocalIndex, session); 268a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastLocalIndex++; 269a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 270a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 271a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } else { 272a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // Then active remote sessions 273a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastActiveIndex, session); 274a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 275a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 276a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 277a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } else { 278a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // inactive sessions go at the end in order of whoever last did 279a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // something. 280a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastPublishedIndex, session); 281a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 282a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 283a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 284a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 285a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return result; 286a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 287a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 288a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private boolean shouldUpdatePriority(int oldState, int newState) { 289a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (containsState(newState, ALWAYS_PRIORITY_STATES)) { 290a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 291a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 292a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!containsState(oldState, TRANSITION_PRIORITY_STATES) 293a8f951462791a16f47e8c07e552232f31dcefac5RoboErik && containsState(newState, TRANSITION_PRIORITY_STATES)) { 294a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 295a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 296a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return false; 297a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 298a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 299a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private boolean containsState(int state, int[] states) { 300a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < states.length; i++) { 301a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (states[i] == state) { 302a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 303a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 304a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 305a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return false; 306a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 307a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 308a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private void clearCache() { 309a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedDefault = null; 310b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik mCachedVolumeDefault = null; 311a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedButtonReceiver = null; 312a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedActiveList = null; 313a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedTransportControlList = null; 314a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 315a8f951462791a16f47e8c07e552232f31dcefac5RoboErik} 316