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