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