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 "IOMXStore"
     19 
     20 #include <utils/Log.h>
     21 
     22 #include <media/IOMX.h>
     23 #include <media/IOMXStore.h>
     24 #include <android/hardware/media/omx/1.0/IOmxStore.h>
     25 
     26 #include <binder/IInterface.h>
     27 #include <binder/IBinder.h>
     28 #include <binder/Parcel.h>
     29 
     30 #include <vector>
     31 #include <string>
     32 
     33 namespace android {
     34 
     35 namespace {
     36 
     37 enum {
     38     CONNECT = IBinder::FIRST_CALL_TRANSACTION,
     39     LIST_SERVICE_ATTRIBUTES,
     40     GET_NODE_PREFIX,
     41     LIST_ROLES,
     42     GET_OMX,
     43 };
     44 
     45 // Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
     46 // depend on writeToParcel() and readToParcel() for T <-> Parcel.
     47 
     48 template <typename T>
     49 status_t writeToParcel(const std::vector<T>& v, Parcel* p);
     50 
     51 template <typename T>
     52 status_t readFromParcel(std::vector<T>* v, const Parcel& p);
     53 
     54 // std::string <-> Parcel
     55 
     56 status_t writeToParcel(const std::string& s, Parcel* p) {
     57     if (s.size() > INT32_MAX) {
     58         return BAD_VALUE;
     59     }
     60     return p->writeByteArray(
     61             s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
     62 }
     63 
     64 status_t readFromParcel(std::string* s, const Parcel& p) {
     65     int32_t len;
     66     status_t status = p.readInt32(&len);
     67     if (status != NO_ERROR) {
     68         return status;
     69     } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
     70         return BAD_VALUE;
     71     }
     72     s->resize(len);
     73     if (len == 0) {
     74         return NO_ERROR;
     75     }
     76     return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
     77 }
     78 
     79 // IOMXStore::Attribute <-> Parcel
     80 
     81 status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
     82     status_t status = writeToParcel(a.key, p);
     83     if (status != NO_ERROR) {
     84         return status;
     85     }
     86     return writeToParcel(a.value, p);
     87 }
     88 
     89 status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
     90     status_t status = readFromParcel(&(a->key), p);
     91     if (status != NO_ERROR) {
     92         return status;
     93     }
     94     return readFromParcel(&(a->value), p);
     95 }
     96 
     97 // IOMXStore::NodeInfo <-> Parcel
     98 
     99 status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
    100     status_t status = writeToParcel(n.name, p);
    101     if (status != NO_ERROR) {
    102         return status;
    103     }
    104     status = writeToParcel(n.owner, p);
    105     if (status != NO_ERROR) {
    106         return status;
    107     }
    108     return writeToParcel(n.attributes, p);
    109 }
    110 
    111 status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
    112     status_t status = readFromParcel(&(n->name), p);
    113     if (status != NO_ERROR) {
    114         return status;
    115     }
    116     status = readFromParcel(&(n->owner), p);
    117     if (status != NO_ERROR) {
    118         return status;
    119     }
    120     return readFromParcel(&(n->attributes), p);
    121 }
    122 
    123 // IOMXStore::RoleInfo <-> Parcel
    124 
    125 status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
    126     status_t status = writeToParcel(r.role, p);
    127     if (status != NO_ERROR) {
    128         return status;
    129     }
    130     status = writeToParcel(r.type, p);
    131     if (status != NO_ERROR) {
    132         return status;
    133     }
    134     status = p->writeBool(r.isEncoder);
    135     if (status != NO_ERROR) {
    136         return status;
    137     }
    138     status = p->writeBool(r.preferPlatformNodes);
    139     if (status != NO_ERROR) {
    140         return status;
    141     }
    142     return writeToParcel(r.nodes, p);
    143 }
    144 
    145 status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
    146     status_t status = readFromParcel(&(r->role), p);
    147     if (status != NO_ERROR) {
    148         return status;
    149     }
    150     status = readFromParcel(&(r->type), p);
    151     if (status != NO_ERROR) {
    152         return status;
    153     }
    154     status = p.readBool(&(r->isEncoder));
    155     if (status != NO_ERROR) {
    156         return status;
    157     }
    158     status = p.readBool(&(r->preferPlatformNodes));
    159     if (status != NO_ERROR) {
    160         return status;
    161     }
    162     return readFromParcel(&(r->nodes), p);
    163 }
    164 
    165 // std::vector<NodeInfo> <-> Parcel
    166 // std::vector<RoleInfo> <-> Parcel
    167 
    168 template <typename T>
    169 status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
    170     status_t status = p->writeVectorSize(v);
    171     if (status != NO_ERROR) {
    172         return status;
    173     }
    174     for (const T& x : v) {
    175         status = writeToParcel(x, p);
    176         if (status != NO_ERROR) {
    177             return status;
    178         }
    179     }
    180     return NO_ERROR;
    181 }
    182 
    183 template <typename T>
    184 status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
    185     status_t status = p.resizeOutVector(v);
    186     if (status != NO_ERROR) {
    187         return status;
    188     }
    189     for (T& x : *v) {
    190         status = readFromParcel(&x, p);
    191         if (status != NO_ERROR) {
    192             return status;
    193         }
    194     }
    195     return NO_ERROR;
    196 }
    197 
    198 } // unnamed namespace
    199 
    200 ////////////////////////////////////////////////////////////////////////////////
    201 
    202 class BpOMXStore : public BpInterface<IOMXStore> {
    203 public:
    204     explicit BpOMXStore(const sp<IBinder> &impl)
    205         : BpInterface<IOMXStore>(impl) {
    206     }
    207 
    208     status_t listServiceAttributes(
    209             std::vector<Attribute>* attributes) override {
    210         Parcel data, reply;
    211         status_t status;
    212         status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
    213         if (status != NO_ERROR) {
    214             return status;
    215         }
    216         status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
    217         if (status != NO_ERROR) {
    218             return status;
    219         }
    220         return readFromParcel(attributes, reply);
    221     }
    222 
    223     status_t getNodePrefix(std::string* prefix) override {
    224         Parcel data, reply;
    225         status_t status;
    226         status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
    227         if (status != NO_ERROR) {
    228             return status;
    229         }
    230         status = remote()->transact(GET_NODE_PREFIX, data, &reply);
    231         if (status != NO_ERROR) {
    232             return status;
    233         }
    234         return readFromParcel(prefix, reply);
    235     }
    236 
    237     status_t listRoles(std::vector<RoleInfo>* roleList) override {
    238         Parcel data, reply;
    239         status_t status;
    240         status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
    241         if (status != NO_ERROR) {
    242             return status;
    243         }
    244         status = remote()->transact(LIST_ROLES, data, &reply);
    245         if (status != NO_ERROR) {
    246             return status;
    247         }
    248         return readFromParcel(roleList, reply);
    249     }
    250 
    251     status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
    252         Parcel data, reply;
    253         status_t status;
    254         status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
    255         if (status != NO_ERROR) {
    256             return status;
    257         }
    258         status = writeToParcel(name, &data);
    259         if (status != NO_ERROR) {
    260             return status;
    261         }
    262         status = remote()->transact(GET_OMX, data, &reply);
    263         if (status != NO_ERROR) {
    264             return status;
    265         }
    266         return reply.readStrongBinder(omx);
    267     }
    268 
    269 };
    270 
    271 IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
    272 
    273 ////////////////////////////////////////////////////////////////////////////////
    274 
    275 #define CHECK_OMX_INTERFACE(interface, data, reply) \
    276         do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
    277             ALOGW("Call incorrectly routed to " #interface); \
    278             return PERMISSION_DENIED; \
    279         } } while (0)
    280 
    281 status_t BnOMXStore::onTransact(
    282     uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    283     switch (code) {
    284         case LIST_SERVICE_ATTRIBUTES: {
    285             CHECK_OMX_INTERFACE(IOMXStore, data, reply);
    286             status_t status;
    287             std::vector<Attribute> attributes;
    288 
    289             status = listServiceAttributes(&attributes);
    290             if (status != NO_ERROR) {
    291                 ALOGE("listServiceAttributes() fails with status %d",
    292                         static_cast<int>(status));
    293                 return NO_ERROR;
    294             }
    295             status = writeToParcel(attributes, reply);
    296             if (status != NO_ERROR) {
    297                 ALOGE("listServiceAttributes() fails to send reply");
    298                 return NO_ERROR;
    299             }
    300             return NO_ERROR;
    301         }
    302         case GET_NODE_PREFIX: {
    303             CHECK_OMX_INTERFACE(IOMXStore, data, reply);
    304             status_t status;
    305             std::string prefix;
    306 
    307             status = getNodePrefix(&prefix);
    308             if (status != NO_ERROR) {
    309                 ALOGE("getNodePrefix() fails with status %d",
    310                         static_cast<int>(status));
    311                 return NO_ERROR;
    312             }
    313             status = writeToParcel(prefix, reply);
    314             if (status != NO_ERROR) {
    315                 ALOGE("getNodePrefix() fails to send reply");
    316                 return NO_ERROR;
    317             }
    318             return NO_ERROR;
    319         }
    320         case LIST_ROLES: {
    321             CHECK_OMX_INTERFACE(IOMXStore, data, reply);
    322             status_t status;
    323             std::vector<RoleInfo> roleList;
    324 
    325             status = listRoles(&roleList);
    326             if (status != NO_ERROR) {
    327                 ALOGE("listRoles() fails with status %d",
    328                         static_cast<int>(status));
    329                 return NO_ERROR;
    330             }
    331             status = writeToParcel(roleList, reply);
    332             if (status != NO_ERROR) {
    333                 ALOGE("listRoles() fails to send reply");
    334                 return NO_ERROR;
    335             }
    336             return NO_ERROR;
    337         }
    338         case GET_OMX: {
    339             CHECK_OMX_INTERFACE(IOMXStore, data, reply);
    340             status_t status;
    341             std::string name;
    342             sp<IOMX> omx;
    343 
    344             status = readFromParcel(&name, data);
    345             if (status != NO_ERROR) {
    346                 ALOGE("getOmx() fails to retrieve name");
    347                 return NO_ERROR;
    348             }
    349             status = getOmx(name, &omx);
    350             if (status != NO_ERROR) {
    351                 ALOGE("getOmx() fails with status %d",
    352                         static_cast<int>(status));
    353                 return NO_ERROR;
    354             }
    355             status = reply->writeStrongBinder(IInterface::asBinder(omx));
    356             if (status != NO_ERROR) {
    357                 ALOGE("getOmx() fails to send reply");
    358                 return NO_ERROR;
    359             }
    360             return NO_ERROR;
    361         }
    362         default:
    363             return BBinder::onTransact(code, data, reply, flags);
    364     }
    365 }
    366 
    367 }  // namespace android
    368