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