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