MediaRouter.java revision 9a1de308cea2d160778fd977825f10a07b49d738
19a1de308cea2d160778fd977825f10a07b49d738Adam Powell/* 29a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Copyright (C) 2012 The Android Open Source Project 39a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 49a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 59a1de308cea2d160778fd977825f10a07b49d738Adam Powell * you may not use this file except in compliance with the License. 69a1de308cea2d160778fd977825f10a07b49d738Adam Powell * You may obtain a copy of the License at 79a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 89a1de308cea2d160778fd977825f10a07b49d738Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 99a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 109a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Unless required by applicable law or agreed to in writing, software 119a1de308cea2d160778fd977825f10a07b49d738Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 129a1de308cea2d160778fd977825f10a07b49d738Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139a1de308cea2d160778fd977825f10a07b49d738Adam Powell * See the License for the specific language governing permissions and 149a1de308cea2d160778fd977825f10a07b49d738Adam Powell * limitations under the License. 159a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 169a1de308cea2d160778fd977825f10a07b49d738Adam Powell 179a1de308cea2d160778fd977825f10a07b49d738Adam Powellpackage android.media; 189a1de308cea2d160778fd977825f10a07b49d738Adam Powell 199a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.bluetooth.BluetoothA2dp; 209a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.content.BroadcastReceiver; 219a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.content.Context; 229a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.content.Intent; 239a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.content.IntentFilter; 249a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.os.Handler; 259a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport android.util.Log; 269a1de308cea2d160778fd977825f10a07b49d738Adam Powell 279a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport java.util.ArrayList; 289a1de308cea2d160778fd977825f10a07b49d738Adam Powellimport java.util.HashMap; 299a1de308cea2d160778fd977825f10a07b49d738Adam Powell 309a1de308cea2d160778fd977825f10a07b49d738Adam Powell/** 319a1de308cea2d160778fd977825f10a07b49d738Adam Powell * MediaRouter allows applications to control the routing of media channels 329a1de308cea2d160778fd977825f10a07b49d738Adam Powell * and streams from the current device to external speakers and destination devices. 339a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 349a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>Media routes should only be modified on your application's main thread.</p> 359a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 369a1de308cea2d160778fd977825f10a07b49d738Adam Powellpublic class MediaRouter { 379a1de308cea2d160778fd977825f10a07b49d738Adam Powell private static final String TAG = "MediaRouter"; 389a1de308cea2d160778fd977825f10a07b49d738Adam Powell 399a1de308cea2d160778fd977825f10a07b49d738Adam Powell private Context mAppContext; 409a1de308cea2d160778fd977825f10a07b49d738Adam Powell private AudioManager mAudioManager; 419a1de308cea2d160778fd977825f10a07b49d738Adam Powell private Handler mHandler; 429a1de308cea2d160778fd977825f10a07b49d738Adam Powell private final ArrayList<CallbackInfo> mCallbacks = new ArrayList<CallbackInfo>(); 439a1de308cea2d160778fd977825f10a07b49d738Adam Powell 449a1de308cea2d160778fd977825f10a07b49d738Adam Powell private final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>(); 459a1de308cea2d160778fd977825f10a07b49d738Adam Powell private final ArrayList<RouteCategory> mCategories = new ArrayList<RouteCategory>(); 469a1de308cea2d160778fd977825f10a07b49d738Adam Powell 479a1de308cea2d160778fd977825f10a07b49d738Adam Powell private final RouteCategory mSystemCategory; 489a1de308cea2d160778fd977825f10a07b49d738Adam Powell private RouteInfo mDefaultAudio; 499a1de308cea2d160778fd977825f10a07b49d738Adam Powell private RouteInfo mBluetoothA2dpRoute; 509a1de308cea2d160778fd977825f10a07b49d738Adam Powell 519a1de308cea2d160778fd977825f10a07b49d738Adam Powell private RouteInfo mSelectedRoute; 529a1de308cea2d160778fd977825f10a07b49d738Adam Powell 539a1de308cea2d160778fd977825f10a07b49d738Adam Powell // These get removed when an activity dies 549a1de308cea2d160778fd977825f10a07b49d738Adam Powell final ArrayList<BroadcastReceiver> mRegisteredReceivers = new ArrayList<BroadcastReceiver>(); 559a1de308cea2d160778fd977825f10a07b49d738Adam Powell 569a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 579a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Route type flag for live audio. 589a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 599a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>A device that supports live audio routing will allow the media audio stream 609a1de308cea2d160778fd977825f10a07b49d738Adam Powell * to be routed to supported destinations. This can include internal speakers or 619a1de308cea2d160778fd977825f10a07b49d738Adam Powell * audio jacks on the device itself, A2DP devices, and more.</p> 629a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 639a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>Once initiated this routing is transparent to the application. All audio 649a1de308cea2d160778fd977825f10a07b49d738Adam Powell * played on the media stream will be routed to the selected destination.</p> 659a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 669a1de308cea2d160778fd977825f10a07b49d738Adam Powell public static final int ROUTE_TYPE_LIVE_AUDIO = 0x1; 679a1de308cea2d160778fd977825f10a07b49d738Adam Powell 689a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 699a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Route type flag for application-specific usage. 709a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 719a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>Unlike other media route types, user routes are managed by the application. 729a1de308cea2d160778fd977825f10a07b49d738Adam Powell * The MediaRouter will manage and dispatch events for user routes, but the application 739a1de308cea2d160778fd977825f10a07b49d738Adam Powell * is expected to interpret the meaning of these events and perform the requested 749a1de308cea2d160778fd977825f10a07b49d738Adam Powell * routing tasks.</p> 759a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 769a1de308cea2d160778fd977825f10a07b49d738Adam Powell public static final int ROUTE_TYPE_USER = 0x00800000; 779a1de308cea2d160778fd977825f10a07b49d738Adam Powell 789a1de308cea2d160778fd977825f10a07b49d738Adam Powell // Maps application contexts 799a1de308cea2d160778fd977825f10a07b49d738Adam Powell static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>(); 809a1de308cea2d160778fd977825f10a07b49d738Adam Powell 819a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 829a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return a MediaRouter for the application that the specified Context belongs to. 839a1de308cea2d160778fd977825f10a07b49d738Adam Powell * The behavior or availability of media routing may depend on 849a1de308cea2d160778fd977825f10a07b49d738Adam Powell * various parameters of the context. 859a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 869a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param context Context for the desired router 879a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return Router for the supplied Context 889a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 899a1de308cea2d160778fd977825f10a07b49d738Adam Powell public static MediaRouter forApplication(Context context) { 909a1de308cea2d160778fd977825f10a07b49d738Adam Powell final Context appContext = context.getApplicationContext(); 919a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (!sRouters.containsKey(appContext)) { 929a1de308cea2d160778fd977825f10a07b49d738Adam Powell final MediaRouter r = new MediaRouter(appContext); 939a1de308cea2d160778fd977825f10a07b49d738Adam Powell sRouters.put(appContext, r); 949a1de308cea2d160778fd977825f10a07b49d738Adam Powell return r; 959a1de308cea2d160778fd977825f10a07b49d738Adam Powell } else { 969a1de308cea2d160778fd977825f10a07b49d738Adam Powell return sRouters.get(appContext); 979a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 989a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 999a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1009a1de308cea2d160778fd977825f10a07b49d738Adam Powell static String typesToString(int types) { 1019a1de308cea2d160778fd977825f10a07b49d738Adam Powell final StringBuilder result = new StringBuilder(); 1029a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((types & ROUTE_TYPE_LIVE_AUDIO) != 0) { 1039a1de308cea2d160778fd977825f10a07b49d738Adam Powell result.append("ROUTE_TYPE_LIVE_AUDIO "); 1049a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1059a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((types & ROUTE_TYPE_USER) != 0) { 1069a1de308cea2d160778fd977825f10a07b49d738Adam Powell result.append("ROUTE_TYPE_USER "); 1079a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1089a1de308cea2d160778fd977825f10a07b49d738Adam Powell return result.toString(); 1099a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1109a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1119a1de308cea2d160778fd977825f10a07b49d738Adam Powell private MediaRouter(Context context) { 1129a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAppContext = context; 1139a1de308cea2d160778fd977825f10a07b49d738Adam Powell mHandler = new Handler(mAppContext.getMainLooper()); 1149a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1159a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAudioManager = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE); 1169a1de308cea2d160778fd977825f10a07b49d738Adam Powell mSystemCategory = new RouteCategory(mAppContext.getText( 1179a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_category_name), 1189a1de308cea2d160778fd977825f10a07b49d738Adam Powell ROUTE_TYPE_LIVE_AUDIO, false); 1199a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1209a1de308cea2d160778fd977825f10a07b49d738Adam Powell registerReceivers(); 1219a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1229a1de308cea2d160778fd977825f10a07b49d738Adam Powell createDefaultRoutes(); 1239a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1249a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1259a1de308cea2d160778fd977825f10a07b49d738Adam Powell private void registerReceivers() { 1269a1de308cea2d160778fd977825f10a07b49d738Adam Powell final BroadcastReceiver volumeReceiver = new VolumeChangedBroadcastReceiver(); 1279a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAppContext.registerReceiver(volumeReceiver, 1289a1de308cea2d160778fd977825f10a07b49d738Adam Powell new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION)); 1299a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRegisteredReceivers.add(volumeReceiver); 1309a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1319a1de308cea2d160778fd977825f10a07b49d738Adam Powell final IntentFilter speakerFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); 1329a1de308cea2d160778fd977825f10a07b49d738Adam Powell speakerFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 1339a1de308cea2d160778fd977825f10a07b49d738Adam Powell speakerFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 1349a1de308cea2d160778fd977825f10a07b49d738Adam Powell speakerFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG); 1359a1de308cea2d160778fd977825f10a07b49d738Adam Powell final BroadcastReceiver plugReceiver = new HeadphoneChangedBroadcastReceiver(); 1369a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAppContext.registerReceiver(plugReceiver, speakerFilter); 1379a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRegisteredReceivers.add(plugReceiver); 1389a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1399a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1409a1de308cea2d160778fd977825f10a07b49d738Adam Powell void unregisterReceivers() { 1419a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mRegisteredReceivers.size(); 1429a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 1439a1de308cea2d160778fd977825f10a07b49d738Adam Powell final BroadcastReceiver r = mRegisteredReceivers.get(i); 1449a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAppContext.unregisterReceiver(r); 1459a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1469a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRegisteredReceivers.clear(); 1479a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1489a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1499a1de308cea2d160778fd977825f10a07b49d738Adam Powell private void createDefaultRoutes() { 1509a1de308cea2d160778fd977825f10a07b49d738Adam Powell mDefaultAudio = new RouteInfo(mSystemCategory); 1519a1de308cea2d160778fd977825f10a07b49d738Adam Powell mDefaultAudio.mName = mAppContext.getText( 1529a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_name); 1539a1de308cea2d160778fd977825f10a07b49d738Adam Powell mDefaultAudio.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO; 1549a1de308cea2d160778fd977825f10a07b49d738Adam Powell addRoute(mDefaultAudio); 1559a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1569a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1579a1de308cea2d160778fd977825f10a07b49d738Adam Powell void onHeadphonesPlugged(boolean headphonesPresent, String headphonesName) { 1589a1de308cea2d160778fd977825f10a07b49d738Adam Powell mDefaultAudio.mName = headphonesPresent ? headphonesName : mAppContext.getText( 1599a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_name); 1609a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteChanged(mDefaultAudio); 1619a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1629a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1639a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 1649a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Set volume for the specified route types. 1659a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 1669a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param types Volume will be set for these route types 1679a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param volume Volume to set in the range 0.f (inaudible) to 1.f (full volume). 1689a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 1699a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void setRouteVolume(int types, float volume) { 1709a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((types & ROUTE_TYPE_LIVE_AUDIO) != 0) { 1719a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int index = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 1729a1de308cea2d160778fd977825f10a07b49d738Adam Powell mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0); 1739a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1749a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((types & ROUTE_TYPE_USER) != 0) { 1759a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchVolumeChanged(ROUTE_TYPE_USER, volume); 1769a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1779a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1789a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1799a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 1809a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Add a callback to listen to events about specific kinds of media routes. 1819a1de308cea2d160778fd977825f10a07b49d738Adam Powell * If the specified callback is already registered, its registration will be updated for any 1829a1de308cea2d160778fd977825f10a07b49d738Adam Powell * additional route types specified. 1839a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 1849a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param types Types of routes this callback is interested in 1859a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param cb Callback to add 1869a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 1879a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void addCallback(int types, Callback cb) { 1889a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 1899a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 1909a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo info = mCallbacks.get(i); 1919a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (info.cb == cb) { 1929a1de308cea2d160778fd977825f10a07b49d738Adam Powell info.type &= types; 1939a1de308cea2d160778fd977825f10a07b49d738Adam Powell return; 1949a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1959a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1969a1de308cea2d160778fd977825f10a07b49d738Adam Powell mCallbacks.add(new CallbackInfo(cb, types)); 1979a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 1989a1de308cea2d160778fd977825f10a07b49d738Adam Powell 1999a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 2009a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Remove the specified callback. It will no longer receive events about media routing. 2019a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 2029a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param cb Callback to remove 2039a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 2049a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void removeCallback(Callback cb) { 2059a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 2069a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 2079a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mCallbacks.get(i).cb == cb) { 2089a1de308cea2d160778fd977825f10a07b49d738Adam Powell mCallbacks.remove(i); 2099a1de308cea2d160778fd977825f10a07b49d738Adam Powell return; 2109a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2119a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2129a1de308cea2d160778fd977825f10a07b49d738Adam Powell Log.w(TAG, "removeCallback(" + cb + "): callback not registered"); 2139a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2149a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2159a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void selectRoute(int types, RouteInfo route) { 2169a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mSelectedRoute == route) return; 2179a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2189a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mSelectedRoute != null) { 2199a1de308cea2d160778fd977825f10a07b49d738Adam Powell // TODO filter types properly 2209a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteUnselected(types & mSelectedRoute.getSupportedTypes(), mSelectedRoute); 2219a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2229a1de308cea2d160778fd977825f10a07b49d738Adam Powell mSelectedRoute = route; 2239a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route != null) { 2249a1de308cea2d160778fd977825f10a07b49d738Adam Powell // TODO filter types properly 2259a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteSelected(types & route.getSupportedTypes(), route); 2269a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2279a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2289a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2299a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 2309a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Add an app-specified route for media to the MediaRouter. 2319a1de308cea2d160778fd977825f10a07b49d738Adam Powell * App-specified route definitions are created using {@link #createUserRoute(RouteCategory)} 2329a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 2339a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Definition of the route to add 2349a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #createUserRoute() 2359a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #removeUserRoute(UserRouteInfo) 2369a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 2379a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void addUserRoute(UserRouteInfo info) { 2389a1de308cea2d160778fd977825f10a07b49d738Adam Powell addRoute(info); 2399a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2409a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2419a1de308cea2d160778fd977825f10a07b49d738Adam Powell void addRoute(RouteInfo info) { 2429a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteCategory cat = info.getCategory(); 2439a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (!mCategories.contains(cat)) { 2449a1de308cea2d160778fd977825f10a07b49d738Adam Powell mCategories.add(cat); 2459a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2469a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (info.getCategory().isGroupable() && !(info instanceof RouteGroup)) { 2479a1de308cea2d160778fd977825f10a07b49d738Adam Powell // Enforce that any added route in a groupable category must be in a group. 2489a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteGroup group = new RouteGroup(info.getCategory()); 2499a1de308cea2d160778fd977825f10a07b49d738Adam Powell group.addRoute(info); 2509a1de308cea2d160778fd977825f10a07b49d738Adam Powell info = group; 2519a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2529a1de308cea2d160778fd977825f10a07b49d738Adam Powell final boolean onlyRoute = mRoutes.isEmpty(); 2539a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRoutes.add(info); 2549a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteAdded(info); 2559a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (onlyRoute) { 2569a1de308cea2d160778fd977825f10a07b49d738Adam Powell selectRoute(info.getSupportedTypes(), info); 2579a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2589a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2599a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2609a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 2619a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Remove an app-specified route for media from the MediaRouter. 2629a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 2639a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Definition of the route to remove 2649a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #addUserRoute(UserRouteInfo) 2659a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 2669a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void removeUserRoute(UserRouteInfo info) { 2679a1de308cea2d160778fd977825f10a07b49d738Adam Powell removeRoute(info); 2689a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2699a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2709a1de308cea2d160778fd977825f10a07b49d738Adam Powell void removeRoute(RouteInfo info) { 2719a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mRoutes.remove(info)) { 2729a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteCategory removingCat = info.getCategory(); 2739a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mRoutes.size(); 2749a1de308cea2d160778fd977825f10a07b49d738Adam Powell boolean found = false; 2759a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 2769a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteCategory cat = mRoutes.get(i).getCategory(); 2779a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (removingCat == cat) { 2789a1de308cea2d160778fd977825f10a07b49d738Adam Powell found = true; 2799a1de308cea2d160778fd977825f10a07b49d738Adam Powell break; 2809a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2819a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2829a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (!found) { 2839a1de308cea2d160778fd977825f10a07b49d738Adam Powell mCategories.remove(removingCat); 2849a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2859a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteRemoved(info); 2869a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2879a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2889a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2899a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 2909a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return the number of {@link MediaRouter.RouteCategory categories} currently 2919a1de308cea2d160778fd977825f10a07b49d738Adam Powell * represented by routes known to this MediaRouter. 2929a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 2939a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the number of unique categories represented by this MediaRouter's known routes 2949a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 2959a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int getCategoryCount() { 2969a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mCategories.size(); 2979a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 2989a1de308cea2d160778fd977825f10a07b49d738Adam Powell 2999a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 3009a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return the {@link MediaRouter.RouteCategory category} at the given index. 3019a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Valid indices are in the range [0-getCategoryCount). 3029a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3039a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param index which category to return 3049a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the category at index 3059a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 3069a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteCategory getCategoryAt(int index) { 3079a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mCategories.get(index); 3089a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3099a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3109a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 3119a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return the number of {@link MediaRouter.RouteInfo routes} currently known 3129a1de308cea2d160778fd977825f10a07b49d738Adam Powell * to this MediaRouter. 3139a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3149a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the number of routes tracked by this router 3159a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 3169a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int getRouteCount() { 3179a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mRoutes.size(); 3189a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3199a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3209a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 3219a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return the route at the specified index. 3229a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3239a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param index index of the route to return 3249a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the route at index 3259a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 3269a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteInfo getRouteAt(int index) { 3279a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mRoutes.get(index); 3289a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3299a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3309a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 3319a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Create a new user route that may be modified and registered for use by the application. 3329a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3339a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param category The category the new route will belong to 3349a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return A new UserRouteInfo for use by the application 3359a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3369a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #addUserRoute(UserRouteInfo) 3379a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #removeUserRoute(UserRouteInfo) 3389a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see #createRouteCategory(CharSequence) 3399a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 3409a1de308cea2d160778fd977825f10a07b49d738Adam Powell public UserRouteInfo createUserRoute(RouteCategory category) { 3419a1de308cea2d160778fd977825f10a07b49d738Adam Powell return new UserRouteInfo(category); 3429a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3439a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3449a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 3459a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Create a new route category. Each route must belong to a category. 3469a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 3479a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param name Name of the new category 3489a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param isGroupable true if routes in this category may be grouped with one another 3499a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the new RouteCategory 3509a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 3519a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteCategory createRouteCategory(CharSequence name, boolean isGroupable) { 3529a1de308cea2d160778fd977825f10a07b49d738Adam Powell return new RouteCategory(name, ROUTE_TYPE_USER, isGroupable); 3539a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3549a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3559a1de308cea2d160778fd977825f10a07b49d738Adam Powell void updateRoute(final RouteInfo info) { 3569a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchRouteChanged(info); 3579a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3589a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3599a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchRouteSelected(int type, RouteInfo info) { 3609a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 3619a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 3629a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 3639a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & type) != 0) { 3649a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onRouteSelected(type, info); 3659a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3669a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3679a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3689a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3699a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchRouteUnselected(int type, RouteInfo info) { 3709a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 3719a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 3729a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 3739a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & type) != 0) { 3749a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onRouteUnselected(type, info); 3759a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3769a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3779a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3789a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3799a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchRouteChanged(RouteInfo info) { 3809a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 3819a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 3829a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 3839a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & info.mSupportedTypes) != 0) { 3849a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onRouteChanged(info); 3859a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3869a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3879a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3889a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3899a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchRouteAdded(RouteInfo info) { 3909a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 3919a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 3929a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 3939a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & info.mSupportedTypes) != 0) { 3949a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onRouteAdded(info.mSupportedTypes, info); 3959a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3969a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3979a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 3989a1de308cea2d160778fd977825f10a07b49d738Adam Powell 3999a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchRouteRemoved(RouteInfo info) { 4009a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 4019a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 4029a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 4039a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & info.mSupportedTypes) != 0) { 4049a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onRouteRemoved(info.mSupportedTypes, info); 4059a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4069a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4079a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4089a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4099a1de308cea2d160778fd977825f10a07b49d738Adam Powell void dispatchVolumeChanged(int type, float volume) { 4109a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mCallbacks.size(); 4119a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 4129a1de308cea2d160778fd977825f10a07b49d738Adam Powell final CallbackInfo cbi = mCallbacks.get(i); 4139a1de308cea2d160778fd977825f10a07b49d738Adam Powell if ((cbi.type & type) != 0) { 4149a1de308cea2d160778fd977825f10a07b49d738Adam Powell cbi.cb.onVolumeChanged(type, volume); 4159a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4169a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4179a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4189a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4199a1de308cea2d160778fd977825f10a07b49d738Adam Powell void onA2dpDeviceConnected() { 4209a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteInfo info = new RouteInfo(mSystemCategory); 4219a1de308cea2d160778fd977825f10a07b49d738Adam Powell info.mName = "Bluetooth"; // TODO Fetch the real name of the device 4229a1de308cea2d160778fd977825f10a07b49d738Adam Powell mBluetoothA2dpRoute = info; 4239a1de308cea2d160778fd977825f10a07b49d738Adam Powell addRoute(mBluetoothA2dpRoute); 4249a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4259a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4269a1de308cea2d160778fd977825f10a07b49d738Adam Powell void onA2dpDeviceDisconnected() { 4279a1de308cea2d160778fd977825f10a07b49d738Adam Powell removeRoute(mBluetoothA2dpRoute); 4289a1de308cea2d160778fd977825f10a07b49d738Adam Powell mBluetoothA2dpRoute = null; 4299a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4309a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4319a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4329a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Information about a media route. 4339a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4349a1de308cea2d160778fd977825f10a07b49d738Adam Powell public class RouteInfo { 4359a1de308cea2d160778fd977825f10a07b49d738Adam Powell CharSequence mName; 4369a1de308cea2d160778fd977825f10a07b49d738Adam Powell private CharSequence mStatus; 4379a1de308cea2d160778fd977825f10a07b49d738Adam Powell int mSupportedTypes; 4389a1de308cea2d160778fd977825f10a07b49d738Adam Powell RouteGroup mGroup; 4399a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteCategory mCategory; 4409a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4419a1de308cea2d160778fd977825f10a07b49d738Adam Powell RouteInfo(RouteCategory category) { 4429a1de308cea2d160778fd977825f10a07b49d738Adam Powell mCategory = category; 4439a1de308cea2d160778fd977825f10a07b49d738Adam Powell category.mRoutes.add(this); 4449a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4459a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4469a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4479a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return The user-friendly name of a media route. This is the string presented 4489a1de308cea2d160778fd977825f10a07b49d738Adam Powell * to users who may select this as the active route. 4499a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4509a1de308cea2d160778fd977825f10a07b49d738Adam Powell public CharSequence getName() { 4519a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mName; 4529a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4539a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4549a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4559a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return The user-friendly status for a media route. This may include a description 4569a1de308cea2d160778fd977825f10a07b49d738Adam Powell * of the currently playing media, if available. 4579a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4589a1de308cea2d160778fd977825f10a07b49d738Adam Powell public CharSequence getStatus() { 4599a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mStatus; 4609a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4619a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4629a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4639a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return A media type flag set describing which types this route supports. 4649a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4659a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int getSupportedTypes() { 4669a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mSupportedTypes; 4679a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4689a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4699a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4709a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return The group that this route belongs to. 4719a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4729a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteGroup getGroup() { 4739a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mGroup; 4749a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4759a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4769a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 4779a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the category this route belongs to. 4789a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 4799a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteCategory getCategory() { 4809a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mCategory; 4819a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4829a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4839a1de308cea2d160778fd977825f10a07b49d738Adam Powell void setStatusInt(CharSequence status) { 4849a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (!status.equals(mStatus)) { 4859a1de308cea2d160778fd977825f10a07b49d738Adam Powell mStatus = status; 4869a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 4879a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mGroup != null) { 4889a1de308cea2d160778fd977825f10a07b49d738Adam Powell mGroup.memberStatusChanged(this, status); 4899a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4909a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 4919a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4929a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4939a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4949a1de308cea2d160778fd977825f10a07b49d738Adam Powell void routeUpdated() { 4959a1de308cea2d160778fd977825f10a07b49d738Adam Powell updateRoute(this); 4969a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 4979a1de308cea2d160778fd977825f10a07b49d738Adam Powell 4989a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 4999a1de308cea2d160778fd977825f10a07b49d738Adam Powell public String toString() { 5009a1de308cea2d160778fd977825f10a07b49d738Adam Powell String supportedTypes = typesToString(mSupportedTypes); 5019a1de308cea2d160778fd977825f10a07b49d738Adam Powell return "RouteInfo{ name=" + mName + ", status=" + mStatus + 5029a1de308cea2d160778fd977825f10a07b49d738Adam Powell " category=" + mCategory + 5039a1de308cea2d160778fd977825f10a07b49d738Adam Powell " supportedTypes=" + supportedTypes + "}"; 5049a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5059a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5069a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5079a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5089a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Information about a route that the application may define and modify. 5099a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 5109a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see MediaRouter.RouteInfo 5119a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5129a1de308cea2d160778fd977825f10a07b49d738Adam Powell public class UserRouteInfo extends RouteInfo { 5139a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5149a1de308cea2d160778fd977825f10a07b49d738Adam Powell UserRouteInfo(RouteCategory category) { 5159a1de308cea2d160778fd977825f10a07b49d738Adam Powell super(category); 5169a1de308cea2d160778fd977825f10a07b49d738Adam Powell mSupportedTypes = ROUTE_TYPE_USER; 5179a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5189a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5199a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5209a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Set the user-visible name of this route. 5219a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param name Name to display to the user to describe this route 5229a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5239a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void setName(CharSequence name) { 5249a1de308cea2d160778fd977825f10a07b49d738Adam Powell mName = name; 5259a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 5269a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5279a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5289a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5299a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Set the current user-visible status for this route. 5309a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param status Status to display to the user to describe what the endpoint 5319a1de308cea2d160778fd977825f10a07b49d738Adam Powell * of this route is currently doing 5329a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5339a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void setStatus(CharSequence status) { 5349a1de308cea2d160778fd977825f10a07b49d738Adam Powell setStatusInt(status); 5359a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5369a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5379a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5389a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5399a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Information about a route that consists of multiple other routes in a group. 5409a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5419a1de308cea2d160778fd977825f10a07b49d738Adam Powell public class RouteGroup extends RouteInfo { 5429a1de308cea2d160778fd977825f10a07b49d738Adam Powell final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>(); 5439a1de308cea2d160778fd977825f10a07b49d738Adam Powell private boolean mUpdateName; 5449a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5459a1de308cea2d160778fd977825f10a07b49d738Adam Powell RouteGroup(RouteCategory category) { 5469a1de308cea2d160778fd977825f10a07b49d738Adam Powell super(category); 5479a1de308cea2d160778fd977825f10a07b49d738Adam Powell mGroup = this; 5489a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5499a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5509a1de308cea2d160778fd977825f10a07b49d738Adam Powell public CharSequence getName() { 5519a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (mUpdateName) updateName(); 5529a1de308cea2d160778fd977825f10a07b49d738Adam Powell return super.getName(); 5539a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5549a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5559a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5569a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Add a route to this group. The route must not currently belong to another group. 5579a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 5589a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param route route to add to this group 5599a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5609a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void addRoute(RouteInfo route) { 5619a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route.getGroup() != null) { 5629a1de308cea2d160778fd977825f10a07b49d738Adam Powell throw new IllegalStateException("Route " + route + " is already part of a group."); 5639a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5649a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route.getCategory() != mCategory) { 5659a1de308cea2d160778fd977825f10a07b49d738Adam Powell throw new IllegalArgumentException( 5669a1de308cea2d160778fd977825f10a07b49d738Adam Powell "Route cannot be added to a group with a different category. " + 5679a1de308cea2d160778fd977825f10a07b49d738Adam Powell "(Route category=" + route.getCategory() + 5689a1de308cea2d160778fd977825f10a07b49d738Adam Powell " group category=" + mCategory + ")"); 5699a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5709a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRoutes.add(route); 5719a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = true; 5729a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 5739a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5749a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5759a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5769a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Add a route to this group before the specified index. 5779a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 5789a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param route route to add 5799a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param insertAt insert the new route before this index 5809a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 5819a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void addRoute(RouteInfo route, int insertAt) { 5829a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route.getGroup() != null) { 5839a1de308cea2d160778fd977825f10a07b49d738Adam Powell throw new IllegalStateException("Route " + route + " is already part of a group."); 5849a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5859a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route.getCategory() != mCategory) { 5869a1de308cea2d160778fd977825f10a07b49d738Adam Powell throw new IllegalArgumentException( 5879a1de308cea2d160778fd977825f10a07b49d738Adam Powell "Route cannot be added to a group with a different category. " + 5889a1de308cea2d160778fd977825f10a07b49d738Adam Powell "(Route category=" + route.getCategory() + 5899a1de308cea2d160778fd977825f10a07b49d738Adam Powell " group category=" + mCategory + ")"); 5909a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5919a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRoutes.add(insertAt, route); 5929a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = true; 5939a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 5949a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 5959a1de308cea2d160778fd977825f10a07b49d738Adam Powell 5969a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 5979a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Remove a route from this group. 5989a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 5999a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param route route to remove 6009a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6019a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void removeRoute(RouteInfo route) { 6029a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (route.getGroup() != this) { 6039a1de308cea2d160778fd977825f10a07b49d738Adam Powell throw new IllegalArgumentException("Route " + route + 6049a1de308cea2d160778fd977825f10a07b49d738Adam Powell " is not a member of this group."); 6059a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6069a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRoutes.remove(route); 6079a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = true; 6089a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 6099a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6109a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6119a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6129a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Remove the route at the specified index from this group. 6139a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 6149a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param index index of the route to remove 6159a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6169a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void removeRoute(int index) { 6179a1de308cea2d160778fd977825f10a07b49d738Adam Powell mRoutes.remove(index); 6189a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = true; 6199a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 6209a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6219a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6229a1de308cea2d160778fd977825f10a07b49d738Adam Powell void memberNameChanged(RouteInfo info, CharSequence name) { 6239a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = true; 6249a1de308cea2d160778fd977825f10a07b49d738Adam Powell routeUpdated(); 6259a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6269a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6279a1de308cea2d160778fd977825f10a07b49d738Adam Powell void memberStatusChanged(RouteInfo info, CharSequence status) { 6289a1de308cea2d160778fd977825f10a07b49d738Adam Powell setStatusInt(status); 6299a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6309a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6319a1de308cea2d160778fd977825f10a07b49d738Adam Powell void updateName() { 6329a1de308cea2d160778fd977825f10a07b49d738Adam Powell final StringBuilder sb = new StringBuilder(); 6339a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int count = mRoutes.size(); 6349a1de308cea2d160778fd977825f10a07b49d738Adam Powell for (int i = 0; i < count; i++) { 6359a1de308cea2d160778fd977825f10a07b49d738Adam Powell final RouteInfo info = mRoutes.get(i); 6369a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (i > 0) sb.append(", "); 6379a1de308cea2d160778fd977825f10a07b49d738Adam Powell sb.append(info.mName); 6389a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6399a1de308cea2d160778fd977825f10a07b49d738Adam Powell mName = sb.toString(); 6409a1de308cea2d160778fd977825f10a07b49d738Adam Powell mUpdateName = false; 6419a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6429a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6439a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6449a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6459a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Definition of a category of routes. All routes belong to a category. 6469a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6479a1de308cea2d160778fd977825f10a07b49d738Adam Powell public class RouteCategory { 6489a1de308cea2d160778fd977825f10a07b49d738Adam Powell final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>(); 6499a1de308cea2d160778fd977825f10a07b49d738Adam Powell CharSequence mName; 6509a1de308cea2d160778fd977825f10a07b49d738Adam Powell int mTypes; 6519a1de308cea2d160778fd977825f10a07b49d738Adam Powell final boolean mGroupable; 6529a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6539a1de308cea2d160778fd977825f10a07b49d738Adam Powell RouteCategory(CharSequence name, int types, boolean groupable) { 6549a1de308cea2d160778fd977825f10a07b49d738Adam Powell mName = name; 6559a1de308cea2d160778fd977825f10a07b49d738Adam Powell mTypes = types; 6569a1de308cea2d160778fd977825f10a07b49d738Adam Powell mGroupable = groupable; 6579a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6589a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6599a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6609a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the name of this route category 6619a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6629a1de308cea2d160778fd977825f10a07b49d738Adam Powell public CharSequence getName() { 6639a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mName; 6649a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6659a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6669a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6679a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the number of routes in this category 6689a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6699a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int getRouteCount() { 6709a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mRoutes.size(); 6719a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6729a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6739a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6749a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return a route from this category 6759a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 6769a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param index Index from [0-getRouteCount) 6779a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return the route at the given index 6789a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6799a1de308cea2d160778fd977825f10a07b49d738Adam Powell public RouteInfo getRouteAt(int index) { 6809a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mRoutes.get(index); 6819a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6829a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6839a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6849a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return Flag set describing the route types supported by this category 6859a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6869a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int getSupportedTypes() { 6879a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mTypes; 6889a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 6899a1de308cea2d160778fd977825f10a07b49d738Adam Powell 6909a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 6919a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Return whether or not this category supports grouping. 6929a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 6939a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>If this method returns true, all routes obtained from this category 6949a1de308cea2d160778fd977825f10a07b49d738Adam Powell * via calls to {@link #getRouteAt(int)} will be {@link MediaRouter.RouteGroup}s. 6959a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 6969a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @return true if this category supports 6979a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 6989a1de308cea2d160778fd977825f10a07b49d738Adam Powell public boolean isGroupable() { 6999a1de308cea2d160778fd977825f10a07b49d738Adam Powell return mGroupable; 7009a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7019a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7029a1de308cea2d160778fd977825f10a07b49d738Adam Powell public String toString() { 7039a1de308cea2d160778fd977825f10a07b49d738Adam Powell return "RouteCategory{ name=" + mName + " types=" + typesToString(mTypes) + 7049a1de308cea2d160778fd977825f10a07b49d738Adam Powell " groupable=" + mGroupable + " routes=" + mRoutes.size() + " }"; 7059a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7069a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7079a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7089a1de308cea2d160778fd977825f10a07b49d738Adam Powell static class CallbackInfo { 7099a1de308cea2d160778fd977825f10a07b49d738Adam Powell public int type; 7109a1de308cea2d160778fd977825f10a07b49d738Adam Powell public Callback cb; 7119a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7129a1de308cea2d160778fd977825f10a07b49d738Adam Powell public CallbackInfo(Callback cb, int type) { 7139a1de308cea2d160778fd977825f10a07b49d738Adam Powell this.cb = cb; 7149a1de308cea2d160778fd977825f10a07b49d738Adam Powell this.type = type; 7159a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7169a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7179a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7189a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7199a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Interface for receiving events about media routing changes. 7209a1de308cea2d160778fd977825f10a07b49d738Adam Powell * All methods of this interface will be called from the application's main thread. 7219a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7229a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>A Callback will only receive events relevant to routes that the callback 7239a1de308cea2d160778fd977825f10a07b49d738Adam Powell * was registered for.</p> 7249a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7259a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see MediaRouter#addCallback(int, Callback) 7269a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @see MediaRouter#removeCallback(Callback) 7279a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7289a1de308cea2d160778fd977825f10a07b49d738Adam Powell public interface Callback { 7299a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7309a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when the supplied route becomes selected as the active route 7319a1de308cea2d160778fd977825f10a07b49d738Adam Powell * for the given route type. 7329a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7339a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param type Type flag set indicating the routes that have been selected 7349a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Route that has been selected for the given route types 7359a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7369a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteSelected(int type, RouteInfo info); 7379a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7389a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7399a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when the supplied route becomes unselected as the active route 7409a1de308cea2d160778fd977825f10a07b49d738Adam Powell * for the given route type. 7419a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7429a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param type Type flag set indicating the routes that have been unselected 7439a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Route that has been unselected for the given route types 7449a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7459a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteUnselected(int type, RouteInfo info); 7469a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7479a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7489a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when the volume is changed for the specified route types. 7499a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7509a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param type Type flags indicating which volume type was changed 7519a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param volume New volume value in the range 0 (inaudible) to 1 (full) 7529a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7539a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onVolumeChanged(int type, float volume); 7549a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7559a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7569a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when a route for the specified type was added. 7579a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7589a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param type Type flags indicating which types the added route supports 7599a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Route that has become available for use 7609a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7619a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteAdded(int type, RouteInfo info); 7629a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7639a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7649a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when a route for the specified type was removed. 7659a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7669a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param type Type flags indicating which types the removed route supported 7679a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info Route that has been removed from availability 7689a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7699a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteRemoved(int type, RouteInfo info); 7709a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7719a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7729a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Called when an aspect of the indicated route has changed. 7739a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7749a1de308cea2d160778fd977825f10a07b49d738Adam Powell * <p>This will not indicate that the types supported by this route have 7759a1de308cea2d160778fd977825f10a07b49d738Adam Powell * changed, only that cosmetic info such as name or status have been updated.</p> 7769a1de308cea2d160778fd977825f10a07b49d738Adam Powell * 7779a1de308cea2d160778fd977825f10a07b49d738Adam Powell * @param info The route that was changed 7789a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7799a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteChanged(RouteInfo info); 7809a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7819a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7829a1de308cea2d160778fd977825f10a07b49d738Adam Powell /** 7839a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Stub implementation of the {@link MediaRouter.Callback} interface. 7849a1de308cea2d160778fd977825f10a07b49d738Adam Powell * Each interface method is defined as a no-op. Override just the ones 7859a1de308cea2d160778fd977825f10a07b49d738Adam Powell * you need. 7869a1de308cea2d160778fd977825f10a07b49d738Adam Powell */ 7879a1de308cea2d160778fd977825f10a07b49d738Adam Powell public static class SimpleCallback implements Callback { 7889a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7899a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 7909a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteSelected(int type, RouteInfo info) { 7919a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7929a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7939a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7949a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 7959a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteUnselected(int type, RouteInfo info) { 7969a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7979a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 7989a1de308cea2d160778fd977825f10a07b49d738Adam Powell 7999a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8009a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onVolumeChanged(int type, float volume) { 8019a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8029a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8039a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8049a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8059a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteAdded(int type, RouteInfo info) { 8069a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8079a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8089a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8099a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8109a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteRemoved(int type, RouteInfo info) { 8119a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8129a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8139a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8149a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8159a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onRouteChanged(RouteInfo info) { 8169a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8179a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8189a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8199a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8209a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8219a1de308cea2d160778fd977825f10a07b49d738Adam Powell class VolumeChangedBroadcastReceiver extends BroadcastReceiver { 8229a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8239a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onReceive(Context context, Intent intent) { 8249a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String action = intent.getAction(); 8259a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (AudioManager.VOLUME_CHANGED_ACTION.equals(action) && 8269a1de308cea2d160778fd977825f10a07b49d738Adam Powell AudioManager.STREAM_MUSIC == intent.getIntExtra( 8279a1de308cea2d160778fd977825f10a07b49d738Adam Powell AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1)) { 8289a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int maxVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 8299a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int volExtra = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); 8309a1de308cea2d160778fd977825f10a07b49d738Adam Powell final float volume = (float) volExtra / maxVol; 8319a1de308cea2d160778fd977825f10a07b49d738Adam Powell dispatchVolumeChanged(ROUTE_TYPE_LIVE_AUDIO, volume); 8329a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8339a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8349a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8359a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8369a1de308cea2d160778fd977825f10a07b49d738Adam Powell class BtChangedBroadcastReceiver extends BroadcastReceiver { 8379a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8389a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onReceive(Context context, Intent intent) { 8399a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String action = intent.getAction(); 8409a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { 8419a1de308cea2d160778fd977825f10a07b49d738Adam Powell final int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1); 8429a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (state == BluetoothA2dp.STATE_CONNECTED) { 8439a1de308cea2d160778fd977825f10a07b49d738Adam Powell onA2dpDeviceConnected(); 8449a1de308cea2d160778fd977825f10a07b49d738Adam Powell } else if (state == BluetoothA2dp.STATE_DISCONNECTING || 8459a1de308cea2d160778fd977825f10a07b49d738Adam Powell state == BluetoothA2dp.STATE_DISCONNECTED) { 8469a1de308cea2d160778fd977825f10a07b49d738Adam Powell onA2dpDeviceDisconnected(); 8479a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8489a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8499a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8509a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8519a1de308cea2d160778fd977825f10a07b49d738Adam Powell 8529a1de308cea2d160778fd977825f10a07b49d738Adam Powell class HeadphoneChangedBroadcastReceiver extends BroadcastReceiver { 8539a1de308cea2d160778fd977825f10a07b49d738Adam Powell @Override 8549a1de308cea2d160778fd977825f10a07b49d738Adam Powell public void onReceive(Context context, Intent intent) { 8559a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String action = intent.getAction(); 8569a1de308cea2d160778fd977825f10a07b49d738Adam Powell if (Intent.ACTION_HEADSET_PLUG.equals(action)) { 8579a1de308cea2d160778fd977825f10a07b49d738Adam Powell final boolean plugged = intent.getIntExtra("state", 0) != 0; 8589a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String name = mAppContext.getString( 8599a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_name_headphones); 8609a1de308cea2d160778fd977825f10a07b49d738Adam Powell onHeadphonesPlugged(plugged, name); 8619a1de308cea2d160778fd977825f10a07b49d738Adam Powell } else if (Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG.equals(action) || 8629a1de308cea2d160778fd977825f10a07b49d738Adam Powell Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG.equals(action)) { 8639a1de308cea2d160778fd977825f10a07b49d738Adam Powell final boolean plugged = intent.getIntExtra("state", 0) != 0; 8649a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String name = mAppContext.getString( 8659a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_name_dock_speakers); 8669a1de308cea2d160778fd977825f10a07b49d738Adam Powell onHeadphonesPlugged(plugged, name); 8679a1de308cea2d160778fd977825f10a07b49d738Adam Powell } else if (Intent.ACTION_HDMI_AUDIO_PLUG.equals(action)) { 8689a1de308cea2d160778fd977825f10a07b49d738Adam Powell final boolean plugged = intent.getIntExtra("state", 0) != 0; 8699a1de308cea2d160778fd977825f10a07b49d738Adam Powell final String name = mAppContext.getString( 8709a1de308cea2d160778fd977825f10a07b49d738Adam Powell com.android.internal.R.string.default_audio_route_name_hdmi); 8719a1de308cea2d160778fd977825f10a07b49d738Adam Powell onHeadphonesPlugged(plugged, name); 8729a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8739a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8749a1de308cea2d160778fd977825f10a07b49d738Adam Powell } 8759a1de308cea2d160778fd977825f10a07b49d738Adam Powell} 876