• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
writeToParcel(const std::string & s,Parcel * p)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 
readFromParcel(std::string * s,const Parcel & p)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 
writeToParcel(const IOMXStore::Attribute & a,Parcel * p)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 
readFromParcel(IOMXStore::Attribute * a,const Parcel & p)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 
writeToParcel(const IOMXStore::NodeInfo & n,Parcel * p)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 
readFromParcel(IOMXStore::NodeInfo * n,const Parcel & p)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 
writeToParcel(const IOMXStore::RoleInfo & r,Parcel * p)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 
readFromParcel(IOMXStore::RoleInfo * r,const Parcel & p)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>
writeToParcel(const std::vector<T> & v,Parcel * p)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>
readFromParcel(std::vector<T> * v,const Parcel & p)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:
BpOMXStore(const sp<IBinder> & impl)204     explicit BpOMXStore(const sp<IBinder> &impl)
205         : BpInterface<IOMXStore>(impl) {
206     }
207 
listServiceAttributes(std::vector<Attribute> * attributes)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 
getNodePrefix(std::string * prefix)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 
listRoles(std::vector<RoleInfo> * roleList)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 
getOmx(const std::string & name,sp<IOMX> * omx)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 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)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