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