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