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