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