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