IOMX.cpp revision e2ce6458659c6e1bad420357b61dc10cd8bbe2ab
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 <media/stagefright/foundation/ADebug.h> 9#include <surfaceflinger/ISurface.h> 10#include <surfaceflinger/Surface.h> 11 12namespace android { 13 14enum { 15 CONNECT = IBinder::FIRST_CALL_TRANSACTION, 16 LIVES_LOCALLY, 17 LIST_NODES, 18 ALLOCATE_NODE, 19 FREE_NODE, 20 SEND_COMMAND, 21 GET_PARAMETER, 22 SET_PARAMETER, 23 GET_CONFIG, 24 SET_CONFIG, 25 ENABLE_GRAPHIC_BUFFERS, 26 USE_BUFFER, 27 USE_GRAPHIC_BUFFER, 28 STORE_META_DATA_IN_BUFFERS, 29 ALLOC_BUFFER, 30 ALLOC_BUFFER_WITH_BACKUP, 31 FREE_BUFFER, 32 FILL_BUFFER, 33 EMPTY_BUFFER, 34 GET_EXTENSION_INDEX, 35 OBSERVER_ON_MSG, 36 GET_GRAPHIC_BUFFER_USAGE, 37}; 38 39class BpOMX : public BpInterface<IOMX> { 40public: 41 BpOMX(const sp<IBinder> &impl) 42 : BpInterface<IOMX>(impl) { 43 } 44 45 virtual bool livesLocally(pid_t pid) { 46 Parcel data, reply; 47 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 48 data.writeInt32(pid); 49 remote()->transact(LIVES_LOCALLY, data, &reply); 50 51 return reply.readInt32() != 0; 52 } 53 54 virtual status_t listNodes(List<ComponentInfo> *list) { 55 list->clear(); 56 57 Parcel data, reply; 58 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 59 remote()->transact(LIST_NODES, data, &reply); 60 61 int32_t n = reply.readInt32(); 62 for (int32_t i = 0; i < n; ++i) { 63 list->push_back(ComponentInfo()); 64 ComponentInfo &info = *--list->end(); 65 66 info.mName = reply.readString8(); 67 int32_t numRoles = reply.readInt32(); 68 for (int32_t j = 0; j < numRoles; ++j) { 69 info.mRoles.push_back(reply.readString8()); 70 } 71 } 72 73 return OK; 74 } 75 76 virtual status_t allocateNode( 77 const char *name, const sp<IOMXObserver> &observer, node_id *node) { 78 Parcel data, reply; 79 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 80 data.writeCString(name); 81 data.writeStrongBinder(observer->asBinder()); 82 remote()->transact(ALLOCATE_NODE, data, &reply); 83 84 status_t err = reply.readInt32(); 85 if (err == OK) { 86 *node = (void*)reply.readIntPtr(); 87 } else { 88 *node = 0; 89 } 90 91 return err; 92 } 93 94 virtual status_t freeNode(node_id node) { 95 Parcel data, reply; 96 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 97 data.writeIntPtr((intptr_t)node); 98 remote()->transact(FREE_NODE, data, &reply); 99 100 return reply.readInt32(); 101 } 102 103 virtual status_t sendCommand( 104 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 105 Parcel data, reply; 106 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 107 data.writeIntPtr((intptr_t)node); 108 data.writeInt32(cmd); 109 data.writeInt32(param); 110 remote()->transact(SEND_COMMAND, data, &reply); 111 112 return reply.readInt32(); 113 } 114 115 virtual status_t getParameter( 116 node_id node, OMX_INDEXTYPE index, 117 void *params, size_t size) { 118 Parcel data, reply; 119 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 120 data.writeIntPtr((intptr_t)node); 121 data.writeInt32(index); 122 data.writeInt32(size); 123 data.write(params, size); 124 remote()->transact(GET_PARAMETER, data, &reply); 125 126 status_t err = reply.readInt32(); 127 if (err != OK) { 128 return err; 129 } 130 131 reply.read(params, size); 132 133 return OK; 134 } 135 136 virtual status_t setParameter( 137 node_id node, OMX_INDEXTYPE index, 138 const void *params, size_t size) { 139 Parcel data, reply; 140 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 141 data.writeIntPtr((intptr_t)node); 142 data.writeInt32(index); 143 data.writeInt32(size); 144 data.write(params, size); 145 remote()->transact(SET_PARAMETER, data, &reply); 146 147 return reply.readInt32(); 148 } 149 150 virtual status_t getConfig( 151 node_id node, OMX_INDEXTYPE index, 152 void *params, size_t size) { 153 Parcel data, reply; 154 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 155 data.writeIntPtr((intptr_t)node); 156 data.writeInt32(index); 157 data.writeInt32(size); 158 data.write(params, size); 159 remote()->transact(GET_CONFIG, data, &reply); 160 161 status_t err = reply.readInt32(); 162 if (err != OK) { 163 return err; 164 } 165 166 reply.read(params, size); 167 168 return OK; 169 } 170 171 virtual status_t setConfig( 172 node_id node, OMX_INDEXTYPE index, 173 const void *params, size_t size) { 174 Parcel data, reply; 175 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 176 data.writeIntPtr((intptr_t)node); 177 data.writeInt32(index); 178 data.writeInt32(size); 179 data.write(params, size); 180 remote()->transact(SET_CONFIG, data, &reply); 181 182 return reply.readInt32(); 183 } 184 185 virtual status_t enableGraphicBuffers( 186 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 187 Parcel data, reply; 188 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 189 data.writeIntPtr((intptr_t)node); 190 data.writeInt32(port_index); 191 data.writeInt32((uint32_t)enable); 192 remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); 193 194 status_t err = reply.readInt32(); 195 return err; 196 } 197 198 virtual status_t getGraphicBufferUsage( 199 node_id node, OMX_U32 port_index, OMX_U32* usage) { 200 Parcel data, reply; 201 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 202 data.writeIntPtr((intptr_t)node); 203 data.writeInt32(port_index); 204 remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply); 205 206 status_t err = reply.readInt32(); 207 *usage = reply.readInt32(); 208 return err; 209 } 210 211 virtual status_t useBuffer( 212 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 213 buffer_id *buffer) { 214 Parcel data, reply; 215 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 216 data.writeIntPtr((intptr_t)node); 217 data.writeInt32(port_index); 218 data.writeStrongBinder(params->asBinder()); 219 remote()->transact(USE_BUFFER, data, &reply); 220 221 status_t err = reply.readInt32(); 222 if (err != OK) { 223 *buffer = 0; 224 225 return err; 226 } 227 228 *buffer = (void*)reply.readIntPtr(); 229 230 return err; 231 } 232 233 234 virtual status_t useGraphicBuffer( 235 node_id node, OMX_U32 port_index, 236 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 237 Parcel data, reply; 238 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 239 data.writeIntPtr((intptr_t)node); 240 data.writeInt32(port_index); 241 data.write(*graphicBuffer); 242 remote()->transact(USE_GRAPHIC_BUFFER, data, &reply); 243 244 status_t err = reply.readInt32(); 245 if (err != OK) { 246 *buffer = 0; 247 248 return err; 249 } 250 251 *buffer = (void*)reply.readIntPtr(); 252 253 return err; 254 } 255 256 virtual status_t storeMetaDataInBuffers( 257 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 258 Parcel data, reply; 259 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 260 data.writeIntPtr((intptr_t)node); 261 data.writeInt32(port_index); 262 data.writeInt32((uint32_t)enable); 263 remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); 264 265 status_t err = reply.readInt32(); 266 return err; 267 } 268 269 virtual status_t allocateBuffer( 270 node_id node, OMX_U32 port_index, size_t size, 271 buffer_id *buffer, void **buffer_data) { 272 Parcel data, reply; 273 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 274 data.writeIntPtr((intptr_t)node); 275 data.writeInt32(port_index); 276 data.writeInt32(size); 277 remote()->transact(ALLOC_BUFFER, data, &reply); 278 279 status_t err = reply.readInt32(); 280 if (err != OK) { 281 *buffer = 0; 282 283 return err; 284 } 285 286 *buffer = (void *)reply.readIntPtr(); 287 *buffer_data = (void *)reply.readIntPtr(); 288 289 return err; 290 } 291 292 virtual status_t allocateBufferWithBackup( 293 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 294 buffer_id *buffer) { 295 Parcel data, reply; 296 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 297 data.writeIntPtr((intptr_t)node); 298 data.writeInt32(port_index); 299 data.writeStrongBinder(params->asBinder()); 300 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 301 302 status_t err = reply.readInt32(); 303 if (err != OK) { 304 *buffer = 0; 305 306 return err; 307 } 308 309 *buffer = (void*)reply.readIntPtr(); 310 311 return err; 312 } 313 314 virtual status_t freeBuffer( 315 node_id node, OMX_U32 port_index, buffer_id buffer) { 316 Parcel data, reply; 317 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 318 data.writeIntPtr((intptr_t)node); 319 data.writeInt32(port_index); 320 data.writeIntPtr((intptr_t)buffer); 321 remote()->transact(FREE_BUFFER, data, &reply); 322 323 return reply.readInt32(); 324 } 325 326 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 327 Parcel data, reply; 328 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 329 data.writeIntPtr((intptr_t)node); 330 data.writeIntPtr((intptr_t)buffer); 331 remote()->transact(FILL_BUFFER, data, &reply); 332 333 return reply.readInt32(); 334 } 335 336 virtual status_t emptyBuffer( 337 node_id node, 338 buffer_id buffer, 339 OMX_U32 range_offset, OMX_U32 range_length, 340 OMX_U32 flags, OMX_TICKS timestamp) { 341 Parcel data, reply; 342 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 343 data.writeIntPtr((intptr_t)node); 344 data.writeIntPtr((intptr_t)buffer); 345 data.writeInt32(range_offset); 346 data.writeInt32(range_length); 347 data.writeInt32(flags); 348 data.writeInt64(timestamp); 349 remote()->transact(EMPTY_BUFFER, data, &reply); 350 351 return reply.readInt32(); 352 } 353 354 virtual status_t getExtensionIndex( 355 node_id node, 356 const char *parameter_name, 357 OMX_INDEXTYPE *index) { 358 Parcel data, reply; 359 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 360 data.writeIntPtr((intptr_t)node); 361 data.writeCString(parameter_name); 362 363 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 364 365 status_t err = reply.readInt32(); 366 if (err == OK) { 367 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 368 } else { 369 *index = OMX_IndexComponentStartUnused; 370 } 371 372 return err; 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 case SET_PARAMETER: 468 case GET_CONFIG: 469 case SET_CONFIG: 470 { 471 CHECK_INTERFACE(IOMX, data, reply); 472 473 node_id node = (void*)data.readIntPtr(); 474 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 475 476 size_t size = data.readInt32(); 477 478 void *params = malloc(size); 479 data.read(params, size); 480 481 status_t err; 482 switch (code) { 483 case GET_PARAMETER: 484 err = getParameter(node, index, params, size); 485 break; 486 case SET_PARAMETER: 487 err = setParameter(node, index, params, size); 488 break; 489 case GET_CONFIG: 490 err = getConfig(node, index, params, size); 491 break; 492 case SET_CONFIG: 493 err = setConfig(node, index, params, size); 494 break; 495 default: 496 TRESPASS(); 497 } 498 499 reply->writeInt32(err); 500 501 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) { 502 reply->write(params, size); 503 } 504 505 free(params); 506 params = NULL; 507 508 return NO_ERROR; 509 } 510 511 case ENABLE_GRAPHIC_BUFFERS: 512 { 513 CHECK_INTERFACE(IOMX, data, reply); 514 515 node_id node = (void*)data.readIntPtr(); 516 OMX_U32 port_index = data.readInt32(); 517 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 518 519 status_t err = enableGraphicBuffers(node, port_index, enable); 520 reply->writeInt32(err); 521 522 return NO_ERROR; 523 } 524 525 case GET_GRAPHIC_BUFFER_USAGE: 526 { 527 CHECK_INTERFACE(IOMX, data, reply); 528 529 node_id node = (void*)data.readIntPtr(); 530 OMX_U32 port_index = data.readInt32(); 531 532 OMX_U32 usage = 0; 533 status_t err = getGraphicBufferUsage(node, port_index, &usage); 534 reply->writeInt32(err); 535 reply->writeInt32(usage); 536 537 return NO_ERROR; 538 } 539 540 case USE_BUFFER: 541 { 542 CHECK_INTERFACE(IOMX, data, reply); 543 544 node_id node = (void*)data.readIntPtr(); 545 OMX_U32 port_index = data.readInt32(); 546 sp<IMemory> params = 547 interface_cast<IMemory>(data.readStrongBinder()); 548 549 buffer_id buffer; 550 status_t err = useBuffer(node, port_index, params, &buffer); 551 reply->writeInt32(err); 552 553 if (err == OK) { 554 reply->writeIntPtr((intptr_t)buffer); 555 } 556 557 return NO_ERROR; 558 } 559 560 case USE_GRAPHIC_BUFFER: 561 { 562 CHECK_INTERFACE(IOMX, data, reply); 563 564 node_id node = (void*)data.readIntPtr(); 565 OMX_U32 port_index = data.readInt32(); 566 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 567 data.read(*graphicBuffer); 568 569 buffer_id buffer; 570 status_t err = useGraphicBuffer( 571 node, port_index, graphicBuffer, &buffer); 572 reply->writeInt32(err); 573 574 if (err == OK) { 575 reply->writeIntPtr((intptr_t)buffer); 576 } 577 578 return NO_ERROR; 579 } 580 581 case STORE_META_DATA_IN_BUFFERS: 582 { 583 CHECK_INTERFACE(IOMX, data, reply); 584 585 node_id node = (void*)data.readIntPtr(); 586 OMX_U32 port_index = data.readInt32(); 587 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 588 589 status_t err = storeMetaDataInBuffers(node, port_index, enable); 590 reply->writeInt32(err); 591 592 return NO_ERROR; 593 } 594 595 case ALLOC_BUFFER: 596 { 597 CHECK_INTERFACE(IOMX, data, reply); 598 599 node_id node = (void*)data.readIntPtr(); 600 OMX_U32 port_index = data.readInt32(); 601 size_t size = data.readInt32(); 602 603 buffer_id buffer; 604 void *buffer_data; 605 status_t err = allocateBuffer( 606 node, port_index, size, &buffer, &buffer_data); 607 reply->writeInt32(err); 608 609 if (err == OK) { 610 reply->writeIntPtr((intptr_t)buffer); 611 reply->writeIntPtr((intptr_t)buffer_data); 612 } 613 614 return NO_ERROR; 615 } 616 617 case ALLOC_BUFFER_WITH_BACKUP: 618 { 619 CHECK_INTERFACE(IOMX, data, reply); 620 621 node_id node = (void*)data.readIntPtr(); 622 OMX_U32 port_index = data.readInt32(); 623 sp<IMemory> params = 624 interface_cast<IMemory>(data.readStrongBinder()); 625 626 buffer_id buffer; 627 status_t err = allocateBufferWithBackup( 628 node, port_index, params, &buffer); 629 630 reply->writeInt32(err); 631 632 if (err == OK) { 633 reply->writeIntPtr((intptr_t)buffer); 634 } 635 636 return NO_ERROR; 637 } 638 639 case FREE_BUFFER: 640 { 641 CHECK_INTERFACE(IOMX, data, reply); 642 643 node_id node = (void*)data.readIntPtr(); 644 OMX_U32 port_index = data.readInt32(); 645 buffer_id buffer = (void*)data.readIntPtr(); 646 reply->writeInt32(freeBuffer(node, port_index, buffer)); 647 648 return NO_ERROR; 649 } 650 651 case FILL_BUFFER: 652 { 653 CHECK_INTERFACE(IOMX, data, reply); 654 655 node_id node = (void*)data.readIntPtr(); 656 buffer_id buffer = (void*)data.readIntPtr(); 657 reply->writeInt32(fillBuffer(node, buffer)); 658 659 return NO_ERROR; 660 } 661 662 case EMPTY_BUFFER: 663 { 664 CHECK_INTERFACE(IOMX, data, reply); 665 666 node_id node = (void*)data.readIntPtr(); 667 buffer_id buffer = (void*)data.readIntPtr(); 668 OMX_U32 range_offset = data.readInt32(); 669 OMX_U32 range_length = data.readInt32(); 670 OMX_U32 flags = data.readInt32(); 671 OMX_TICKS timestamp = data.readInt64(); 672 673 reply->writeInt32( 674 emptyBuffer( 675 node, buffer, range_offset, range_length, 676 flags, timestamp)); 677 678 return NO_ERROR; 679 } 680 681 case GET_EXTENSION_INDEX: 682 { 683 CHECK_INTERFACE(IOMX, data, reply); 684 685 node_id node = (void*)data.readIntPtr(); 686 const char *parameter_name = data.readCString(); 687 688 OMX_INDEXTYPE index; 689 status_t err = getExtensionIndex(node, parameter_name, &index); 690 691 reply->writeInt32(err); 692 693 if (err == OK) { 694 reply->writeInt32(index); 695 } 696 697 return OK; 698 } 699 700 default: 701 return BBinder::onTransact(code, data, reply, flags); 702 } 703} 704 705//////////////////////////////////////////////////////////////////////////////// 706 707class BpOMXObserver : public BpInterface<IOMXObserver> { 708public: 709 BpOMXObserver(const sp<IBinder> &impl) 710 : BpInterface<IOMXObserver>(impl) { 711 } 712 713 virtual void onMessage(const omx_message &msg) { 714 Parcel data, reply; 715 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 716 data.write(&msg, sizeof(msg)); 717 718 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 719 } 720}; 721 722IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 723 724status_t BnOMXObserver::onTransact( 725 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 726 switch (code) { 727 case OBSERVER_ON_MSG: 728 { 729 CHECK_INTERFACE(IOMXObserver, data, reply); 730 731 omx_message msg; 732 data.read(&msg, sizeof(msg)); 733 734 // XXX Could use readInplace maybe? 735 onMessage(msg); 736 737 return NO_ERROR; 738 } 739 740 default: 741 return BBinder::onTransact(code, data, reply, flags); 742 } 743} 744 745} // namespace android 746