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; 219c83739aefcb1748551645a656bece0d864cef76Sungsoo Limimport android.os.Bundle; 229c83739aefcb1748551645a656bece0d864cef76Sungsoo Limimport android.os.DeadObjectException; 23fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.Handler; 24fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder; 25fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.os.IBinder.DeathRecipient; 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; 349c83739aefcb1748551645a656bece0d864cef76Sungsoo Limimport java.util.List; 35fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 363efa63d3b896244713e84acbb5945562dce41d77Jeff Brownimport static android.support.v7.media.MediaRouteProviderProtocol.*; 373efa63d3b896244713e84acbb5945562dce41d77Jeff Brown 38fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/** 39fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Base class for media route provider services. 40fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 41d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * A media router will bind to media route provider services when a callback is added via 42d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#addCallback(MediaRouteSelector, MediaRouter.Callback, int)} with a discovery 43d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * flag: {@link MediaRouter#CALLBACK_FLAG_REQUEST_DISCOVERY}, 44d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#CALLBACK_FLAG_FORCE_DISCOVERY}, or 45d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * {@link MediaRouter#CALLBACK_FLAG_PERFORM_ACTIVE_SCAN}, and will unbind when the callback 46d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * is removed via {@link MediaRouter#removeCallback(MediaRouter.Callback)}. 47d8e02077fc00aabc7432246e2301626fb342129dSungsoo Lim * </p><p> 48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * To implement your own media route provider service, extend this class and 49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * override the {@link #onCreateMediaRouteProvider} method to return an 50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * instance of your {@link MediaRouteProvider}. 51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Declare your media route provider service in your application manifest 53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * like this: 54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 55fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <pre> 56fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <service android:name=".MyMediaRouteProviderService" 57fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * android:label="@string/my_media_route_provider_service"> 58fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <intent-filter> 59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <action android:name="android.media.MediaRouteProviderService" /> 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </intent-filter> 61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </service> 62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </pre> 63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 64fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpublic abstract class MediaRouteProviderService extends Service { 65e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static final String TAG = "MediaRouteProviderSrv"; // max. 23 chars 66e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 67fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 68fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>(); 69fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ReceiveHandler mReceiveHandler; 70fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final Messenger mReceiveMessenger; 71e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas final PrivateHandler mPrivateHandler; 72fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ProviderCallback mProviderCallback; 73fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 74e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas MediaRouteProvider mProvider; 7511417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteDiscoveryRequest mCompositeDiscoveryRequest; 76fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * The {@link Intent} that must be declared as handled by the service. 79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Put this in your manifest. 80fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 813efa63d3b896244713e84acbb5945562dce41d77Jeff Brown public static final String SERVICE_INTERFACE = MediaRouteProviderProtocol.SERVICE_INTERFACE; 82fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 83fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 84fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Private messages used internally. (Yes, you can renumber these.) 85fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 87e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static final int PRIVATE_MSG_CLIENT_DIED = 1; 88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Creates a media route provider service. 91fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 92fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProviderService() { 93fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveHandler = new ReceiveHandler(this); 94fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveMessenger = new Messenger(mReceiveHandler); 95fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler = new PrivateHandler(); 96fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviderCallback = new ProviderCallback(); 97fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 98fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 99fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 100fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Called by the system when it is time to create the media route provider. 101fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 102fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 103fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * this service has decided not to offer a media route provider. 104fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 105fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public abstract MediaRouteProvider onCreateMediaRouteProvider(); 106fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 107fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 108fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Gets the media route provider offered by this service. 109fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 110fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 111fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * it has not yet been created. 112fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 113fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @see #onCreateMediaRouteProvider() 114fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 115fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider getMediaRouteProvider() { 116fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mProvider; 117fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 118fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 119fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 120fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public IBinder onBind(Intent intent) { 121fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (intent.getAction().equals(SERVICE_INTERFACE)) { 122fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider == null) { 123fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider provider = onCreateMediaRouteProvider(); 124fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (provider != null) { 125fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String providerPackage = provider.getMetadata().getPackageName(); 126fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!providerPackage.equals(getPackageName())) { 127fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown throw new IllegalStateException("onCreateMediaRouteProvider() returned " 128fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "a provider whose package name does not match the package " 129fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "name of the service. A media route provider service can " 130fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "only export its own media route providers. " 131fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "Provider package name: " + providerPackage 132fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ". Service package name: " + getPackageName() + "."); 133fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 134350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown mProvider = provider; 13511417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setCallback(mProviderCallback); 136fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 137fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 138fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider != null) { 139fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mReceiveMessenger.getBinder(); 140fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 141fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 142fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return null; 143fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 144fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 14542c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim @Override 14642c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim public boolean onUnbind(Intent intent) { 14742c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim if (mProvider != null) { 14842c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim mProvider.setCallback(null); 14942c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim } 15042c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim return super.onUnbind(intent); 15142c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim } 15242c2365e621434a241af1909593b9c5d592b8ad7Sungsoo Lim 153e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onRegisterClient(Messenger messenger, int requestId, int version) { 154fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (version >= CLIENT_VERSION_1) { 155fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 156fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index < 0) { 157fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = new ClientRecord(messenger, version); 158fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.register()) { 159fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mClients.add(client); 160fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 161fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Registered, version=" + version); 162fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 163fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 16411417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor = mProvider.getDescriptor(); 165fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_REGISTERED, 166fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown requestId, SERVICE_VERSION_CURRENT, 1679c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim createDescriptorBundleForClient(descriptor, client), null); 168fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 169fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 170fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 171fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 172fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 173fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 174fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 175fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 176e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onUnregisterClient(Messenger messenger, int requestId) { 177fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 178fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 179fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 180fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 181fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Unregistered"); 182fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 183fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 184fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 185fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 186fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 187fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 188fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 189fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 190e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas void onBinderDied(Messenger messenger) { 191fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 195fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Binder died"); 196fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 197fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 198fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 199fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 200fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 201e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onCreateRouteController(Messenger messenger, int requestId, 2022f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim int controllerId, String routeId, String routeGroupId) { 203fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 204fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 2052f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim if (client.createRouteController(routeId, routeGroupId, controllerId)) { 206fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 2072f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim Log.d(TAG, client + ": Route controller created, controllerId=" + controllerId 2082f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim + ", routeId=" + routeId + ", routeGroupId=" + routeGroupId); 209fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 210fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 211fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 212fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 214fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 215fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 216fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 217e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onReleaseRouteController(Messenger messenger, int requestId, 218fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 219fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 220fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 221fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.releaseRouteController(controllerId)) { 222fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 223fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller released" 224fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 225fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 226fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 227fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 228fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 229fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 230fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 231fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 232fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 233e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onSelectRoute(Messenger messenger, int requestId, 234fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 235fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 236fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 237fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 238fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 239fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 240129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSelect(); 241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 242fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route selected" 243fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 244fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 245fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 246fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 247fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 248fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 249fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 250fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 251fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 252e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onUnselectRoute(Messenger messenger, int requestId, 25394be6100218126ce6a08bf1f56209578500b361fRoboErik int controllerId, int reason) { 254fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 255fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 256fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 257fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 258fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 25994be6100218126ce6a08bf1f56209578500b361fRoboErik controller.onUnselect(reason); 260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 261fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route unselected" 262fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 263fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 264fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 265fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 271e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onSetRouteVolume(Messenger messenger, int requestId, 272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int volume) { 273fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 274fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 275fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 276fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 277fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 278129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSetVolume(volume); 279fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 280fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume changed" 281fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", volume=" + volume); 282fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 283fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 284fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 285fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 286fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 287fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 288fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 289fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 290e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onUpdateRouteVolume(Messenger messenger, int requestId, 291fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int delta) { 292fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 293fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 294fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 295fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 296fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 297129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onUpdateVolume(delta); 298fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume updated" 300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", delta=" + delta); 301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 302fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 303fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 304fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 305fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 306fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 307fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 308fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 309e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onRouteControlRequest(final Messenger messenger, final int requestId, 310fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int controllerId, final Intent intent) { 311fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final ClientRecord client = getClient(messenger); 312fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 313fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 314fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 315fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 316fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouter.ControlRequestCallback callback = null; 317fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 318fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown callback = new MediaRouter.ControlRequestCallback() { 319fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 3203d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onResult(Bundle data) { 3213d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (DEBUG) { 3223d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request succeeded" 3233d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", controllerId=" + controllerId 3243d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", intent=" + intent 3253d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", data=" + data); 3263d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3273d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (findClient(messenger) >= 0) { 3283d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED, 3293d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3303d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3313d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3323d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 3333d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown @Override 3343d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onError(String error, Bundle data) { 335fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 3363d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request failed" 337fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId 338fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", intent=" + intent 3393d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", error=" + error + ", data=" + data); 340fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 341fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (findClient(messenger) >= 0) { 3423d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (error != null) { 3433d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Bundle bundle = new Bundle(); 3443d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown bundle.putString(SERVICE_DATA_ERROR, error); 3453d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3463d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, bundle); 3473d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } else { 3483d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3493d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3503d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 351fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 352fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 353fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown }; 354fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 355129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown if (controller.onControlRequest(intent, callback)) { 356fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 357fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route control request delivered" 358fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", intent=" + intent); 359fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 360fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 361fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 362fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 363fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 364fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 365fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 366fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 367e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean onSetDiscoveryRequest(Messenger messenger, int requestId, 36811417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request) { 36928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown ClientRecord client = getClient(messenger); 37028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (client != null) { 37111417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean actuallyChanged = client.setDiscoveryRequest(request); 37228520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (DEBUG) { 37311417b1cfde8f1749905f2d735623af9214148afJeff Brown Log.d(TAG, client + ": Set discovery request, request=" + request 37411417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", actuallyChanged=" + actuallyChanged 37511417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", compositeDiscoveryRequest=" + mCompositeDiscoveryRequest); 37628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 37728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown sendGenericSuccess(messenger, requestId); 37828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return true; 37928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 38028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 38128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 38228520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 383e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas void sendDescriptorChanged(MediaRouteProviderDescriptor descriptor) { 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, 3889c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim createDescriptorBundleForClient(descriptor, client), 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 3959c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim private Bundle createDescriptorBundleForClient(MediaRouteProviderDescriptor descriptor, 3969c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim ClientRecord client) { 3979c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim if (descriptor == null) { 3989c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim return null; 3999c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim } 4009c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim List<MediaRouteDescriptor> routes = descriptor.getRoutes(); 4019c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim for (int i = routes.size() - 1; i >= 0; i--) { 4029c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim if (client.mVersion < routes.get(i).getMinClientVersion() 4039c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim || client.mVersion > routes.get(i).getMaxClientVersion()) { 4049c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim routes.remove(i); 4059c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim } 4069c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim } 4079c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim 4089c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim // Keep the values of the bundle from descriptor excepts routes values. 4099c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim Bundle bundle = descriptor.asBundle(); 4109c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim bundle.remove(MediaRouteProviderDescriptor.KEY_ROUTES); 4119c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim return new MediaRouteProviderDescriptor.Builder( 4129c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim MediaRouteProviderDescriptor.fromBundle(bundle)) 4139c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim .addRoutes(routes).build().asBundle(); 4149c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim } 4159c83739aefcb1748551645a656bece0d864cef76Sungsoo Lim 416e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas boolean updateCompositeDiscoveryRequest() { 41711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest composite = null; 41811417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteSelector.Builder selectorBuilder = null; 41911417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean activeScan = false; 42011417b1cfde8f1749905f2d735623af9214148afJeff Brown final int count = mClients.size(); 42111417b1cfde8f1749905f2d735623af9214148afJeff Brown for (int i = 0; i < count; i++) { 42211417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = mClients.get(i).mDiscoveryRequest; 42311417b1cfde8f1749905f2d735623af9214148afJeff Brown if (request != null 42411417b1cfde8f1749905f2d735623af9214148afJeff Brown && (!request.getSelector().isEmpty() || request.isActiveScan())) { 42511417b1cfde8f1749905f2d735623af9214148afJeff Brown activeScan |= request.isActiveScan(); 42611417b1cfde8f1749905f2d735623af9214148afJeff Brown if (composite == null) { 42711417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = request; 42811417b1cfde8f1749905f2d735623af9214148afJeff Brown } else { 42911417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder == null) { 43011417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder = new MediaRouteSelector.Builder(composite.getSelector()); 43111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43211417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder.addSelector(request.getSelector()); 43311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43611417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder != null) { 43711417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = new MediaRouteDiscoveryRequest(selectorBuilder.build(), activeScan); 43811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43911417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mCompositeDiscoveryRequest != composite 44011417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mCompositeDiscoveryRequest == null 44111417b1cfde8f1749905f2d735623af9214148afJeff Brown || !mCompositeDiscoveryRequest.equals(composite))) { 44211417b1cfde8f1749905f2d735623af9214148afJeff Brown mCompositeDiscoveryRequest = composite; 44311417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setDiscoveryRequest(composite); 44411417b1cfde8f1749905f2d735623af9214148afJeff Brown return true; 44511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44611417b1cfde8f1749905f2d735623af9214148afJeff Brown return false; 44711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44811417b1cfde8f1749905f2d735623af9214148afJeff Brown 449fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private ClientRecord getClient(Messenger messenger) { 450fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 451fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return index >= 0 ? mClients.get(index) : null; 452fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 453fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 454e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas int findClient(Messenger messenger) { 455fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 456fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 457fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 458fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.hasMessenger(messenger)) { 459fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return i; 460fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 461fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 462fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return -1; 463fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 464fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 465e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static void sendGenericFailure(Messenger messenger, int requestId) { 466fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 467fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null); 468fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 469fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 470fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 471fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericSuccess(Messenger messenger, int requestId) { 472fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 473fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null); 474fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 475fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 476fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 477e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static void sendReply(Messenger messenger, int what, 478fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int requestId, int arg, Object obj, Bundle data) { 479fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Message msg = Message.obtain(); 480fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.what = what; 481fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg1 = requestId; 482fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg2 = arg; 483fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.obj = obj; 484fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.setData(data); 485fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 486fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger.send(msg); 487fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (DeadObjectException ex) { 488fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // The client died. 489fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 490fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.e(TAG, "Could not send message to " + getClientId(messenger), ex); 491fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 492fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 493fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 494e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas static String getClientId(Messenger messenger) { 495fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return "Client connection " + messenger.getBinder().toString(); 496fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 497fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 498fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class PrivateHandler extends Handler { 499e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas PrivateHandler() { 500e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas } 501e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas 502fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 503fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 504fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (msg.what) { 505fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case PRIVATE_MSG_CLIENT_DIED: 506fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown onBinderDied((Messenger)msg.obj); 507fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 508fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 509fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 510fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 511fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 512fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ProviderCallback extends MediaRouteProvider.Callback { 513e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas ProviderCallback() { 514e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas } 515e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas 516fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 517fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void onDescriptorChanged(MediaRouteProvider provider, 51811417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor) { 519fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendDescriptorChanged(descriptor); 520fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 521fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 522fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 523fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ClientRecord implements DeathRecipient { 524fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final Messenger mMessenger; 525fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final int mVersion; 52611417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteDiscoveryRequest mDiscoveryRequest; 527fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 528fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final SparseArray<MediaRouteProvider.RouteController> mControllers = 529fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new SparseArray<MediaRouteProvider.RouteController>(); 530fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 531fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ClientRecord(Messenger messenger, int version) { 532fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger = messenger; 533fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mVersion = version; 534fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 535fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 536fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean register() { 537fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 538fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().linkToDeath(this, 0); 539fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 540fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 541fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown binderDied(); 542fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 543fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 544fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 545fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 546fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void dispose() { 547fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int count = mControllers.size(); 548fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 549129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown mControllers.valueAt(i).onRelease(); 550fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 551fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.clear(); 552fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 553fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().unlinkToDeath(this, 0); 55428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 55511417b1cfde8f1749905f2d735623af9214148afJeff Brown setDiscoveryRequest(null); 556fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 557fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 558fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean hasMessenger(Messenger other) { 559fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mMessenger.getBinder() == other.getBinder(); 560fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 561fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 5622f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim public boolean createRouteController(String routeId, String routeGroupId, 5632f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim int controllerId) { 564fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mControllers.indexOfKey(controllerId) < 0) { 5652f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim MediaRouteProvider.RouteController controller = routeGroupId == null 5662f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim ? mProvider.onCreateRouteController(routeId) 5672f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim : mProvider.onCreateRouteController(routeId, routeGroupId); 568ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown if (controller != null) { 569ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown mControllers.put(controllerId, controller); 570ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown return true; 571ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown } 572fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 573fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 574fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 575fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 576fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean releaseRouteController(int controllerId) { 577fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = mControllers.get(controllerId); 578fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 579fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.remove(controllerId); 580129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onRelease(); 581fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 582fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 583fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 584fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 585fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 586fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider.RouteController getRouteController(int controllerId) { 587fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mControllers.get(controllerId); 588fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 589fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 59011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean setDiscoveryRequest(MediaRouteDiscoveryRequest request) { 59111417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mDiscoveryRequest != request 59211417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mDiscoveryRequest == null || !mDiscoveryRequest.equals(request))) { 59311417b1cfde8f1749905f2d735623af9214148afJeff Brown mDiscoveryRequest = request; 59411417b1cfde8f1749905f2d735623af9214148afJeff Brown return updateCompositeDiscoveryRequest(); 59528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 59628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 59728520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 59828520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 59928520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown // Runs on a binder thread. 600fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 601fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void binderDied() { 602fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget(); 603fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 604fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 605fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 606fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public String toString() { 607fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return getClientId(mMessenger); 608fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 609fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 610fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 611fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 612fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Handler that receives messages from clients. 613fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 614fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This inner class is static and only retains a weak reference to the service 615fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * to prevent the service from being leaked in case one of the clients is holding an 616fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * active reference to the server's messenger. 617fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 618fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This handler should not be used to handle any messages other than those 619fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * that come from the client. 620fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 621fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 622fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final class ReceiveHandler extends Handler { 623fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final WeakReference<MediaRouteProviderService> mServiceRef; 624fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 625fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ReceiveHandler(MediaRouteProviderService service) { 626fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mServiceRef = new WeakReference<MediaRouteProviderService>(service); 627fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 628fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 629fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 630fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 631fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Messenger messenger = msg.replyTo; 632fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (isValidRemoteMessenger(messenger)) { 633fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int what = msg.what; 634fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int requestId = msg.arg1; 635fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int arg = msg.arg2; 636fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Object obj = msg.obj; 637fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Bundle data = msg.peekData(); 638fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!processMessage(what, messenger, requestId, arg, obj, data)) { 639fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 640fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what 641fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", requestId=" + requestId + ", arg=" + arg 642fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", obj=" + obj + ", data=" + data); 643fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 644fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericFailure(messenger, requestId); 645fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 646fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else { 647fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 648fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, "Ignoring message without valid reply messenger."); 649fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 650fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 651fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 652fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 653fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean processMessage(int what, 654fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Messenger messenger, int requestId, int arg, Object obj, Bundle data) { 655fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProviderService service = mServiceRef.get(); 656fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (service != null) { 657fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (what) { 658fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_REGISTER: 659fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRegisterClient(messenger, requestId, arg); 660fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 661fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNREGISTER: 662fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUnregisterClient(messenger, requestId); 663fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 664fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: { 665fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String routeId = data.getString(CLIENT_DATA_ROUTE_ID); 6662f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim String routeGroupId = data.getString(CLIENT_DATA_ROUTE_GROUP_ID); 667fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (routeId != null) { 668fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onCreateRouteController( 6692f829125aef3796ca674d0ca5fccf9bd37b8417bSungsoo Lim messenger, requestId, arg, routeId, routeGroupId); 670fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 671fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 672fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 673fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 674fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER: 675fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onReleaseRouteController(messenger, requestId, arg); 676fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 677fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SELECT_ROUTE: 678fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSelectRoute(messenger, requestId, arg); 679fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 680fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNSELECT_ROUTE: 68194be6100218126ce6a08bf1f56209578500b361fRoboErik int reason = data == null ? 68294be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN 68394be6100218126ce6a08bf1f56209578500b361fRoboErik : data.getInt(CLIENT_DATA_UNSELECT_REASON, 68494be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN); 68594be6100218126ce6a08bf1f56209578500b361fRoboErik return service.onUnselectRoute(messenger, requestId, arg, reason); 686fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 687fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SET_ROUTE_VOLUME: { 688fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int volume = data.getInt(CLIENT_DATA_VOLUME, -1); 689fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (volume >= 0) { 690fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSetRouteVolume( 691fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, volume); 692fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 693fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 694fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 695fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 696fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UPDATE_ROUTE_VOLUME: { 697fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int delta = data.getInt(CLIENT_DATA_VOLUME, 0); 698fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (delta != 0) { 699fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUpdateRouteVolume( 700fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, delta); 701fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 702fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 703fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 704fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 705fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_ROUTE_CONTROL_REQUEST: 706fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (obj instanceof Intent) { 707fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRouteControlRequest( 708fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, (Intent)obj); 709fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 710fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 71128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 71211417b1cfde8f1749905f2d735623af9214148afJeff Brown case CLIENT_MSG_SET_DISCOVERY_REQUEST: { 713f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown if (obj == null || obj instanceof Bundle) { 71411417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = 71511417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest.fromBundle((Bundle)obj); 71611417b1cfde8f1749905f2d735623af9214148afJeff Brown return service.onSetDiscoveryRequest( 717f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown messenger, requestId, 718f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown request != null && request.isValid() ? request : null); 71911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 72011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 721fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 722fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 723fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 724fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 725fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 726fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown} 727