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