IOMX.cpp revision 8b938cdab5bd3d074d9b41bc2915fcfc11e47f27
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 <ui/ISurface.h> 9 10namespace android { 11 12enum { 13 CONNECT = IBinder::FIRST_CALL_TRANSACTION, 14 LIST_NODES, 15 ALLOCATE_NODE, 16 FREE_NODE, 17 SEND_COMMAND, 18 GET_PARAMETER, 19 SET_PARAMETER, 20 USE_BUFFER, 21 ALLOC_BUFFER, 22 ALLOC_BUFFER_WITH_BACKUP, 23 FREE_BUFFER, 24 OBSERVE_NODE, 25 FILL_BUFFER, 26 EMPTY_BUFFER, 27 CREATE_RENDERER, 28 OBSERVER_ON_MSG, 29 RENDERER_RENDER, 30}; 31 32static void *readVoidStar(const Parcel *parcel) { 33 // FIX if sizeof(void *) != sizeof(int32) 34 return (void *)parcel->readInt32(); 35} 36 37static void writeVoidStar(void *x, Parcel *parcel) { 38 // FIX if sizeof(void *) != sizeof(int32) 39 parcel->writeInt32((int32_t)x); 40} 41 42class BpOMX : public BpInterface<IOMX> { 43public: 44 BpOMX(const sp<IBinder> &impl) 45 : BpInterface<IOMX>(impl) { 46 } 47 48#if IOMX_USES_SOCKETS 49 virtual status_t connect(int *sd) { 50 Parcel data, reply; 51 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 52 remote()->transact(CONNECT, data, &reply); 53 54 status_t err = reply.readInt32(); 55 if (err == OK) { 56 *sd = dup(reply.readFileDescriptor()); 57 } else { 58 *sd = -1; 59 } 60 61 return reply.readInt32(); 62 } 63#endif 64 65 virtual status_t list_nodes(List<String8> *list) { 66 list->clear(); 67 68 Parcel data, reply; 69 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 70 remote()->transact(LIST_NODES, data, &reply); 71 72 int32_t n = reply.readInt32(); 73 for (int32_t i = 0; i < n; ++i) { 74 String8 s = reply.readString8(); 75 76 list->push_back(s); 77 } 78 79 return OK; 80 } 81 82 virtual status_t allocate_node(const char *name, node_id *node) { 83 Parcel data, reply; 84 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 85 data.writeCString(name); 86 remote()->transact(ALLOCATE_NODE, data, &reply); 87 88 status_t err = reply.readInt32(); 89 if (err == OK) { 90 *node = readVoidStar(&reply); 91 } else { 92 *node = 0; 93 } 94 95 return err; 96 } 97 98 virtual status_t free_node(node_id node) { 99 Parcel data, reply; 100 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 101 writeVoidStar(node, &data); 102 remote()->transact(FREE_NODE, data, &reply); 103 104 return reply.readInt32(); 105 } 106 107 virtual status_t send_command( 108 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 109 Parcel data, reply; 110 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 111 writeVoidStar(node, &data); 112 data.writeInt32(cmd); 113 data.writeInt32(param); 114 remote()->transact(SEND_COMMAND, data, &reply); 115 116 return reply.readInt32(); 117 } 118 119 virtual status_t get_parameter( 120 node_id node, OMX_INDEXTYPE index, 121 void *params, size_t size) { 122 Parcel data, reply; 123 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 124 writeVoidStar(node, &data); 125 data.writeInt32(index); 126 data.writeInt32(size); 127 data.write(params, size); 128 remote()->transact(GET_PARAMETER, data, &reply); 129 130 status_t err = reply.readInt32(); 131 if (err != OK) { 132 return err; 133 } 134 135 reply.read(params, size); 136 137 return OK; 138 } 139 140 virtual status_t set_parameter( 141 node_id node, OMX_INDEXTYPE index, 142 const void *params, size_t size) { 143 Parcel data, reply; 144 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 145 writeVoidStar(node, &data); 146 data.writeInt32(index); 147 data.writeInt32(size); 148 data.write(params, size); 149 remote()->transact(SET_PARAMETER, data, &reply); 150 151 return reply.readInt32(); 152 } 153 154 virtual status_t use_buffer( 155 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 156 buffer_id *buffer) { 157 Parcel data, reply; 158 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 159 writeVoidStar(node, &data); 160 data.writeInt32(port_index); 161 data.writeStrongBinder(params->asBinder()); 162 remote()->transact(USE_BUFFER, data, &reply); 163 164 status_t err = reply.readInt32(); 165 if (err != OK) { 166 *buffer = 0; 167 168 return err; 169 } 170 171 *buffer = readVoidStar(&reply); 172 173 return err; 174 } 175 176 virtual status_t allocate_buffer( 177 node_id node, OMX_U32 port_index, size_t size, 178 buffer_id *buffer) { 179 Parcel data, reply; 180 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 181 writeVoidStar(node, &data); 182 data.writeInt32(port_index); 183 data.writeInt32(size); 184 remote()->transact(ALLOC_BUFFER, data, &reply); 185 186 status_t err = reply.readInt32(); 187 if (err != OK) { 188 *buffer = 0; 189 190 return err; 191 } 192 193 *buffer = readVoidStar(&reply); 194 195 return err; 196 } 197 198 virtual status_t allocate_buffer_with_backup( 199 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 200 buffer_id *buffer) { 201 Parcel data, reply; 202 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 203 writeVoidStar(node, &data); 204 data.writeInt32(port_index); 205 data.writeStrongBinder(params->asBinder()); 206 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 207 208 status_t err = reply.readInt32(); 209 if (err != OK) { 210 *buffer = 0; 211 212 return err; 213 } 214 215 *buffer = readVoidStar(&reply); 216 217 return err; 218 } 219 220 virtual status_t free_buffer( 221 node_id node, OMX_U32 port_index, buffer_id buffer) { 222 Parcel data, reply; 223 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 224 writeVoidStar(node, &data); 225 data.writeInt32(port_index); 226 writeVoidStar(buffer, &data); 227 remote()->transact(FREE_BUFFER, data, &reply); 228 229 return reply.readInt32(); 230 } 231 232#if !IOMX_USES_SOCKETS 233 virtual status_t observe_node( 234 node_id node, const sp<IOMXObserver> &observer) { 235 Parcel data, reply; 236 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 237 writeVoidStar(node, &data); 238 data.writeStrongBinder(observer->asBinder()); 239 remote()->transact(OBSERVE_NODE, data, &reply); 240 241 return reply.readInt32(); 242 } 243 244 virtual void fill_buffer(node_id node, buffer_id buffer) { 245 Parcel data, reply; 246 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 247 writeVoidStar(node, &data); 248 writeVoidStar(buffer, &data); 249 remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); 250 } 251 252 virtual void empty_buffer( 253 node_id node, 254 buffer_id buffer, 255 OMX_U32 range_offset, OMX_U32 range_length, 256 OMX_U32 flags, OMX_TICKS timestamp) { 257 Parcel data, reply; 258 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 259 writeVoidStar(node, &data); 260 writeVoidStar(buffer, &data); 261 data.writeInt32(range_offset); 262 data.writeInt32(range_length); 263 data.writeInt32(flags); 264 data.writeInt64(timestamp); 265 remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); 266 } 267#endif 268 269 virtual sp<IOMXRenderer> createRenderer( 270 const sp<ISurface> &surface, 271 const char *componentName, 272 OMX_COLOR_FORMATTYPE colorFormat, 273 size_t encodedWidth, size_t encodedHeight, 274 size_t displayWidth, size_t displayHeight) { 275 Parcel data, reply; 276 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 277 278 data.writeStrongBinder(surface->asBinder()); 279 data.writeCString(componentName); 280 data.writeInt32(colorFormat); 281 data.writeInt32(encodedWidth); 282 data.writeInt32(encodedHeight); 283 data.writeInt32(displayWidth); 284 data.writeInt32(displayHeight); 285 286 remote()->transact(CREATE_RENDERER, data, &reply); 287 288 return interface_cast<IOMXRenderer>(reply.readStrongBinder()); 289 } 290}; 291 292IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 293 294//////////////////////////////////////////////////////////////////////////////// 295 296#define CHECK_INTERFACE(interface, data, reply) \ 297 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 298 LOGW("Call incorrectly routed to " #interface); \ 299 return PERMISSION_DENIED; \ 300 } } while (0) 301 302status_t BnOMX::onTransact( 303 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 304 switch (code) { 305#if IOMX_USES_SOCKETS 306 case CONNECT: 307 { 308 CHECK_INTERFACE(IOMX, data, reply); 309 310 int s; 311 status_t err = connect(&s); 312 313 reply->writeInt32(err); 314 if (err == OK) { 315 assert(s >= 0); 316 reply->writeDupFileDescriptor(s); 317 close(s); 318 s = -1; 319 } else { 320 assert(s == -1); 321 } 322 323 return NO_ERROR; 324 } 325#endif 326 327 case LIST_NODES: 328 { 329 CHECK_INTERFACE(IOMX, data, reply); 330 331 List<String8> list; 332 list_nodes(&list); 333 334 reply->writeInt32(list.size()); 335 for (List<String8>::iterator it = list.begin(); 336 it != list.end(); ++it) { 337 reply->writeString8(*it); 338 } 339 340 return NO_ERROR; 341 } 342 343 case ALLOCATE_NODE: 344 { 345 CHECK_INTERFACE(IOMX, data, reply); 346 347 node_id node; 348 status_t err = allocate_node(data.readCString(), &node); 349 reply->writeInt32(err); 350 if (err == OK) { 351 writeVoidStar(node, reply); 352 } 353 354 return NO_ERROR; 355 } 356 357 case FREE_NODE: 358 { 359 CHECK_INTERFACE(IOMX, data, reply); 360 361 node_id node = readVoidStar(&data); 362 363 reply->writeInt32(free_node(node)); 364 365 return NO_ERROR; 366 } 367 368 case SEND_COMMAND: 369 { 370 CHECK_INTERFACE(IOMX, data, reply); 371 372 node_id node = readVoidStar(&data); 373 374 OMX_COMMANDTYPE cmd = 375 static_cast<OMX_COMMANDTYPE>(data.readInt32()); 376 377 OMX_S32 param = data.readInt32(); 378 reply->writeInt32(send_command(node, cmd, param)); 379 380 return NO_ERROR; 381 } 382 383 case GET_PARAMETER: 384 { 385 CHECK_INTERFACE(IOMX, data, reply); 386 387 node_id node = readVoidStar(&data); 388 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 389 390 size_t size = data.readInt32(); 391 392 // XXX I am not happy with this but Parcel::readInplace didn't work. 393 void *params = malloc(size); 394 data.read(params, size); 395 396 status_t err = get_parameter(node, index, params, size); 397 398 reply->writeInt32(err); 399 400 if (err == OK) { 401 reply->write(params, size); 402 } 403 404 free(params); 405 params = NULL; 406 407 return NO_ERROR; 408 } 409 410 case SET_PARAMETER: 411 { 412 CHECK_INTERFACE(IOMX, data, reply); 413 414 node_id node = readVoidStar(&data); 415 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 416 417 size_t size = data.readInt32(); 418 void *params = const_cast<void *>(data.readInplace(size)); 419 420 reply->writeInt32(set_parameter(node, index, params, size)); 421 422 return NO_ERROR; 423 } 424 425 case USE_BUFFER: 426 { 427 CHECK_INTERFACE(IOMX, data, reply); 428 429 node_id node = readVoidStar(&data); 430 OMX_U32 port_index = data.readInt32(); 431 sp<IMemory> params = 432 interface_cast<IMemory>(data.readStrongBinder()); 433 434 buffer_id buffer; 435 status_t err = use_buffer(node, port_index, params, &buffer); 436 reply->writeInt32(err); 437 438 if (err == OK) { 439 writeVoidStar(buffer, reply); 440 } 441 442 return NO_ERROR; 443 } 444 445 case ALLOC_BUFFER: 446 { 447 CHECK_INTERFACE(IOMX, data, reply); 448 449 node_id node = readVoidStar(&data); 450 OMX_U32 port_index = data.readInt32(); 451 size_t size = data.readInt32(); 452 453 buffer_id buffer; 454 status_t err = allocate_buffer(node, port_index, size, &buffer); 455 reply->writeInt32(err); 456 457 if (err == OK) { 458 writeVoidStar(buffer, reply); 459 } 460 461 return NO_ERROR; 462 } 463 464 case ALLOC_BUFFER_WITH_BACKUP: 465 { 466 CHECK_INTERFACE(IOMX, data, reply); 467 468 node_id node = readVoidStar(&data); 469 OMX_U32 port_index = data.readInt32(); 470 sp<IMemory> params = 471 interface_cast<IMemory>(data.readStrongBinder()); 472 473 buffer_id buffer; 474 status_t err = allocate_buffer_with_backup( 475 node, port_index, params, &buffer); 476 477 reply->writeInt32(err); 478 479 if (err == OK) { 480 writeVoidStar(buffer, reply); 481 } 482 483 return NO_ERROR; 484 } 485 486 case FREE_BUFFER: 487 { 488 CHECK_INTERFACE(IOMX, data, reply); 489 490 node_id node = readVoidStar(&data); 491 OMX_U32 port_index = data.readInt32(); 492 buffer_id buffer = readVoidStar(&data); 493 reply->writeInt32(free_buffer(node, port_index, buffer)); 494 495 return NO_ERROR; 496 } 497 498#if !IOMX_USES_SOCKETS 499 case OBSERVE_NODE: 500 { 501 CHECK_INTERFACE(IOMX, data, reply); 502 503 node_id node = readVoidStar(&data); 504 sp<IOMXObserver> observer = 505 interface_cast<IOMXObserver>(data.readStrongBinder()); 506 reply->writeInt32(observe_node(node, observer)); 507 508 return NO_ERROR; 509 } 510 511 case FILL_BUFFER: 512 { 513 CHECK_INTERFACE(IOMX, data, reply); 514 515 node_id node = readVoidStar(&data); 516 buffer_id buffer = readVoidStar(&data); 517 fill_buffer(node, buffer); 518 519 return NO_ERROR; 520 } 521 522 case EMPTY_BUFFER: 523 { 524 CHECK_INTERFACE(IOMX, data, reply); 525 526 node_id node = readVoidStar(&data); 527 buffer_id buffer = readVoidStar(&data); 528 OMX_U32 range_offset = data.readInt32(); 529 OMX_U32 range_length = data.readInt32(); 530 OMX_U32 flags = data.readInt32(); 531 OMX_TICKS timestamp = data.readInt64(); 532 533 empty_buffer( 534 node, buffer, range_offset, range_length, 535 flags, timestamp); 536 537 return NO_ERROR; 538 } 539#endif 540 541 case CREATE_RENDERER: 542 { 543 CHECK_INTERFACE(IOMX, data, reply); 544 545 sp<ISurface> isurface = 546 interface_cast<ISurface>(data.readStrongBinder()); 547 548 const char *componentName = data.readCString(); 549 550 OMX_COLOR_FORMATTYPE colorFormat = 551 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32()); 552 553 size_t encodedWidth = (size_t)data.readInt32(); 554 size_t encodedHeight = (size_t)data.readInt32(); 555 size_t displayWidth = (size_t)data.readInt32(); 556 size_t displayHeight = (size_t)data.readInt32(); 557 558 sp<IOMXRenderer> renderer = 559 createRenderer(isurface, componentName, colorFormat, 560 encodedWidth, encodedHeight, 561 displayWidth, displayHeight); 562 563 reply->writeStrongBinder(renderer->asBinder()); 564 565 return OK; 566 } 567 568 default: 569 return BBinder::onTransact(code, data, reply, flags); 570 } 571} 572 573//////////////////////////////////////////////////////////////////////////////// 574 575class BpOMXObserver : public BpInterface<IOMXObserver> { 576public: 577 BpOMXObserver(const sp<IBinder> &impl) 578 : BpInterface<IOMXObserver>(impl) { 579 } 580 581 virtual void on_message(const omx_message &msg) { 582 Parcel data, reply; 583 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 584 data.write(&msg, sizeof(msg)); 585 586 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 587 } 588}; 589 590IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 591 592status_t BnOMXObserver::onTransact( 593 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 594 switch (code) { 595 case OBSERVER_ON_MSG: 596 { 597 CHECK_INTERFACE(IOMXObserver, data, reply); 598 599 omx_message msg; 600 data.read(&msg, sizeof(msg)); 601 602 // XXX Could use readInplace maybe? 603 on_message(msg); 604 605 return NO_ERROR; 606 } 607 608 default: 609 return BBinder::onTransact(code, data, reply, flags); 610 } 611} 612 613//////////////////////////////////////////////////////////////////////////////// 614 615class BpOMXRenderer : public BpInterface<IOMXRenderer> { 616public: 617 BpOMXRenderer(const sp<IBinder> &impl) 618 : BpInterface<IOMXRenderer>(impl) { 619 } 620 621 virtual void render(IOMX::buffer_id buffer) { 622 Parcel data, reply; 623 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor()); 624 writeVoidStar(buffer, &data); 625 626 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous 627 // so that the caller knows when to recycle the buffer. 628 remote()->transact(RENDERER_RENDER, data, &reply); 629 } 630}; 631 632IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer"); 633 634status_t BnOMXRenderer::onTransact( 635 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 636 switch (code) { 637 case RENDERER_RENDER: 638 { 639 CHECK_INTERFACE(IOMXRenderer, data, reply); 640 641 IOMX::buffer_id buffer = readVoidStar(&data); 642 643 render(buffer); 644 645 return NO_ERROR; 646 } 647 648 default: 649 return BBinder::onTransact(code, data, reply, flags); 650 } 651} 652 653} // namespace android 654