1 /* 2 * Copyright (c) 2009 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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "IOMX" 19 #include <utils/Log.h> 20 21 #include <binder/IMemory.h> 22 #include <binder/Parcel.h> 23 #include <media/IOMX.h> 24 #include <media/stagefright/foundation/ADebug.h> 25 26 namespace android { 27 28 enum { 29 CONNECT = IBinder::FIRST_CALL_TRANSACTION, 30 LIVES_LOCALLY, 31 LIST_NODES, 32 ALLOCATE_NODE, 33 FREE_NODE, 34 SEND_COMMAND, 35 GET_PARAMETER, 36 SET_PARAMETER, 37 GET_CONFIG, 38 SET_CONFIG, 39 GET_STATE, 40 ENABLE_GRAPHIC_BUFFERS, 41 USE_BUFFER, 42 USE_GRAPHIC_BUFFER, 43 STORE_META_DATA_IN_BUFFERS, 44 ALLOC_BUFFER, 45 ALLOC_BUFFER_WITH_BACKUP, 46 FREE_BUFFER, 47 FILL_BUFFER, 48 EMPTY_BUFFER, 49 GET_EXTENSION_INDEX, 50 OBSERVER_ON_MSG, 51 GET_GRAPHIC_BUFFER_USAGE, 52 }; 53 54 class BpOMX : public BpInterface<IOMX> { 55 public: 56 BpOMX(const sp<IBinder> &impl) 57 : BpInterface<IOMX>(impl) { 58 } 59 60 virtual bool livesLocally(node_id node, pid_t pid) { 61 Parcel data, reply; 62 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 63 data.writeIntPtr((intptr_t)node); 64 data.writeInt32(pid); 65 remote()->transact(LIVES_LOCALLY, data, &reply); 66 67 return reply.readInt32() != 0; 68 } 69 70 virtual status_t listNodes(List<ComponentInfo> *list) { 71 list->clear(); 72 73 Parcel data, reply; 74 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 75 remote()->transact(LIST_NODES, data, &reply); 76 77 int32_t n = reply.readInt32(); 78 for (int32_t i = 0; i < n; ++i) { 79 list->push_back(ComponentInfo()); 80 ComponentInfo &info = *--list->end(); 81 82 info.mName = reply.readString8(); 83 int32_t numRoles = reply.readInt32(); 84 for (int32_t j = 0; j < numRoles; ++j) { 85 info.mRoles.push_back(reply.readString8()); 86 } 87 } 88 89 return OK; 90 } 91 92 virtual status_t allocateNode( 93 const char *name, const sp<IOMXObserver> &observer, node_id *node) { 94 Parcel data, reply; 95 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 96 data.writeCString(name); 97 data.writeStrongBinder(observer->asBinder()); 98 remote()->transact(ALLOCATE_NODE, data, &reply); 99 100 status_t err = reply.readInt32(); 101 if (err == OK) { 102 *node = (void*)reply.readIntPtr(); 103 } else { 104 *node = 0; 105 } 106 107 return err; 108 } 109 110 virtual status_t freeNode(node_id node) { 111 Parcel data, reply; 112 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 113 data.writeIntPtr((intptr_t)node); 114 remote()->transact(FREE_NODE, data, &reply); 115 116 return reply.readInt32(); 117 } 118 119 virtual status_t sendCommand( 120 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 121 Parcel data, reply; 122 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 123 data.writeIntPtr((intptr_t)node); 124 data.writeInt32(cmd); 125 data.writeInt32(param); 126 remote()->transact(SEND_COMMAND, data, &reply); 127 128 return reply.readInt32(); 129 } 130 131 virtual status_t getParameter( 132 node_id node, OMX_INDEXTYPE index, 133 void *params, size_t size) { 134 Parcel data, reply; 135 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 136 data.writeIntPtr((intptr_t)node); 137 data.writeInt32(index); 138 data.writeInt32(size); 139 data.write(params, size); 140 remote()->transact(GET_PARAMETER, data, &reply); 141 142 status_t err = reply.readInt32(); 143 if (err != OK) { 144 return err; 145 } 146 147 reply.read(params, size); 148 149 return OK; 150 } 151 152 virtual status_t setParameter( 153 node_id node, OMX_INDEXTYPE index, 154 const void *params, size_t size) { 155 Parcel data, reply; 156 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 157 data.writeIntPtr((intptr_t)node); 158 data.writeInt32(index); 159 data.writeInt32(size); 160 data.write(params, size); 161 remote()->transact(SET_PARAMETER, data, &reply); 162 163 return reply.readInt32(); 164 } 165 166 virtual status_t getConfig( 167 node_id node, OMX_INDEXTYPE index, 168 void *params, size_t size) { 169 Parcel data, reply; 170 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 171 data.writeIntPtr((intptr_t)node); 172 data.writeInt32(index); 173 data.writeInt32(size); 174 data.write(params, size); 175 remote()->transact(GET_CONFIG, data, &reply); 176 177 status_t err = reply.readInt32(); 178 if (err != OK) { 179 return err; 180 } 181 182 reply.read(params, size); 183 184 return OK; 185 } 186 187 virtual status_t setConfig( 188 node_id node, OMX_INDEXTYPE index, 189 const void *params, size_t size) { 190 Parcel data, reply; 191 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 192 data.writeIntPtr((intptr_t)node); 193 data.writeInt32(index); 194 data.writeInt32(size); 195 data.write(params, size); 196 remote()->transact(SET_CONFIG, data, &reply); 197 198 return reply.readInt32(); 199 } 200 201 virtual status_t getState( 202 node_id node, OMX_STATETYPE* state) { 203 Parcel data, reply; 204 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 205 data.writeIntPtr((intptr_t)node); 206 remote()->transact(GET_STATE, data, &reply); 207 208 *state = static_cast<OMX_STATETYPE>(reply.readInt32()); 209 return reply.readInt32(); 210 } 211 212 virtual status_t enableGraphicBuffers( 213 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 214 Parcel data, reply; 215 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 216 data.writeIntPtr((intptr_t)node); 217 data.writeInt32(port_index); 218 data.writeInt32((uint32_t)enable); 219 remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); 220 221 status_t err = reply.readInt32(); 222 return err; 223 } 224 225 virtual status_t getGraphicBufferUsage( 226 node_id node, OMX_U32 port_index, OMX_U32* usage) { 227 Parcel data, reply; 228 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 229 data.writeIntPtr((intptr_t)node); 230 data.writeInt32(port_index); 231 remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply); 232 233 status_t err = reply.readInt32(); 234 *usage = reply.readInt32(); 235 return err; 236 } 237 238 virtual status_t useBuffer( 239 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 240 buffer_id *buffer) { 241 Parcel data, reply; 242 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 243 data.writeIntPtr((intptr_t)node); 244 data.writeInt32(port_index); 245 data.writeStrongBinder(params->asBinder()); 246 remote()->transact(USE_BUFFER, data, &reply); 247 248 status_t err = reply.readInt32(); 249 if (err != OK) { 250 *buffer = 0; 251 252 return err; 253 } 254 255 *buffer = (void*)reply.readIntPtr(); 256 257 return err; 258 } 259 260 261 virtual status_t useGraphicBuffer( 262 node_id node, OMX_U32 port_index, 263 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 264 Parcel data, reply; 265 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 266 data.writeIntPtr((intptr_t)node); 267 data.writeInt32(port_index); 268 data.write(*graphicBuffer); 269 remote()->transact(USE_GRAPHIC_BUFFER, data, &reply); 270 271 status_t err = reply.readInt32(); 272 if (err != OK) { 273 *buffer = 0; 274 275 return err; 276 } 277 278 *buffer = (void*)reply.readIntPtr(); 279 280 return err; 281 } 282 283 virtual status_t storeMetaDataInBuffers( 284 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 285 Parcel data, reply; 286 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 287 data.writeIntPtr((intptr_t)node); 288 data.writeInt32(port_index); 289 data.writeInt32((uint32_t)enable); 290 remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); 291 292 status_t err = reply.readInt32(); 293 return err; 294 } 295 296 virtual status_t allocateBuffer( 297 node_id node, OMX_U32 port_index, size_t size, 298 buffer_id *buffer, void **buffer_data) { 299 Parcel data, reply; 300 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 301 data.writeIntPtr((intptr_t)node); 302 data.writeInt32(port_index); 303 data.writeInt32(size); 304 remote()->transact(ALLOC_BUFFER, data, &reply); 305 306 status_t err = reply.readInt32(); 307 if (err != OK) { 308 *buffer = 0; 309 310 return err; 311 } 312 313 *buffer = (void *)reply.readIntPtr(); 314 *buffer_data = (void *)reply.readIntPtr(); 315 316 return err; 317 } 318 319 virtual status_t allocateBufferWithBackup( 320 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 321 buffer_id *buffer) { 322 Parcel data, reply; 323 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 324 data.writeIntPtr((intptr_t)node); 325 data.writeInt32(port_index); 326 data.writeStrongBinder(params->asBinder()); 327 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 328 329 status_t err = reply.readInt32(); 330 if (err != OK) { 331 *buffer = 0; 332 333 return err; 334 } 335 336 *buffer = (void*)reply.readIntPtr(); 337 338 return err; 339 } 340 341 virtual status_t freeBuffer( 342 node_id node, OMX_U32 port_index, buffer_id buffer) { 343 Parcel data, reply; 344 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 345 data.writeIntPtr((intptr_t)node); 346 data.writeInt32(port_index); 347 data.writeIntPtr((intptr_t)buffer); 348 remote()->transact(FREE_BUFFER, data, &reply); 349 350 return reply.readInt32(); 351 } 352 353 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 354 Parcel data, reply; 355 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 356 data.writeIntPtr((intptr_t)node); 357 data.writeIntPtr((intptr_t)buffer); 358 remote()->transact(FILL_BUFFER, data, &reply); 359 360 return reply.readInt32(); 361 } 362 363 virtual status_t emptyBuffer( 364 node_id node, 365 buffer_id buffer, 366 OMX_U32 range_offset, OMX_U32 range_length, 367 OMX_U32 flags, OMX_TICKS timestamp) { 368 Parcel data, reply; 369 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 370 data.writeIntPtr((intptr_t)node); 371 data.writeIntPtr((intptr_t)buffer); 372 data.writeInt32(range_offset); 373 data.writeInt32(range_length); 374 data.writeInt32(flags); 375 data.writeInt64(timestamp); 376 remote()->transact(EMPTY_BUFFER, data, &reply); 377 378 return reply.readInt32(); 379 } 380 381 virtual status_t getExtensionIndex( 382 node_id node, 383 const char *parameter_name, 384 OMX_INDEXTYPE *index) { 385 Parcel data, reply; 386 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 387 data.writeIntPtr((intptr_t)node); 388 data.writeCString(parameter_name); 389 390 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 391 392 status_t err = reply.readInt32(); 393 if (err == OK) { 394 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 395 } else { 396 *index = OMX_IndexComponentStartUnused; 397 } 398 399 return err; 400 } 401 }; 402 403 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 404 405 //////////////////////////////////////////////////////////////////////////////// 406 407 #define CHECK_INTERFACE(interface, data, reply) \ 408 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 409 ALOGW("Call incorrectly routed to " #interface); \ 410 return PERMISSION_DENIED; \ 411 } } while (0) 412 413 status_t BnOMX::onTransact( 414 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 415 switch (code) { 416 case LIVES_LOCALLY: 417 { 418 CHECK_INTERFACE(IOMX, data, reply); 419 node_id node = (void *)data.readIntPtr(); 420 pid_t pid = (pid_t)data.readInt32(); 421 reply->writeInt32(livesLocally(node, pid)); 422 423 return OK; 424 } 425 426 case LIST_NODES: 427 { 428 CHECK_INTERFACE(IOMX, data, reply); 429 430 List<ComponentInfo> list; 431 listNodes(&list); 432 433 reply->writeInt32(list.size()); 434 for (List<ComponentInfo>::iterator it = list.begin(); 435 it != list.end(); ++it) { 436 ComponentInfo &cur = *it; 437 438 reply->writeString8(cur.mName); 439 reply->writeInt32(cur.mRoles.size()); 440 for (List<String8>::iterator role_it = cur.mRoles.begin(); 441 role_it != cur.mRoles.end(); ++role_it) { 442 reply->writeString8(*role_it); 443 } 444 } 445 446 return NO_ERROR; 447 } 448 449 case ALLOCATE_NODE: 450 { 451 CHECK_INTERFACE(IOMX, data, reply); 452 453 const char *name = data.readCString(); 454 455 sp<IOMXObserver> observer = 456 interface_cast<IOMXObserver>(data.readStrongBinder()); 457 458 node_id node; 459 460 status_t err = allocateNode(name, observer, &node); 461 reply->writeInt32(err); 462 if (err == OK) { 463 reply->writeIntPtr((intptr_t)node); 464 } 465 466 return NO_ERROR; 467 } 468 469 case FREE_NODE: 470 { 471 CHECK_INTERFACE(IOMX, data, reply); 472 473 node_id node = (void*)data.readIntPtr(); 474 475 reply->writeInt32(freeNode(node)); 476 477 return NO_ERROR; 478 } 479 480 case SEND_COMMAND: 481 { 482 CHECK_INTERFACE(IOMX, data, reply); 483 484 node_id node = (void*)data.readIntPtr(); 485 486 OMX_COMMANDTYPE cmd = 487 static_cast<OMX_COMMANDTYPE>(data.readInt32()); 488 489 OMX_S32 param = data.readInt32(); 490 reply->writeInt32(sendCommand(node, cmd, param)); 491 492 return NO_ERROR; 493 } 494 495 case GET_PARAMETER: 496 case SET_PARAMETER: 497 case GET_CONFIG: 498 case SET_CONFIG: 499 { 500 CHECK_INTERFACE(IOMX, data, reply); 501 502 node_id node = (void*)data.readIntPtr(); 503 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 504 505 size_t size = data.readInt32(); 506 507 void *params = malloc(size); 508 data.read(params, size); 509 510 status_t err; 511 switch (code) { 512 case GET_PARAMETER: 513 err = getParameter(node, index, params, size); 514 break; 515 case SET_PARAMETER: 516 err = setParameter(node, index, params, size); 517 break; 518 case GET_CONFIG: 519 err = getConfig(node, index, params, size); 520 break; 521 case SET_CONFIG: 522 err = setConfig(node, index, params, size); 523 break; 524 default: 525 TRESPASS(); 526 } 527 528 reply->writeInt32(err); 529 530 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) { 531 reply->write(params, size); 532 } 533 534 free(params); 535 params = NULL; 536 537 return NO_ERROR; 538 } 539 540 case GET_STATE: 541 { 542 CHECK_INTERFACE(IOMX, data, reply); 543 544 node_id node = (void*)data.readIntPtr(); 545 OMX_STATETYPE state = OMX_StateInvalid; 546 547 status_t err = getState(node, &state); 548 reply->writeInt32(state); 549 reply->writeInt32(err); 550 551 return NO_ERROR; 552 } 553 554 case ENABLE_GRAPHIC_BUFFERS: 555 { 556 CHECK_INTERFACE(IOMX, data, reply); 557 558 node_id node = (void*)data.readIntPtr(); 559 OMX_U32 port_index = data.readInt32(); 560 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 561 562 status_t err = enableGraphicBuffers(node, port_index, enable); 563 reply->writeInt32(err); 564 565 return NO_ERROR; 566 } 567 568 case GET_GRAPHIC_BUFFER_USAGE: 569 { 570 CHECK_INTERFACE(IOMX, data, reply); 571 572 node_id node = (void*)data.readIntPtr(); 573 OMX_U32 port_index = data.readInt32(); 574 575 OMX_U32 usage = 0; 576 status_t err = getGraphicBufferUsage(node, port_index, &usage); 577 reply->writeInt32(err); 578 reply->writeInt32(usage); 579 580 return NO_ERROR; 581 } 582 583 case USE_BUFFER: 584 { 585 CHECK_INTERFACE(IOMX, data, reply); 586 587 node_id node = (void*)data.readIntPtr(); 588 OMX_U32 port_index = data.readInt32(); 589 sp<IMemory> params = 590 interface_cast<IMemory>(data.readStrongBinder()); 591 592 buffer_id buffer; 593 status_t err = useBuffer(node, port_index, params, &buffer); 594 reply->writeInt32(err); 595 596 if (err == OK) { 597 reply->writeIntPtr((intptr_t)buffer); 598 } 599 600 return NO_ERROR; 601 } 602 603 case USE_GRAPHIC_BUFFER: 604 { 605 CHECK_INTERFACE(IOMX, data, reply); 606 607 node_id node = (void*)data.readIntPtr(); 608 OMX_U32 port_index = data.readInt32(); 609 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 610 data.read(*graphicBuffer); 611 612 buffer_id buffer; 613 status_t err = useGraphicBuffer( 614 node, port_index, graphicBuffer, &buffer); 615 reply->writeInt32(err); 616 617 if (err == OK) { 618 reply->writeIntPtr((intptr_t)buffer); 619 } 620 621 return NO_ERROR; 622 } 623 624 case STORE_META_DATA_IN_BUFFERS: 625 { 626 CHECK_INTERFACE(IOMX, data, reply); 627 628 node_id node = (void*)data.readIntPtr(); 629 OMX_U32 port_index = data.readInt32(); 630 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 631 632 status_t err = storeMetaDataInBuffers(node, port_index, enable); 633 reply->writeInt32(err); 634 635 return NO_ERROR; 636 } 637 638 case ALLOC_BUFFER: 639 { 640 CHECK_INTERFACE(IOMX, data, reply); 641 642 node_id node = (void*)data.readIntPtr(); 643 OMX_U32 port_index = data.readInt32(); 644 size_t size = data.readInt32(); 645 646 buffer_id buffer; 647 void *buffer_data; 648 status_t err = allocateBuffer( 649 node, port_index, size, &buffer, &buffer_data); 650 reply->writeInt32(err); 651 652 if (err == OK) { 653 reply->writeIntPtr((intptr_t)buffer); 654 reply->writeIntPtr((intptr_t)buffer_data); 655 } 656 657 return NO_ERROR; 658 } 659 660 case ALLOC_BUFFER_WITH_BACKUP: 661 { 662 CHECK_INTERFACE(IOMX, data, reply); 663 664 node_id node = (void*)data.readIntPtr(); 665 OMX_U32 port_index = data.readInt32(); 666 sp<IMemory> params = 667 interface_cast<IMemory>(data.readStrongBinder()); 668 669 buffer_id buffer; 670 status_t err = allocateBufferWithBackup( 671 node, port_index, params, &buffer); 672 673 reply->writeInt32(err); 674 675 if (err == OK) { 676 reply->writeIntPtr((intptr_t)buffer); 677 } 678 679 return NO_ERROR; 680 } 681 682 case FREE_BUFFER: 683 { 684 CHECK_INTERFACE(IOMX, data, reply); 685 686 node_id node = (void*)data.readIntPtr(); 687 OMX_U32 port_index = data.readInt32(); 688 buffer_id buffer = (void*)data.readIntPtr(); 689 reply->writeInt32(freeBuffer(node, port_index, buffer)); 690 691 return NO_ERROR; 692 } 693 694 case FILL_BUFFER: 695 { 696 CHECK_INTERFACE(IOMX, data, reply); 697 698 node_id node = (void*)data.readIntPtr(); 699 buffer_id buffer = (void*)data.readIntPtr(); 700 reply->writeInt32(fillBuffer(node, buffer)); 701 702 return NO_ERROR; 703 } 704 705 case EMPTY_BUFFER: 706 { 707 CHECK_INTERFACE(IOMX, data, reply); 708 709 node_id node = (void*)data.readIntPtr(); 710 buffer_id buffer = (void*)data.readIntPtr(); 711 OMX_U32 range_offset = data.readInt32(); 712 OMX_U32 range_length = data.readInt32(); 713 OMX_U32 flags = data.readInt32(); 714 OMX_TICKS timestamp = data.readInt64(); 715 716 reply->writeInt32( 717 emptyBuffer( 718 node, buffer, range_offset, range_length, 719 flags, timestamp)); 720 721 return NO_ERROR; 722 } 723 724 case GET_EXTENSION_INDEX: 725 { 726 CHECK_INTERFACE(IOMX, data, reply); 727 728 node_id node = (void*)data.readIntPtr(); 729 const char *parameter_name = data.readCString(); 730 731 OMX_INDEXTYPE index; 732 status_t err = getExtensionIndex(node, parameter_name, &index); 733 734 reply->writeInt32(err); 735 736 if (err == OK) { 737 reply->writeInt32(index); 738 } 739 740 return OK; 741 } 742 743 default: 744 return BBinder::onTransact(code, data, reply, flags); 745 } 746 } 747 748 //////////////////////////////////////////////////////////////////////////////// 749 750 class BpOMXObserver : public BpInterface<IOMXObserver> { 751 public: 752 BpOMXObserver(const sp<IBinder> &impl) 753 : BpInterface<IOMXObserver>(impl) { 754 } 755 756 virtual void onMessage(const omx_message &msg) { 757 Parcel data, reply; 758 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 759 data.write(&msg, sizeof(msg)); 760 761 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 762 } 763 }; 764 765 IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 766 767 status_t BnOMXObserver::onTransact( 768 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 769 switch (code) { 770 case OBSERVER_ON_MSG: 771 { 772 CHECK_INTERFACE(IOMXObserver, data, reply); 773 774 omx_message msg; 775 data.read(&msg, sizeof(msg)); 776 777 // XXX Could use readInplace maybe? 778 onMessage(msg); 779 780 return NO_ERROR; 781 } 782 783 default: 784 return BBinder::onTransact(code, data, reply, flags); 785 } 786 } 787 788 } // namespace android 789