blob: 4948f1ad2542edb13ac4450a290f867ee1bfe852 [file] [log] [blame]
Colin Cross85e88d92017-10-26 16:16:55 -07001/*
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
33namespace android {
34
35namespace {
36
37enum {
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
48template <typename T>
49status_t writeToParcel(const std::vector<T>& v, Parcel* p);
50
51template <typename T>
52status_t readFromParcel(std::vector<T>* v, const Parcel& p);
53
54// std::string <-> Parcel
55
56status_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
64status_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
81status_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
89status_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
99status_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
111status_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
125status_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
145status_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
168template <typename T>
169status_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
183template <typename T>
184status_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
202class BpOMXStore : public BpInterface<IOMXStore> {
203public:
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
271IMPLEMENT_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
281status_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