IOMX.cpp revision e353ce4b3c95a55df510da9376ad7878338e984f
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 <sys/mman.h> 22 23#include <binder/IMemory.h> 24#include <binder/Parcel.h> 25#include <media/IOMX.h> 26#include <media/stagefright/foundation/ADebug.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 GET_STATE, 42 ENABLE_GRAPHIC_BUFFERS, 43 USE_BUFFER, 44 USE_GRAPHIC_BUFFER, 45 CREATE_INPUT_SURFACE, 46 SIGNAL_END_OF_INPUT_STREAM, 47 STORE_META_DATA_IN_BUFFERS, 48 PREPARE_FOR_ADAPTIVE_PLAYBACK, 49 ALLOC_BUFFER, 50 ALLOC_BUFFER_WITH_BACKUP, 51 FREE_BUFFER, 52 FILL_BUFFER, 53 EMPTY_BUFFER, 54 GET_EXTENSION_INDEX, 55 OBSERVER_ON_MSG, 56 GET_GRAPHIC_BUFFER_USAGE, 57 SET_INTERNAL_OPTION, 58 UPDATE_GRAPHIC_BUFFER_IN_META, 59 CONFIGURE_VIDEO_TUNNEL_MODE, 60}; 61 62class BpOMX : public BpInterface<IOMX> { 63public: 64 BpOMX(const sp<IBinder> &impl) 65 : BpInterface<IOMX>(impl) { 66 } 67 68 virtual bool livesLocally(node_id node, pid_t pid) { 69 Parcel data, reply; 70 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 71 data.writeInt32((int32_t)node); 72 data.writeInt32(pid); 73 remote()->transact(LIVES_LOCALLY, data, &reply); 74 75 return reply.readInt32() != 0; 76 } 77 78 virtual status_t listNodes(List<ComponentInfo> *list) { 79 list->clear(); 80 81 Parcel data, reply; 82 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 83 remote()->transact(LIST_NODES, data, &reply); 84 85 int32_t n = reply.readInt32(); 86 for (int32_t i = 0; i < n; ++i) { 87 list->push_back(ComponentInfo()); 88 ComponentInfo &info = *--list->end(); 89 90 info.mName = reply.readString8(); 91 int32_t numRoles = reply.readInt32(); 92 for (int32_t j = 0; j < numRoles; ++j) { 93 info.mRoles.push_back(reply.readString8()); 94 } 95 } 96 97 return OK; 98 } 99 100 virtual status_t allocateNode( 101 const char *name, const sp<IOMXObserver> &observer, node_id *node) { 102 Parcel data, reply; 103 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 104 data.writeCString(name); 105 data.writeStrongBinder(observer->asBinder()); 106 remote()->transact(ALLOCATE_NODE, data, &reply); 107 108 status_t err = reply.readInt32(); 109 if (err == OK) { 110 *node = (node_id)reply.readInt32(); 111 } else { 112 *node = 0; 113 } 114 115 return err; 116 } 117 118 virtual status_t freeNode(node_id node) { 119 Parcel data, reply; 120 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 121 data.writeInt32((int32_t)node); 122 remote()->transact(FREE_NODE, data, &reply); 123 124 return reply.readInt32(); 125 } 126 127 virtual status_t sendCommand( 128 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 129 Parcel data, reply; 130 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 131 data.writeInt32((int32_t)node); 132 data.writeInt32(cmd); 133 data.writeInt32(param); 134 remote()->transact(SEND_COMMAND, data, &reply); 135 136 return reply.readInt32(); 137 } 138 139 virtual status_t getParameter( 140 node_id node, OMX_INDEXTYPE index, 141 void *params, size_t size) { 142 Parcel data, reply; 143 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 144 data.writeInt32((int32_t)node); 145 data.writeInt32(index); 146 data.writeInt64(size); 147 data.write(params, size); 148 remote()->transact(GET_PARAMETER, data, &reply); 149 150 status_t err = reply.readInt32(); 151 if (err != OK) { 152 return err; 153 } 154 155 reply.read(params, size); 156 157 return OK; 158 } 159 160 virtual status_t setParameter( 161 node_id node, OMX_INDEXTYPE index, 162 const void *params, size_t size) { 163 Parcel data, reply; 164 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 165 data.writeInt32((int32_t)node); 166 data.writeInt32(index); 167 data.writeInt64(size); 168 data.write(params, size); 169 remote()->transact(SET_PARAMETER, data, &reply); 170 171 return reply.readInt32(); 172 } 173 174 virtual status_t getConfig( 175 node_id node, OMX_INDEXTYPE index, 176 void *params, size_t size) { 177 Parcel data, reply; 178 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 179 data.writeInt32((int32_t)node); 180 data.writeInt32(index); 181 data.writeInt64(size); 182 data.write(params, size); 183 remote()->transact(GET_CONFIG, data, &reply); 184 185 status_t err = reply.readInt32(); 186 if (err != OK) { 187 return err; 188 } 189 190 reply.read(params, size); 191 192 return OK; 193 } 194 195 virtual status_t setConfig( 196 node_id node, OMX_INDEXTYPE index, 197 const void *params, size_t size) { 198 Parcel data, reply; 199 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 200 data.writeInt32((int32_t)node); 201 data.writeInt32(index); 202 data.writeInt64(size); 203 data.write(params, size); 204 remote()->transact(SET_CONFIG, data, &reply); 205 206 return reply.readInt32(); 207 } 208 209 virtual status_t getState( 210 node_id node, OMX_STATETYPE* state) { 211 Parcel data, reply; 212 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 213 data.writeInt32((int32_t)node); 214 remote()->transact(GET_STATE, data, &reply); 215 216 *state = static_cast<OMX_STATETYPE>(reply.readInt32()); 217 return reply.readInt32(); 218 } 219 220 virtual status_t enableGraphicBuffers( 221 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 222 Parcel data, reply; 223 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 224 data.writeInt32((int32_t)node); 225 data.writeInt32(port_index); 226 data.writeInt32((uint32_t)enable); 227 remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); 228 229 status_t err = reply.readInt32(); 230 return err; 231 } 232 233 virtual status_t getGraphicBufferUsage( 234 node_id node, OMX_U32 port_index, OMX_U32* usage) { 235 Parcel data, reply; 236 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 237 data.writeInt32((int32_t)node); 238 data.writeInt32(port_index); 239 remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply); 240 241 status_t err = reply.readInt32(); 242 *usage = reply.readInt32(); 243 return err; 244 } 245 246 virtual status_t useBuffer( 247 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 248 buffer_id *buffer, OMX_BOOL /* crossProcess */) { 249 Parcel data, reply; 250 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 251 data.writeInt32((int32_t)node); 252 data.writeInt32(port_index); 253 data.writeStrongBinder(params->asBinder()); 254 remote()->transact(USE_BUFFER, data, &reply); 255 256 status_t err = reply.readInt32(); 257 if (err != OK) { 258 *buffer = 0; 259 260 return err; 261 } 262 263 *buffer = (buffer_id)reply.readInt32(); 264 265 return err; 266 } 267 268 269 virtual status_t useGraphicBuffer( 270 node_id node, OMX_U32 port_index, 271 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 272 Parcel data, reply; 273 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 274 data.writeInt32((int32_t)node); 275 data.writeInt32(port_index); 276 data.write(*graphicBuffer); 277 remote()->transact(USE_GRAPHIC_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 = (buffer_id)reply.readInt32(); 287 288 return err; 289 } 290 291 virtual status_t updateGraphicBufferInMeta( 292 node_id node, OMX_U32 port_index, 293 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) { 294 Parcel data, reply; 295 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 296 data.writeInt32((int32_t)node); 297 data.writeInt32(port_index); 298 data.write(*graphicBuffer); 299 data.writeInt32((int32_t)buffer); 300 remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply); 301 302 status_t err = reply.readInt32(); 303 return err; 304 } 305 306 virtual status_t createInputSurface( 307 node_id node, OMX_U32 port_index, 308 sp<IGraphicBufferProducer> *bufferProducer) { 309 Parcel data, reply; 310 status_t err; 311 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 312 data.writeInt32((int32_t)node); 313 data.writeInt32(port_index); 314 err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply); 315 if (err != OK) { 316 ALOGW("binder transaction failed: %d", err); 317 return err; 318 } 319 320 err = reply.readInt32(); 321 if (err != OK) { 322 return err; 323 } 324 325 *bufferProducer = IGraphicBufferProducer::asInterface( 326 reply.readStrongBinder()); 327 328 return err; 329 } 330 331 virtual status_t signalEndOfInputStream(node_id node) { 332 Parcel data, reply; 333 status_t err; 334 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 335 data.writeInt32((int32_t)node); 336 err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply); 337 if (err != OK) { 338 ALOGW("binder transaction failed: %d", err); 339 return err; 340 } 341 342 return reply.readInt32(); 343 } 344 345 virtual status_t storeMetaDataInBuffers( 346 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 347 Parcel data, reply; 348 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 349 data.writeInt32((int32_t)node); 350 data.writeInt32(port_index); 351 data.writeInt32((uint32_t)enable); 352 remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); 353 354 status_t err = reply.readInt32(); 355 return err; 356 } 357 358 virtual status_t prepareForAdaptivePlayback( 359 node_id node, OMX_U32 port_index, OMX_BOOL enable, 360 OMX_U32 max_width, OMX_U32 max_height) { 361 Parcel data, reply; 362 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 363 data.writeInt32((int32_t)node); 364 data.writeInt32(port_index); 365 data.writeInt32((int32_t)enable); 366 data.writeInt32(max_width); 367 data.writeInt32(max_height); 368 remote()->transact(PREPARE_FOR_ADAPTIVE_PLAYBACK, data, &reply); 369 370 status_t err = reply.readInt32(); 371 return err; 372 } 373 374 virtual status_t configureVideoTunnelMode( 375 node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, 376 OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) { 377 Parcel data, reply; 378 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 379 data.writeInt32((int32_t)node); 380 data.writeInt32(portIndex); 381 data.writeInt32((int32_t)tunneled); 382 data.writeInt32(audioHwSync); 383 remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply); 384 385 status_t err = reply.readInt32(); 386 if (err == OK && sidebandHandle) { 387 *sidebandHandle = (native_handle_t *)reply.readNativeHandle(); 388 } 389 return err; 390 } 391 392 393 virtual status_t allocateBuffer( 394 node_id node, OMX_U32 port_index, size_t size, 395 buffer_id *buffer, void **buffer_data) { 396 Parcel data, reply; 397 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 398 data.writeInt32((int32_t)node); 399 data.writeInt32(port_index); 400 data.writeInt64(size); 401 remote()->transact(ALLOC_BUFFER, data, &reply); 402 403 status_t err = reply.readInt32(); 404 if (err != OK) { 405 *buffer = 0; 406 407 return err; 408 } 409 410 *buffer = (buffer_id)reply.readInt32(); 411 *buffer_data = (void *)reply.readInt64(); 412 413 return err; 414 } 415 416 virtual status_t allocateBufferWithBackup( 417 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 418 buffer_id *buffer, OMX_BOOL /* crossProcess */) { 419 Parcel data, reply; 420 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 421 data.writeInt32((int32_t)node); 422 data.writeInt32(port_index); 423 data.writeStrongBinder(params->asBinder()); 424 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 425 426 status_t err = reply.readInt32(); 427 if (err != OK) { 428 *buffer = 0; 429 430 return err; 431 } 432 433 *buffer = (buffer_id)reply.readInt32(); 434 435 return err; 436 } 437 438 virtual status_t freeBuffer( 439 node_id node, OMX_U32 port_index, buffer_id buffer) { 440 Parcel data, reply; 441 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 442 data.writeInt32((int32_t)node); 443 data.writeInt32(port_index); 444 data.writeInt32((int32_t)buffer); 445 remote()->transact(FREE_BUFFER, data, &reply); 446 447 return reply.readInt32(); 448 } 449 450 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 451 Parcel data, reply; 452 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 453 data.writeInt32((int32_t)node); 454 data.writeInt32((int32_t)buffer); 455 remote()->transact(FILL_BUFFER, data, &reply); 456 457 return reply.readInt32(); 458 } 459 460 virtual status_t emptyBuffer( 461 node_id node, 462 buffer_id buffer, 463 OMX_U32 range_offset, OMX_U32 range_length, 464 OMX_U32 flags, OMX_TICKS timestamp) { 465 Parcel data, reply; 466 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 467 data.writeInt32((int32_t)node); 468 data.writeInt32((int32_t)buffer); 469 data.writeInt32(range_offset); 470 data.writeInt32(range_length); 471 data.writeInt32(flags); 472 data.writeInt64(timestamp); 473 remote()->transact(EMPTY_BUFFER, data, &reply); 474 475 return reply.readInt32(); 476 } 477 478 virtual status_t getExtensionIndex( 479 node_id node, 480 const char *parameter_name, 481 OMX_INDEXTYPE *index) { 482 Parcel data, reply; 483 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 484 data.writeInt32((int32_t)node); 485 data.writeCString(parameter_name); 486 487 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 488 489 status_t err = reply.readInt32(); 490 if (err == OK) { 491 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 492 } else { 493 *index = OMX_IndexComponentStartUnused; 494 } 495 496 return err; 497 } 498 499 virtual status_t setInternalOption( 500 node_id node, 501 OMX_U32 port_index, 502 InternalOptionType type, 503 const void *optionData, 504 size_t size) { 505 Parcel data, reply; 506 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 507 data.writeInt32((int32_t)node); 508 data.writeInt32(port_index); 509 data.writeInt64(size); 510 data.write(optionData, size); 511 data.writeInt32(type); 512 remote()->transact(SET_INTERNAL_OPTION, data, &reply); 513 514 return reply.readInt32(); 515 } 516}; 517 518IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 519 520//////////////////////////////////////////////////////////////////////////////// 521 522#define CHECK_OMX_INTERFACE(interface, data, reply) \ 523 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 524 ALOGW("Call incorrectly routed to " #interface); \ 525 return PERMISSION_DENIED; \ 526 } } while (0) 527 528status_t BnOMX::onTransact( 529 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 530 switch (code) { 531 case LIVES_LOCALLY: 532 { 533 CHECK_OMX_INTERFACE(IOMX, data, reply); 534 node_id node = (node_id)data.readInt32(); 535 pid_t pid = (pid_t)data.readInt32(); 536 reply->writeInt32(livesLocally(node, pid)); 537 538 return OK; 539 } 540 541 case LIST_NODES: 542 { 543 CHECK_OMX_INTERFACE(IOMX, data, reply); 544 545 List<ComponentInfo> list; 546 listNodes(&list); 547 548 reply->writeInt32(list.size()); 549 for (List<ComponentInfo>::iterator it = list.begin(); 550 it != list.end(); ++it) { 551 ComponentInfo &cur = *it; 552 553 reply->writeString8(cur.mName); 554 reply->writeInt32(cur.mRoles.size()); 555 for (List<String8>::iterator role_it = cur.mRoles.begin(); 556 role_it != cur.mRoles.end(); ++role_it) { 557 reply->writeString8(*role_it); 558 } 559 } 560 561 return NO_ERROR; 562 } 563 564 case ALLOCATE_NODE: 565 { 566 CHECK_OMX_INTERFACE(IOMX, data, reply); 567 568 const char *name = data.readCString(); 569 570 sp<IOMXObserver> observer = 571 interface_cast<IOMXObserver>(data.readStrongBinder()); 572 573 node_id node; 574 575 status_t err = allocateNode(name, observer, &node); 576 reply->writeInt32(err); 577 if (err == OK) { 578 reply->writeInt32((int32_t)node); 579 } 580 581 return NO_ERROR; 582 } 583 584 case FREE_NODE: 585 { 586 CHECK_OMX_INTERFACE(IOMX, data, reply); 587 588 node_id node = (node_id)data.readInt32(); 589 590 reply->writeInt32(freeNode(node)); 591 592 return NO_ERROR; 593 } 594 595 case SEND_COMMAND: 596 { 597 CHECK_OMX_INTERFACE(IOMX, data, reply); 598 599 node_id node = (node_id)data.readInt32(); 600 601 OMX_COMMANDTYPE cmd = 602 static_cast<OMX_COMMANDTYPE>(data.readInt32()); 603 604 OMX_S32 param = data.readInt32(); 605 reply->writeInt32(sendCommand(node, cmd, param)); 606 607 return NO_ERROR; 608 } 609 610 case GET_PARAMETER: 611 case SET_PARAMETER: 612 case GET_CONFIG: 613 case SET_CONFIG: 614 case SET_INTERNAL_OPTION: 615 { 616 CHECK_OMX_INTERFACE(IOMX, data, reply); 617 618 node_id node = (node_id)data.readInt32(); 619 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 620 621 size_t size = data.readInt64(); 622 623 status_t err = NOT_ENOUGH_DATA; 624 void *params = NULL; 625 size_t pageSize = 0; 626 size_t allocSize = 0; 627 // this only applies to a subset of devices, and was obsoleted in M 628 bool mightBeThumbnailMode = (code == SET_CONFIG && size == sizeof(OMX_BOOL)); 629 if (!mightBeThumbnailMode && (code != SET_INTERNAL_OPTION && size < 8)) { 630 // we expect the structure to contain at least the size and 631 // version, 8 bytes total 632 ALOGE("b/27207275 (%zu)", size); 633 android_errorWriteLog(0x534e4554, "27207275"); 634 } else { 635 err = NO_MEMORY; 636 pageSize = (size_t) sysconf(_SC_PAGE_SIZE); 637 if (size > SIZE_MAX - (pageSize * 2)) { 638 ALOGE("requested param size too big"); 639 } else { 640 allocSize = (size + pageSize * 2) & ~(pageSize - 1); 641 params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE, 642 MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */); 643 } 644 if (params != MAP_FAILED) { 645 err = data.read(params, size); 646 if (err != OK) { 647 android_errorWriteLog(0x534e4554, "26914474"); 648 } else { 649 err = NOT_ENOUGH_DATA; 650 OMX_U32 declaredSize = *(OMX_U32*)params; 651 if (!mightBeThumbnailMode && 652 code != SET_INTERNAL_OPTION && declaredSize > size) { 653 // the buffer says it's bigger than it actually is 654 ALOGE("b/27207275 (%u/%zu)", declaredSize, size); 655 android_errorWriteLog(0x534e4554, "27207275"); 656 } else { 657 // mark the last page as inaccessible, to avoid exploitation 658 // of codecs that access past the end of the allocation because 659 // they didn't check the size 660 if (mprotect((char*)params + allocSize - pageSize, pageSize, 661 PROT_NONE) != 0) { 662 ALOGE("mprotect failed: %s", strerror(errno)); 663 } else { 664 switch (code) { 665 case GET_PARAMETER: 666 err = getParameter(node, index, params, size); 667 break; 668 case SET_PARAMETER: 669 err = setParameter(node, index, params, size); 670 break; 671 case GET_CONFIG: 672 err = getConfig(node, index, params, size); 673 break; 674 case SET_CONFIG: 675 err = setConfig(node, index, params, size); 676 break; 677 case SET_INTERNAL_OPTION: 678 { 679 InternalOptionType type = 680 (InternalOptionType)data.readInt32(); 681 682 err = setInternalOption(node, index, type, params, size); 683 break; 684 } 685 686 default: 687 TRESPASS(); 688 } 689 } 690 } 691 } 692 } else { 693 ALOGE("couldn't map: %s", strerror(errno)); 694 } 695 } 696 697 reply->writeInt32(err); 698 699 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) { 700 reply->write(params, size); 701 } 702 703 if (params) { 704 munmap(params, allocSize); 705 } 706 params = NULL; 707 708 return NO_ERROR; 709 } 710 711 case GET_STATE: 712 { 713 CHECK_OMX_INTERFACE(IOMX, data, reply); 714 715 node_id node = (node_id)data.readInt32(); 716 OMX_STATETYPE state = OMX_StateInvalid; 717 718 status_t err = getState(node, &state); 719 reply->writeInt32(state); 720 reply->writeInt32(err); 721 722 return NO_ERROR; 723 } 724 725 case ENABLE_GRAPHIC_BUFFERS: 726 { 727 CHECK_OMX_INTERFACE(IOMX, data, reply); 728 729 node_id node = (node_id)data.readInt32(); 730 OMX_U32 port_index = data.readInt32(); 731 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 732 733 status_t err = enableGraphicBuffers(node, port_index, enable); 734 reply->writeInt32(err); 735 736 return NO_ERROR; 737 } 738 739 case GET_GRAPHIC_BUFFER_USAGE: 740 { 741 CHECK_OMX_INTERFACE(IOMX, data, reply); 742 743 node_id node = (node_id)data.readInt32(); 744 OMX_U32 port_index = data.readInt32(); 745 746 OMX_U32 usage = 0; 747 status_t err = getGraphicBufferUsage(node, port_index, &usage); 748 reply->writeInt32(err); 749 reply->writeInt32(usage); 750 751 return NO_ERROR; 752 } 753 754 case USE_BUFFER: 755 { 756 CHECK_OMX_INTERFACE(IOMX, data, reply); 757 758 node_id node = (node_id)data.readInt32(); 759 OMX_U32 port_index = data.readInt32(); 760 sp<IMemory> params = 761 interface_cast<IMemory>(data.readStrongBinder()); 762 763 buffer_id buffer; 764 status_t err = useBuffer( 765 node, port_index, params, &buffer, OMX_TRUE /* crossProcess */); 766 reply->writeInt32(err); 767 768 if (err == OK) { 769 reply->writeInt32((int32_t)buffer); 770 } 771 772 return NO_ERROR; 773 } 774 775 case USE_GRAPHIC_BUFFER: 776 { 777 CHECK_OMX_INTERFACE(IOMX, data, reply); 778 779 node_id node = (node_id)data.readInt32(); 780 OMX_U32 port_index = data.readInt32(); 781 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 782 data.read(*graphicBuffer); 783 784 buffer_id buffer; 785 status_t err = useGraphicBuffer( 786 node, port_index, graphicBuffer, &buffer); 787 reply->writeInt32(err); 788 789 if (err == OK) { 790 reply->writeInt32((int32_t)buffer); 791 } 792 793 return NO_ERROR; 794 } 795 796 case UPDATE_GRAPHIC_BUFFER_IN_META: 797 { 798 CHECK_OMX_INTERFACE(IOMX, data, reply); 799 800 node_id node = (node_id)data.readInt32(); 801 OMX_U32 port_index = data.readInt32(); 802 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 803 data.read(*graphicBuffer); 804 buffer_id buffer = (buffer_id)data.readInt32(); 805 806 status_t err = updateGraphicBufferInMeta( 807 node, port_index, graphicBuffer, buffer); 808 reply->writeInt32(err); 809 810 return NO_ERROR; 811 } 812 813 case CREATE_INPUT_SURFACE: 814 { 815 CHECK_OMX_INTERFACE(IOMX, data, reply); 816 817 node_id node = (node_id)data.readInt32(); 818 OMX_U32 port_index = data.readInt32(); 819 820 sp<IGraphicBufferProducer> bufferProducer; 821 status_t err = createInputSurface(node, port_index, 822 &bufferProducer); 823 824 reply->writeInt32(err); 825 826 if (err == OK) { 827 reply->writeStrongBinder(bufferProducer->asBinder()); 828 } 829 830 return NO_ERROR; 831 } 832 833 case SIGNAL_END_OF_INPUT_STREAM: 834 { 835 CHECK_OMX_INTERFACE(IOMX, data, reply); 836 837 node_id node = (node_id)data.readInt32(); 838 839 status_t err = signalEndOfInputStream(node); 840 reply->writeInt32(err); 841 842 return NO_ERROR; 843 } 844 845 case STORE_META_DATA_IN_BUFFERS: 846 { 847 CHECK_OMX_INTERFACE(IOMX, data, reply); 848 849 node_id node = (node_id)data.readInt32(); 850 OMX_U32 port_index = data.readInt32(); 851 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 852 853 status_t err = 854 // only control output metadata via Binder 855 port_index != 1 /* kOutputPortIndex */ ? BAD_VALUE : 856 storeMetaDataInBuffers(node, port_index, enable); 857 reply->writeInt32(err); 858 859 return NO_ERROR; 860 } 861 862 case PREPARE_FOR_ADAPTIVE_PLAYBACK: 863 { 864 CHECK_OMX_INTERFACE(IOMX, data, reply); 865 866 node_id node = (node_id)data.readInt32(); 867 OMX_U32 port_index = data.readInt32(); 868 OMX_BOOL enable = (OMX_BOOL)data.readInt32(); 869 OMX_U32 max_width = data.readInt32(); 870 OMX_U32 max_height = data.readInt32(); 871 872 status_t err = prepareForAdaptivePlayback( 873 node, port_index, enable, max_width, max_height); 874 reply->writeInt32(err); 875 876 return NO_ERROR; 877 } 878 879 case CONFIGURE_VIDEO_TUNNEL_MODE: 880 { 881 CHECK_OMX_INTERFACE(IOMX, data, reply); 882 883 node_id node = (node_id)data.readInt32(); 884 OMX_U32 port_index = data.readInt32(); 885 OMX_BOOL tunneled = (OMX_BOOL)data.readInt32(); 886 OMX_U32 audio_hw_sync = data.readInt32(); 887 888 native_handle_t *sideband_handle = NULL; 889 status_t err = configureVideoTunnelMode( 890 node, port_index, tunneled, audio_hw_sync, &sideband_handle); 891 reply->writeInt32(err); 892 if(err == OK){ 893 reply->writeNativeHandle(sideband_handle); 894 } 895 896 return NO_ERROR; 897 } 898 899 case ALLOC_BUFFER: 900 { 901 CHECK_OMX_INTERFACE(IOMX, data, reply); 902 903 node_id node = (node_id)data.readInt32(); 904 OMX_U32 port_index = data.readInt32(); 905 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) { 906 ALOGE("b/24310423"); 907 reply->writeInt32(INVALID_OPERATION); 908 return NO_ERROR; 909 } 910 911 size_t size = data.readInt64(); 912 913 buffer_id buffer; 914 void *buffer_data; 915 status_t err = allocateBuffer( 916 node, port_index, size, &buffer, &buffer_data); 917 reply->writeInt32(err); 918 919 if (err == OK) { 920 reply->writeInt32((int32_t)buffer); 921 reply->writeInt64((uintptr_t)buffer_data); 922 } 923 924 return NO_ERROR; 925 } 926 927 case ALLOC_BUFFER_WITH_BACKUP: 928 { 929 CHECK_OMX_INTERFACE(IOMX, data, reply); 930 931 node_id node = (node_id)data.readInt32(); 932 OMX_U32 port_index = data.readInt32(); 933 sp<IMemory> params = 934 interface_cast<IMemory>(data.readStrongBinder()); 935 936 buffer_id buffer; 937 status_t err = allocateBufferWithBackup( 938 node, port_index, params, &buffer, OMX_TRUE /* crossProcess */); 939 940 reply->writeInt32(err); 941 942 if (err == OK) { 943 reply->writeInt32((int32_t)buffer); 944 } 945 946 return NO_ERROR; 947 } 948 949 case FREE_BUFFER: 950 { 951 CHECK_OMX_INTERFACE(IOMX, data, reply); 952 953 node_id node = (node_id)data.readInt32(); 954 OMX_U32 port_index = data.readInt32(); 955 buffer_id buffer = (buffer_id)data.readInt32(); 956 reply->writeInt32(freeBuffer(node, port_index, buffer)); 957 958 return NO_ERROR; 959 } 960 961 case FILL_BUFFER: 962 { 963 CHECK_OMX_INTERFACE(IOMX, data, reply); 964 965 node_id node = (node_id)data.readInt32(); 966 buffer_id buffer = (buffer_id)data.readInt32(); 967 reply->writeInt32(fillBuffer(node, buffer)); 968 969 return NO_ERROR; 970 } 971 972 case EMPTY_BUFFER: 973 { 974 CHECK_OMX_INTERFACE(IOMX, data, reply); 975 976 node_id node = (node_id)data.readInt32(); 977 buffer_id buffer = (buffer_id)data.readInt32(); 978 OMX_U32 range_offset = data.readInt32(); 979 OMX_U32 range_length = data.readInt32(); 980 OMX_U32 flags = data.readInt32(); 981 OMX_TICKS timestamp = data.readInt64(); 982 983 reply->writeInt32( 984 emptyBuffer( 985 node, buffer, range_offset, range_length, 986 flags, timestamp)); 987 988 return NO_ERROR; 989 } 990 991 case GET_EXTENSION_INDEX: 992 { 993 CHECK_OMX_INTERFACE(IOMX, data, reply); 994 995 node_id node = (node_id)data.readInt32(); 996 const char *parameter_name = data.readCString(); 997 998 OMX_INDEXTYPE index; 999 status_t err = getExtensionIndex(node, parameter_name, &index); 1000 1001 reply->writeInt32(err); 1002 1003 if (err == OK) { 1004 reply->writeInt32(index); 1005 } 1006 1007 return OK; 1008 } 1009 1010 default: 1011 return BBinder::onTransact(code, data, reply, flags); 1012 } 1013} 1014 1015//////////////////////////////////////////////////////////////////////////////// 1016 1017class BpOMXObserver : public BpInterface<IOMXObserver> { 1018public: 1019 BpOMXObserver(const sp<IBinder> &impl) 1020 : BpInterface<IOMXObserver>(impl) { 1021 } 1022 1023 virtual void onMessage(const omx_message &msg) { 1024 Parcel data, reply; 1025 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 1026 data.write(&msg, sizeof(msg)); 1027 1028 ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg)); 1029 1030 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 1031 } 1032}; 1033 1034IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 1035 1036status_t BnOMXObserver::onTransact( 1037 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 1038 switch (code) { 1039 case OBSERVER_ON_MSG: 1040 { 1041 CHECK_OMX_INTERFACE(IOMXObserver, data, reply); 1042 1043 omx_message msg; 1044 data.read(&msg, sizeof(msg)); 1045 1046 ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg)); 1047 1048 // XXX Could use readInplace maybe? 1049 onMessage(msg); 1050 1051 return NO_ERROR; 1052 } 1053 1054 default: 1055 return BBinder::onTransact(code, data, reply, flags); 1056 } 1057} 1058 1059} // namespace android 1060