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