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