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