MediaSessionStack.java revision a8f951462791a16f47e8c07e552232f31dcefac5
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; 20a8f951462791a16f47e8c07e552232f31dcefac5RoboErikimport android.media.session.Session; 21a8f951462791a16f47e8c07e552232f31dcefac5RoboErikimport android.text.TextUtils; 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 = { 36a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_FAST_FORWARDING, 37a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_REWINDING, 38a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_SKIPPING_BACKWARDS, 39a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_SKIPPING_FORWARDS }; 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 = { 45a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_BUFFERING, 46a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_CONNECTING, 47a8f951462791a16f47e8c07e552232f31dcefac5RoboErik PlaybackState.PLAYSTATE_PLAYING }; 48a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 49a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>(); 50a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 51a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private MediaSessionRecord mCachedButtonReceiver; 52a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private MediaSessionRecord mCachedDefault; 53a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private ArrayList<MediaSessionRecord> mCachedActiveList; 54a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private ArrayList<MediaSessionRecord> mCachedTransportControlList; 55a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 56a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 57a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Add a record to the priority tracker. 58a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 59a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record to add. 60a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 61a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void addSession(MediaSessionRecord record) { 62a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.add(record); 63a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 64a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 65a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 66a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 67a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Remove a record from the priority tracker. 68a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 69a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record to remove. 70a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 71a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void removeSession(MediaSessionRecord record) { 72a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.remove(record); 73a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 74a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 75a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 76a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 77a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Notify the priority tracker that a session's state changed. 78a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 79a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record that changed. 80a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param oldState Its old playback state. 81a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param newState Its new playback state. 82a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 83a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void onPlaystateChange(MediaSessionRecord record, int oldState, int newState) { 84a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (shouldUpdatePriority(oldState, newState)) { 85a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.remove(record); 86a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mSessions.add(0, record); 87a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 88a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 89a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 90a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 91a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 92a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Handle any stack changes that need to occur in response to a session 93a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * state change. TODO add the old and new session state as params 94a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 95a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param record The record that changed. 96a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 97a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void onSessionStateChange(MediaSessionRecord record) { 98a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // For now just clear the cache. Eventually we'll selectively clear 99a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // depending on what changed. 100a8f951462791a16f47e8c07e552232f31dcefac5RoboErik clearCache(); 101a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 102a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 103a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 104a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the current priority sorted list of active sessions. The most 105a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * important session is at index 0 and the least important at size - 1. 106a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 107a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return All the active sessions in priority order. 108a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 109a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public ArrayList<MediaSessionRecord> getActiveSessions() { 110a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedActiveList == null) { 111a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedActiveList = getPriorityListLocked(true, 0); 112a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 113a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedActiveList; 114a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 115a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 116a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 117a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the current priority sorted list of active sessions that use 118a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * transport controls. The most important session is at index 0 and the 119a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * least important at size -1. 120a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 121a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return All the active sessions that handle transport controls in 122a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * priority order. 123a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 124a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public ArrayList<MediaSessionRecord> getTransportControlSessions() { 125a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedTransportControlList == null) { 126a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedTransportControlList = getPriorityListLocked(true, 127a8f951462791a16f47e8c07e552232f31dcefac5RoboErik Session.FLAG_HANDLES_TRANSPORT_CONTROLS); 128a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 129a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedTransportControlList; 130a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 131a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 132a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 133a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the highest priority active session. 134a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 135a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The current highest priority session or null. 136a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 137a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public MediaSessionRecord getDefaultSession() { 138a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedDefault != null) { 139a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedDefault; 140a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 141a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0); 142a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (records.size() > 0) { 143a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return records.get(0); 144a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 145a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return null; 146a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 147a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 148a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 149a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get the highest priority session that can handle media buttons. 150a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 151a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The default media button session or null. 152a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 153a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public MediaSessionRecord getDefaultMediaButtonSession() { 154a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (mCachedButtonReceiver != null) { 155a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedButtonReceiver; 156a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 157a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 158a8f951462791a16f47e8c07e552232f31dcefac5RoboErik Session.FLAG_HANDLES_MEDIA_BUTTONS); 159a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (records.size() > 0) { 160a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedButtonReceiver = records.get(0); 161a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 162a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return mCachedButtonReceiver; 163a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 164a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 165a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void dumpLocked(PrintWriter pw, String prefix) { 166a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> sortedSessions = getPriorityListLocked(false, 0); 167a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int count = sortedSessions.size(); 168a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(prefix + "Sessions Stack - have " + count + " sessions:"); 169a8f951462791a16f47e8c07e552232f31dcefac5RoboErik String indent = prefix + " "; 170a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < count; i++) { 171a8f951462791a16f47e8c07e552232f31dcefac5RoboErik MediaSessionRecord record = sortedSessions.get(i); 172a8f951462791a16f47e8c07e552232f31dcefac5RoboErik record.dump(pw, indent); 173a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(); 174a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 175a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 176a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 177a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 178a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Get a priority sorted list of sessions. Can filter to only return active 179a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * sessions or sessions with specific flags. 180a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 181a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param activeOnly True to only return active sessions, false to return 182a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * all sessions. 183a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param withFlags Only return sessions with all the specified flags set. 0 184a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * returns all sessions. 185a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return The priority sorted list of sessions. 186a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 187a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags) { 188a8f951462791a16f47e8c07e552232f31dcefac5RoboErik ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>(); 189a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastLocalIndex = 0; 190a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastActiveIndex = 0; 191a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int lastPublishedIndex = 0; 192a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 193a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int size = mSessions.size(); 194a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < size; i++) { 195a8f951462791a16f47e8c07e552232f31dcefac5RoboErik final MediaSessionRecord session = mSessions.get(i); 196a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 197a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if ((session.getFlags() & withFlags) != withFlags) { 198a8f951462791a16f47e8c07e552232f31dcefac5RoboErik continue; 199a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 200a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!session.isActive()) { 201a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!activeOnly) { 202a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // If we're getting unpublished as well always put them at 203a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // the end 204a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(session); 205a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 206a8f951462791a16f47e8c07e552232f31dcefac5RoboErik continue; 207a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 208a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 209a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (session.isSystemPriority()) { 210a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // System priority sessions are special and always go at the 211a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // front. We expect there to only be one of these at a time. 212a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(0, session); 213a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastLocalIndex++; 214a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 215a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 216a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } else if (session.isPlaybackActive()) { 217a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // TODO replace getRoute() == null with real local route check 218a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if(session.getRoute() == null) { 219a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // Active local sessions get top priority 220a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastLocalIndex, session); 221a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastLocalIndex++; 222a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 223a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 224a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } else { 225a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // Then active remote sessions 226a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastActiveIndex, session); 227a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastActiveIndex++; 228a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 229a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 230a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } else { 231a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // inactive sessions go at the end in order of whoever last did 232a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // something. 233a8f951462791a16f47e8c07e552232f31dcefac5RoboErik result.add(lastPublishedIndex, session); 234a8f951462791a16f47e8c07e552232f31dcefac5RoboErik lastPublishedIndex++; 235a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 236a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 237a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 238a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return result; 239a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 240a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 241a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private boolean shouldUpdatePriority(int oldState, int newState) { 242a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (containsState(newState, ALWAYS_PRIORITY_STATES)) { 243a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 244a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 245a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (!containsState(oldState, TRANSITION_PRIORITY_STATES) 246a8f951462791a16f47e8c07e552232f31dcefac5RoboErik && containsState(newState, TRANSITION_PRIORITY_STATES)) { 247a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 248a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 249a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return false; 250a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 251a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 252a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private boolean containsState(int state, int[] states) { 253a8f951462791a16f47e8c07e552232f31dcefac5RoboErik for (int i = 0; i < states.length; i++) { 254a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (states[i] == state) { 255a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 256a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 257a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 258a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return false; 259a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 260a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 261a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private void clearCache() { 262a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedDefault = null; 263a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedButtonReceiver = null; 264a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedActiveList = null; 265a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mCachedTransportControlList = null; 266a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 267a8f951462791a16f47e8c07e552232f31dcefac5RoboErik} 268