MediaRouteProviderService.java revision 94be6100218126ce6a08bf1f56209578500b361f
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> 40fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * To implement your own media route provider service, extend this class and 41fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * override the {@link #onCreateMediaRouteProvider} method to return an 42fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * instance of your {@link MediaRouteProvider}. 43fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 44fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Declare your media route provider service in your application manifest 45fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * like this: 46fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 47fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <pre> 48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <service android:name=".MyMediaRouteProviderService" 49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * android:label="@string/my_media_route_provider_service"> 50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <intent-filter> 51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <action android:name="android.media.MediaRouteProviderService" /> 52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </intent-filter> 53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </service> 54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </pre> 55fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 56fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpublic abstract class MediaRouteProviderService extends Service { 57f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final String TAG = "MediaRouteProviderSrv"; // max. 23 chars 58f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>(); 61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ReceiveHandler mReceiveHandler; 62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final Messenger mReceiveMessenger; 63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final PrivateHandler mPrivateHandler; 64fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ProviderCallback mProviderCallback; 65fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 66fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private MediaRouteProvider mProvider; 6711417b1cfde8f1749905f2d735623af9214148afJeff Brown private MediaRouteDiscoveryRequest mCompositeDiscoveryRequest; 68fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 69fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 70fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * The {@link Intent} that must be declared as handled by the service. 71fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Put this in your manifest. 72fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 733efa63d3b896244713e84acbb5945562dce41d77Jeff Brown public static final String SERVICE_INTERFACE = MediaRouteProviderProtocol.SERVICE_INTERFACE; 74fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 75fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /* 76fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Private messages used internally. (Yes, you can renumber these.) 77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final int PRIVATE_MSG_CLIENT_DIED = 1; 80fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 81fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 82fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Creates a media route provider service. 83fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 84fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProviderService() { 85fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveHandler = new ReceiveHandler(this); 86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mReceiveMessenger = new Messenger(mReceiveHandler); 87fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler = new PrivateHandler(); 88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviderCallback = new ProviderCallback(); 89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 91fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 92fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Called by the system when it is time to create the media route provider. 93fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 94fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 95fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * this service has decided not to offer a media route provider. 96fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 97fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public abstract MediaRouteProvider onCreateMediaRouteProvider(); 98fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 99fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 100fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Gets the media route provider offered by this service. 101fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 102fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @return The media route provider offered by this service, or null if 103fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * it has not yet been created. 104fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 105fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @see #onCreateMediaRouteProvider() 106fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 107fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider getMediaRouteProvider() { 108fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mProvider; 109fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 110fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 111fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 112fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public IBinder onBind(Intent intent) { 113fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (intent.getAction().equals(SERVICE_INTERFACE)) { 114fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider == null) { 115fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider provider = onCreateMediaRouteProvider(); 116fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (provider != null) { 117fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String providerPackage = provider.getMetadata().getPackageName(); 118fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!providerPackage.equals(getPackageName())) { 119fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown throw new IllegalStateException("onCreateMediaRouteProvider() returned " 120fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "a provider whose package name does not match the package " 121fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "name of the service. A media route provider service can " 122fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "only export its own media route providers. " 123fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + "Provider package name: " + providerPackage 124fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ". Service package name: " + getPackageName() + "."); 125fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 126350ba6e4a1b5ec28721a098e50eaf6a508eb28f0Jeff Brown mProvider = provider; 12711417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setCallback(mProviderCallback); 128fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 129fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 130fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mProvider != null) { 131fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mReceiveMessenger.getBinder(); 132fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 133fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 134fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return null; 135fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 136fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 137fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRegisterClient(Messenger messenger, int requestId, int version) { 138fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (version >= CLIENT_VERSION_1) { 139fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 140fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index < 0) { 141fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = new ClientRecord(messenger, version); 142fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.register()) { 143fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mClients.add(client); 144fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 145fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Registered, version=" + version); 146fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 147fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 14811417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor = mProvider.getDescriptor(); 149fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_REGISTERED, 150fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown requestId, SERVICE_VERSION_CURRENT, 151fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptor != null ? descriptor.asBundle() : null, null); 152fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 153fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 154fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 155fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 156fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 157fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 158fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 159fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 160fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnregisterClient(Messenger messenger, int requestId) { 161fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 162fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 163fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 164fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 165fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Unregistered"); 166fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 167fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 168fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 169fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 170fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 171fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 172fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 173fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 174fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private void onBinderDied(Messenger messenger) { 175fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 176fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (index >= 0) { 177fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.remove(index); 178fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 179fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Binder died"); 180fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 181fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.dispose(); 182fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 183fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 184fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 185fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onCreateRouteController(Messenger messenger, int requestId, 186fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, String routeId) { 187fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 188fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 189fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.createRouteController(routeId, controllerId)) { 190fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 191fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller created" 192fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", routeId=" + routeId); 193fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 194fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 195fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 196fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 197fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 198fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 199fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 200fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 201fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onReleaseRouteController(Messenger messenger, int requestId, 202fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 203fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 204fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 205fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.releaseRouteController(controllerId)) { 206fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 207fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route controller released" 208fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 209fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 210fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 211fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 212fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 213fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 214fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 215fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 216fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 217fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSelectRoute(Messenger messenger, int requestId, 218fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId) { 219fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 220fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 221fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 222fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 223fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 224129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSelect(); 225fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 226fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route selected" 227fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 228fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 229fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 230fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 231fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 232fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 233fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 234fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 235fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 236fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUnselectRoute(Messenger messenger, int requestId, 23794be6100218126ce6a08bf1f56209578500b361fRoboErik int controllerId, int reason) { 238fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 239fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 240fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 241fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 242fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 24394be6100218126ce6a08bf1f56209578500b361fRoboErik controller.onUnselect(reason); 244fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 245fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route unselected" 246fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId); 247fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 248fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 249fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 250fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 251fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 252fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 253fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 254fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 255fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onSetRouteVolume(Messenger messenger, int requestId, 256fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int volume) { 257fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 258fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 259fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 260fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 261fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 262129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onSetVolume(volume); 263fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 264fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume changed" 265fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", volume=" + volume); 266fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 267fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 268fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 269fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 270fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 271fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 272fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 273fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 274fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onUpdateRouteVolume(Messenger messenger, int requestId, 275fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int controllerId, int delta) { 276fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = getClient(messenger); 277fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 278fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 279fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 280fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 281129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onUpdateVolume(delta); 282fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 283fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route volume updated" 284fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", delta=" + delta); 285fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 286fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericSuccess(messenger, requestId); 287fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 288fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 289fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 290fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 291fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 292fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 293fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean onRouteControlRequest(final Messenger messenger, final int requestId, 294fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int controllerId, final Intent intent) { 295fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final ClientRecord client = getClient(messenger); 296fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client != null) { 297fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 298fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown client.getRouteController(controllerId); 299fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 300fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouter.ControlRequestCallback callback = null; 301fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 302fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown callback = new MediaRouter.ControlRequestCallback() { 303fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 3043d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onResult(Bundle data) { 3053d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (DEBUG) { 3063d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request succeeded" 3073d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", controllerId=" + controllerId 3083d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", intent=" + intent 3093d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", data=" + data); 3103d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3113d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (findClient(messenger) >= 0) { 3123d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED, 3133d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3143d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3153d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 3163d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown 3173d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown @Override 3183d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown public void onError(String error, Bundle data) { 319fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 3203d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Log.d(TAG, client + ": Route control request failed" 321fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId 322fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", intent=" + intent 3233d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown + ", error=" + error + ", data=" + data); 324fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 325fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (findClient(messenger) >= 0) { 3263d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown if (error != null) { 3273d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown Bundle bundle = new Bundle(); 3283d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown bundle.putString(SERVICE_DATA_ERROR, error); 3293d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3303d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, bundle); 3313d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } else { 3323d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED, 3333d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown requestId, 0, data, null); 3343d4c9459ed77f732dd3ba602713af6ebf9280c8cJeff Brown } 335fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 336fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 337fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown }; 338fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 339129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown if (controller.onControlRequest(intent, callback)) { 340fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 341fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Route control request delivered" 342fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", controllerId=" + controllerId + ", intent=" + intent); 343fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 344fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 345fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 346fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 347fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 348fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 349fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 350fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 35111417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean onSetDiscoveryRequest(Messenger messenger, int requestId, 35211417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request) { 35328520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown ClientRecord client = getClient(messenger); 35428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (client != null) { 35511417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean actuallyChanged = client.setDiscoveryRequest(request); 35628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown if (DEBUG) { 35711417b1cfde8f1749905f2d735623af9214148afJeff Brown Log.d(TAG, client + ": Set discovery request, request=" + request 35811417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", actuallyChanged=" + actuallyChanged 35911417b1cfde8f1749905f2d735623af9214148afJeff Brown + ", compositeDiscoveryRequest=" + mCompositeDiscoveryRequest); 36028520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 36128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown sendGenericSuccess(messenger, requestId); 36228520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return true; 36328520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 36428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 36528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 36628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 36711417b1cfde8f1749905f2d735623af9214148afJeff Brown private void sendDescriptorChanged(MediaRouteProviderDescriptor descriptor) { 368fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Bundle descriptorBundle = descriptor != null ? descriptor.asBundle() : null; 369fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 370fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 371fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 372fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(client.mMessenger, SERVICE_MSG_DESCRIPTOR_CHANGED, 0, 0, 373fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown descriptorBundle, null); 374fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 375fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, client + ": Sent descriptor change event, descriptor=" + descriptor); 376fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 377fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 378fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 379fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 38011417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean updateCompositeDiscoveryRequest() { 38111417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest composite = null; 38211417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteSelector.Builder selectorBuilder = null; 38311417b1cfde8f1749905f2d735623af9214148afJeff Brown boolean activeScan = false; 38411417b1cfde8f1749905f2d735623af9214148afJeff Brown final int count = mClients.size(); 38511417b1cfde8f1749905f2d735623af9214148afJeff Brown for (int i = 0; i < count; i++) { 38611417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = mClients.get(i).mDiscoveryRequest; 38711417b1cfde8f1749905f2d735623af9214148afJeff Brown if (request != null 38811417b1cfde8f1749905f2d735623af9214148afJeff Brown && (!request.getSelector().isEmpty() || request.isActiveScan())) { 38911417b1cfde8f1749905f2d735623af9214148afJeff Brown activeScan |= request.isActiveScan(); 39011417b1cfde8f1749905f2d735623af9214148afJeff Brown if (composite == null) { 39111417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = request; 39211417b1cfde8f1749905f2d735623af9214148afJeff Brown } else { 39311417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder == null) { 39411417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder = new MediaRouteSelector.Builder(composite.getSelector()); 39511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 39611417b1cfde8f1749905f2d735623af9214148afJeff Brown selectorBuilder.addSelector(request.getSelector()); 39711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 39811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 39911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 40011417b1cfde8f1749905f2d735623af9214148afJeff Brown if (selectorBuilder != null) { 40111417b1cfde8f1749905f2d735623af9214148afJeff Brown composite = new MediaRouteDiscoveryRequest(selectorBuilder.build(), activeScan); 40211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 40311417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mCompositeDiscoveryRequest != composite 40411417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mCompositeDiscoveryRequest == null 40511417b1cfde8f1749905f2d735623af9214148afJeff Brown || !mCompositeDiscoveryRequest.equals(composite))) { 40611417b1cfde8f1749905f2d735623af9214148afJeff Brown mCompositeDiscoveryRequest = composite; 40711417b1cfde8f1749905f2d735623af9214148afJeff Brown mProvider.setDiscoveryRequest(composite); 40811417b1cfde8f1749905f2d735623af9214148afJeff Brown return true; 40911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41011417b1cfde8f1749905f2d735623af9214148afJeff Brown return false; 41111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41211417b1cfde8f1749905f2d735623af9214148afJeff Brown 413fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private ClientRecord getClient(Messenger messenger) { 414fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int index = findClient(messenger); 415fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return index >= 0 ? mClients.get(index) : null; 416fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 417fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 418fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private int findClient(Messenger messenger) { 419fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int count = mClients.size(); 420fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 421fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ClientRecord client = mClients.get(i); 422fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (client.hasMessenger(messenger)) { 423fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return i; 424fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 425fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 426fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return -1; 427fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 428fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 429fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericFailure(Messenger messenger, int requestId) { 430fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 431fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null); 432fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 433fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 434fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 435fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendGenericSuccess(Messenger messenger, int requestId) { 436fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (requestId != 0) { 437fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null); 438fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 439fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 440fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 441fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static void sendReply(Messenger messenger, int what, 442fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int requestId, int arg, Object obj, Bundle data) { 443fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Message msg = Message.obtain(); 444fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.what = what; 445fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg1 = requestId; 446fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.arg2 = arg; 447fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.obj = obj; 448fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown msg.setData(data); 449fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 450fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger.send(msg); 451fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (DeadObjectException ex) { 452fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // The client died. 453fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 454fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.e(TAG, "Could not send message to " + getClientId(messenger), ex); 455fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 456fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 457fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 458fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static String getClientId(Messenger messenger) { 459fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return "Client connection " + messenger.getBinder().toString(); 460fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 461fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 462fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class PrivateHandler extends Handler { 463fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 464fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 465fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (msg.what) { 466fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case PRIVATE_MSG_CLIENT_DIED: 467fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown onBinderDied((Messenger)msg.obj); 468fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 469fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 470fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 471fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 472fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 473fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ProviderCallback extends MediaRouteProvider.Callback { 474fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 475fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void onDescriptorChanged(MediaRouteProvider provider, 47611417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteProviderDescriptor descriptor) { 477fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendDescriptorChanged(descriptor); 478fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 479fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 480fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 481fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final class ClientRecord implements DeathRecipient { 482fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final Messenger mMessenger; 483fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public final int mVersion; 48411417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteDiscoveryRequest mDiscoveryRequest; 485fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 486fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final SparseArray<MediaRouteProvider.RouteController> mControllers = 487fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new SparseArray<MediaRouteProvider.RouteController>(); 488fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 489fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ClientRecord(Messenger messenger, int version) { 490fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger = messenger; 491fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mVersion = version; 492fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 493fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 494fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean register() { 495fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown try { 496fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().linkToDeath(this, 0); 497fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 498fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } catch (RemoteException ex) { 499fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown binderDied(); 500fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 501fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 502fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 503fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 504fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void dispose() { 505fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int count = mControllers.size(); 506fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 507129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown mControllers.valueAt(i).onRelease(); 508fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 509fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.clear(); 510fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 511fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mMessenger.getBinder().unlinkToDeath(this, 0); 51228520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 51311417b1cfde8f1749905f2d735623af9214148afJeff Brown setDiscoveryRequest(null); 514fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 515fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 516fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean hasMessenger(Messenger other) { 517fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mMessenger.getBinder() == other.getBinder(); 518fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 519fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 520fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean createRouteController(String routeId, int controllerId) { 521fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (mControllers.indexOfKey(controllerId) < 0) { 522fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = 523fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProvider.onCreateRouteController(routeId); 524ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown if (controller != null) { 525ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown mControllers.put(controllerId, controller); 526ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown return true; 527ae161a4d000a10dafd844d17145de631933f21f3Jeff Brown } 528fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 529fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 530fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 531fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 532fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public boolean releaseRouteController(int controllerId) { 533fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProvider.RouteController controller = mControllers.get(controllerId); 534fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (controller != null) { 535fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mControllers.remove(controllerId); 536129abf73ce9be1bc172b945263c7975ad1a3006fJeff Brown controller.onRelease(); 537fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return true; 538fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 539fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 540fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 541fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 542fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public MediaRouteProvider.RouteController getRouteController(int controllerId) { 543fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return mControllers.get(controllerId); 544fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 545fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 54611417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean setDiscoveryRequest(MediaRouteDiscoveryRequest request) { 54711417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mDiscoveryRequest != request 54811417b1cfde8f1749905f2d735623af9214148afJeff Brown && (mDiscoveryRequest == null || !mDiscoveryRequest.equals(request))) { 54911417b1cfde8f1749905f2d735623af9214148afJeff Brown mDiscoveryRequest = request; 55011417b1cfde8f1749905f2d735623af9214148afJeff Brown return updateCompositeDiscoveryRequest(); 55128520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 55228520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown return false; 55328520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown } 55428520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 55528520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown // Runs on a binder thread. 556fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 557fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void binderDied() { 558fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget(); 559fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 560fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 561fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 562fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public String toString() { 563fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return getClientId(mMessenger); 564fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 565fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 566fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 567fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown /** 568fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Handler that receives messages from clients. 569fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * <p> 570fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This inner class is static and only retains a weak reference to the service 571fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * to prevent the service from being leaked in case one of the clients is holding an 572fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * active reference to the server's messenger. 573fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p><p> 574fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * This handler should not be used to handle any messages other than those 575fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * that come from the client. 576fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * </p> 577fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 578fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private static final class ReceiveHandler extends Handler { 579fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final WeakReference<MediaRouteProviderService> mServiceRef; 580fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 581fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public ReceiveHandler(MediaRouteProviderService service) { 582fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mServiceRef = new WeakReference<MediaRouteProviderService>(service); 583fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 584fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 585fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 586fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void handleMessage(Message msg) { 587fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Messenger messenger = msg.replyTo; 588fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (isValidRemoteMessenger(messenger)) { 589fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int what = msg.what; 590fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int requestId = msg.arg1; 591fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final int arg = msg.arg2; 592fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Object obj = msg.obj; 593fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown final Bundle data = msg.peekData(); 594fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (!processMessage(what, messenger, requestId, arg, obj, data)) { 595fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 596fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what 597fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", requestId=" + requestId + ", arg=" + arg 598fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown + ", obj=" + obj + ", data=" + data); 599fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 600fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown sendGenericFailure(messenger, requestId); 601fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 602fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else { 603fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (DEBUG) { 604fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Log.d(TAG, "Ignoring message without valid reply messenger."); 605fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 606fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 607fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 608fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 609fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private boolean processMessage(int what, 610fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Messenger messenger, int requestId, int arg, Object obj, Bundle data) { 611fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown MediaRouteProviderService service = mServiceRef.get(); 612fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (service != null) { 613fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown switch (what) { 614fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_REGISTER: 615fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRegisterClient(messenger, requestId, arg); 616fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 617fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNREGISTER: 618fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUnregisterClient(messenger, requestId); 619fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 620fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: { 621fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown String routeId = data.getString(CLIENT_DATA_ROUTE_ID); 622fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (routeId != null) { 623fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onCreateRouteController( 624fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, routeId); 625fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 626fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 627fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 628fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 629fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER: 630fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onReleaseRouteController(messenger, requestId, arg); 631fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 632fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SELECT_ROUTE: 633fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSelectRoute(messenger, requestId, arg); 634fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 635fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UNSELECT_ROUTE: 63694be6100218126ce6a08bf1f56209578500b361fRoboErik int reason = data == null ? 63794be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN 63894be6100218126ce6a08bf1f56209578500b361fRoboErik : data.getInt(CLIENT_DATA_UNSELECT_REASON, 63994be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_UNKNOWN); 64094be6100218126ce6a08bf1f56209578500b361fRoboErik return service.onUnselectRoute(messenger, requestId, arg, reason); 641fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 642fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_SET_ROUTE_VOLUME: { 643fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int volume = data.getInt(CLIENT_DATA_VOLUME, -1); 644fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (volume >= 0) { 645fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onSetRouteVolume( 646fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, volume); 647fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 648fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 649fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 650fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 651fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_UPDATE_ROUTE_VOLUME: { 652fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int delta = data.getInt(CLIENT_DATA_VOLUME, 0); 653fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (delta != 0) { 654fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onUpdateRouteVolume( 655fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, delta); 656fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 657fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 658fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 659fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 660fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown case CLIENT_MSG_ROUTE_CONTROL_REQUEST: 661fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (obj instanceof Intent) { 662fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return service.onRouteControlRequest( 663fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown messenger, requestId, arg, (Intent)obj); 664fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 665fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown break; 66628520a15611522424b52cf88e4a2dbeb1a9be42bJeff Brown 66711417b1cfde8f1749905f2d735623af9214148afJeff Brown case CLIENT_MSG_SET_DISCOVERY_REQUEST: { 668f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown if (obj == null || obj instanceof Bundle) { 66911417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest request = 67011417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouteDiscoveryRequest.fromBundle((Bundle)obj); 67111417b1cfde8f1749905f2d735623af9214148afJeff Brown return service.onSetDiscoveryRequest( 672f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown messenger, requestId, 673f03da4a9e6cc02251c2f804eb6f25da61821d6a7Jeff Brown request != null && request.isValid() ? request : null); 67411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 67511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 676fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 677fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 678fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return false; 679fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 680fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 681fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown} 682