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 <binder/IMemory.h>
22 #include <binder/Parcel.h>
23 #include <media/IOMX.h>
24 #include <media/stagefright/foundation/ADebug.h>
25
26 namespace android {
27
28 enum {
29 CONNECT = IBinder::FIRST_CALL_TRANSACTION,
30 LIVES_LOCALLY,
31 LIST_NODES,
32 ALLOCATE_NODE,
33 FREE_NODE,
34 SEND_COMMAND,
35 GET_PARAMETER,
36 SET_PARAMETER,
37 GET_CONFIG,
38 SET_CONFIG,
39 GET_STATE,
40 ENABLE_GRAPHIC_BUFFERS,
41 USE_BUFFER,
42 USE_GRAPHIC_BUFFER,
43 CREATE_INPUT_SURFACE,
44 CREATE_PERSISTENT_INPUT_SURFACE,
45 SET_INPUT_SURFACE,
46 SIGNAL_END_OF_INPUT_STREAM,
47 STORE_META_DATA_IN_BUFFERS,
48 PREPARE_FOR_ADAPTIVE_PLAYBACK,
49 ALLOC_BUFFER,
50 ALLOC_BUFFER_WITH_BACKUP,
51 FREE_BUFFER,
52 FILL_BUFFER,
53 EMPTY_BUFFER,
54 GET_EXTENSION_INDEX,
55 OBSERVER_ON_MSG,
56 GET_GRAPHIC_BUFFER_USAGE,
57 SET_INTERNAL_OPTION,
58 UPDATE_GRAPHIC_BUFFER_IN_META,
59 CONFIGURE_VIDEO_TUNNEL_MODE,
60 };
61
62 class BpOMX : public BpInterface<IOMX> {
63 public:
BpOMX(const sp<IBinder> & impl)64 BpOMX(const sp<IBinder> &impl)
65 : BpInterface<IOMX>(impl) {
66 }
67
livesLocally(node_id node,pid_t pid)68 virtual bool livesLocally(node_id node, pid_t pid) {
69 Parcel data, reply;
70 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
71 data.writeInt32((int32_t)node);
72 data.writeInt32(pid);
73 remote()->transact(LIVES_LOCALLY, data, &reply);
74
75 return reply.readInt32() != 0;
76 }
77
listNodes(List<ComponentInfo> * list)78 virtual status_t listNodes(List<ComponentInfo> *list) {
79 list->clear();
80
81 Parcel data, reply;
82 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
83 remote()->transact(LIST_NODES, data, &reply);
84
85 int32_t n = reply.readInt32();
86 for (int32_t i = 0; i < n; ++i) {
87 list->push_back(ComponentInfo());
88 ComponentInfo &info = *--list->end();
89
90 info.mName = reply.readString8();
91 int32_t numRoles = reply.readInt32();
92 for (int32_t j = 0; j < numRoles; ++j) {
93 info.mRoles.push_back(reply.readString8());
94 }
95 }
96
97 return OK;
98 }
99
allocateNode(const char * name,const sp<IOMXObserver> & observer,node_id * node)100 virtual status_t allocateNode(
101 const char *name, const sp<IOMXObserver> &observer, node_id *node) {
102 Parcel data, reply;
103 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
104 data.writeCString(name);
105 data.writeStrongBinder(IInterface::asBinder(observer));
106 remote()->transact(ALLOCATE_NODE, data, &reply);
107
108 status_t err = reply.readInt32();
109 if (err == OK) {
110 *node = (node_id)reply.readInt32();
111 } else {
112 *node = 0;
113 }
114
115 return err;
116 }
117
freeNode(node_id node)118 virtual status_t freeNode(node_id node) {
119 Parcel data, reply;
120 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
121 data.writeInt32((int32_t)node);
122 remote()->transact(FREE_NODE, data, &reply);
123
124 return reply.readInt32();
125 }
126
sendCommand(node_id node,OMX_COMMANDTYPE cmd,OMX_S32 param)127 virtual status_t sendCommand(
128 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
129 Parcel data, reply;
130 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
131 data.writeInt32((int32_t)node);
132 data.writeInt32(cmd);
133 data.writeInt32(param);
134 remote()->transact(SEND_COMMAND, data, &reply);
135
136 return reply.readInt32();
137 }
138
getParameter(node_id node,OMX_INDEXTYPE index,void * params,size_t size)139 virtual status_t getParameter(
140 node_id node, OMX_INDEXTYPE index,
141 void *params, size_t size) {
142 Parcel data, reply;
143 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
144 data.writeInt32((int32_t)node);
145 data.writeInt32(index);
146 data.writeInt64(size);
147 data.write(params, size);
148 remote()->transact(GET_PARAMETER, data, &reply);
149
150 status_t err = reply.readInt32();
151 if (err != OK) {
152 return err;
153 }
154
155 reply.read(params, size);
156
157 return OK;
158 }
159
setParameter(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)160 virtual status_t setParameter(
161 node_id node, OMX_INDEXTYPE index,
162 const void *params, size_t size) {
163 Parcel data, reply;
164 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
165 data.writeInt32((int32_t)node);
166 data.writeInt32(index);
167 data.writeInt64(size);
168 data.write(params, size);
169 remote()->transact(SET_PARAMETER, data, &reply);
170
171 return reply.readInt32();
172 }
173
getConfig(node_id node,OMX_INDEXTYPE index,void * params,size_t size)174 virtual status_t getConfig(
175 node_id node, OMX_INDEXTYPE index,
176 void *params, size_t size) {
177 Parcel data, reply;
178 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
179 data.writeInt32((int32_t)node);
180 data.writeInt32(index);
181 data.writeInt64(size);
182 data.write(params, size);
183 remote()->transact(GET_CONFIG, data, &reply);
184
185 status_t err = reply.readInt32();
186 if (err != OK) {
187 return err;
188 }
189
190 reply.read(params, size);
191
192 return OK;
193 }
194
setConfig(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)195 virtual status_t setConfig(
196 node_id node, OMX_INDEXTYPE index,
197 const void *params, size_t size) {
198 Parcel data, reply;
199 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
200 data.writeInt32((int32_t)node);
201 data.writeInt32(index);
202 data.writeInt64(size);
203 data.write(params, size);
204 remote()->transact(SET_CONFIG, data, &reply);
205
206 return reply.readInt32();
207 }
208
getState(node_id node,OMX_STATETYPE * state)209 virtual status_t getState(
210 node_id node, OMX_STATETYPE* state) {
211 Parcel data, reply;
212 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
213 data.writeInt32((int32_t)node);
214 remote()->transact(GET_STATE, data, &reply);
215
216 *state = static_cast<OMX_STATETYPE>(reply.readInt32());
217 return reply.readInt32();
218 }
219
enableGraphicBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable)220 virtual status_t enableGraphicBuffers(
221 node_id node, OMX_U32 port_index, OMX_BOOL enable) {
222 Parcel data, reply;
223 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
224 data.writeInt32((int32_t)node);
225 data.writeInt32(port_index);
226 data.writeInt32((uint32_t)enable);
227 remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply);
228
229 status_t err = reply.readInt32();
230 return err;
231 }
232
getGraphicBufferUsage(node_id node,OMX_U32 port_index,OMX_U32 * usage)233 virtual status_t getGraphicBufferUsage(
234 node_id node, OMX_U32 port_index, OMX_U32* usage) {
235 Parcel data, reply;
236 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
237 data.writeInt32((int32_t)node);
238 data.writeInt32(port_index);
239 remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
240
241 status_t err = reply.readInt32();
242 *usage = reply.readInt32();
243 return err;
244 }
245
useBuffer(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)246 virtual status_t useBuffer(
247 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
248 buffer_id *buffer, OMX_U32 allottedSize) {
249 Parcel data, reply;
250 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
251 data.writeInt32((int32_t)node);
252 data.writeInt32(port_index);
253 data.writeStrongBinder(IInterface::asBinder(params));
254 data.writeInt32(allottedSize);
255 remote()->transact(USE_BUFFER, data, &reply);
256
257 status_t err = reply.readInt32();
258 if (err != OK) {
259 *buffer = 0;
260
261 return err;
262 }
263
264 *buffer = (buffer_id)reply.readInt32();
265
266 return err;
267 }
268
269
useGraphicBuffer(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id * buffer)270 virtual status_t useGraphicBuffer(
271 node_id node, OMX_U32 port_index,
272 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
273 Parcel data, reply;
274 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
275 data.writeInt32((int32_t)node);
276 data.writeInt32(port_index);
277 data.write(*graphicBuffer);
278 remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
279
280 status_t err = reply.readInt32();
281 if (err != OK) {
282 *buffer = 0;
283
284 return err;
285 }
286
287 *buffer = (buffer_id)reply.readInt32();
288
289 return err;
290 }
291
updateGraphicBufferInMeta(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id buffer)292 virtual status_t updateGraphicBufferInMeta(
293 node_id node, OMX_U32 port_index,
294 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
295 Parcel data, reply;
296 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
297 data.writeInt32((int32_t)node);
298 data.writeInt32(port_index);
299 data.write(*graphicBuffer);
300 data.writeInt32((int32_t)buffer);
301 remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply);
302
303 status_t err = reply.readInt32();
304 return err;
305 }
306
createInputSurface(node_id node,OMX_U32 port_index,sp<IGraphicBufferProducer> * bufferProducer,MetadataBufferType * type)307 virtual status_t createInputSurface(
308 node_id node, OMX_U32 port_index,
309 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
310 Parcel data, reply;
311 status_t err;
312 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
313 data.writeInt32((int32_t)node);
314 data.writeInt32(port_index);
315 err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
316 if (err != OK) {
317 ALOGW("binder transaction failed: %d", err);
318 return err;
319 }
320
321 // read type even if createInputSurface failed
322 int negotiatedType = reply.readInt32();
323 if (type != NULL) {
324 *type = (MetadataBufferType)negotiatedType;
325 }
326
327 err = reply.readInt32();
328 if (err != OK) {
329 return err;
330 }
331
332 *bufferProducer = IGraphicBufferProducer::asInterface(
333 reply.readStrongBinder());
334
335 return err;
336 }
337
createPersistentInputSurface(sp<IGraphicBufferProducer> * bufferProducer,sp<IGraphicBufferConsumer> * bufferConsumer)338 virtual status_t createPersistentInputSurface(
339 sp<IGraphicBufferProducer> *bufferProducer,
340 sp<IGraphicBufferConsumer> *bufferConsumer) {
341 Parcel data, reply;
342 status_t err;
343 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
344 err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
345 if (err != OK) {
346 ALOGW("binder transaction failed: %d", err);
347 return err;
348 }
349
350 err = reply.readInt32();
351 if (err != OK) {
352 return err;
353 }
354
355 *bufferProducer = IGraphicBufferProducer::asInterface(
356 reply.readStrongBinder());
357 *bufferConsumer = IGraphicBufferConsumer::asInterface(
358 reply.readStrongBinder());
359
360 return err;
361 }
362
setInputSurface(node_id node,OMX_U32 port_index,const sp<IGraphicBufferConsumer> & bufferConsumer,MetadataBufferType * type)363 virtual status_t setInputSurface(
364 node_id node, OMX_U32 port_index,
365 const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
366 Parcel data, reply;
367 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
368 status_t err;
369 data.writeInt32((int32_t)node);
370 data.writeInt32(port_index);
371 data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
372
373 err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
374
375 if (err != OK) {
376 ALOGW("binder transaction failed: %d", err);
377 return err;
378 }
379
380 // read type even if setInputSurface failed
381 int negotiatedType = reply.readInt32();
382 if (type != NULL) {
383 *type = (MetadataBufferType)negotiatedType;
384 }
385
386 return reply.readInt32();
387 }
388
signalEndOfInputStream(node_id node)389 virtual status_t signalEndOfInputStream(node_id node) {
390 Parcel data, reply;
391 status_t err;
392 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
393 data.writeInt32((int32_t)node);
394 err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply);
395 if (err != OK) {
396 ALOGW("binder transaction failed: %d", err);
397 return err;
398 }
399
400 return reply.readInt32();
401 }
402
storeMetaDataInBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable,MetadataBufferType * type)403 virtual status_t storeMetaDataInBuffers(
404 node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
405 Parcel data, reply;
406 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
407 data.writeInt32((int32_t)node);
408 data.writeInt32(port_index);
409 data.writeInt32((uint32_t)enable);
410 remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
411
412 // read type even storeMetaDataInBuffers failed
413 int negotiatedType = reply.readInt32();
414 if (type != NULL) {
415 *type = (MetadataBufferType)negotiatedType;
416 }
417
418 return reply.readInt32();
419 }
420
prepareForAdaptivePlayback(node_id node,OMX_U32 port_index,OMX_BOOL enable,OMX_U32 max_width,OMX_U32 max_height)421 virtual status_t prepareForAdaptivePlayback(
422 node_id node, OMX_U32 port_index, OMX_BOOL enable,
423 OMX_U32 max_width, OMX_U32 max_height) {
424 Parcel data, reply;
425 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
426 data.writeInt32((int32_t)node);
427 data.writeInt32(port_index);
428 data.writeInt32((int32_t)enable);
429 data.writeInt32(max_width);
430 data.writeInt32(max_height);
431 remote()->transact(PREPARE_FOR_ADAPTIVE_PLAYBACK, data, &reply);
432
433 status_t err = reply.readInt32();
434 return err;
435 }
436
configureVideoTunnelMode(node_id node,OMX_U32 portIndex,OMX_BOOL tunneled,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)437 virtual status_t configureVideoTunnelMode(
438 node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
439 OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
440 Parcel data, reply;
441 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
442 data.writeInt32((int32_t)node);
443 data.writeInt32(portIndex);
444 data.writeInt32((int32_t)tunneled);
445 data.writeInt32(audioHwSync);
446 remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply);
447
448 status_t err = reply.readInt32();
449 if (sidebandHandle) {
450 *sidebandHandle = (native_handle_t *)reply.readNativeHandle();
451 }
452 return err;
453 }
454
455
allocateBuffer(node_id node,OMX_U32 port_index,size_t size,buffer_id * buffer,void ** buffer_data)456 virtual status_t allocateBuffer(
457 node_id node, OMX_U32 port_index, size_t size,
458 buffer_id *buffer, void **buffer_data) {
459 Parcel data, reply;
460 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
461 data.writeInt32((int32_t)node);
462 data.writeInt32(port_index);
463 data.writeInt64(size);
464 remote()->transact(ALLOC_BUFFER, data, &reply);
465
466 status_t err = reply.readInt32();
467 if (err != OK) {
468 *buffer = 0;
469
470 return err;
471 }
472
473 *buffer = (buffer_id)reply.readInt32();
474 *buffer_data = (void *)reply.readInt64();
475
476 return err;
477 }
478
allocateBufferWithBackup(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)479 virtual status_t allocateBufferWithBackup(
480 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
481 buffer_id *buffer, OMX_U32 allottedSize) {
482 Parcel data, reply;
483 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
484 data.writeInt32((int32_t)node);
485 data.writeInt32(port_index);
486 data.writeStrongBinder(IInterface::asBinder(params));
487 data.writeInt32(allottedSize);
488 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
489
490 status_t err = reply.readInt32();
491 if (err != OK) {
492 *buffer = 0;
493
494 return err;
495 }
496
497 *buffer = (buffer_id)reply.readInt32();
498
499 return err;
500 }
501
freeBuffer(node_id node,OMX_U32 port_index,buffer_id buffer)502 virtual status_t freeBuffer(
503 node_id node, OMX_U32 port_index, buffer_id buffer) {
504 Parcel data, reply;
505 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
506 data.writeInt32((int32_t)node);
507 data.writeInt32(port_index);
508 data.writeInt32((int32_t)buffer);
509 remote()->transact(FREE_BUFFER, data, &reply);
510
511 return reply.readInt32();
512 }
513
fillBuffer(node_id node,buffer_id buffer,int fenceFd)514 virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
515 Parcel data, reply;
516 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
517 data.writeInt32((int32_t)node);
518 data.writeInt32((int32_t)buffer);
519 data.writeInt32(fenceFd >= 0);
520 if (fenceFd >= 0) {
521 data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
522 }
523 remote()->transact(FILL_BUFFER, data, &reply);
524
525 return reply.readInt32();
526 }
527
emptyBuffer(node_id node,buffer_id buffer,OMX_U32 range_offset,OMX_U32 range_length,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)528 virtual status_t emptyBuffer(
529 node_id node,
530 buffer_id buffer,
531 OMX_U32 range_offset, OMX_U32 range_length,
532 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
533 Parcel data, reply;
534 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
535 data.writeInt32((int32_t)node);
536 data.writeInt32((int32_t)buffer);
537 data.writeInt32(range_offset);
538 data.writeInt32(range_length);
539 data.writeInt32(flags);
540 data.writeInt64(timestamp);
541 data.writeInt32(fenceFd >= 0);
542 if (fenceFd >= 0) {
543 data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
544 }
545 remote()->transact(EMPTY_BUFFER, data, &reply);
546
547 return reply.readInt32();
548 }
549
getExtensionIndex(node_id node,const char * parameter_name,OMX_INDEXTYPE * index)550 virtual status_t getExtensionIndex(
551 node_id node,
552 const char *parameter_name,
553 OMX_INDEXTYPE *index) {
554 Parcel data, reply;
555 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
556 data.writeInt32((int32_t)node);
557 data.writeCString(parameter_name);
558
559 remote()->transact(GET_EXTENSION_INDEX, data, &reply);
560
561 status_t err = reply.readInt32();
562 if (err == OK) {
563 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
564 } else {
565 *index = OMX_IndexComponentStartUnused;
566 }
567
568 return err;
569 }
570
setInternalOption(node_id node,OMX_U32 port_index,InternalOptionType type,const void * optionData,size_t size)571 virtual status_t setInternalOption(
572 node_id node,
573 OMX_U32 port_index,
574 InternalOptionType type,
575 const void *optionData,
576 size_t size) {
577 Parcel data, reply;
578 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
579 data.writeInt32((int32_t)node);
580 data.writeInt32(port_index);
581 data.writeInt64(size);
582 data.write(optionData, size);
583 data.writeInt32(type);
584 remote()->transact(SET_INTERNAL_OPTION, data, &reply);
585
586 return reply.readInt32();
587 }
588 };
589
590 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
591
592 ////////////////////////////////////////////////////////////////////////////////
593
594 #define CHECK_OMX_INTERFACE(interface, data, reply) \
595 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
596 ALOGW("Call incorrectly routed to " #interface); \
597 return PERMISSION_DENIED; \
598 } } while (0)
599
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)600 status_t BnOMX::onTransact(
601 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
602 switch (code) {
603 case LIVES_LOCALLY:
604 {
605 CHECK_OMX_INTERFACE(IOMX, data, reply);
606 node_id node = (node_id)data.readInt32();
607 pid_t pid = (pid_t)data.readInt32();
608 reply->writeInt32(livesLocally(node, pid));
609
610 return OK;
611 }
612
613 case LIST_NODES:
614 {
615 CHECK_OMX_INTERFACE(IOMX, data, reply);
616
617 List<ComponentInfo> list;
618 listNodes(&list);
619
620 reply->writeInt32(list.size());
621 for (List<ComponentInfo>::iterator it = list.begin();
622 it != list.end(); ++it) {
623 ComponentInfo &cur = *it;
624
625 reply->writeString8(cur.mName);
626 reply->writeInt32(cur.mRoles.size());
627 for (List<String8>::iterator role_it = cur.mRoles.begin();
628 role_it != cur.mRoles.end(); ++role_it) {
629 reply->writeString8(*role_it);
630 }
631 }
632
633 return NO_ERROR;
634 }
635
636 case ALLOCATE_NODE:
637 {
638 CHECK_OMX_INTERFACE(IOMX, data, reply);
639
640 const char *name = data.readCString();
641
642 sp<IOMXObserver> observer =
643 interface_cast<IOMXObserver>(data.readStrongBinder());
644
645 node_id node;
646
647 status_t err = allocateNode(name, observer, &node);
648 reply->writeInt32(err);
649 if (err == OK) {
650 reply->writeInt32((int32_t)node);
651 }
652
653 return NO_ERROR;
654 }
655
656 case FREE_NODE:
657 {
658 CHECK_OMX_INTERFACE(IOMX, data, reply);
659
660 node_id node = (node_id)data.readInt32();
661
662 reply->writeInt32(freeNode(node));
663
664 return NO_ERROR;
665 }
666
667 case SEND_COMMAND:
668 {
669 CHECK_OMX_INTERFACE(IOMX, data, reply);
670
671 node_id node = (node_id)data.readInt32();
672
673 OMX_COMMANDTYPE cmd =
674 static_cast<OMX_COMMANDTYPE>(data.readInt32());
675
676 OMX_S32 param = data.readInt32();
677 reply->writeInt32(sendCommand(node, cmd, param));
678
679 return NO_ERROR;
680 }
681
682 case GET_PARAMETER:
683 case SET_PARAMETER:
684 case GET_CONFIG:
685 case SET_CONFIG:
686 case SET_INTERNAL_OPTION:
687 {
688 CHECK_OMX_INTERFACE(IOMX, data, reply);
689
690 node_id node = (node_id)data.readInt32();
691 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
692
693 size_t size = data.readInt64();
694
695 void *params = malloc(size);
696 data.read(params, size);
697
698 status_t err;
699 switch (code) {
700 case GET_PARAMETER:
701 err = getParameter(node, index, params, size);
702 break;
703 case SET_PARAMETER:
704 err = setParameter(node, index, params, size);
705 break;
706 case GET_CONFIG:
707 err = getConfig(node, index, params, size);
708 break;
709 case SET_CONFIG:
710 err = setConfig(node, index, params, size);
711 break;
712 case SET_INTERNAL_OPTION:
713 {
714 InternalOptionType type =
715 (InternalOptionType)data.readInt32();
716
717 err = setInternalOption(node, index, type, params, size);
718 break;
719 }
720
721 default:
722 TRESPASS();
723 }
724
725 reply->writeInt32(err);
726
727 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
728 reply->write(params, size);
729 }
730
731 free(params);
732 params = NULL;
733
734 return NO_ERROR;
735 }
736
737 case GET_STATE:
738 {
739 CHECK_OMX_INTERFACE(IOMX, data, reply);
740
741 node_id node = (node_id)data.readInt32();
742 OMX_STATETYPE state = OMX_StateInvalid;
743
744 status_t err = getState(node, &state);
745 reply->writeInt32(state);
746 reply->writeInt32(err);
747
748 return NO_ERROR;
749 }
750
751 case ENABLE_GRAPHIC_BUFFERS:
752 {
753 CHECK_OMX_INTERFACE(IOMX, data, reply);
754
755 node_id node = (node_id)data.readInt32();
756 OMX_U32 port_index = data.readInt32();
757 OMX_BOOL enable = (OMX_BOOL)data.readInt32();
758
759 status_t err = enableGraphicBuffers(node, port_index, enable);
760 reply->writeInt32(err);
761
762 return NO_ERROR;
763 }
764
765 case GET_GRAPHIC_BUFFER_USAGE:
766 {
767 CHECK_OMX_INTERFACE(IOMX, data, reply);
768
769 node_id node = (node_id)data.readInt32();
770 OMX_U32 port_index = data.readInt32();
771
772 OMX_U32 usage = 0;
773 status_t err = getGraphicBufferUsage(node, port_index, &usage);
774 reply->writeInt32(err);
775 reply->writeInt32(usage);
776
777 return NO_ERROR;
778 }
779
780 case USE_BUFFER:
781 {
782 CHECK_OMX_INTERFACE(IOMX, data, reply);
783
784 node_id node = (node_id)data.readInt32();
785 OMX_U32 port_index = data.readInt32();
786 sp<IMemory> params =
787 interface_cast<IMemory>(data.readStrongBinder());
788 OMX_U32 allottedSize = data.readInt32();
789
790 buffer_id buffer;
791 status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
792 reply->writeInt32(err);
793
794 if (err == OK) {
795 reply->writeInt32((int32_t)buffer);
796 }
797
798 return NO_ERROR;
799 }
800
801 case USE_GRAPHIC_BUFFER:
802 {
803 CHECK_OMX_INTERFACE(IOMX, data, reply);
804
805 node_id node = (node_id)data.readInt32();
806 OMX_U32 port_index = data.readInt32();
807 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
808 data.read(*graphicBuffer);
809
810 buffer_id buffer;
811 status_t err = useGraphicBuffer(
812 node, port_index, graphicBuffer, &buffer);
813 reply->writeInt32(err);
814
815 if (err == OK) {
816 reply->writeInt32((int32_t)buffer);
817 }
818
819 return NO_ERROR;
820 }
821
822 case UPDATE_GRAPHIC_BUFFER_IN_META:
823 {
824 CHECK_OMX_INTERFACE(IOMX, data, reply);
825
826 node_id node = (node_id)data.readInt32();
827 OMX_U32 port_index = data.readInt32();
828 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
829 data.read(*graphicBuffer);
830 buffer_id buffer = (buffer_id)data.readInt32();
831
832 status_t err = updateGraphicBufferInMeta(
833 node, port_index, graphicBuffer, buffer);
834 reply->writeInt32(err);
835
836 return NO_ERROR;
837 }
838
839 case CREATE_INPUT_SURFACE:
840 {
841 CHECK_OMX_INTERFACE(IOMX, data, reply);
842
843 node_id node = (node_id)data.readInt32();
844 OMX_U32 port_index = data.readInt32();
845
846 sp<IGraphicBufferProducer> bufferProducer;
847 MetadataBufferType type;
848 status_t err = createInputSurface(node, port_index, &bufferProducer, &type);
849
850 reply->writeInt32(type);
851 reply->writeInt32(err);
852
853 if (err == OK) {
854 reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
855 }
856
857 return NO_ERROR;
858 }
859
860 case CREATE_PERSISTENT_INPUT_SURFACE:
861 {
862 CHECK_OMX_INTERFACE(IOMX, data, reply);
863
864 sp<IGraphicBufferProducer> bufferProducer;
865 sp<IGraphicBufferConsumer> bufferConsumer;
866 status_t err = createPersistentInputSurface(
867 &bufferProducer, &bufferConsumer);
868
869 reply->writeInt32(err);
870
871 if (err == OK) {
872 reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
873 reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
874 }
875
876 return NO_ERROR;
877 }
878
879 case SET_INPUT_SURFACE:
880 {
881 CHECK_OMX_INTERFACE(IOMX, data, reply);
882
883 node_id node = (node_id)data.readInt32();
884 OMX_U32 port_index = data.readInt32();
885
886 sp<IGraphicBufferConsumer> bufferConsumer =
887 interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
888
889 MetadataBufferType type;
890 status_t err = setInputSurface(node, port_index, bufferConsumer, &type);
891
892 reply->writeInt32(type);
893 reply->writeInt32(err);
894 return NO_ERROR;
895 }
896
897 case SIGNAL_END_OF_INPUT_STREAM:
898 {
899 CHECK_OMX_INTERFACE(IOMX, data, reply);
900
901 node_id node = (node_id)data.readInt32();
902
903 status_t err = signalEndOfInputStream(node);
904 reply->writeInt32(err);
905
906 return NO_ERROR;
907 }
908
909 case STORE_META_DATA_IN_BUFFERS:
910 {
911 CHECK_OMX_INTERFACE(IOMX, data, reply);
912
913 node_id node = (node_id)data.readInt32();
914 OMX_U32 port_index = data.readInt32();
915 OMX_BOOL enable = (OMX_BOOL)data.readInt32();
916
917 MetadataBufferType type;
918 status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
919 reply->writeInt32(type);
920 reply->writeInt32(err);
921
922 return NO_ERROR;
923 }
924
925 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
926 {
927 CHECK_OMX_INTERFACE(IOMX, data, reply);
928
929 node_id node = (node_id)data.readInt32();
930 OMX_U32 port_index = data.readInt32();
931 OMX_BOOL enable = (OMX_BOOL)data.readInt32();
932 OMX_U32 max_width = data.readInt32();
933 OMX_U32 max_height = data.readInt32();
934
935 status_t err = prepareForAdaptivePlayback(
936 node, port_index, enable, max_width, max_height);
937 reply->writeInt32(err);
938
939 return NO_ERROR;
940 }
941
942 case CONFIGURE_VIDEO_TUNNEL_MODE:
943 {
944 CHECK_OMX_INTERFACE(IOMX, data, reply);
945
946 node_id node = (node_id)data.readInt32();
947 OMX_U32 port_index = data.readInt32();
948 OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
949 OMX_U32 audio_hw_sync = data.readInt32();
950
951 native_handle_t *sideband_handle;
952 status_t err = configureVideoTunnelMode(
953 node, port_index, tunneled, audio_hw_sync, &sideband_handle);
954 reply->writeInt32(err);
955 reply->writeNativeHandle(sideband_handle);
956
957 return NO_ERROR;
958 }
959
960 case ALLOC_BUFFER:
961 {
962 CHECK_OMX_INTERFACE(IOMX, data, reply);
963
964 node_id node = (node_id)data.readInt32();
965 OMX_U32 port_index = data.readInt32();
966 size_t size = data.readInt64();
967
968 buffer_id buffer;
969 void *buffer_data;
970 status_t err = allocateBuffer(
971 node, port_index, size, &buffer, &buffer_data);
972 reply->writeInt32(err);
973
974 if (err == OK) {
975 reply->writeInt32((int32_t)buffer);
976 reply->writeInt64((uintptr_t)buffer_data);
977 }
978
979 return NO_ERROR;
980 }
981
982 case ALLOC_BUFFER_WITH_BACKUP:
983 {
984 CHECK_OMX_INTERFACE(IOMX, data, reply);
985
986 node_id node = (node_id)data.readInt32();
987 OMX_U32 port_index = data.readInt32();
988 sp<IMemory> params =
989 interface_cast<IMemory>(data.readStrongBinder());
990 OMX_U32 allottedSize = data.readInt32();
991
992 buffer_id buffer;
993 status_t err = allocateBufferWithBackup(
994 node, port_index, params, &buffer, allottedSize);
995
996 reply->writeInt32(err);
997
998 if (err == OK) {
999 reply->writeInt32((int32_t)buffer);
1000 }
1001
1002 return NO_ERROR;
1003 }
1004
1005 case FREE_BUFFER:
1006 {
1007 CHECK_OMX_INTERFACE(IOMX, data, reply);
1008
1009 node_id node = (node_id)data.readInt32();
1010 OMX_U32 port_index = data.readInt32();
1011 buffer_id buffer = (buffer_id)data.readInt32();
1012 reply->writeInt32(freeBuffer(node, port_index, buffer));
1013
1014 return NO_ERROR;
1015 }
1016
1017 case FILL_BUFFER:
1018 {
1019 CHECK_OMX_INTERFACE(IOMX, data, reply);
1020
1021 node_id node = (node_id)data.readInt32();
1022 buffer_id buffer = (buffer_id)data.readInt32();
1023 bool haveFence = data.readInt32();
1024 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1025 reply->writeInt32(fillBuffer(node, buffer, fenceFd));
1026
1027 return NO_ERROR;
1028 }
1029
1030 case EMPTY_BUFFER:
1031 {
1032 CHECK_OMX_INTERFACE(IOMX, data, reply);
1033
1034 node_id node = (node_id)data.readInt32();
1035 buffer_id buffer = (buffer_id)data.readInt32();
1036 OMX_U32 range_offset = data.readInt32();
1037 OMX_U32 range_length = data.readInt32();
1038 OMX_U32 flags = data.readInt32();
1039 OMX_TICKS timestamp = data.readInt64();
1040 bool haveFence = data.readInt32();
1041 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1042 reply->writeInt32(emptyBuffer(
1043 node, buffer, range_offset, range_length, flags, timestamp, fenceFd));
1044
1045 return NO_ERROR;
1046 }
1047
1048 case GET_EXTENSION_INDEX:
1049 {
1050 CHECK_OMX_INTERFACE(IOMX, data, reply);
1051
1052 node_id node = (node_id)data.readInt32();
1053 const char *parameter_name = data.readCString();
1054
1055 OMX_INDEXTYPE index;
1056 status_t err = getExtensionIndex(node, parameter_name, &index);
1057
1058 reply->writeInt32(err);
1059
1060 if (err == OK) {
1061 reply->writeInt32(index);
1062 }
1063
1064 return OK;
1065 }
1066
1067 default:
1068 return BBinder::onTransact(code, data, reply, flags);
1069 }
1070 }
1071
1072 ////////////////////////////////////////////////////////////////////////////////
1073
1074 class BpOMXObserver : public BpInterface<IOMXObserver> {
1075 public:
BpOMXObserver(const sp<IBinder> & impl)1076 BpOMXObserver(const sp<IBinder> &impl)
1077 : BpInterface<IOMXObserver>(impl) {
1078 }
1079
onMessages(const std::list<omx_message> & messages)1080 virtual void onMessages(const std::list<omx_message> &messages) {
1081 Parcel data, reply;
1082 std::list<omx_message>::const_iterator it = messages.cbegin();
1083 bool first = true;
1084 while (it != messages.cend()) {
1085 const omx_message &msg = *it++;
1086 if (first) {
1087 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
1088 data.writeInt32(msg.node);
1089 first = false;
1090 }
1091 data.writeInt32(msg.fenceFd >= 0);
1092 if (msg.fenceFd >= 0) {
1093 data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
1094 }
1095 data.writeInt32(msg.type);
1096 data.write(&msg.u, sizeof(msg.u));
1097 ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
1098 }
1099 if (!first) {
1100 data.writeInt32(-1); // mark end
1101 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
1102 }
1103 }
1104 };
1105
1106 IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
1107
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)1108 status_t BnOMXObserver::onTransact(
1109 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
1110 switch (code) {
1111 case OBSERVER_ON_MSG:
1112 {
1113 CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
1114 IOMX::node_id node = data.readInt32();
1115 std::list<omx_message> messages;
1116 status_t err = FAILED_TRANSACTION; // must receive at least one message
1117 do {
1118 int haveFence = data.readInt32();
1119 if (haveFence < 0) { // we use -1 to mark end of messages
1120 break;
1121 }
1122 omx_message msg;
1123 msg.node = node;
1124 msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1125 msg.type = (typeof(msg.type))data.readInt32();
1126 err = data.read(&msg.u, sizeof(msg.u));
1127 ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg));
1128 messages.push_back(msg);
1129 } while (err == OK);
1130
1131 if (err == OK) {
1132 onMessages(messages);
1133 }
1134
1135 return err;
1136 }
1137
1138 default:
1139 return BBinder::onTransact(code, data, reply, flags);
1140 }
1141 }
1142
1143 } // namespace android
1144