Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.support.v7.media;
     18 
     19 import android.app.Service;
     20 import android.content.Intent;
     21 import android.os.Handler;
     22 import android.os.IBinder;
     23 import android.os.IBinder.DeathRecipient;
     24 import android.os.Bundle;
     25 import android.os.DeadObjectException;
     26 import android.os.Message;
     27 import android.os.Messenger;
     28 import android.os.RemoteException;
     29 import android.util.Log;
     30 import android.util.SparseArray;
     31 
     32 import java.lang.ref.WeakReference;
     33 import java.util.ArrayList;
     34 
     35 import static android.support.v7.media.MediaRouteProviderProtocol.*;
     36 
     37 /**
     38  * Base class for media route provider services.
     39  * <p>
     40  * To implement your own media route provider service, extend this class and
     41  * override the {@link #onCreateMediaRouteProvider} method to return an
     42  * instance of your {@link MediaRouteProvider}.
     43  * </p><p>
     44  * Declare your media route provider service in your application manifest
     45  * like this:
     46  * </p>
     47  * <pre>
     48  *   &lt;service android:name=".MyMediaRouteProviderService"
     49  *           android:label="@string/my_media_route_provider_service">
     50  *       &lt;intent-filter>
     51  *           &lt;action android:name="android.media.MediaRouteProviderService" />
     52  *       &lt;/intent-filter>
     53  *   &lt;/service>
     54  * </pre>
     55  */
     56 public abstract class MediaRouteProviderService extends Service {
     57     private static final String TAG = "MediaRouteProviderSrv"; // max. 23 chars
     58     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     59 
     60     private final ArrayList<ClientRecord> mClients = new ArrayList<ClientRecord>();
     61     private final ReceiveHandler mReceiveHandler;
     62     private final Messenger mReceiveMessenger;
     63     private final PrivateHandler mPrivateHandler;
     64     private final ProviderCallback mProviderCallback;
     65 
     66     private MediaRouteProvider mProvider;
     67     private MediaRouteDiscoveryRequest mCompositeDiscoveryRequest;
     68 
     69     /**
     70      * The {@link Intent} that must be declared as handled by the service.
     71      * Put this in your manifest.
     72      */
     73     public static final String SERVICE_INTERFACE = MediaRouteProviderProtocol.SERVICE_INTERFACE;
     74 
     75     /*
     76      * Private messages used internally.  (Yes, you can renumber these.)
     77      */
     78 
     79     private static final int PRIVATE_MSG_CLIENT_DIED = 1;
     80 
     81     /**
     82      * Creates a media route provider service.
     83      */
     84     public MediaRouteProviderService() {
     85         mReceiveHandler = new ReceiveHandler(this);
     86         mReceiveMessenger = new Messenger(mReceiveHandler);
     87         mPrivateHandler = new PrivateHandler();
     88         mProviderCallback = new ProviderCallback();
     89     }
     90 
     91     /**
     92      * Called by the system when it is time to create the media route provider.
     93      *
     94      * @return The media route provider offered by this service, or null if
     95      * this service has decided not to offer a media route provider.
     96      */
     97     public abstract MediaRouteProvider onCreateMediaRouteProvider();
     98 
     99     /**
    100      * Gets the media route provider offered by this service.
    101      *
    102      * @return The media route provider offered by this service, or null if
    103      * it has not yet been created.
    104      *
    105      * @see #onCreateMediaRouteProvider()
    106      */
    107     public MediaRouteProvider getMediaRouteProvider() {
    108         return mProvider;
    109     }
    110 
    111     @Override
    112     public IBinder onBind(Intent intent) {
    113         if (intent.getAction().equals(SERVICE_INTERFACE)) {
    114             if (mProvider == null) {
    115                 MediaRouteProvider provider = onCreateMediaRouteProvider();
    116                 if (provider != null) {
    117                     String providerPackage = provider.getMetadata().getPackageName();
    118                     if (!providerPackage.equals(getPackageName())) {
    119                         throw new IllegalStateException("onCreateMediaRouteProvider() returned "
    120                                 + "a provider whose package name does not match the package "
    121                                 + "name of the service.  A media route provider service can "
    122                                 + "only export its own media route providers.  "
    123                                 + "Provider package name: " + providerPackage
    124                                 + ".  Service package name: " + getPackageName() + ".");
    125                     }
    126                     mProvider = provider;
    127                     mProvider.setCallback(mProviderCallback);
    128                 }
    129             }
    130             if (mProvider != null) {
    131                 return mReceiveMessenger.getBinder();
    132             }
    133         }
    134         return null;
    135     }
    136 
    137     private boolean onRegisterClient(Messenger messenger, int requestId, int version) {
    138         if (version >= CLIENT_VERSION_1) {
    139             int index = findClient(messenger);
    140             if (index < 0) {
    141                 ClientRecord client = new ClientRecord(messenger, version);
    142                 if (client.register()) {
    143                     mClients.add(client);
    144                     if (DEBUG) {
    145                         Log.d(TAG, client + ": Registered, version=" + version);
    146                     }
    147                     if (requestId != 0) {
    148                         MediaRouteProviderDescriptor descriptor = mProvider.getDescriptor();
    149                         sendReply(messenger, SERVICE_MSG_REGISTERED,
    150                                 requestId, SERVICE_VERSION_CURRENT,
    151                                 descriptor != null ? descriptor.asBundle() : null, null);
    152                     }
    153                     return true;
    154                 }
    155             }
    156         }
    157         return false;
    158     }
    159 
    160     private boolean onUnregisterClient(Messenger messenger, int requestId) {
    161         int index = findClient(messenger);
    162         if (index >= 0) {
    163             ClientRecord client = mClients.remove(index);
    164             if (DEBUG) {
    165                 Log.d(TAG, client + ": Unregistered");
    166             }
    167             client.dispose();
    168             sendGenericSuccess(messenger, requestId);
    169             return true;
    170         }
    171         return false;
    172     }
    173 
    174     private void onBinderDied(Messenger messenger) {
    175         int index = findClient(messenger);
    176         if (index >= 0) {
    177             ClientRecord client = mClients.remove(index);
    178             if (DEBUG) {
    179                 Log.d(TAG, client + ": Binder died");
    180             }
    181             client.dispose();
    182         }
    183     }
    184 
    185     private boolean onCreateRouteController(Messenger messenger, int requestId,
    186             int controllerId, String routeId) {
    187         ClientRecord client = getClient(messenger);
    188         if (client != null) {
    189             if (client.createRouteController(routeId, controllerId)) {
    190                 if (DEBUG) {
    191                     Log.d(TAG, client + ": Route controller created"
    192                             + ", controllerId=" + controllerId + ", routeId=" + routeId);
    193                 }
    194                 sendGenericSuccess(messenger, requestId);
    195                 return true;
    196             }
    197         }
    198         return false;
    199     }
    200 
    201     private boolean onReleaseRouteController(Messenger messenger, int requestId,
    202             int controllerId) {
    203         ClientRecord client = getClient(messenger);
    204         if (client != null) {
    205             if (client.releaseRouteController(controllerId)) {
    206                 if (DEBUG) {
    207                     Log.d(TAG, client + ": Route controller released"
    208                             + ", controllerId=" + controllerId);
    209                 }
    210                 sendGenericSuccess(messenger, requestId);
    211                 return true;
    212             }
    213         }
    214         return false;
    215     }
    216 
    217     private boolean onSelectRoute(Messenger messenger, int requestId,
    218             int controllerId) {
    219         ClientRecord client = getClient(messenger);
    220         if (client != null) {
    221             MediaRouteProvider.RouteController controller =
    222                     client.getRouteController(controllerId);
    223             if (controller != null) {
    224                 controller.onSelect();
    225                 if (DEBUG) {
    226                     Log.d(TAG, client + ": Route selected"
    227                             + ", controllerId=" + controllerId);
    228                 }
    229                 sendGenericSuccess(messenger, requestId);
    230                 return true;
    231             }
    232         }
    233         return false;
    234     }
    235 
    236     private boolean onUnselectRoute(Messenger messenger, int requestId,
    237             int controllerId) {
    238         ClientRecord client = getClient(messenger);
    239         if (client != null) {
    240             MediaRouteProvider.RouteController controller =
    241                     client.getRouteController(controllerId);
    242             if (controller != null) {
    243                 controller.onUnselect();
    244                 if (DEBUG) {
    245                     Log.d(TAG, client + ": Route unselected"
    246                             + ", controllerId=" + controllerId);
    247                 }
    248                 sendGenericSuccess(messenger, requestId);
    249                 return true;
    250             }
    251         }
    252         return false;
    253     }
    254 
    255     private boolean onSetRouteVolume(Messenger messenger, int requestId,
    256             int controllerId, int volume) {
    257         ClientRecord client = getClient(messenger);
    258         if (client != null) {
    259             MediaRouteProvider.RouteController controller =
    260                     client.getRouteController(controllerId);
    261             if (controller != null) {
    262                 controller.onSetVolume(volume);
    263                 if (DEBUG) {
    264                     Log.d(TAG, client + ": Route volume changed"
    265                             + ", controllerId=" + controllerId + ", volume=" + volume);
    266                 }
    267                 sendGenericSuccess(messenger, requestId);
    268                 return true;
    269             }
    270         }
    271         return false;
    272     }
    273 
    274     private boolean onUpdateRouteVolume(Messenger messenger, int requestId,
    275             int controllerId, int delta) {
    276         ClientRecord client = getClient(messenger);
    277         if (client != null) {
    278             MediaRouteProvider.RouteController controller =
    279                     client.getRouteController(controllerId);
    280             if (controller != null) {
    281                 controller.onUpdateVolume(delta);
    282                 if (DEBUG) {
    283                     Log.d(TAG, client + ": Route volume updated"
    284                             + ", controllerId=" + controllerId + ", delta=" + delta);
    285                 }
    286                 sendGenericSuccess(messenger, requestId);
    287                 return true;
    288             }
    289         }
    290         return false;
    291     }
    292 
    293     private boolean onRouteControlRequest(final Messenger messenger, final int requestId,
    294             final int controllerId, final Intent intent) {
    295         final ClientRecord client = getClient(messenger);
    296         if (client != null) {
    297             MediaRouteProvider.RouteController controller =
    298                     client.getRouteController(controllerId);
    299             if (controller != null) {
    300                 MediaRouter.ControlRequestCallback callback = null;
    301                 if (requestId != 0) {
    302                     callback = new MediaRouter.ControlRequestCallback() {
    303                         @Override
    304                         public void onResult(Bundle data) {
    305                             if (DEBUG) {
    306                                 Log.d(TAG, client + ": Route control request succeeded"
    307                                         + ", controllerId=" + controllerId
    308                                         + ", intent=" + intent
    309                                         + ", data=" + data);
    310                             }
    311                             if (findClient(messenger) >= 0) {
    312                                 sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED,
    313                                         requestId, 0, data, null);
    314                             }
    315                         }
    316 
    317                         @Override
    318                         public void onError(String error, Bundle data) {
    319                             if (DEBUG) {
    320                                 Log.d(TAG, client + ": Route control request failed"
    321                                         + ", controllerId=" + controllerId
    322                                         + ", intent=" + intent
    323                                         + ", error=" + error + ", data=" + data);
    324                             }
    325                             if (findClient(messenger) >= 0) {
    326                                 if (error != null) {
    327                                     Bundle bundle = new Bundle();
    328                                     bundle.putString(SERVICE_DATA_ERROR, error);
    329                                     sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED,
    330                                             requestId, 0, data, bundle);
    331                                 } else {
    332                                     sendReply(messenger, SERVICE_MSG_CONTROL_REQUEST_FAILED,
    333                                             requestId, 0, data, null);
    334                                 }
    335                             }
    336                         }
    337                     };
    338                 }
    339                 if (controller.onControlRequest(intent, callback)) {
    340                     if (DEBUG) {
    341                         Log.d(TAG, client + ": Route control request delivered"
    342                                 + ", controllerId=" + controllerId + ", intent=" + intent);
    343                     }
    344                     return true;
    345                 }
    346             }
    347         }
    348         return false;
    349     }
    350 
    351     private boolean onSetDiscoveryRequest(Messenger messenger, int requestId,
    352             MediaRouteDiscoveryRequest request) {
    353         ClientRecord client = getClient(messenger);
    354         if (client != null) {
    355             boolean actuallyChanged = client.setDiscoveryRequest(request);
    356             if (DEBUG) {
    357                 Log.d(TAG, client + ": Set discovery request, request=" + request
    358                         + ", actuallyChanged=" + actuallyChanged
    359                         + ", compositeDiscoveryRequest=" + mCompositeDiscoveryRequest);
    360             }
    361             sendGenericSuccess(messenger, requestId);
    362             return true;
    363         }
    364         return false;
    365     }
    366 
    367     private void sendDescriptorChanged(MediaRouteProviderDescriptor descriptor) {
    368         Bundle descriptorBundle = descriptor != null ? descriptor.asBundle() : null;
    369         final int count = mClients.size();
    370         for (int i = 0; i < count; i++) {
    371             ClientRecord client = mClients.get(i);
    372             sendReply(client.mMessenger, SERVICE_MSG_DESCRIPTOR_CHANGED, 0, 0,
    373                     descriptorBundle, null);
    374             if (DEBUG) {
    375                 Log.d(TAG, client + ": Sent descriptor change event, descriptor=" + descriptor);
    376             }
    377         }
    378     }
    379 
    380     private boolean updateCompositeDiscoveryRequest() {
    381         MediaRouteDiscoveryRequest composite = null;
    382         MediaRouteSelector.Builder selectorBuilder = null;
    383         boolean activeScan = false;
    384         final int count = mClients.size();
    385         for (int i = 0; i < count; i++) {
    386             MediaRouteDiscoveryRequest request = mClients.get(i).mDiscoveryRequest;
    387             if (request != null
    388                     && (!request.getSelector().isEmpty() || request.isActiveScan())) {
    389                 activeScan |= request.isActiveScan();
    390                 if (composite == null) {
    391                     composite = request;
    392                 } else {
    393                     if (selectorBuilder == null) {
    394                         selectorBuilder = new MediaRouteSelector.Builder(composite.getSelector());
    395                     }
    396                     selectorBuilder.addSelector(request.getSelector());
    397                 }
    398             }
    399         }
    400         if (selectorBuilder != null) {
    401             composite = new MediaRouteDiscoveryRequest(selectorBuilder.build(), activeScan);
    402         }
    403         if (mCompositeDiscoveryRequest != composite
    404                 && (mCompositeDiscoveryRequest == null
    405                         || !mCompositeDiscoveryRequest.equals(composite))) {
    406             mCompositeDiscoveryRequest = composite;
    407             mProvider.setDiscoveryRequest(composite);
    408             return true;
    409         }
    410         return false;
    411     }
    412 
    413     private ClientRecord getClient(Messenger messenger) {
    414         int index = findClient(messenger);
    415         return index >= 0 ? mClients.get(index) : null;
    416     }
    417 
    418     private int findClient(Messenger messenger) {
    419         final int count = mClients.size();
    420         for (int i = 0; i < count; i++) {
    421             ClientRecord client = mClients.get(i);
    422             if (client.hasMessenger(messenger)) {
    423                 return i;
    424             }
    425         }
    426         return -1;
    427     }
    428 
    429     private static void sendGenericFailure(Messenger messenger, int requestId) {
    430         if (requestId != 0) {
    431             sendReply(messenger, SERVICE_MSG_GENERIC_FAILURE, requestId, 0, null, null);
    432         }
    433     }
    434 
    435     private static void sendGenericSuccess(Messenger messenger, int requestId) {
    436         if (requestId != 0) {
    437             sendReply(messenger, SERVICE_MSG_GENERIC_SUCCESS, requestId, 0, null, null);
    438         }
    439     }
    440 
    441     private static void sendReply(Messenger messenger, int what,
    442             int requestId, int arg, Object obj, Bundle data) {
    443         Message msg = Message.obtain();
    444         msg.what = what;
    445         msg.arg1 = requestId;
    446         msg.arg2 = arg;
    447         msg.obj = obj;
    448         msg.setData(data);
    449         try {
    450             messenger.send(msg);
    451         } catch (DeadObjectException ex) {
    452             // The client died.
    453         } catch (RemoteException ex) {
    454             Log.e(TAG, "Could not send message to " + getClientId(messenger), ex);
    455         }
    456     }
    457 
    458     private static String getClientId(Messenger messenger) {
    459         return "Client connection " + messenger.getBinder().toString();
    460     }
    461 
    462     private final class PrivateHandler extends Handler {
    463         @Override
    464         public void handleMessage(Message msg) {
    465             switch (msg.what) {
    466                 case PRIVATE_MSG_CLIENT_DIED:
    467                     onBinderDied((Messenger)msg.obj);
    468                     break;
    469             }
    470         }
    471     }
    472 
    473     private final class ProviderCallback extends MediaRouteProvider.Callback {
    474         @Override
    475         public void onDescriptorChanged(MediaRouteProvider provider,
    476                 MediaRouteProviderDescriptor descriptor) {
    477             sendDescriptorChanged(descriptor);
    478         }
    479     }
    480 
    481     private final class ClientRecord implements DeathRecipient {
    482         public final Messenger mMessenger;
    483         public final int mVersion;
    484         public MediaRouteDiscoveryRequest mDiscoveryRequest;
    485 
    486         private final SparseArray<MediaRouteProvider.RouteController> mControllers =
    487                 new SparseArray<MediaRouteProvider.RouteController>();
    488 
    489         public ClientRecord(Messenger messenger, int version) {
    490             mMessenger = messenger;
    491             mVersion = version;
    492         }
    493 
    494         public boolean register() {
    495             try {
    496                 mMessenger.getBinder().linkToDeath(this, 0);
    497                 return true;
    498             } catch (RemoteException ex) {
    499                 binderDied();
    500             }
    501             return false;
    502         }
    503 
    504         public void dispose() {
    505             int count = mControllers.size();
    506             for (int i = 0; i < count; i++) {
    507                 mControllers.valueAt(i).onRelease();
    508             }
    509             mControllers.clear();
    510 
    511             mMessenger.getBinder().unlinkToDeath(this, 0);
    512 
    513             setDiscoveryRequest(null);
    514         }
    515 
    516         public boolean hasMessenger(Messenger other) {
    517             return mMessenger.getBinder() == other.getBinder();
    518         }
    519 
    520         public boolean createRouteController(String routeId, int controllerId) {
    521             if (mControllers.indexOfKey(controllerId) < 0) {
    522                 MediaRouteProvider.RouteController controller =
    523                         mProvider.onCreateRouteController(routeId);
    524                 if (controller != null) {
    525                     mControllers.put(controllerId, controller);
    526                     return true;
    527                 }
    528             }
    529             return false;
    530         }
    531 
    532         public boolean releaseRouteController(int controllerId) {
    533             MediaRouteProvider.RouteController controller = mControllers.get(controllerId);
    534             if (controller != null) {
    535                 mControllers.remove(controllerId);
    536                 controller.onRelease();
    537                 return true;
    538             }
    539             return false;
    540         }
    541 
    542         public MediaRouteProvider.RouteController getRouteController(int controllerId) {
    543             return mControllers.get(controllerId);
    544         }
    545 
    546         public boolean setDiscoveryRequest(MediaRouteDiscoveryRequest request) {
    547             if (mDiscoveryRequest != request
    548                     && (mDiscoveryRequest == null || !mDiscoveryRequest.equals(request))) {
    549                 mDiscoveryRequest = request;
    550                 return updateCompositeDiscoveryRequest();
    551             }
    552             return false;
    553         }
    554 
    555         // Runs on a binder thread.
    556         @Override
    557         public void binderDied() {
    558             mPrivateHandler.obtainMessage(PRIVATE_MSG_CLIENT_DIED, mMessenger).sendToTarget();
    559         }
    560 
    561         @Override
    562         public String toString() {
    563             return getClientId(mMessenger);
    564         }
    565     }
    566 
    567     /**
    568      * Handler that receives messages from clients.
    569      * <p>
    570      * This inner class is static and only retains a weak reference to the service
    571      * to prevent the service from being leaked in case one of the clients is holding an
    572      * active reference to the server's messenger.
    573      * </p><p>
    574      * This handler should not be used to handle any messages other than those
    575      * that come from the client.
    576      * </p>
    577      */
    578     private static final class ReceiveHandler extends Handler {
    579         private final WeakReference<MediaRouteProviderService> mServiceRef;
    580 
    581         public ReceiveHandler(MediaRouteProviderService service) {
    582             mServiceRef = new WeakReference<MediaRouteProviderService>(service);
    583         }
    584 
    585         @Override
    586         public void handleMessage(Message msg) {
    587             final Messenger messenger = msg.replyTo;
    588             if (isValidRemoteMessenger(messenger)) {
    589                 final int what = msg.what;
    590                 final int requestId = msg.arg1;
    591                 final int arg = msg.arg2;
    592                 final Object obj = msg.obj;
    593                 final Bundle data = msg.peekData();
    594                 if (!processMessage(what, messenger, requestId, arg, obj, data)) {
    595                     if (DEBUG) {
    596                         Log.d(TAG, getClientId(messenger) + ": Message failed, what=" + what
    597                                 + ", requestId=" + requestId + ", arg=" + arg
    598                                 + ", obj=" + obj + ", data=" + data);
    599                     }
    600                     sendGenericFailure(messenger, requestId);
    601                 }
    602             } else {
    603                 if (DEBUG) {
    604                     Log.d(TAG, "Ignoring message without valid reply messenger.");
    605                 }
    606             }
    607         }
    608 
    609         private boolean processMessage(int what,
    610                 Messenger messenger, int requestId, int arg, Object obj, Bundle data) {
    611             MediaRouteProviderService service = mServiceRef.get();
    612             if (service != null) {
    613                 switch (what) {
    614                     case CLIENT_MSG_REGISTER:
    615                         return service.onRegisterClient(messenger, requestId, arg);
    616 
    617                     case CLIENT_MSG_UNREGISTER:
    618                         return service.onUnregisterClient(messenger, requestId);
    619 
    620                     case CLIENT_MSG_CREATE_ROUTE_CONTROLLER: {
    621                         String routeId = data.getString(CLIENT_DATA_ROUTE_ID);
    622                         if (routeId != null) {
    623                             return service.onCreateRouteController(
    624                                     messenger, requestId, arg, routeId);
    625                         }
    626                         break;
    627                     }
    628 
    629                     case CLIENT_MSG_RELEASE_ROUTE_CONTROLLER:
    630                         return service.onReleaseRouteController(messenger, requestId, arg);
    631 
    632                     case CLIENT_MSG_SELECT_ROUTE:
    633                         return service.onSelectRoute(messenger, requestId, arg);
    634 
    635                     case CLIENT_MSG_UNSELECT_ROUTE:
    636                         return service.onUnselectRoute(messenger, requestId, arg);
    637 
    638                     case CLIENT_MSG_SET_ROUTE_VOLUME: {
    639                         int volume = data.getInt(CLIENT_DATA_VOLUME, -1);
    640                         if (volume >= 0) {
    641                             return service.onSetRouteVolume(
    642                                     messenger, requestId, arg, volume);
    643                         }
    644                         break;
    645                     }
    646 
    647                     case CLIENT_MSG_UPDATE_ROUTE_VOLUME: {
    648                         int delta = data.getInt(CLIENT_DATA_VOLUME, 0);
    649                         if (delta != 0) {
    650                             return service.onUpdateRouteVolume(
    651                                     messenger, requestId, arg, delta);
    652                         }
    653                         break;
    654                     }
    655 
    656                     case CLIENT_MSG_ROUTE_CONTROL_REQUEST:
    657                         if (obj instanceof Intent) {
    658                             return service.onRouteControlRequest(
    659                                     messenger, requestId, arg, (Intent)obj);
    660                         }
    661                         break;
    662 
    663                     case CLIENT_MSG_SET_DISCOVERY_REQUEST: {
    664                         if (obj == null || obj instanceof Bundle) {
    665                             MediaRouteDiscoveryRequest request =
    666                                     MediaRouteDiscoveryRequest.fromBundle((Bundle)obj);
    667                             return service.onSetDiscoveryRequest(
    668                                     messenger, requestId,
    669                                     request != null && request.isValid() ? request : null);
    670                         }
    671                     }
    672                 }
    673             }
    674             return false;
    675         }
    676     }
    677 }
    678