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