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