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