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 <sys/mman.h>
     22 
     23 #include <binder/IMemory.h>
     24 #include <binder/Parcel.h>
     25 #include <media/IOMX.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/openmax/OMX_IndexExt.h>
     28 #include <media/OMXBuffer.h>
     29 #include <utils/NativeHandle.h>
     30 
     31 #include <media/omx/1.0/WOmxNode.h>
     32 #include <android/IGraphicBufferSource.h>
     33 #include <android/IOMXBufferSource.h>
     34 
     35 namespace android {
     36 
     37 enum {
     38     CONNECT = IBinder::FIRST_CALL_TRANSACTION,
     39     LIST_NODES,
     40     ALLOCATE_NODE,
     41     CREATE_INPUT_SURFACE,
     42     FREE_NODE,
     43     SEND_COMMAND,
     44     GET_PARAMETER,
     45     SET_PARAMETER,
     46     GET_CONFIG,
     47     SET_CONFIG,
     48     SET_PORT_MODE,
     49     SET_INPUT_SURFACE,
     50     PREPARE_FOR_ADAPTIVE_PLAYBACK,
     51     ALLOC_SECURE_BUFFER,
     52     USE_BUFFER,
     53     FREE_BUFFER,
     54     FILL_BUFFER,
     55     EMPTY_BUFFER,
     56     GET_EXTENSION_INDEX,
     57     OBSERVER_ON_MSG,
     58     GET_GRAPHIC_BUFFER_USAGE,
     59     CONFIGURE_VIDEO_TUNNEL_MODE,
     60     DISPATCH_MESSAGE,
     61     SET_QUIRKS,
     62 };
     63 
     64 class BpOMXNode : public BpInterface<IOMXNode> {
     65 public:
     66     explicit BpOMXNode(const sp<IBinder> &impl)
     67         : BpInterface<IOMXNode>(impl) {
     68     }
     69 
     70     virtual status_t freeNode() {
     71         Parcel data, reply;
     72         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
     73         remote()->transact(FREE_NODE, data, &reply);
     74 
     75         return reply.readInt32();
     76     }
     77 
     78     virtual status_t sendCommand(
     79             OMX_COMMANDTYPE cmd, OMX_S32 param) {
     80         Parcel data, reply;
     81         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
     82         data.writeInt32(cmd);
     83         data.writeInt32(param);
     84         remote()->transact(SEND_COMMAND, data, &reply);
     85 
     86         return reply.readInt32();
     87     }
     88 
     89     virtual status_t getParameter(
     90             OMX_INDEXTYPE index,
     91             void *params, size_t size) {
     92         Parcel data, reply;
     93         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
     94         data.writeInt32(index);
     95         data.writeInt64(size);
     96         data.write(params, size);
     97         remote()->transact(GET_PARAMETER, data, &reply);
     98 
     99         status_t err = reply.readInt32();
    100         if (err != OK) {
    101             return err;
    102         }
    103 
    104         reply.read(params, size);
    105 
    106         return OK;
    107     }
    108 
    109     virtual status_t setParameter(
    110             OMX_INDEXTYPE index,
    111             const void *params, size_t size) {
    112         Parcel data, reply;
    113         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    114         data.writeInt32(index);
    115         data.writeInt64(size);
    116         data.write(params, size);
    117         remote()->transact(SET_PARAMETER, data, &reply);
    118 
    119         return reply.readInt32();
    120     }
    121 
    122     virtual status_t getConfig(
    123             OMX_INDEXTYPE index,
    124             void *params, size_t size) {
    125         Parcel data, reply;
    126         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    127         data.writeInt32(index);
    128         data.writeInt64(size);
    129         data.write(params, size);
    130         remote()->transact(GET_CONFIG, data, &reply);
    131 
    132         status_t err = reply.readInt32();
    133         if (err != OK) {
    134             return err;
    135         }
    136 
    137         reply.read(params, size);
    138 
    139         return OK;
    140     }
    141 
    142     virtual status_t setConfig(
    143             OMX_INDEXTYPE index,
    144             const void *params, size_t size) {
    145         Parcel data, reply;
    146         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    147         data.writeInt32(index);
    148         data.writeInt64(size);
    149         data.write(params, size);
    150         remote()->transact(SET_CONFIG, data, &reply);
    151 
    152         return reply.readInt32();
    153     }
    154 
    155     virtual status_t setPortMode(
    156             OMX_U32 port_index, IOMX::PortMode mode) {
    157         Parcel data, reply;
    158         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    159         data.writeInt32(port_index);
    160         data.writeInt32(mode);
    161         remote()->transact(SET_PORT_MODE, data, &reply);
    162 
    163         return reply.readInt32();
    164     }
    165 
    166     virtual status_t getGraphicBufferUsage(
    167             OMX_U32 port_index, OMX_U32* usage) {
    168         Parcel data, reply;
    169         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    170         data.writeInt32(port_index);
    171         remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
    172 
    173         status_t err = reply.readInt32();
    174         *usage = reply.readInt32();
    175         return err;
    176     }
    177 
    178     virtual status_t useBuffer(
    179             OMX_U32 port_index, const OMXBuffer &omxBuf, buffer_id *buffer) {
    180         Parcel data, reply;
    181         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    182         data.writeInt32(port_index);
    183 
    184         status_t err = omxBuf.writeToParcel(&data);
    185         if (err != OK) {
    186             return err;
    187         }
    188 
    189         remote()->transact(USE_BUFFER, data, &reply);
    190 
    191         err = reply.readInt32();
    192         if (err != OK) {
    193             *buffer = 0;
    194 
    195             return err;
    196         }
    197 
    198         *buffer = (buffer_id)reply.readInt32();
    199 
    200         return err;
    201     }
    202 
    203     virtual status_t setInputSurface(
    204             const sp<IOMXBufferSource> &bufferSource) {
    205         Parcel data, reply;
    206         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    207 
    208         data.writeStrongBinder(IInterface::asBinder(bufferSource));
    209 
    210         status_t err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
    211 
    212         if (err != OK) {
    213             ALOGW("binder transaction failed: %d", err);
    214             return err;
    215         }
    216 
    217         err = reply.readInt32();
    218 
    219         return err;
    220     }
    221 
    222     virtual status_t prepareForAdaptivePlayback(
    223             OMX_U32 port_index, OMX_BOOL enable,
    224             OMX_U32 max_width, OMX_U32 max_height) {
    225         Parcel data, reply;
    226         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    227         data.writeInt32(port_index);
    228         data.writeInt32((int32_t)enable);
    229         data.writeInt32(max_width);
    230         data.writeInt32(max_height);
    231         remote()->transact(PREPARE_FOR_ADAPTIVE_PLAYBACK, data, &reply);
    232 
    233         status_t err = reply.readInt32();
    234         return err;
    235     }
    236 
    237     virtual status_t configureVideoTunnelMode(
    238             OMX_U32 portIndex, OMX_BOOL tunneled,
    239             OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
    240         Parcel data, reply;
    241         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    242         data.writeInt32(portIndex);
    243         data.writeInt32((int32_t)tunneled);
    244         data.writeInt32(audioHwSync);
    245         remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply);
    246 
    247         status_t err = reply.readInt32();
    248         if (err == OK && sidebandHandle) {
    249             *sidebandHandle = (native_handle_t *)reply.readNativeHandle();
    250         }
    251         return err;
    252     }
    253 
    254 
    255     virtual status_t allocateSecureBuffer(
    256             OMX_U32 port_index, size_t size,
    257             buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
    258         Parcel data, reply;
    259         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    260         data.writeInt32(port_index);
    261         data.writeInt64(size);
    262         remote()->transact(ALLOC_SECURE_BUFFER, data, &reply);
    263 
    264         status_t err = reply.readInt32();
    265         if (err != OK) {
    266             *buffer = 0;
    267             *buffer_data = NULL;
    268             *native_handle = NULL;
    269             return err;
    270         }
    271 
    272         *buffer = (buffer_id)reply.readInt32();
    273         *buffer_data = (void *)reply.readInt64();
    274         if (*buffer_data == NULL) {
    275             *native_handle = NativeHandle::create(
    276                     reply.readNativeHandle(), true /* ownsHandle */);
    277         } else {
    278             *native_handle = NULL;
    279         }
    280         return err;
    281     }
    282 
    283     virtual status_t freeBuffer(
    284             OMX_U32 port_index, buffer_id buffer) {
    285         Parcel data, reply;
    286         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    287         data.writeInt32(port_index);
    288         data.writeInt32((int32_t)buffer);
    289         remote()->transact(FREE_BUFFER, data, &reply);
    290 
    291         return reply.readInt32();
    292     }
    293 
    294     virtual status_t fillBuffer(
    295             buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd) {
    296         Parcel data, reply;
    297         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    298         data.writeInt32((int32_t)buffer);
    299         status_t err = omxBuf.writeToParcel(&data);
    300         if (err != OK) {
    301             return err;
    302         }
    303         data.writeInt32(fenceFd >= 0);
    304         if (fenceFd >= 0) {
    305             data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
    306         }
    307         remote()->transact(FILL_BUFFER, data, &reply);
    308 
    309         return reply.readInt32();
    310     }
    311 
    312     virtual status_t emptyBuffer(
    313             buffer_id buffer, const OMXBuffer &omxBuf,
    314             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    315         Parcel data, reply;
    316         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    317         data.writeInt32((int32_t)buffer);
    318         status_t err = omxBuf.writeToParcel(&data);
    319         if (err != OK) {
    320             return err;
    321         }
    322         data.writeInt32(flags);
    323         data.writeInt64(timestamp);
    324         data.writeInt32(fenceFd >= 0);
    325         if (fenceFd >= 0) {
    326             data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
    327         }
    328         remote()->transact(EMPTY_BUFFER, data, &reply);
    329 
    330         return reply.readInt32();
    331     }
    332 
    333     virtual status_t getExtensionIndex(
    334             const char *parameter_name,
    335             OMX_INDEXTYPE *index) {
    336         Parcel data, reply;
    337         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    338         data.writeCString(parameter_name);
    339 
    340         remote()->transact(GET_EXTENSION_INDEX, data, &reply);
    341 
    342         status_t err = reply.readInt32();
    343         if (err == OK) {
    344             *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
    345         } else {
    346             *index = OMX_IndexComponentStartUnused;
    347         }
    348 
    349         return err;
    350     }
    351 
    352     virtual status_t dispatchMessage(const omx_message &msg) {
    353         Parcel data, reply;
    354         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    355         data.writeInt32(msg.fenceFd >= 0);
    356         if (msg.fenceFd >= 0) {
    357             data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
    358         }
    359         data.writeInt32(msg.type);
    360         data.write(&msg.u, sizeof(msg.u));
    361 
    362         remote()->transact(DISPATCH_MESSAGE, data, &reply);
    363 
    364         return reply.readInt32();
    365     }
    366 
    367     virtual status_t setQuirks(OMX_U32 quirks) {
    368         Parcel data, reply;
    369         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
    370         data.writeInt32(quirks);
    371 
    372         remote()->transact(SET_QUIRKS, data, &reply);
    373 
    374         return reply.readInt32();
    375     }
    376 };
    377 
    378 using ::android::hardware::media::omx::V1_0::utils::LWOmxNode;
    379 class HpOMXNode : public HpInterface<BpOMXNode, LWOmxNode> {
    380 public:
    381     HpOMXNode(const sp<IBinder>& base) : PBase(base) {}
    382 
    383     virtual status_t freeNode() {
    384         return mBase->freeNode();
    385     }
    386 
    387     virtual status_t sendCommand(
    388             OMX_COMMANDTYPE cmd, OMX_S32 param) {
    389         return mBase->sendCommand(cmd, param);
    390     }
    391 
    392     virtual status_t getParameter(
    393             OMX_INDEXTYPE index, void *params, size_t size) {
    394         return mBase->getParameter(index, params, size);
    395     }
    396 
    397     virtual status_t setParameter(
    398             OMX_INDEXTYPE index, const void *params, size_t size) {
    399         return mBase->setParameter(index, params, size);
    400     }
    401 
    402     virtual status_t getConfig(
    403             OMX_INDEXTYPE index, void *params, size_t size) {
    404         return mBase->getConfig(index, params, size);
    405     }
    406 
    407     virtual status_t setConfig(
    408             OMX_INDEXTYPE index, const void *params, size_t size) {
    409         return mBase->setConfig(index, params, size);
    410     }
    411 
    412     virtual status_t setPortMode(
    413             OMX_U32 port_index, IOMX::PortMode mode) {
    414         return mBase->setPortMode(port_index, mode);
    415     }
    416 
    417     virtual status_t prepareForAdaptivePlayback(
    418             OMX_U32 portIndex, OMX_BOOL enable,
    419             OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
    420         return mBase->prepareForAdaptivePlayback(
    421                 portIndex, enable, maxFrameWidth, maxFrameHeight);
    422     }
    423 
    424     virtual status_t configureVideoTunnelMode(
    425             OMX_U32 portIndex, OMX_BOOL tunneled,
    426             OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
    427         return mBase->configureVideoTunnelMode(
    428                 portIndex, tunneled, audioHwSync, sidebandHandle);
    429     }
    430 
    431     virtual status_t getGraphicBufferUsage(
    432             OMX_U32 port_index, OMX_U32* usage) {
    433         return mBase->getGraphicBufferUsage(port_index, usage);
    434     }
    435 
    436     virtual status_t setInputSurface(
    437             const sp<IOMXBufferSource> &bufferSource) {
    438         return mBase->setInputSurface(bufferSource);
    439     }
    440 
    441     virtual status_t allocateSecureBuffer(
    442             OMX_U32 port_index, size_t size, buffer_id *buffer,
    443             void **buffer_data, sp<NativeHandle> *native_handle) {
    444         return mBase->allocateSecureBuffer(
    445                 port_index, size, buffer, buffer_data, native_handle);
    446     }
    447 
    448     virtual status_t useBuffer(
    449             OMX_U32 port_index, const OMXBuffer &omxBuf, buffer_id *buffer) {
    450         return mBase->useBuffer(port_index, omxBuf, buffer);
    451     }
    452 
    453     virtual status_t freeBuffer(
    454             OMX_U32 port_index, buffer_id buffer) {
    455         return mBase->freeBuffer(port_index, buffer);
    456     }
    457 
    458     virtual status_t fillBuffer(
    459             buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd = -1) {
    460         return mBase->fillBuffer(buffer, omxBuf, fenceFd);
    461     }
    462 
    463     virtual status_t emptyBuffer(
    464             buffer_id buffer, const OMXBuffer &omxBuf,
    465             OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) {
    466         return mBase->emptyBuffer(buffer, omxBuf, flags, timestamp, fenceFd);
    467     }
    468 
    469     virtual status_t getExtensionIndex(
    470             const char *parameter_name,
    471             OMX_INDEXTYPE *index) {
    472         return mBase->getExtensionIndex(parameter_name, index);
    473     }
    474 
    475     virtual status_t dispatchMessage(const omx_message &msg) {
    476         return mBase->dispatchMessage(msg);
    477     }
    478 };
    479 
    480 IMPLEMENT_HYBRID_META_INTERFACE(OMXNode, "android.hardware.IOMXNode");
    481 
    482 ////////////////////////////////////////////////////////////////////////////////
    483 
    484 #define CHECK_OMX_INTERFACE(interface, data, reply) \
    485         do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
    486             ALOGW("Call incorrectly routed to " #interface); \
    487             return PERMISSION_DENIED; \
    488         } } while (0)
    489 
    490 status_t BnOMXNode::onTransact(
    491     uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    492     switch (code) {
    493         case FREE_NODE:
    494         {
    495             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    496 
    497             reply->writeInt32(freeNode());
    498 
    499             return NO_ERROR;
    500         }
    501 
    502         case SEND_COMMAND:
    503         {
    504             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    505 
    506             OMX_COMMANDTYPE cmd =
    507                 static_cast<OMX_COMMANDTYPE>(data.readInt32());
    508 
    509             OMX_S32 param = data.readInt32();
    510             reply->writeInt32(sendCommand(cmd, param));
    511 
    512             return NO_ERROR;
    513         }
    514 
    515         case GET_PARAMETER:
    516         case SET_PARAMETER:
    517         case GET_CONFIG:
    518         case SET_CONFIG:
    519         {
    520             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    521 
    522             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
    523 
    524             size_t size = data.readInt64();
    525 
    526             status_t err = NOT_ENOUGH_DATA;
    527             void *params = NULL;
    528             size_t pageSize = 0;
    529             size_t allocSize = 0;
    530             bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
    531             if ((isUsageBits && size < 4) || (!isUsageBits && size < 8)) {
    532                 // we expect the structure to contain at least the size and
    533                 // version, 8 bytes total
    534                 ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
    535                 android_errorWriteLog(0x534e4554, "27207275");
    536             } else {
    537                 err = NO_MEMORY;
    538                 pageSize = (size_t) sysconf(_SC_PAGE_SIZE);
    539                 if (size > SIZE_MAX - (pageSize * 2)) {
    540                     ALOGE("requested param size too big");
    541                 } else {
    542                     allocSize = (size + pageSize * 2) & ~(pageSize - 1);
    543                     params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
    544                             MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
    545                 }
    546                 if (params != MAP_FAILED && params != NULL) {
    547                     err = data.read(params, size);
    548                     if (err != OK) {
    549                         android_errorWriteLog(0x534e4554, "26914474");
    550                     } else {
    551                         err = NOT_ENOUGH_DATA;
    552                         OMX_U32 declaredSize = *(OMX_U32*)params;
    553                         if (index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
    554                                 declaredSize > size) {
    555                             // the buffer says it's bigger than it actually is
    556                             ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
    557                             android_errorWriteLog(0x534e4554, "27207275");
    558                         } else {
    559                             // mark the last page as inaccessible, to avoid exploitation
    560                             // of codecs that access past the end of the allocation because
    561                             // they didn't check the size
    562                             if (mprotect((char*)params + allocSize - pageSize, pageSize,
    563                                     PROT_NONE) != 0) {
    564                                 ALOGE("mprotect failed: %s", strerror(errno));
    565                             } else {
    566                                 switch (code) {
    567                                     case GET_PARAMETER:
    568                                         err = getParameter(index, params, size);
    569                                         break;
    570                                     case SET_PARAMETER:
    571                                         err = setParameter(index, params, size);
    572                                         break;
    573                                     case GET_CONFIG:
    574                                         err = getConfig(index, params, size);
    575                                         break;
    576                                     case SET_CONFIG:
    577                                         err = setConfig(index, params, size);
    578                                         break;
    579                                     default:
    580                                         TRESPASS();
    581                                 }
    582                             }
    583                         }
    584                     }
    585                 } else {
    586                     ALOGE("couldn't map: %s", strerror(errno));
    587                 }
    588             }
    589 
    590             reply->writeInt32(err);
    591 
    592             if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
    593                 reply->write(params, size);
    594             }
    595 
    596             if (params) {
    597                 munmap(params, allocSize);
    598             }
    599             params = NULL;
    600 
    601             return NO_ERROR;
    602         }
    603 
    604         case SET_PORT_MODE:
    605         {
    606             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    607             OMX_U32 port_index = data.readInt32();
    608             IOMX::PortMode mode = (IOMX::PortMode) data.readInt32();
    609             reply->writeInt32(setPortMode(port_index, mode));
    610 
    611             return NO_ERROR;
    612         }
    613 
    614         case GET_GRAPHIC_BUFFER_USAGE:
    615         {
    616             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    617 
    618             OMX_U32 port_index = data.readInt32();
    619 
    620             OMX_U32 usage = 0;
    621             status_t err = getGraphicBufferUsage(port_index, &usage);
    622             reply->writeInt32(err);
    623             reply->writeInt32(usage);
    624 
    625             return NO_ERROR;
    626         }
    627 
    628         case USE_BUFFER:
    629         {
    630             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    631 
    632             OMX_U32 port_index = data.readInt32();
    633 
    634             OMXBuffer omxBuf;
    635             status_t err = omxBuf.readFromParcel(&data);
    636             if (err != OK) {
    637                 return err;
    638             }
    639 
    640             buffer_id buffer;
    641             err = useBuffer(port_index, omxBuf, &buffer);
    642             reply->writeInt32(err);
    643 
    644             if (err == OK) {
    645                 reply->writeInt32((int32_t)buffer);
    646             }
    647 
    648             return NO_ERROR;
    649         }
    650 
    651         case SET_INPUT_SURFACE:
    652         {
    653             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    654 
    655             sp<IOMXBufferSource> bufferSource =
    656                     interface_cast<IOMXBufferSource>(data.readStrongBinder());
    657 
    658             status_t err = setInputSurface(bufferSource);
    659             reply->writeInt32(err);
    660 
    661             return NO_ERROR;
    662         }
    663 
    664         case PREPARE_FOR_ADAPTIVE_PLAYBACK:
    665         {
    666             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    667 
    668             OMX_U32 port_index = data.readInt32();
    669             OMX_BOOL enable = (OMX_BOOL)data.readInt32();
    670             OMX_U32 max_width = data.readInt32();
    671             OMX_U32 max_height = data.readInt32();
    672 
    673             status_t err = prepareForAdaptivePlayback(
    674                     port_index, enable, max_width, max_height);
    675             reply->writeInt32(err);
    676 
    677             return NO_ERROR;
    678         }
    679 
    680         case CONFIGURE_VIDEO_TUNNEL_MODE:
    681         {
    682             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    683 
    684             OMX_U32 port_index = data.readInt32();
    685             OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
    686             OMX_U32 audio_hw_sync = data.readInt32();
    687 
    688             native_handle_t *sideband_handle = NULL;
    689             status_t err = configureVideoTunnelMode(
    690                     port_index, tunneled, audio_hw_sync, &sideband_handle);
    691             reply->writeInt32(err);
    692             if(err == OK){
    693                 reply->writeNativeHandle(sideband_handle);
    694             }
    695 
    696             return NO_ERROR;
    697         }
    698 
    699         case ALLOC_SECURE_BUFFER:
    700         {
    701             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    702 
    703             OMX_U32 port_index = data.readInt32();
    704             if (!isSecure() || port_index != 0 /* kPortIndexInput */) {
    705                 ALOGE("b/24310423");
    706                 reply->writeInt32(INVALID_OPERATION);
    707                 return NO_ERROR;
    708             }
    709 
    710             size_t size = data.readInt64();
    711 
    712             buffer_id buffer;
    713             void *buffer_data = NULL;
    714             sp<NativeHandle> native_handle;
    715             status_t err = allocateSecureBuffer(
    716                     port_index, size, &buffer, &buffer_data, &native_handle);
    717             reply->writeInt32(err);
    718 
    719             if (err == OK) {
    720                 reply->writeInt32((int32_t)buffer);
    721                 reply->writeInt64((uintptr_t)buffer_data);
    722                 if (buffer_data == NULL) {
    723                     reply->writeNativeHandle(native_handle == NULL ? NULL : native_handle->handle());
    724                 }
    725             }
    726 
    727             return NO_ERROR;
    728         }
    729 
    730         case FREE_BUFFER:
    731         {
    732             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    733 
    734             OMX_U32 port_index = data.readInt32();
    735             buffer_id buffer = (buffer_id)data.readInt32();
    736             reply->writeInt32(freeBuffer(port_index, buffer));
    737 
    738             return NO_ERROR;
    739         }
    740 
    741         case FILL_BUFFER:
    742         {
    743             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    744 
    745             buffer_id buffer = (buffer_id)data.readInt32();
    746 
    747             OMXBuffer omxBuf;
    748             status_t err = omxBuf.readFromParcel(&data);
    749             if (err != OK) {
    750                 return err;
    751             }
    752 
    753             bool haveFence = data.readInt32();
    754             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
    755 
    756             reply->writeInt32(fillBuffer(buffer, omxBuf, fenceFd));
    757 
    758             return NO_ERROR;
    759         }
    760 
    761         case EMPTY_BUFFER:
    762         {
    763             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    764 
    765             buffer_id buffer = (buffer_id)data.readInt32();
    766             OMXBuffer omxBuf;
    767             status_t err = omxBuf.readFromParcel(&data);
    768             if (err != OK) {
    769                 return err;
    770             }
    771             OMX_U32 flags = data.readInt32();
    772             OMX_TICKS timestamp = data.readInt64();
    773             bool haveFence = data.readInt32();
    774             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
    775             reply->writeInt32(emptyBuffer(
    776                     buffer, omxBuf, flags, timestamp, fenceFd));
    777 
    778             return NO_ERROR;
    779         }
    780 
    781         case GET_EXTENSION_INDEX:
    782         {
    783             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    784 
    785             const char *parameter_name = data.readCString();
    786 
    787             if (parameter_name == NULL) {
    788                 ALOGE("b/26392700");
    789                 reply->writeInt32(INVALID_OPERATION);
    790                 return NO_ERROR;
    791             }
    792 
    793             OMX_INDEXTYPE index;
    794             status_t err = getExtensionIndex(parameter_name, &index);
    795 
    796             reply->writeInt32(err);
    797 
    798             if (err == OK) {
    799                 reply->writeInt32(index);
    800             }
    801 
    802             return OK;
    803         }
    804 
    805         case DISPATCH_MESSAGE:
    806         {
    807             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
    808             omx_message msg;
    809             int haveFence = data.readInt32();
    810             msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
    811             msg.type = (typeof(msg.type))data.readInt32();
    812             status_t err = data.read(&msg.u, sizeof(msg.u));
    813 
    814             if (err == OK) {
    815                 err = dispatchMessage(msg);
    816             }
    817             reply->writeInt32(err);
    818 
    819             return NO_ERROR;
    820         }
    821 
    822         default:
    823             return BBinder::onTransact(code, data, reply, flags);
    824     }
    825 }
    826 
    827 ////////////////////////////////////////////////////////////////////////////////
    828 
    829 class BpOMXObserver : public BpInterface<IOMXObserver> {
    830 public:
    831     explicit BpOMXObserver(const sp<IBinder> &impl)
    832         : BpInterface<IOMXObserver>(impl) {
    833     }
    834 
    835     virtual void onMessages(const std::list<omx_message> &messages) {
    836         Parcel data, reply;
    837         std::list<omx_message>::const_iterator it = messages.cbegin();
    838         if (messages.empty()) {
    839             return;
    840         }
    841         data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
    842         while (it != messages.cend()) {
    843             const omx_message &msg = *it++;
    844             data.writeInt32(msg.fenceFd >= 0);
    845             if (msg.fenceFd >= 0) {
    846                 data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
    847             }
    848             data.writeInt32(msg.type);
    849             data.write(&msg.u, sizeof(msg.u));
    850             ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
    851         }
    852         data.writeInt32(-1); // mark end
    853         remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
    854     }
    855 };
    856 
    857 IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
    858 
    859 status_t BnOMXObserver::onTransact(
    860     uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    861     switch (code) {
    862         case OBSERVER_ON_MSG:
    863         {
    864             CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
    865             std::list<omx_message> messages;
    866             status_t err = FAILED_TRANSACTION; // must receive at least one message
    867             do {
    868                 int haveFence = data.readInt32();
    869                 if (haveFence < 0) { // we use -1 to mark end of messages
    870                     break;
    871                 }
    872                 omx_message msg;
    873                 msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
    874                 msg.type = (typeof(msg.type))data.readInt32();
    875                 err = data.read(&msg.u, sizeof(msg.u));
    876                 ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg));
    877                 messages.push_back(msg);
    878             } while (err == OK);
    879 
    880             if (err == OK) {
    881                 onMessages(messages);
    882             }
    883 
    884             return err;
    885         }
    886 
    887         default:
    888             return BBinder::onTransact(code, data, reply, flags);
    889     }
    890 }
    891 
    892 }  // namespace android
    893