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