1fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/* 2fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Copyright (C) 2013 The Android Open Source Project 3fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 4fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * you may not use this file except in compliance with the License. 6fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * You may obtain a copy of the License at 7fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 8fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 10fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Unless required by applicable law or agreed to in writing, software 11fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * See the License for the specific language governing permissions and 14fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * limitations under the License. 15fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 16fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 17b507e525a61ed761eecfc2eaaf19af7e8db5dca5Jeff Brownpackage android.support.v7.media; 18fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 19fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.app.Service; 20fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.Intent; 21fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Handler; 22fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder; 23fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder.DeathRecipient; 24fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Bundle; 25fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.DeadObjectException; 26fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Message; 27fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Messenger; 28fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.RemoteException; 29fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.Log; 30fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.util.SparseArray; 31fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 32fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.lang.ref.WeakReference; 33fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.util.ArrayList; 34fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 353efa63d3b896244713e84acbb5945562dce41d77Jeff Brownimport static android.support.v7.media.MediaRouteProviderProtocol.*; 363efa63d3b896244713e84acbb5945562dce41d77Jeff Brown 37fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/** 38fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Base class for media route provider services. 39fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 40d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * A media router will bind to media route provider services when a callback is added via 41d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#addCallback(MediaRouteSelector, MediaRouter.Callback, int)} with a discovery 42d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * flag: {@link MediaRouter#CALLBACK_FLAG_REQUEST_DISCOVERY}, 43d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#CALLBACK_FLAG_FORCE_DISCOVERY}, or 44d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#CALLBACK_FLAG_PERFORM_ACTIVE_SCAN}, and will unbind when the callback 45d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * is removed via {@link MediaRouter#removeCallback(MediaRouter.Callback)}. 46d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * </p><p> 47fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * To implement your own media route provider service, extend this class and 48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * override the {@link #onCreateMediaRouteProvider} method to return an 49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * instance of your {@link MediaRouteProvider}. 50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Declare your media route provider service in your application manifest 52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * like this: 53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <pre> 55fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <service android:name=".MyMediaRouteProviderService" 56fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * android:label="@string/my_media_route_provider_service"> 57fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <intent-filter> 58fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <action android:name="android.media.MediaRouteProviderService" /> 59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </intent-filter> 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </service> 61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </pre> 62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpublic abstract class MediaRouteProviderService extends Service { 64f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final String TAG = "MediaRouteProviderSrv"; // max. 23 chars 65f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 66fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 67fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>(); 68fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ReceiveHandler mReceiveHandler; 69fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final Messenger mReceiveMessenger; 70fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final PrivateHandler mPrivateHandler; 71fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ProviderCallback mProviderCallback; 72fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 73fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private MediaRouteProvider mProvider; 7411417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteDiscoveryRequest mCompositeDiscoveryRequest; 75fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 76fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * The {@link Intent} that must be declared as handled by the service. 78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Put this in your manifest. 79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 803efa63d3b896244713e84acbb5945562dce41d77Jeff Brown public static final String SERVICE_INTERFACE = MediaRouteProviderProtocol.SERVICE_INTERFACE; 81fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 82fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 83fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Private messages used internally. (Yes, you can renumber these.) 84fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 85fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final int PRIVATE_MSG_CLIENT_DIED = 1; 87fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Creates a media route provider service. 90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 91fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProviderService() { 92fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveHandler = new ReceiveHandler(this); 93fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveMessenger = new Messenger(mReceiveHandler); 94fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler = new PrivateHandler(); 95fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviderCallback = new ProviderCallback(); 96fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 97fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 98fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 99fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Called by the system when it is time to create the media route provider. 100fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 101fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 102fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * this service has decided not to offer a media route provider. 103fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 104fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public abstract MediaRouteProvider onCreateMediaRouteProvider(); 105fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 106fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 107fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Gets the media route provider offered by this service. 108fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 109fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 110fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * it has not yet been created. 111fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 112fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @see #onCreateMediaRouteProvider() 113fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 114fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider getMediaRouteProvider() { 115fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mProvider; 116fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 117fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 118fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 119fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public IBinder onBind(Intent intent) { 120fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (intent.getAction().equals(SERVICE_INTERFACE)) { 121fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider == null) { 122fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider provider = onCreateMediaRouteProvider(); 123fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (provider != null) { 124fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String providerPackage = provider.getMetadata().getPackageName(); 125fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!providerPackage.equals(getPackageName())) { 126fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown throw new IllegalStateException("onCreateMediaRouteProvider() returned " 127fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "a provider whose package name does not match the package " 128fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "name of the service. A media route provider service can " 129fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "only export its own media route providers. " 130fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "Provider package name: " + providerPackage 131fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ". Service package name: " + getPackageName() + "."); 132fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 133350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown mProvider = provider; 13411417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setCallback(mProviderCallback); 135fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 136fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 137fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider != null) { 138fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mReceiveMessenger.getBinder(); 139fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 140fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 141fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return null; 142fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 143fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 14442c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim @Override 14542c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim public boolean onUnbind(Intent intent) { 14642c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim if (mProvider != null) { 14742c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim mProvider.setCallback(null); 14842c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim } 14942c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim return super.onUnbind(intent); 15042c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim } 15142c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim 152fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRegisterClient(Messenger messenger, int requestId, int version) { 153fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (version >= CLIENT_VERSION_1) { 154fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 155fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index < 0) { 156fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = new ClientRecord(messenger, version); 157fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.register()) { 158fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mClients.add(client); 159fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 160fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Registered, version=" + version); 161fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 162fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 16311417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor = mProvider.getDescriptor(); 164fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_REGISTERED, 165fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown requestId, SERVICE_VERSION_CURRENT, 166fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptor != null ? descriptor.asBundle() : null, null); 167fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 168fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 169fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 170fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 171fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 172fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 173fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 174fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 175fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnregisterClient(Messenger messenger, int requestId) { 176fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 177fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 178fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 179fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 180fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Unregistered"); 181fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 182fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 183fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 184fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 185fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 186fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 187fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 188fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 189fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private void onBinderDied(Messenger messenger) { 190fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 191fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Binder died"); 195fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 196fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 197fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 198fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 199fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 200fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onCreateRouteController(Messenger messenger, int requestId, 201fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, String routeId) { 202fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 203fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 204fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.createRouteController(routeId, controllerId)) { 205fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 206fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller created" 207fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", routeId=" + routeId); 208fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 209fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 210fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 211fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 212fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 214fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 215fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 216fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onReleaseRouteController(Messenger messenger, int requestId, 217fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 218fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 219fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 220fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.releaseRouteController(controllerId)) { 221fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 222fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller released" 223fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 224fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 225fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 226fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 227fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 228fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 229fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 230fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 231fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 232fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSelectRoute(Messenger messenger, int requestId, 233fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 234fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 235fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 236fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 237fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 238fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 239129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSelect(); 240fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route selected" 242fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 243fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 244fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 245fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 246fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 247fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 248fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 249fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 250fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 251fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnselectRoute(Messenger messenger, int requestId, 25294be6100218126ce6a08bf1f56209578500b361fRoboErik int controllerId, int reason) { 253fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 254fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 255fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 256fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 257fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 25894be6100218126ce6a08bf1f56209578500b361fRoboErik controller.onUnselect(reason); 259fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route unselected" 261fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 262fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 263fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 264fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 265fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSetRouteVolume(Messenger messenger, int requestId, 271fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int volume) { 272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 273fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 274fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 275fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 276fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 277129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSetVolume(volume); 278fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 279fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume changed" 280fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", volume=" + volume); 281fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 282fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 283fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 284fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 285fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 286fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 287fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 288fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 289fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUpdateRouteVolume(Messenger messenger, int requestId, 290fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int delta) { 291fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 292fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 293fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 294fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 295fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 296129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onUpdateVolume(delta); 297fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 298fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume updated" 299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", delta=" + delta); 300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 302fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 303fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 304fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 305fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 306fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 307fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 308fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRouteControlRequest(final Messenger messenger, final int requestId, 309fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int controllerId, final Intent intent) { 310fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final ClientRecord client = getClient(messenger); 311fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 312fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 313fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 314fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 315fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouter.ControlRequestCallback callback = null; 316fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 317fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown callback = new MediaRouter.ControlRequestCallback() { 318fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 3193d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onResult(Bundle data) { 3203d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (DEBUG) { 3213d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request succeeded" 3223d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", controllerId=" + controllerId 3233d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", intent=" + intent 3243d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", data=" + data); 3253d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3263d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (findClient(messenger) >= 0) { 3273d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED, 3283d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3293d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3303d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3313d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 3323d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown @Override 3333d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onError(String error, Bundle data) { 334fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 3353d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request failed" 336fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId 337fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", intent=" + intent 3383d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", error=" + error + ", data=" + data); 339fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 340fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (findClient(messenger) >= 0) { 3413d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (error != null) { 3423d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Bundle bundle = new Bundle(); 3433d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown bundle.putString(SERVICE_DATA_ERROR, error); 3443d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3453d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, bundle); 3463d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } else { 3473d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3483d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3493d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 350fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 351fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 352fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown }; 353fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 354129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown if (controller.onControlRequest(intent, callback)) { 355fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 356fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route control request delivered" 357fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", intent=" + intent); 358fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 359fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 360fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 361fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 362fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 363fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 364fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 365fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 36611417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean onSetDiscoveryRequest(Messenger messenger, int requestId, 36711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request) { 36828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown ClientRecord client = getClient(messenger); 36928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (client != null) { 37011417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean actuallyChanged = client.setDiscoveryRequest(request); 37128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (DEBUG) { 37211417b1cfde8f1749905f2d735623af9214148afJeff Brown Log.d(TAG, client + ": Set discovery request, request=" + request 37311417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", actuallyChanged=" + actuallyChanged 37411417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", compositeDiscoveryRequest=" + mCompositeDiscoveryRequest); 37528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 37628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown sendGenericSuccess(messenger, requestId); 37728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return true; 37828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 37928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 38028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 38128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 38211417b1cfde8f1749905f2d735623af9214148afJeff Brown private void sendDescriptorChanged(MediaRouteProviderDescriptor descriptor) { 383fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Bundle descriptorBundle = descriptor != null ? descriptor.asBundle() : null; 384fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 385fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 386fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 387fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(client.mMessenger, SERVICE_MSG_DESCRIPTOR_CHANGED, 0, 0, 388fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptorBundle, null); 389fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 390fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Sent descriptor change event, descriptor=" + descriptor); 391fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 392fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 393fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 394fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 39511417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean updateCompositeDiscoveryRequest() { 39611417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest composite = null; 39711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteSelector.Builder selectorBuilder = null; 39811417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean activeScan = false; 39911417b1cfde8f1749905f2d735623af9214148afJeff Brown final int count = mClients.size(); 40011417b1cfde8f1749905f2d735623af9214148afJeff Brown for (int i = 0; i < count; i++) { 40111417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = mClients.get(i).mDiscoveryRequest; 40211417b1cfde8f1749905f2d735623af9214148afJeff Brown if (request != null 40311417b1cfde8f1749905f2d735623af9214148afJeff Brown && (!request.getSelector().isEmpty() || request.isActiveScan())) { 40411417b1cfde8f1749905f2d735623af9214148afJeff Brown activeScan |= request.isActiveScan(); 40511417b1cfde8f1749905f2d735623af9214148afJeff Brown if (composite == null) { 40611417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = request; 40711417b1cfde8f1749905f2d735623af9214148afJeff Brown } else { 40811417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder == null) { 40911417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder = new MediaRouteSelector.Builder(composite.getSelector()); 41011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41111417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder.addSelector(request.getSelector()); 41211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41511417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder != null) { 41611417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = new MediaRouteDiscoveryRequest(selectorBuilder.build(), activeScan); 41711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41811417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mCompositeDiscoveryRequest != composite 41911417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mCompositeDiscoveryRequest == null 42011417b1cfde8f1749905f2d735623af9214148afJeff Brown || !mCompositeDiscoveryRequest.equals(composite))) { 42111417b1cfde8f1749905f2d735623af9214148afJeff Brown mCompositeDiscoveryRequest = composite; 42211417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setDiscoveryRequest(composite); 42311417b1cfde8f1749905f2d735623af9214148afJeff Brown return true; 42411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 42511417b1cfde8f1749905f2d735623af9214148afJeff Brown return false; 42611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 42711417b1cfde8f1749905f2d735623af9214148afJeff Brown 428fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private ClientRecord getClient(Messenger messenger) { 429fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 430fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return index >= 0 ? mClients.get(index) : null; 431fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 432fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 433fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private int findClient(Messenger messenger) { 434fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 435fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 436fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 437fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.hasMessenger(messenger)) { 438fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return i; 439fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 440fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 441fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return -1; 442fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 443fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 444fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericFailure(Messenger messenger, int requestId) { 445fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 446fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null); 447fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 448fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 449fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 450fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericSuccess(Messenger messenger, int requestId) { 451fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 452fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null); 453fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 454fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 455fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 456fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendReply(Messenger messenger, int what, 457fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int requestId, int arg, Object obj, Bundle data) { 458fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Message msg = Message.obtain(); 459fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.what = what; 460fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg1 = requestId; 461fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg2 = arg; 462fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.obj = obj; 463fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.setData(data); 464fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 465fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger.send(msg); 466fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (DeadObjectException ex) { 467fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // The client died. 468fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 469fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.e(TAG, "Could not send message to " + getClientId(messenger), ex); 470fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 471fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 472fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 473fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static String getClientId(Messenger messenger) { 474fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return "Client connection " + messenger.getBinder().toString(); 475fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 476fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 477fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class PrivateHandler extends Handler { 478fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 479fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 480fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (msg.what) { 481fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case PRIVATE_MSG_CLIENT_DIED: 482fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown onBinderDied((Messenger)msg.obj); 483fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 484fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 485fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 486fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 487fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 488fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ProviderCallback extends MediaRouteProvider.Callback { 489fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 490fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void onDescriptorChanged(MediaRouteProvider provider, 49111417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor) { 492fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendDescriptorChanged(descriptor); 493fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 494fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 495fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 496fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ClientRecord implements DeathRecipient { 497fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final Messenger mMessenger; 498fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final int mVersion; 49911417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteDiscoveryRequest mDiscoveryRequest; 500fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 501fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final SparseArray<MediaRouteProvider.RouteController> mControllers = 502fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new SparseArray<MediaRouteProvider.RouteController>(); 503fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 504fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ClientRecord(Messenger messenger, int version) { 505fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger = messenger; 506fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mVersion = version; 507fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 508fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 509fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean register() { 510fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 511fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().linkToDeath(this, 0); 512fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 513fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 514fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown binderDied(); 515fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 516fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 517fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 518fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 519fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void dispose() { 520fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int count = mControllers.size(); 521fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 522129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown mControllers.valueAt(i).onRelease(); 523fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 524fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.clear(); 525fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 526fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().unlinkToDeath(this, 0); 52728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 52811417b1cfde8f1749905f2d735623af9214148afJeff Brown setDiscoveryRequest(null); 529fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 530fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 531fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean hasMessenger(Messenger other) { 532fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mMessenger.getBinder() == other.getBinder(); 533fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 534fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 535fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean createRouteController(String routeId, int controllerId) { 536fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mControllers.indexOfKey(controllerId) < 0) { 537fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 538fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProvider.onCreateRouteController(routeId); 539ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown if (controller != null) { 540ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown mControllers.put(controllerId, controller); 541ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown return true; 542ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown } 543fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 544fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 545fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 546fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 547fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean releaseRouteController(int controllerId) { 548fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = mControllers.get(controllerId); 549fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 550fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.remove(controllerId); 551129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onRelease(); 552fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 553fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 554fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 555fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 556fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 557fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider.RouteController getRouteController(int controllerId) { 558fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mControllers.get(controllerId); 559fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 560fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 56111417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean setDiscoveryRequest(MediaRouteDiscoveryRequest request) { 56211417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mDiscoveryRequest != request 56311417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mDiscoveryRequest == null || !mDiscoveryRequest.equals(request))) { 56411417b1cfde8f1749905f2d735623af9214148afJeff Brown mDiscoveryRequest = request; 56511417b1cfde8f1749905f2d735623af9214148afJeff Brown return updateCompositeDiscoveryRequest(); 56628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 56728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 56828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 56928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 57028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown // Runs on a binder thread. 571fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 572fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void binderDied() { 573fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget(); 574fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 575fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 576fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 577fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public String toString() { 578fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return getClientId(mMessenger); 579fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 580fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 581fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 582fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 583fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Handler that receives messages from clients. 584fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 585fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This inner class is static and only retains a weak reference to the service 586fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * to prevent the service from being leaked in case one of the clients is holding an 587fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * active reference to the server's messenger. 588fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 589fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This handler should not be used to handle any messages other than those 590fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * that come from the client. 591fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 592fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 593fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final class ReceiveHandler extends Handler { 594fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final WeakReference<MediaRouteProviderService> mServiceRef; 595fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 596fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ReceiveHandler(MediaRouteProviderService service) { 597fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mServiceRef = new WeakReference<MediaRouteProviderService>(service); 598fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 599fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 600fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 601fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 602fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Messenger messenger = msg.replyTo; 603fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (isValidRemoteMessenger(messenger)) { 604fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int what = msg.what; 605fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int requestId = msg.arg1; 606fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int arg = msg.arg2; 607fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Object obj = msg.obj; 608fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Bundle data = msg.peekData(); 609fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!processMessage(what, messenger, requestId, arg, obj, data)) { 610fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 611fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what 612fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", requestId=" + requestId + ", arg=" + arg 613fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", obj=" + obj + ", data=" + data); 614fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 615fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericFailure(messenger, requestId); 616fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 617fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else { 618fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 619fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, "Ignoring message without valid reply messenger."); 620fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 621fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 622fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 623fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 624fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean processMessage(int what, 625fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Messenger messenger, int requestId, int arg, Object obj, Bundle data) { 626fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProviderService service = mServiceRef.get(); 627fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (service != null) { 628fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (what) { 629fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_REGISTER: 630fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRegisterClient(messenger, requestId, arg); 631fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 632fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNREGISTER: 633fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUnregisterClient(messenger, requestId); 634fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 635fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: { 636fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String routeId = data.getString(CLIENT_DATA_ROUTE_ID); 637fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (routeId != null) { 638fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onCreateRouteController( 639fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, routeId); 640fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 641fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 642fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 643fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 644fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER: 645fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onReleaseRouteController(messenger, requestId, arg); 646fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 647fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SELECT_ROUTE: 648fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSelectRoute(messenger, requestId, arg); 649fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 650fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNSELECT_ROUTE: 65194be6100218126ce6a08bf1f56209578500b361fRoboErik int reason = data == null ? 65294be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN 65394be6100218126ce6a08bf1f56209578500b361fRoboErik : data.getInt(CLIENT_DATA_UNSELECT_REASON, 65494be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN); 65594be6100218126ce6a08bf1f56209578500b361fRoboErik return service.onUnselectRoute(messenger, requestId, arg, reason); 656fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 657fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SET_ROUTE_VOLUME: { 658fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int volume = data.getInt(CLIENT_DATA_VOLUME, -1); 659fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (volume >= 0) { 660fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSetRouteVolume( 661fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, volume); 662fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 663fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 664fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 665fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 666fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UPDATE_ROUTE_VOLUME: { 667fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int delta = data.getInt(CLIENT_DATA_VOLUME, 0); 668fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (delta != 0) { 669fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUpdateRouteVolume( 670fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, delta); 671fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 672fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 673fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 674fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 675fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_ROUTE_CONTROL_REQUEST: 676fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (obj instanceof Intent) { 677fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRouteControlRequest( 678fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, (Intent)obj); 679fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 680fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 68128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 68211417b1cfde8f1749905f2d735623af9214148afJeff Brown case CLIENT_MSG_SET_DISCOVERY_REQUEST: { 683f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown if (obj == null || obj instanceof Bundle) { 68411417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = 68511417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest.fromBundle((Bundle)obj); 68611417b1cfde8f1749905f2d735623af9214148afJeff Brown return service.onSetDiscoveryRequest( 687f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown messenger, requestId, 688f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown request != null && request.isValid() ? request : null); 68911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 69011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 691fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 692fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 693fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 694fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 695fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 696fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown} 697