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