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