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