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