1c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown/* 2c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Copyright (C) 2013 The Android Open Source Project 3c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 4c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * you may not use this file except in compliance with the License. 6c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * You may obtain a copy of the License at 7c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 8c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 10c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Unless required by applicable law or agreed to in writing, software 11c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * See the License for the specific language governing permissions and 14c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * limitations under the License. 15c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 16c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 17b507e525a61ed761eecfc2eaaf19af7e8db5dca5Jeff Brownpackage android.support.v7.media; 18c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 19c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownimport android.content.Context; 20c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownimport android.content.Intent; 21c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownimport android.os.Handler; 22c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownimport android.os.Message; 23b507e525a61ed761eecfc2eaaf19af7e8db5dca5Jeff Brownimport android.support.v7.media.MediaRouter.ControlRequestCallback; 24c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownimport android.text.TextUtils; 25c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 26c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown/** 27c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Media route providers are used to publish additional media routes for 28c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * use within an application. Media route providers may also be declared 29c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * as a service to publish additional media routes to all applications 30c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * in the system. 31c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * <p> 3211417b1cfde8f1749905f2d735623af9214148afJeff Brown * The purpose of a media route provider is to discover media routes that satisfy 3311417b1cfde8f1749905f2d735623af9214148afJeff Brown * the criteria specified by the current {@link MediaRouteDiscoveryRequest} and publish a 3411417b1cfde8f1749905f2d735623af9214148afJeff Brown * {@link MediaRouteProviderDescriptor} with information about each route by calling 3511417b1cfde8f1749905f2d735623af9214148afJeff Brown * {@link #setDescriptor} to notify the currently registered {@link Callback}. 3611417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p><p> 3711417b1cfde8f1749905f2d735623af9214148afJeff Brown * The provider should watch for changes to the discovery request by implementing 3811417b1cfde8f1749905f2d735623af9214148afJeff Brown * {@link #onDiscoveryRequestChanged} and updating the set of routes that it is 3911417b1cfde8f1749905f2d735623af9214148afJeff Brown * attempting to discover. It should also handle route control requests such 4011417b1cfde8f1749905f2d735623af9214148afJeff Brown * as volume changes or {@link MediaControlIntent media control intents} 4111417b1cfde8f1749905f2d735623af9214148afJeff Brown * by implementing {@link #onCreateRouteController} to return a {@link RouteController} 4211417b1cfde8f1749905f2d735623af9214148afJeff Brown * for a particular route. 4311417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p><p> 4411417b1cfde8f1749905f2d735623af9214148afJeff Brown * A media route provider may be used privately within the scope of a single 4511417b1cfde8f1749905f2d735623af9214148afJeff Brown * application process by calling {@link MediaRouter#addProvider MediaRouter.addProvider} 4611417b1cfde8f1749905f2d735623af9214148afJeff Brown * to add it to the local {@link MediaRouter}. A media route provider may also be made 4711417b1cfde8f1749905f2d735623af9214148afJeff Brown * available globally to all applications by registering a {@link MediaRouteProviderService} 4811417b1cfde8f1749905f2d735623af9214148afJeff Brown * in the provider's manifest. When the media route provider is registered 4911417b1cfde8f1749905f2d735623af9214148afJeff Brown * as a service, all applications that use the media router API will be able to 5011417b1cfde8f1749905f2d735623af9214148afJeff Brown * discover and used the provider's routes without having to install anything else. 51c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p><p> 52c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * This object must only be accessed on the main thread. 53c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p> 54c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 55c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brownpublic abstract class MediaRouteProvider { 56c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private static final int MSG_DELIVER_DESCRIPTOR_CHANGED = 1; 5711417b1cfde8f1749905f2d735623af9214148afJeff Brown private static final int MSG_DELIVER_DISCOVERY_REQUEST_CHANGED = 2; 58c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 59c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private final Context mContext; 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ProviderMetadata mMetadata; 61c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private final ProviderHandler mHandler = new ProviderHandler(); 62c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 6311417b1cfde8f1749905f2d735623af9214148afJeff Brown private Callback mCallback; 6411417b1cfde8f1749905f2d735623af9214148afJeff Brown 6511417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteDiscoveryRequest mDiscoveryRequest; 6611417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean mPendingDiscoveryRequestChange; 6711417b1cfde8f1749905f2d735623af9214148afJeff Brown 6811417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteProviderDescriptor mDescriptor; 69c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private boolean mPendingDescriptorChange; 70c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 71c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 72c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Creates a media route provider. 73c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 74c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @param context The context. 75c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 76c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public MediaRouteProvider(Context context) { 77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown this(context, null); 78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 80fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider(Context context, ProviderMetadata metadata) { 81c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown if (context == null) { 82c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown throw new IllegalArgumentException("context must not be null"); 83c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 84c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 85c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown mContext = context; 86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (metadata == null) { 87fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMetadata = new ProviderMetadata(context.getPackageName()); 88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else { 89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMetadata = metadata; 90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 91c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 92c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 93c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 94c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Gets the context of the media route provider. 95c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 96c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public final Context getContext() { 97c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown return mContext; 98c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 99c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 10011417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 10111417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the provider's handler which is associated with the main thread. 10211417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 10311417b1cfde8f1749905f2d735623af9214148afJeff Brown public final Handler getHandler() { 10411417b1cfde8f1749905f2d735623af9214148afJeff Brown return mHandler; 10511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 10611417b1cfde8f1749905f2d735623af9214148afJeff Brown 10711417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 10811417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets some metadata about the provider's implementation. 10911417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 11011417b1cfde8f1749905f2d735623af9214148afJeff Brown public final ProviderMetadata getMetadata() { 111fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mMetadata; 112fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 113fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 114c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 11511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Sets a callback to invoke when the provider's descriptor changes. 11611417b1cfde8f1749905f2d735623af9214148afJeff Brown * 11711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param callback The callback to use, or null if none. 11811417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 11911417b1cfde8f1749905f2d735623af9214148afJeff Brown public final void setCallback(Callback callback) { 12011417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.checkCallingThread(); 12111417b1cfde8f1749905f2d735623af9214148afJeff Brown mCallback = callback; 12211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 12311417b1cfde8f1749905f2d735623af9214148afJeff Brown 12411417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 12511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the current discovery request which informs the provider about the 12611417b1cfde8f1749905f2d735623af9214148afJeff Brown * kinds of routes to discover and whether to perform active scanning. 12711417b1cfde8f1749905f2d735623af9214148afJeff Brown * 12811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The current discovery request, or null if no discovery is needed at this time. 12911417b1cfde8f1749905f2d735623af9214148afJeff Brown * 13011417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see #onDiscoveryRequestChanged 13111417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 13211417b1cfde8f1749905f2d735623af9214148afJeff Brown public final MediaRouteDiscoveryRequest getDiscoveryRequest() { 13311417b1cfde8f1749905f2d735623af9214148afJeff Brown return mDiscoveryRequest; 13411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 13511417b1cfde8f1749905f2d735623af9214148afJeff Brown 13611417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 13711417b1cfde8f1749905f2d735623af9214148afJeff Brown * Sets a discovery request to inform the provider about the kinds of 13811417b1cfde8f1749905f2d735623af9214148afJeff Brown * routes that its clients would like to discover and whether to perform active scanning. 13911417b1cfde8f1749905f2d735623af9214148afJeff Brown * 14011417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param request The discovery request, or null if no discovery is needed at this time. 14111417b1cfde8f1749905f2d735623af9214148afJeff Brown * 14211417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see #onDiscoveryRequestChanged 14311417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 14411417b1cfde8f1749905f2d735623af9214148afJeff Brown public final void setDiscoveryRequest(MediaRouteDiscoveryRequest request) { 14511417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.checkCallingThread(); 14611417b1cfde8f1749905f2d735623af9214148afJeff Brown 14711417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mDiscoveryRequest == request 14811417b1cfde8f1749905f2d735623af9214148afJeff Brown || (mDiscoveryRequest != null && mDiscoveryRequest.equals(request))) { 14911417b1cfde8f1749905f2d735623af9214148afJeff Brown return; 15011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15111417b1cfde8f1749905f2d735623af9214148afJeff Brown 15211417b1cfde8f1749905f2d735623af9214148afJeff Brown mDiscoveryRequest = request; 15311417b1cfde8f1749905f2d735623af9214148afJeff Brown if (!mPendingDiscoveryRequestChange) { 15411417b1cfde8f1749905f2d735623af9214148afJeff Brown mPendingDiscoveryRequestChange = true; 15511417b1cfde8f1749905f2d735623af9214148afJeff Brown mHandler.sendEmptyMessage(MSG_DELIVER_DISCOVERY_REQUEST_CHANGED); 15611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15811417b1cfde8f1749905f2d735623af9214148afJeff Brown 15911417b1cfde8f1749905f2d735623af9214148afJeff Brown private void deliverDiscoveryRequestChanged() { 16011417b1cfde8f1749905f2d735623af9214148afJeff Brown mPendingDiscoveryRequestChange = false; 16111417b1cfde8f1749905f2d735623af9214148afJeff Brown onDiscoveryRequestChanged(mDiscoveryRequest); 16211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 16311417b1cfde8f1749905f2d735623af9214148afJeff Brown 16411417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 16511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Called by the media router when the {@link MediaRouteDiscoveryRequest discovery request} 16611417b1cfde8f1749905f2d735623af9214148afJeff Brown * has changed. 16711417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p> 16811417b1cfde8f1749905f2d735623af9214148afJeff Brown * Whenever an applications calls {@link MediaRouter#addCallback} to register 16911417b1cfde8f1749905f2d735623af9214148afJeff Brown * a callback, it also provides a selector to specify the kinds of routes that 17011417b1cfde8f1749905f2d735623af9214148afJeff Brown * it is interested in. The media router combines all of these selectors together 17111417b1cfde8f1749905f2d735623af9214148afJeff Brown * to generate a {@link MediaRouteDiscoveryRequest} and notifies each provider when a change 17211417b1cfde8f1749905f2d735623af9214148afJeff Brown * occurs by calling {@link #setDiscoveryRequest} which posts a message to invoke 17311417b1cfde8f1749905f2d735623af9214148afJeff Brown * this method asynchronously. 17411417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p><p> 17511417b1cfde8f1749905f2d735623af9214148afJeff Brown * The provider should examine the {@link MediaControlIntent media control categories} 17611417b1cfde8f1749905f2d735623af9214148afJeff Brown * in the discovery request's {@link MediaRouteSelector selector} to determine what 17711417b1cfde8f1749905f2d735623af9214148afJeff Brown * kinds of routes it should try to discover and whether it should perform active 17811417b1cfde8f1749905f2d735623af9214148afJeff Brown * or passive scans. In many cases, the provider may be able to save power by 17911417b1cfde8f1749905f2d735623af9214148afJeff Brown * determining that the selector does not contain any categories that it supports 18011417b1cfde8f1749905f2d735623af9214148afJeff Brown * and it can therefore avoid performing any scans at all. 18111417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p> 18211417b1cfde8f1749905f2d735623af9214148afJeff Brown * 18311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param request The new discovery request, or null if no discovery is needed at this time. 18411417b1cfde8f1749905f2d735623af9214148afJeff Brown * 18511417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouter#addCallback 18611417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 18711417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) { 18811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 18911417b1cfde8f1749905f2d735623af9214148afJeff Brown 19011417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 191fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Gets the provider's descriptor. 192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * The descriptor describes the state of the media route provider and 194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * the routes that it publishes. Watch for changes to the descriptor 19511417b1cfde8f1749905f2d735623af9214148afJeff Brown * by registering a {@link Callback callback} with {@link #setCallback}. 196fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 197c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 19811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media route provider descriptor, or null if none. 19911417b1cfde8f1749905f2d735623af9214148afJeff Brown * 20011417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see Callback#onDescriptorChanged 201c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 20211417b1cfde8f1749905f2d735623af9214148afJeff Brown public final MediaRouteProviderDescriptor getDescriptor() { 203c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown return mDescriptor; 204c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 205c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 206c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 207c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Sets the provider's descriptor. 208c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * <p> 20911417b1cfde8f1749905f2d735623af9214148afJeff Brown * The provider must call this method to notify the currently registered 21011417b1cfde8f1749905f2d735623af9214148afJeff Brown * {@link Callback callback} about the change to the provider's descriptor. 211c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p> 212c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @param descriptor The updated route provider descriptor, or null if none. 21411417b1cfde8f1749905f2d735623af9214148afJeff Brown * 21511417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see Callback#onDescriptorChanged 216c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 21711417b1cfde8f1749905f2d735623af9214148afJeff Brown public final void setDescriptor(MediaRouteProviderDescriptor descriptor) { 218c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown MediaRouter.checkCallingThread(); 219c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 220c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown if (mDescriptor != descriptor) { 221c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown mDescriptor = descriptor; 222c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown if (!mPendingDescriptorChange) { 223c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown mPendingDescriptorChange = true; 224c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown mHandler.sendEmptyMessage(MSG_DELIVER_DESCRIPTOR_CHANGED); 225c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 226c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 227c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 228c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 229c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private void deliverDescriptorChanged() { 230c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown mPendingDescriptorChange = false; 231c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 23211417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mCallback != null) { 23311417b1cfde8f1749905f2d735623af9214148afJeff Brown mCallback.onDescriptorChanged(this, mDescriptor); 234c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 235c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 236c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 237c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 238c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Called by the media router to obtain a route controller for a particular route. 239c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * <p> 2403b11cd2027d3249ec1d56939d3d3236cbd7ec91aJeff Brown * The media router will invoke the {@link RouteController#onRelease} method of the route 241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * controller when it is no longer needed to allow it to free its resources. 242c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p> 243c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 244c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @param routeId The unique id of the route. 245c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @return The route controller. Returns null if there is no such route or if the route 246c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * cannot be controlled using the route controller interface. 247c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 248c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public RouteController onCreateRouteController(String routeId) { 249c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown return null; 250c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 251c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 252c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 25311417b1cfde8f1749905f2d735623af9214148afJeff Brown * Describes properties of the route provider's implementation. 25428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown * <p> 25511417b1cfde8f1749905f2d735623af9214148afJeff Brown * This object is immutable once created. 25628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown * </p> 25728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown */ 25811417b1cfde8f1749905f2d735623af9214148afJeff Brown public static final class ProviderMetadata { 259fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final String mPackageName; 260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 26111417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 26211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Creates a provider metadata object. 26311417b1cfde8f1749905f2d735623af9214148afJeff Brown * 26411417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param packageName The provider application's package name. 26511417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ProviderMetadata(String packageName) { 267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (TextUtils.isEmpty(packageName)) { 268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown throw new IllegalArgumentException("packageName must not be null or empty"); 269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPackageName = packageName; 271fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 273c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 27411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the provider application's package name. 275c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 27611417b1cfde8f1749905f2d735623af9214148afJeff Brown public String getPackageName() { 27711417b1cfde8f1749905f2d735623af9214148afJeff Brown return mPackageName; 278c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 279c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 280c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown @Override 281c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public String toString() { 28211417b1cfde8f1749905f2d735623af9214148afJeff Brown return "ProviderMetadata{ packageName=" + mPackageName + " }"; 283c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 284c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 285c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 286c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 287c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Provides control over a particular route. 288c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * <p> 289c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * The media router obtains a route controller for a route whenever it needs 290c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * to control a route. When a route is selected, the media router invokes 2913b11cd2027d3249ec1d56939d3d3236cbd7ec91aJeff Brown * the {@link #onSelect} method of its route controller. While selected, 292c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * the media router may call other methods of the route controller to 293c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * request that it perform certain actions to the route. When a route is 2943b11cd2027d3249ec1d56939d3d3236cbd7ec91aJeff Brown * unselected, the media router invokes the {@link #onUnselect} method of its 295c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * route controller. When the media route no longer needs the route controller 2963b11cd2027d3249ec1d56939d3d3236cbd7ec91aJeff Brown * it will invoke the {@link #onRelease} method to allow the route controller 297c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * to free its resources. 298c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p><p> 299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * There may be multiple route controllers simultaneously active for the 300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * same route. Each route controller will be released separately. 301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 302c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * All operations on the route controller are asynchronous and 303c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * results are communicated via callbacks. 304c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * </p> 305c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 306c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public static abstract class RouteController { 307c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 308c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Releases the route controller, allowing it to free its resources. 309c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 310129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public void onRelease() { 311c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 312c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 313c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 314c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Selects the route. 315c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 316129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public void onSelect() { 317c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 318c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 319c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 320c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Unselects the route. 321c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 322129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public void onUnselect() { 323c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 324c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 325c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 326c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Requests to set the volume of the route. 327c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 32811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param volume The new volume value between 0 and {@link MediaRouteDescriptor#getVolumeMax}. 329c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 330129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public void onSetVolume(int volume) { 331c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 332c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 333c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 334c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Requests an incremental volume update for the route. 335c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 336c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @param delta The delta to add to the current volume. 337c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 338129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public void onUpdateVolume(int delta) { 339c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 340c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 341c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 342129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown * Performs a {@link MediaControlIntent media control} request 343129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown * asynchronously on behalf of the route. 344c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 345c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @param intent A {@link MediaControlIntent media control intent}. 346c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @param callback A {@link ControlRequestCallback} to invoke with the result 347c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * of the request, or null if no result is required. 348fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return True if the controller intends to handle the request and will 34911417b1cfde8f1749905f2d735623af9214148afJeff Brown * invoke the callback when finished. False if the controller will not 350fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * handle the request and will not invoke the callback. 351c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 352c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * @see MediaControlIntent 353c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 354129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { 355c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown return false; 356c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 357c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 358c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 359c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 360c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Callback which is invoked when route information becomes available or changes. 361c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 362c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public static abstract class Callback { 363c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown /** 364c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * Called when information about a route provider and its routes changes. 365c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown * 36611417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param provider The media route provider that changed, never null. 36711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param descriptor The new media route provider descriptor, or null if none. 368c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown */ 369c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public void onDescriptorChanged(MediaRouteProvider provider, 37011417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor) { 371c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 372c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 373c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown 374c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown private final class ProviderHandler extends Handler { 375c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown @Override 376c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown public void handleMessage(Message msg) { 377c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown switch (msg.what) { 378c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown case MSG_DELIVER_DESCRIPTOR_CHANGED: 379c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown deliverDescriptorChanged(); 380c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown break; 38111417b1cfde8f1749905f2d735623af9214148afJeff Brown case MSG_DELIVER_DISCOVERY_REQUEST_CHANGED: 38211417b1cfde8f1749905f2d735623af9214148afJeff Brown deliverDiscoveryRequestChanged(); 38311417b1cfde8f1749905f2d735623af9214148afJeff Brown break; 384c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 385c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 386c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown } 387c21f57ed68b81a77167f1df000b0e272e1598bc0Jeff Brown} 388