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