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