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