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