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