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 CREATE_INPUT_SURFACE, 44 SIGNAL_END_OF_INPUT_STREAM, 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(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 createInputSurface( 286 node_id node, OMX_U32 port_index, 287 sp<IGraphicBufferProducer> *bufferProducer) { 288 Parcel data, reply; 289 status_t err; 290 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 291 data.writeIntPtr((intptr_t)node); 292 data.writeInt32(port_index); 293 err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply); 294 if (err != OK) { 295 ALOGW("binder transaction failed: %d", err); 296 return err; 297 } 298 299 err = reply.readInt32(); 300 if (err != OK) { 301 return err; 302 } 303 304 *bufferProducer = IGraphicBufferProducer::asInterface( 305 reply.readStrongBinder()); 306 307 return err; 308 } 309 310 virtual status_t signalEndOfInputStream(node_id node) { 311 Parcel data, reply; 312 status_t err; 313 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 314 data.writeIntPtr((intptr_t)node); 315 err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply); 316 if (err != OK) { 317 ALOGW("binder transaction failed: %d", err); 318 return err; 319 } 320 321 return reply.readInt32(); 322 } 323 324 virtual status_t storeMetaDataInBuffers( 325 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 326 Parcel data, reply; 327 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 328 data.writeIntPtr((intptr_t)node); 329 data.writeInt32(port_index); 330 data.writeInt32((uint32_t)enable); 331 remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); 332 333 status_t err = reply.readInt32(); 334 return err; 335 } 336 337 virtual status_t allocateBuffer( 338 node_id node, OMX_U32 port_index, size_t size, 339 buffer_id *buffer, void **buffer_data) { 340 Parcel data, reply; 341 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 342 data.writeIntPtr((intptr_t)node); 343 data.writeInt32(port_index); 344 data.writeInt32(size); 345 remote()->transact(ALLOC_BUFFER, data, &reply); 346 347 status_t err = reply.readInt32(); 348 if (err != OK) { 349 *buffer = 0; 350 351 return err; 352 } 353 354 *buffer = (void *)reply.readIntPtr(); 355 *buffer_data = (void *)reply.readIntPtr(); 356 357 return err; 358 } 359 360 virtual status_t allocateBufferWithBackup( 361 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 362 buffer_id *buffer) { 363 Parcel data, reply; 364 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 365 data.writeIntPtr((intptr_t)node); 366 data.writeInt32(port_index); 367 data.writeStrongBinder(params->asBinder()); 368 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 369 370 status_t err = reply.readInt32(); 371 if (err != OK) { 372 *buffer = 0; 373 374 return err; 375 } 376 377 *buffer = (void*)reply.readIntPtr(); 378 379 return err; 380 } 381 382 virtual status_t freeBuffer( 383 node_id node, OMX_U32 port_index, buffer_id buffer) { 384 Parcel data, reply; 385 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 386 data.writeIntPtr((intptr_t)node); 387 data.writeInt32(port_index); 388 data.writeIntPtr((intptr_t)buffer); 389 remote()->transact(FREE_BUFFER, data, &reply); 390 391 return reply.readInt32(); 392 } 393 394 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 395 Parcel data, reply; 396 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 397 data.writeIntPtr((intptr_t)node); 398 data.writeIntPtr((intptr_t)buffer); 399 remote()->transact(FILL_BUFFER, data, &reply); 400 401 return reply.readInt32(); 402 } 403 404 virtual status_t emptyBuffer( 405 node_id node, 406 buffer_id buffer, 407 OMX_U32 range_offset, OMX_U32 range_length, 408 OMX_U32 flags, OMX_TICKS timestamp) { 409 Parcel data, reply; 410 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 411 data.writeIntPtr((intptr_t)node); 412 data.writeIntPtr((intptr_t)buffer); 413 data.writeInt32(range_offset); 414 data.writeInt32(range_length); 415 data.writeInt32(flags); 416 data.writeInt64(timestamp); 417 remote()->transact(EMPTY_BUFFER, data, &reply); 418 419 return reply.readInt32(); 420 } 421 422 virtual status_t getExtensionIndex( 423 node_id node, 424 const char *parameter_name, 425 OMX_INDEXTYPE *index) { 426 Parcel data, reply; 427 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 428 data.writeIntPtr((intptr_t)node); 429 data.writeCString(parameter_name); 430 431 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 432 433 status_t err = reply.readInt32(); 434 if (err == OK) { 435 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 436 } else { 437 *index = OMX_IndexComponentStartUnused; 438 } 439 440 return err; 441 } 442 }; 443 444 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 445 446 //////////////////////////////////////////////////////////////////////////////// 447 448 #define CHECK_OMX_INTERFACE(interface, data, reply) \ 449 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 450 ALOGW("Call incorrectly routed to " #interface); \ 451 return PERMISSION_DENIED; \ 452 } } while (0) 453 454 status_t BnOMX::onTransact( 455 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 456 switch (code) { 457 case LIVES_LOCALLY: 458 { 459 CHECK_OMX_INTERFACE(IOMX, data, reply); 460 node_id node = (void *)data.readIntPtr(); 461 pid_t pid = (pid_t)data.readInt32(); 462 reply->writeInt32(livesLocally(node, pid)); 463 464 return OK; 465 } 466 467 case LIST_NODES: 468 { 469 CHECK_OMX_INTERFACE(IOMX, data, reply); 470 471 List<ComponentInfo> list; 472 listNodes(&list); 473 474 reply->writeInt32(list.size()); 475 for (List<ComponentInfo>::iterator it = list.begin(); 476 it != list.end(); ++it) { 477 ComponentInfo &cur = *it; 478 479 reply->writeString8(cur.mName); 480 reply->writeInt32(cur.mRoles.size()); 481 for (List<String8>::iterator role_it = cur.mRoles.begin(); 482 role_it != cur.mRoles.end(); ++role_it) { 483 reply->writeString8(*role_it); 484 } 485 } 486 487 return NO_ERROR; 488 } 489 490 case ALLOCATE_NODE: 491 { 492 CHECK_OMX_INTERFACE(IOMX, data, reply); 493 494 const char *name = data.readCString(); 495 496 sp<IOMXObserver> observer = 497 interface_cast<IOMXObserver>(data.readStrongBinder()); 498 499 node_id node; 500 501 status_t err = allocateNode(name, observer, &node); 502 reply->writeInt32(err); 503 if (err == OK) { 504 reply->writeIntPtr((intptr_t)node); 505 } 506 507 return NO_ERROR; 508 } 509 510 case FREE_NODE: 511 { 512 CHECK_OMX_INTERFACE(IOMX, data, reply); 513 514 node_id node = (void*)data.readIntPtr(); 515 516 reply->writeInt32(freeNode(node)); 517 518 return NO_ERROR; 519 } 520 521 case SEND_COMMAND: 522 { 523 CHECK_OMX_INTERFACE(IOMX, data, reply); 524 525 node_id node = (void*)data.readIntPtr(); 526 527 OMX_COMMANDTYPE cmd = 528 static_cast<OMX_COMMANDTYPE>(data.readInt32()); 529 530 OMX_S32 param = data.readInt32(); 531 reply->writeInt32(sendCommand(node, cmd, param)); 532 533 return NO_ERROR; 534 } 535 536 case GET_PARAMETER: 537 case SET_PARAMETER: 538 case GET_CONFIG: 539 case SET_CONFIG: 540 { 541 CHECK_OMX_INTERFACE(IOMX, data, reply); 542 543 node_id node = (void*)data.readIntPtr(); 544 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 545 546 size_t size = data.readInt32(); 547 548 void *params = malloc(size); 549 data.read(params, size); 550 551 status_t err; 552 switch (code) { 553 case GET_PARAMETER: 554 err = getParameter(node, index, params, size); 555 break; 556 case SET_PARAMETER: 557 err = setParameter(node, index, params, size); 558 break; 559 case GET_CONFIG: 560 err = getConfig(node, index, params, size); 561 break; 562 case SET_CONFIG: 563 err = setConfig(node, index, params, size); 564 break; 565 default: 566 TRESPASS(); 567 } 568 569 reply->writeInt32(err); 570 571 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) { 572 reply->write(params, size); 573 } 574 575 free(params); 576 params = NULL; 577 578 return NO_ERROR; 579 } 580 581 case GET_STATE: 582 { 583 CHECK_OMX_INTERFACE(IOMX, data, reply); 584 585 node_id node = (void*)data.readIntPtr(); 586 OMX_STATETYPE state = OMX_StateInvalid; 587 588 status_t err = getState(node, &state); 589 reply->writeInt32(state); 590 reply->writeInt32(err); 591 592 return NO_ERROR; 593 } 594 595 case ENABLE_GRAPHIC_BUFFERS: 596 { 597 CHECK_OMX_INTERFACE(IOMX, data, reply); 598 599 node_id node = (void*)data.readIntPtr(); 600 OMX_U32 port_index = data.readInt32(); 601 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 602 603 status_t err = enableGraphicBuffers(node, port_index, enable); 604 reply->writeInt32(err); 605 606 return NO_ERROR; 607 } 608 609 case GET_GRAPHIC_BUFFER_USAGE: 610 { 611 CHECK_OMX_INTERFACE(IOMX, data, reply); 612 613 node_id node = (void*)data.readIntPtr(); 614 OMX_U32 port_index = data.readInt32(); 615 616 OMX_U32 usage = 0; 617 status_t err = getGraphicBufferUsage(node, port_index, &usage); 618 reply->writeInt32(err); 619 reply->writeInt32(usage); 620 621 return NO_ERROR; 622 } 623 624 case USE_BUFFER: 625 { 626 CHECK_OMX_INTERFACE(IOMX, data, reply); 627 628 node_id node = (void*)data.readIntPtr(); 629 OMX_U32 port_index = data.readInt32(); 630 sp<IMemory> params = 631 interface_cast<IMemory>(data.readStrongBinder()); 632 633 buffer_id buffer; 634 status_t err = useBuffer(node, port_index, params, &buffer); 635 reply->writeInt32(err); 636 637 if (err == OK) { 638 reply->writeIntPtr((intptr_t)buffer); 639 } 640 641 return NO_ERROR; 642 } 643 644 case USE_GRAPHIC_BUFFER: 645 { 646 CHECK_OMX_INTERFACE(IOMX, data, reply); 647 648 node_id node = (void*)data.readIntPtr(); 649 OMX_U32 port_index = data.readInt32(); 650 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 651 data.read(*graphicBuffer); 652 653 buffer_id buffer; 654 status_t err = useGraphicBuffer( 655 node, port_index, graphicBuffer, &buffer); 656 reply->writeInt32(err); 657 658 if (err == OK) { 659 reply->writeIntPtr((intptr_t)buffer); 660 } 661 662 return NO_ERROR; 663 } 664 665 case CREATE_INPUT_SURFACE: 666 { 667 CHECK_OMX_INTERFACE(IOMX, data, reply); 668 669 node_id node = (void*)data.readIntPtr(); 670 OMX_U32 port_index = data.readInt32(); 671 672 sp<IGraphicBufferProducer> bufferProducer; 673 status_t err = createInputSurface(node, port_index, 674 &bufferProducer); 675 676 reply->writeInt32(err); 677 678 if (err == OK) { 679 reply->writeStrongBinder(bufferProducer->asBinder()); 680 } 681 682 return NO_ERROR; 683 } 684 685 case SIGNAL_END_OF_INPUT_STREAM: 686 { 687 CHECK_OMX_INTERFACE(IOMX, data, reply); 688 689 node_id node = (void*)data.readIntPtr(); 690 691 status_t err = signalEndOfInputStream(node); 692 reply->writeInt32(err); 693 694 return NO_ERROR; 695 } 696 697 case STORE_META_DATA_IN_BUFFERS: 698 { 699 CHECK_OMX_INTERFACE(IOMX, data, reply); 700 701 node_id node = (void*)data.readIntPtr(); 702 OMX_U32 port_index = data.readInt32(); 703 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 704 705 status_t err = storeMetaDataInBuffers(node, port_index, enable); 706 reply->writeInt32(err); 707 708 return NO_ERROR; 709 } 710 711 case ALLOC_BUFFER: 712 { 713 CHECK_OMX_INTERFACE(IOMX, data, reply); 714 715 node_id node = (void*)data.readIntPtr(); 716 OMX_U32 port_index = data.readInt32(); 717 size_t size = data.readInt32(); 718 719 buffer_id buffer; 720 void *buffer_data; 721 status_t err = allocateBuffer( 722 node, port_index, size, &buffer, &buffer_data); 723 reply->writeInt32(err); 724 725 if (err == OK) { 726 reply->writeIntPtr((intptr_t)buffer); 727 reply->writeIntPtr((intptr_t)buffer_data); 728 } 729 730 return NO_ERROR; 731 } 732 733 case ALLOC_BUFFER_WITH_BACKUP: 734 { 735 CHECK_OMX_INTERFACE(IOMX, data, reply); 736 737 node_id node = (void*)data.readIntPtr(); 738 OMX_U32 port_index = data.readInt32(); 739 sp<IMemory> params = 740 interface_cast<IMemory>(data.readStrongBinder()); 741 742 buffer_id buffer; 743 status_t err = allocateBufferWithBackup( 744 node, port_index, params, &buffer); 745 746 reply->writeInt32(err); 747 748 if (err == OK) { 749 reply->writeIntPtr((intptr_t)buffer); 750 } 751 752 return NO_ERROR; 753 } 754 755 case FREE_BUFFER: 756 { 757 CHECK_OMX_INTERFACE(IOMX, data, reply); 758 759 node_id node = (void*)data.readIntPtr(); 760 OMX_U32 port_index = data.readInt32(); 761 buffer_id buffer = (void*)data.readIntPtr(); 762 reply->writeInt32(freeBuffer(node, port_index, buffer)); 763 764 return NO_ERROR; 765 } 766 767 case FILL_BUFFER: 768 { 769 CHECK_OMX_INTERFACE(IOMX, data, reply); 770 771 node_id node = (void*)data.readIntPtr(); 772 buffer_id buffer = (void*)data.readIntPtr(); 773 reply->writeInt32(fillBuffer(node, buffer)); 774 775 return NO_ERROR; 776 } 777 778 case EMPTY_BUFFER: 779 { 780 CHECK_OMX_INTERFACE(IOMX, data, reply); 781 782 node_id node = (void*)data.readIntPtr(); 783 buffer_id buffer = (void*)data.readIntPtr(); 784 OMX_U32 range_offset = data.readInt32(); 785 OMX_U32 range_length = data.readInt32(); 786 OMX_U32 flags = data.readInt32(); 787 OMX_TICKS timestamp = data.readInt64(); 788 789 reply->writeInt32( 790 emptyBuffer( 791 node, buffer, range_offset, range_length, 792 flags, timestamp)); 793 794 return NO_ERROR; 795 } 796 797 case GET_EXTENSION_INDEX: 798 { 799 CHECK_OMX_INTERFACE(IOMX, data, reply); 800 801 node_id node = (void*)data.readIntPtr(); 802 const char *parameter_name = data.readCString(); 803 804 OMX_INDEXTYPE index; 805 status_t err = getExtensionIndex(node, parameter_name, &index); 806 807 reply->writeInt32(err); 808 809 if (err == OK) { 810 reply->writeInt32(index); 811 } 812 813 return OK; 814 } 815 816 default: 817 return BBinder::onTransact(code, data, reply, flags); 818 } 819 } 820 821 //////////////////////////////////////////////////////////////////////////////// 822 823 class BpOMXObserver : public BpInterface<IOMXObserver> { 824 public: 825 BpOMXObserver(const sp<IBinder> &impl) 826 : BpInterface<IOMXObserver>(impl) { 827 } 828 829 virtual void onMessage(const omx_message &msg) { 830 Parcel data, reply; 831 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 832 data.write(&msg, sizeof(msg)); 833 834 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 835 } 836 }; 837 838 IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 839 840 status_t BnOMXObserver::onTransact( 841 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 842 switch (code) { 843 case OBSERVER_ON_MSG: 844 { 845 CHECK_OMX_INTERFACE(IOMXObserver, data, reply); 846 847 omx_message msg; 848 data.read(&msg, sizeof(msg)); 849 850 // XXX Could use readInplace maybe? 851 onMessage(msg); 852 853 return NO_ERROR; 854 } 855 856 default: 857 return BBinder::onTransact(code, data, reply, flags); 858 } 859 } 860 861 } // namespace android 862