IOMX.cpp revision af9c466b91eb43ffa4590b559fa8bb1003191ab5
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_NATIVE_BUFFERS,
41    USE_BUFFER,
42    USE_GRAPHIC_BUFFER,
43    CREATE_INPUT_SURFACE,
44    CREATE_PERSISTENT_INPUT_SURFACE,
45    SET_INPUT_SURFACE,
46    SIGNAL_END_OF_INPUT_STREAM,
47    STORE_META_DATA_IN_BUFFERS,
48    PREPARE_FOR_ADAPTIVE_PLAYBACK,
49    ALLOC_SECURE_BUFFER,
50    ALLOC_BUFFER_WITH_BACKUP,
51    FREE_BUFFER,
52    FILL_BUFFER,
53    EMPTY_BUFFER,
54    GET_EXTENSION_INDEX,
55    OBSERVER_ON_MSG,
56    GET_GRAPHIC_BUFFER_USAGE,
57    SET_INTERNAL_OPTION,
58    UPDATE_GRAPHIC_BUFFER_IN_META,
59    CONFIGURE_VIDEO_TUNNEL_MODE,
60};
61
62class BpOMX : public BpInterface<IOMX> {
63public:
64    BpOMX(const sp<IBinder> &impl)
65        : BpInterface<IOMX>(impl) {
66    }
67
68    virtual bool livesLocally(node_id node, pid_t pid) {
69        Parcel data, reply;
70        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
71        data.writeInt32((int32_t)node);
72        data.writeInt32(pid);
73        remote()->transact(LIVES_LOCALLY, data, &reply);
74
75        return reply.readInt32() != 0;
76    }
77
78    virtual status_t listNodes(List<ComponentInfo> *list) {
79        list->clear();
80
81        Parcel data, reply;
82        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
83        remote()->transact(LIST_NODES, data, &reply);
84
85        int32_t n = reply.readInt32();
86        for (int32_t i = 0; i < n; ++i) {
87            list->push_back(ComponentInfo());
88            ComponentInfo &info = *--list->end();
89
90            info.mName = reply.readString8();
91            int32_t numRoles = reply.readInt32();
92            for (int32_t j = 0; j < numRoles; ++j) {
93                info.mRoles.push_back(reply.readString8());
94            }
95        }
96
97        return OK;
98    }
99
100    virtual status_t allocateNode(
101            const char *name, const sp<IOMXObserver> &observer,
102            sp<IBinder> *nodeBinder,
103            node_id *node) {
104        Parcel data, reply;
105        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
106        data.writeCString(name);
107        data.writeStrongBinder(IInterface::asBinder(observer));
108        remote()->transact(ALLOCATE_NODE, data, &reply);
109
110        status_t err = reply.readInt32();
111        if (err == OK) {
112            *node = (node_id)reply.readInt32();
113            if (nodeBinder != NULL) {
114                *nodeBinder = remote();
115            }
116        } else {
117            *node = 0;
118        }
119
120        return err;
121    }
122
123    virtual status_t freeNode(node_id node) {
124        Parcel data, reply;
125        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
126        data.writeInt32((int32_t)node);
127        remote()->transact(FREE_NODE, data, &reply);
128
129        return reply.readInt32();
130    }
131
132    virtual status_t sendCommand(
133            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
134        Parcel data, reply;
135        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
136        data.writeInt32((int32_t)node);
137        data.writeInt32(cmd);
138        data.writeInt32(param);
139        remote()->transact(SEND_COMMAND, data, &reply);
140
141        return reply.readInt32();
142    }
143
144    virtual status_t getParameter(
145            node_id node, OMX_INDEXTYPE index,
146            void *params, size_t size) {
147        Parcel data, reply;
148        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
149        data.writeInt32((int32_t)node);
150        data.writeInt32(index);
151        data.writeInt64(size);
152        data.write(params, size);
153        remote()->transact(GET_PARAMETER, data, &reply);
154
155        status_t err = reply.readInt32();
156        if (err != OK) {
157            return err;
158        }
159
160        reply.read(params, size);
161
162        return OK;
163    }
164
165    virtual status_t setParameter(
166            node_id node, OMX_INDEXTYPE index,
167            const void *params, size_t size) {
168        Parcel data, reply;
169        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
170        data.writeInt32((int32_t)node);
171        data.writeInt32(index);
172        data.writeInt64(size);
173        data.write(params, size);
174        remote()->transact(SET_PARAMETER, data, &reply);
175
176        return reply.readInt32();
177    }
178
179    virtual status_t getConfig(
180            node_id node, OMX_INDEXTYPE index,
181            void *params, size_t size) {
182        Parcel data, reply;
183        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
184        data.writeInt32((int32_t)node);
185        data.writeInt32(index);
186        data.writeInt64(size);
187        data.write(params, size);
188        remote()->transact(GET_CONFIG, data, &reply);
189
190        status_t err = reply.readInt32();
191        if (err != OK) {
192            return err;
193        }
194
195        reply.read(params, size);
196
197        return OK;
198    }
199
200    virtual status_t setConfig(
201            node_id node, OMX_INDEXTYPE index,
202            const void *params, size_t size) {
203        Parcel data, reply;
204        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
205        data.writeInt32((int32_t)node);
206        data.writeInt32(index);
207        data.writeInt64(size);
208        data.write(params, size);
209        remote()->transact(SET_CONFIG, data, &reply);
210
211        return reply.readInt32();
212    }
213
214    virtual status_t getState(
215            node_id node, OMX_STATETYPE* state) {
216        Parcel data, reply;
217        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
218        data.writeInt32((int32_t)node);
219        remote()->transact(GET_STATE, data, &reply);
220
221        *state = static_cast<OMX_STATETYPE>(reply.readInt32());
222        return reply.readInt32();
223    }
224
225    virtual status_t enableNativeBuffers(
226            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
227        Parcel data, reply;
228        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
229        data.writeInt32((int32_t)node);
230        data.writeInt32(port_index);
231        data.writeInt32((uint32_t)graphic);
232        data.writeInt32((uint32_t)enable);
233        remote()->transact(ENABLE_NATIVE_BUFFERS, data, &reply);
234
235        status_t err = reply.readInt32();
236        return err;
237    }
238
239    virtual status_t getGraphicBufferUsage(
240            node_id node, OMX_U32 port_index, OMX_U32* usage) {
241        Parcel data, reply;
242        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
243        data.writeInt32((int32_t)node);
244        data.writeInt32(port_index);
245        remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
246
247        status_t err = reply.readInt32();
248        *usage = reply.readInt32();
249        return err;
250    }
251
252    virtual status_t useBuffer(
253            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
254            buffer_id *buffer, OMX_U32 allottedSize) {
255        Parcel data, reply;
256        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
257        data.writeInt32((int32_t)node);
258        data.writeInt32(port_index);
259        data.writeStrongBinder(IInterface::asBinder(params));
260        data.writeInt32(allottedSize);
261        remote()->transact(USE_BUFFER, data, &reply);
262
263        status_t err = reply.readInt32();
264        if (err != OK) {
265            *buffer = 0;
266
267            return err;
268        }
269
270        *buffer = (buffer_id)reply.readInt32();
271
272        return err;
273    }
274
275
276    virtual status_t useGraphicBuffer(
277            node_id node, OMX_U32 port_index,
278            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
279        Parcel data, reply;
280        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
281        data.writeInt32((int32_t)node);
282        data.writeInt32(port_index);
283        data.write(*graphicBuffer);
284        remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
285
286        status_t err = reply.readInt32();
287        if (err != OK) {
288            *buffer = 0;
289
290            return err;
291        }
292
293        *buffer = (buffer_id)reply.readInt32();
294
295        return err;
296    }
297
298    virtual status_t updateGraphicBufferInMeta(
299            node_id node, OMX_U32 port_index,
300            const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
301        Parcel data, reply;
302        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
303        data.writeInt32((int32_t)node);
304        data.writeInt32(port_index);
305        data.write(*graphicBuffer);
306        data.writeInt32((int32_t)buffer);
307        remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply);
308
309        status_t err = reply.readInt32();
310        return err;
311    }
312
313    virtual status_t createInputSurface(
314            node_id node, OMX_U32 port_index,
315            sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
316        Parcel data, reply;
317        status_t err;
318        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
319        data.writeInt32((int32_t)node);
320        data.writeInt32(port_index);
321        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
322        if (err != OK) {
323            ALOGW("binder transaction failed: %d", err);
324            return err;
325        }
326
327        // read type even if createInputSurface failed
328        int negotiatedType = reply.readInt32();
329        if (type != NULL) {
330            *type = (MetadataBufferType)negotiatedType;
331        }
332
333        err = reply.readInt32();
334        if (err != OK) {
335            return err;
336        }
337
338        *bufferProducer = IGraphicBufferProducer::asInterface(
339                reply.readStrongBinder());
340
341        return err;
342    }
343
344    virtual status_t createPersistentInputSurface(
345            sp<IGraphicBufferProducer> *bufferProducer,
346            sp<IGraphicBufferConsumer> *bufferConsumer) {
347        Parcel data, reply;
348        status_t err;
349        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
350        err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
351        if (err != OK) {
352            ALOGW("binder transaction failed: %d", err);
353            return err;
354        }
355
356        err = reply.readInt32();
357        if (err != OK) {
358            return err;
359        }
360
361        *bufferProducer = IGraphicBufferProducer::asInterface(
362                reply.readStrongBinder());
363        *bufferConsumer = IGraphicBufferConsumer::asInterface(
364                reply.readStrongBinder());
365
366        return err;
367    }
368
369    virtual status_t setInputSurface(
370            node_id node, OMX_U32 port_index,
371            const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
372        Parcel data, reply;
373        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
374        status_t err;
375        data.writeInt32((int32_t)node);
376        data.writeInt32(port_index);
377        data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
378
379        err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
380
381        if (err != OK) {
382            ALOGW("binder transaction failed: %d", err);
383            return err;
384        }
385
386        // read type even if setInputSurface failed
387        int negotiatedType = reply.readInt32();
388        if (type != NULL) {
389            *type = (MetadataBufferType)negotiatedType;
390        }
391
392        return reply.readInt32();
393    }
394
395    virtual status_t signalEndOfInputStream(node_id node) {
396        Parcel data, reply;
397        status_t err;
398        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
399        data.writeInt32((int32_t)node);
400        err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply);
401        if (err != OK) {
402            ALOGW("binder transaction failed: %d", err);
403            return err;
404        }
405
406        return reply.readInt32();
407    }
408
409    virtual status_t storeMetaDataInBuffers(
410            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
411        Parcel data, reply;
412        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
413        data.writeInt32((int32_t)node);
414        data.writeInt32(port_index);
415        data.writeInt32((uint32_t)enable);
416        remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
417
418        // read type even storeMetaDataInBuffers failed
419        int negotiatedType = reply.readInt32();
420        if (type != NULL) {
421            *type = (MetadataBufferType)negotiatedType;
422        }
423
424        return reply.readInt32();
425    }
426
427    virtual status_t prepareForAdaptivePlayback(
428            node_id node, OMX_U32 port_index, OMX_BOOL enable,
429            OMX_U32 max_width, OMX_U32 max_height) {
430        Parcel data, reply;
431        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
432        data.writeInt32((int32_t)node);
433        data.writeInt32(port_index);
434        data.writeInt32((int32_t)enable);
435        data.writeInt32(max_width);
436        data.writeInt32(max_height);
437        remote()->transact(PREPARE_FOR_ADAPTIVE_PLAYBACK, data, &reply);
438
439        status_t err = reply.readInt32();
440        return err;
441    }
442
443    virtual status_t configureVideoTunnelMode(
444            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
445            OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
446        Parcel data, reply;
447        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
448        data.writeInt32((int32_t)node);
449        data.writeInt32(portIndex);
450        data.writeInt32((int32_t)tunneled);
451        data.writeInt32(audioHwSync);
452        remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply);
453
454        status_t err = reply.readInt32();
455        if (err == OK && sidebandHandle) {
456            *sidebandHandle = (native_handle_t *)reply.readNativeHandle();
457        }
458        return err;
459    }
460
461
462    virtual status_t allocateSecureBuffer(
463            node_id node, OMX_U32 port_index, size_t size,
464            buffer_id *buffer, void **buffer_data, native_handle_t **native_handle) {
465        Parcel data, reply;
466        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
467        data.writeInt32((int32_t)node);
468        data.writeInt32(port_index);
469        data.writeInt64(size);
470        remote()->transact(ALLOC_SECURE_BUFFER, data, &reply);
471
472        status_t err = reply.readInt32();
473        if (err != OK) {
474            *buffer = 0;
475            *buffer_data = NULL;
476            *native_handle = NULL;
477            return err;
478        }
479
480        *buffer = (buffer_id)reply.readInt32();
481        *buffer_data = (void *)reply.readInt64();
482        if (*buffer_data == NULL) {
483            *native_handle = reply.readNativeHandle();
484        } else {
485            *native_handle = NULL;
486        }
487        return err;
488    }
489
490    virtual status_t allocateBufferWithBackup(
491            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
492            buffer_id *buffer, OMX_U32 allottedSize) {
493        Parcel data, reply;
494        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
495        data.writeInt32((int32_t)node);
496        data.writeInt32(port_index);
497        data.writeStrongBinder(IInterface::asBinder(params));
498        data.writeInt32(allottedSize);
499        remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
500
501        status_t err = reply.readInt32();
502        if (err != OK) {
503            *buffer = 0;
504
505            return err;
506        }
507
508        *buffer = (buffer_id)reply.readInt32();
509
510        return err;
511    }
512
513    virtual status_t freeBuffer(
514            node_id node, OMX_U32 port_index, buffer_id buffer) {
515        Parcel data, reply;
516        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
517        data.writeInt32((int32_t)node);
518        data.writeInt32(port_index);
519        data.writeInt32((int32_t)buffer);
520        remote()->transact(FREE_BUFFER, data, &reply);
521
522        return reply.readInt32();
523    }
524
525    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
526        Parcel data, reply;
527        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
528        data.writeInt32((int32_t)node);
529        data.writeInt32((int32_t)buffer);
530        data.writeInt32(fenceFd >= 0);
531        if (fenceFd >= 0) {
532            data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
533        }
534        remote()->transact(FILL_BUFFER, data, &reply);
535
536        return reply.readInt32();
537    }
538
539    virtual status_t emptyBuffer(
540            node_id node,
541            buffer_id buffer,
542            OMX_U32 range_offset, OMX_U32 range_length,
543            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
544        Parcel data, reply;
545        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
546        data.writeInt32((int32_t)node);
547        data.writeInt32((int32_t)buffer);
548        data.writeInt32(range_offset);
549        data.writeInt32(range_length);
550        data.writeInt32(flags);
551        data.writeInt64(timestamp);
552        data.writeInt32(fenceFd >= 0);
553        if (fenceFd >= 0) {
554            data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
555        }
556        remote()->transact(EMPTY_BUFFER, data, &reply);
557
558        return reply.readInt32();
559    }
560
561    virtual status_t getExtensionIndex(
562            node_id node,
563            const char *parameter_name,
564            OMX_INDEXTYPE *index) {
565        Parcel data, reply;
566        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
567        data.writeInt32((int32_t)node);
568        data.writeCString(parameter_name);
569
570        remote()->transact(GET_EXTENSION_INDEX, data, &reply);
571
572        status_t err = reply.readInt32();
573        if (err == OK) {
574            *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
575        } else {
576            *index = OMX_IndexComponentStartUnused;
577        }
578
579        return err;
580    }
581
582    virtual status_t setInternalOption(
583            node_id node,
584            OMX_U32 port_index,
585            InternalOptionType type,
586            const void *optionData,
587            size_t size) {
588        Parcel data, reply;
589        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
590        data.writeInt32((int32_t)node);
591        data.writeInt32(port_index);
592        data.writeInt64(size);
593        data.write(optionData, size);
594        data.writeInt32(type);
595        remote()->transact(SET_INTERNAL_OPTION, data, &reply);
596
597        return reply.readInt32();
598    }
599};
600
601IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
602
603////////////////////////////////////////////////////////////////////////////////
604
605#define CHECK_OMX_INTERFACE(interface, data, reply) \
606        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
607            ALOGW("Call incorrectly routed to " #interface); \
608            return PERMISSION_DENIED; \
609        } } while (0)
610
611status_t BnOMX::onTransact(
612    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
613    switch (code) {
614        case LIVES_LOCALLY:
615        {
616            CHECK_OMX_INTERFACE(IOMX, data, reply);
617            node_id node = (node_id)data.readInt32();
618            pid_t pid = (pid_t)data.readInt32();
619            reply->writeInt32(livesLocally(node, pid));
620
621            return OK;
622        }
623
624        case LIST_NODES:
625        {
626            CHECK_OMX_INTERFACE(IOMX, data, reply);
627
628            List<ComponentInfo> list;
629            listNodes(&list);
630
631            reply->writeInt32(list.size());
632            for (List<ComponentInfo>::iterator it = list.begin();
633                 it != list.end(); ++it) {
634                ComponentInfo &cur = *it;
635
636                reply->writeString8(cur.mName);
637                reply->writeInt32(cur.mRoles.size());
638                for (List<String8>::iterator role_it = cur.mRoles.begin();
639                     role_it != cur.mRoles.end(); ++role_it) {
640                    reply->writeString8(*role_it);
641                }
642            }
643
644            return NO_ERROR;
645        }
646
647        case ALLOCATE_NODE:
648        {
649            CHECK_OMX_INTERFACE(IOMX, data, reply);
650
651            const char *name = data.readCString();
652
653            sp<IOMXObserver> observer =
654                interface_cast<IOMXObserver>(data.readStrongBinder());
655
656            if (name == NULL || observer == NULL) {
657                ALOGE("b/26392700");
658                reply->writeInt32(INVALID_OPERATION);
659                return NO_ERROR;
660            }
661
662            node_id node;
663
664            status_t err = allocateNode(name, observer,
665                    NULL /* nodeBinder */, &node);
666            reply->writeInt32(err);
667            if (err == OK) {
668                reply->writeInt32((int32_t)node);
669            }
670
671            return NO_ERROR;
672        }
673
674        case FREE_NODE:
675        {
676            CHECK_OMX_INTERFACE(IOMX, data, reply);
677
678            node_id node = (node_id)data.readInt32();
679
680            reply->writeInt32(freeNode(node));
681
682            return NO_ERROR;
683        }
684
685        case SEND_COMMAND:
686        {
687            CHECK_OMX_INTERFACE(IOMX, data, reply);
688
689            node_id node = (node_id)data.readInt32();
690
691            OMX_COMMANDTYPE cmd =
692                static_cast<OMX_COMMANDTYPE>(data.readInt32());
693
694            OMX_S32 param = data.readInt32();
695            reply->writeInt32(sendCommand(node, cmd, param));
696
697            return NO_ERROR;
698        }
699
700        case GET_PARAMETER:
701        case SET_PARAMETER:
702        case GET_CONFIG:
703        case SET_CONFIG:
704        case SET_INTERNAL_OPTION:
705        {
706            CHECK_OMX_INTERFACE(IOMX, data, reply);
707
708            node_id node = (node_id)data.readInt32();
709            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
710
711            size_t size = data.readInt64();
712
713            status_t err = NO_MEMORY;
714            void *params = calloc(size, 1);
715            if (params) {
716                err = data.read(params, size);
717                if (err != OK) {
718                    android_errorWriteLog(0x534e4554, "26914474");
719                } else {
720                    switch (code) {
721                        case GET_PARAMETER:
722                            err = getParameter(node, index, params, size);
723                            break;
724                        case SET_PARAMETER:
725                            err = setParameter(node, index, params, size);
726                            break;
727                        case GET_CONFIG:
728                            err = getConfig(node, index, params, size);
729                            break;
730                        case SET_CONFIG:
731                            err = setConfig(node, index, params, size);
732                            break;
733                        case SET_INTERNAL_OPTION:
734                        {
735                            InternalOptionType type =
736                                (InternalOptionType)data.readInt32();
737
738                            err = setInternalOption(node, index, type, params, size);
739                            break;
740                        }
741
742                        default:
743                            TRESPASS();
744                    }
745                }
746            }
747
748            reply->writeInt32(err);
749
750            if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
751                reply->write(params, size);
752            }
753
754            free(params);
755            params = NULL;
756
757            return NO_ERROR;
758        }
759
760        case GET_STATE:
761        {
762            CHECK_OMX_INTERFACE(IOMX, data, reply);
763
764            node_id node = (node_id)data.readInt32();
765            OMX_STATETYPE state = OMX_StateInvalid;
766
767            status_t err = getState(node, &state);
768            reply->writeInt32(state);
769            reply->writeInt32(err);
770
771            return NO_ERROR;
772        }
773
774        case ENABLE_NATIVE_BUFFERS:
775        {
776            CHECK_OMX_INTERFACE(IOMX, data, reply);
777
778            node_id node = (node_id)data.readInt32();
779            OMX_U32 port_index = data.readInt32();
780            OMX_BOOL graphic = (OMX_BOOL)data.readInt32();
781            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
782
783            status_t err = enableNativeBuffers(node, port_index, graphic, enable);
784            reply->writeInt32(err);
785
786            return NO_ERROR;
787        }
788
789        case GET_GRAPHIC_BUFFER_USAGE:
790        {
791            CHECK_OMX_INTERFACE(IOMX, data, reply);
792
793            node_id node = (node_id)data.readInt32();
794            OMX_U32 port_index = data.readInt32();
795
796            OMX_U32 usage = 0;
797            status_t err = getGraphicBufferUsage(node, port_index, &usage);
798            reply->writeInt32(err);
799            reply->writeInt32(usage);
800
801            return NO_ERROR;
802        }
803
804        case USE_BUFFER:
805        {
806            CHECK_OMX_INTERFACE(IOMX, data, reply);
807
808            node_id node = (node_id)data.readInt32();
809            OMX_U32 port_index = data.readInt32();
810            sp<IMemory> params =
811                interface_cast<IMemory>(data.readStrongBinder());
812            OMX_U32 allottedSize = data.readInt32();
813
814            if (params == NULL) {
815                ALOGE("b/26392700");
816                reply->writeInt32(INVALID_OPERATION);
817                return NO_ERROR;
818            }
819
820            buffer_id buffer;
821            status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
822            reply->writeInt32(err);
823
824            if (err == OK) {
825                reply->writeInt32((int32_t)buffer);
826            }
827
828            return NO_ERROR;
829        }
830
831        case USE_GRAPHIC_BUFFER:
832        {
833            CHECK_OMX_INTERFACE(IOMX, data, reply);
834
835            node_id node = (node_id)data.readInt32();
836            OMX_U32 port_index = data.readInt32();
837            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
838            data.read(*graphicBuffer);
839
840            buffer_id buffer;
841            status_t err = useGraphicBuffer(
842                    node, port_index, graphicBuffer, &buffer);
843            reply->writeInt32(err);
844
845            if (err == OK) {
846                reply->writeInt32((int32_t)buffer);
847            }
848
849            return NO_ERROR;
850        }
851
852        case UPDATE_GRAPHIC_BUFFER_IN_META:
853        {
854            CHECK_OMX_INTERFACE(IOMX, data, reply);
855
856            node_id node = (node_id)data.readInt32();
857            OMX_U32 port_index = data.readInt32();
858            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
859            data.read(*graphicBuffer);
860            buffer_id buffer = (buffer_id)data.readInt32();
861
862            status_t err = updateGraphicBufferInMeta(
863                    node, port_index, graphicBuffer, buffer);
864            reply->writeInt32(err);
865
866            return NO_ERROR;
867        }
868
869        case CREATE_INPUT_SURFACE:
870        {
871            CHECK_OMX_INTERFACE(IOMX, data, reply);
872
873            node_id node = (node_id)data.readInt32();
874            OMX_U32 port_index = data.readInt32();
875
876            sp<IGraphicBufferProducer> bufferProducer;
877            MetadataBufferType type = kMetadataBufferTypeInvalid;
878            status_t err = createInputSurface(node, port_index, &bufferProducer, &type);
879
880            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
881                android_errorWriteLog(0x534e4554, "26324358");
882            }
883
884            reply->writeInt32(type);
885            reply->writeInt32(err);
886
887            if (err == OK) {
888                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
889            }
890
891            return NO_ERROR;
892        }
893
894        case CREATE_PERSISTENT_INPUT_SURFACE:
895        {
896            CHECK_OMX_INTERFACE(IOMX, data, reply);
897
898            sp<IGraphicBufferProducer> bufferProducer;
899            sp<IGraphicBufferConsumer> bufferConsumer;
900            status_t err = createPersistentInputSurface(
901                    &bufferProducer, &bufferConsumer);
902
903            reply->writeInt32(err);
904
905            if (err == OK) {
906                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
907                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
908            }
909
910            return NO_ERROR;
911        }
912
913        case SET_INPUT_SURFACE:
914        {
915            CHECK_OMX_INTERFACE(IOMX, data, reply);
916
917            node_id node = (node_id)data.readInt32();
918            OMX_U32 port_index = data.readInt32();
919
920            sp<IGraphicBufferConsumer> bufferConsumer =
921                    interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
922
923            MetadataBufferType type = kMetadataBufferTypeInvalid;
924
925            status_t err = INVALID_OPERATION;
926            if (bufferConsumer == NULL) {
927                ALOGE("b/26392700");
928            } else {
929                err = setInputSurface(node, port_index, bufferConsumer, &type);
930
931                if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
932                   android_errorWriteLog(0x534e4554, "26324358");
933                }
934            }
935
936            reply->writeInt32(type);
937            reply->writeInt32(err);
938            return NO_ERROR;
939        }
940
941        case SIGNAL_END_OF_INPUT_STREAM:
942        {
943            CHECK_OMX_INTERFACE(IOMX, data, reply);
944
945            node_id node = (node_id)data.readInt32();
946
947            status_t err = signalEndOfInputStream(node);
948            reply->writeInt32(err);
949
950            return NO_ERROR;
951        }
952
953        case STORE_META_DATA_IN_BUFFERS:
954        {
955            CHECK_OMX_INTERFACE(IOMX, data, reply);
956
957            node_id node = (node_id)data.readInt32();
958            OMX_U32 port_index = data.readInt32();
959            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
960
961            MetadataBufferType type = kMetadataBufferTypeInvalid;
962            status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
963
964            reply->writeInt32(type);
965            reply->writeInt32(err);
966
967            return NO_ERROR;
968        }
969
970        case PREPARE_FOR_ADAPTIVE_PLAYBACK:
971        {
972            CHECK_OMX_INTERFACE(IOMX, data, reply);
973
974            node_id node = (node_id)data.readInt32();
975            OMX_U32 port_index = data.readInt32();
976            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
977            OMX_U32 max_width = data.readInt32();
978            OMX_U32 max_height = data.readInt32();
979
980            status_t err = prepareForAdaptivePlayback(
981                    node, port_index, enable, max_width, max_height);
982            reply->writeInt32(err);
983
984            return NO_ERROR;
985        }
986
987        case CONFIGURE_VIDEO_TUNNEL_MODE:
988        {
989            CHECK_OMX_INTERFACE(IOMX, data, reply);
990
991            node_id node = (node_id)data.readInt32();
992            OMX_U32 port_index = data.readInt32();
993            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
994            OMX_U32 audio_hw_sync = data.readInt32();
995
996            native_handle_t *sideband_handle = NULL;
997            status_t err = configureVideoTunnelMode(
998                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
999            reply->writeInt32(err);
1000            if(err == OK){
1001                reply->writeNativeHandle(sideband_handle);
1002            }
1003
1004            return NO_ERROR;
1005        }
1006
1007        case ALLOC_SECURE_BUFFER:
1008        {
1009            CHECK_OMX_INTERFACE(IOMX, data, reply);
1010
1011            node_id node = (node_id)data.readInt32();
1012            OMX_U32 port_index = data.readInt32();
1013            if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
1014                ALOGE("b/24310423");
1015                reply->writeInt32(INVALID_OPERATION);
1016                return NO_ERROR;
1017            }
1018
1019            size_t size = data.readInt64();
1020
1021            buffer_id buffer;
1022            void *buffer_data = NULL;
1023            native_handle_t *native_handle = NULL;
1024            status_t err = allocateSecureBuffer(
1025                    node, port_index, size, &buffer, &buffer_data, &native_handle);
1026            reply->writeInt32(err);
1027
1028            if (err == OK) {
1029                reply->writeInt32((int32_t)buffer);
1030                reply->writeInt64((uintptr_t)buffer_data);
1031                if (buffer_data == NULL) {
1032                    reply->writeNativeHandle(native_handle);
1033                }
1034            }
1035
1036            return NO_ERROR;
1037        }
1038
1039        case ALLOC_BUFFER_WITH_BACKUP:
1040        {
1041            CHECK_OMX_INTERFACE(IOMX, data, reply);
1042
1043            node_id node = (node_id)data.readInt32();
1044            OMX_U32 port_index = data.readInt32();
1045            sp<IMemory> params =
1046                interface_cast<IMemory>(data.readStrongBinder());
1047            OMX_U32 allottedSize = data.readInt32();
1048
1049            if (params == NULL) {
1050                ALOGE("b/26392700");
1051                reply->writeInt32(INVALID_OPERATION);
1052                return NO_ERROR;
1053            }
1054
1055            buffer_id buffer;
1056            status_t err = allocateBufferWithBackup(
1057                    node, port_index, params, &buffer, allottedSize);
1058
1059            reply->writeInt32(err);
1060
1061            if (err == OK) {
1062                reply->writeInt32((int32_t)buffer);
1063            }
1064
1065            return NO_ERROR;
1066        }
1067
1068        case FREE_BUFFER:
1069        {
1070            CHECK_OMX_INTERFACE(IOMX, data, reply);
1071
1072            node_id node = (node_id)data.readInt32();
1073            OMX_U32 port_index = data.readInt32();
1074            buffer_id buffer = (buffer_id)data.readInt32();
1075            reply->writeInt32(freeBuffer(node, port_index, buffer));
1076
1077            return NO_ERROR;
1078        }
1079
1080        case FILL_BUFFER:
1081        {
1082            CHECK_OMX_INTERFACE(IOMX, data, reply);
1083
1084            node_id node = (node_id)data.readInt32();
1085            buffer_id buffer = (buffer_id)data.readInt32();
1086            bool haveFence = data.readInt32();
1087            int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1088            reply->writeInt32(fillBuffer(node, buffer, fenceFd));
1089
1090            return NO_ERROR;
1091        }
1092
1093        case EMPTY_BUFFER:
1094        {
1095            CHECK_OMX_INTERFACE(IOMX, data, reply);
1096
1097            node_id node = (node_id)data.readInt32();
1098            buffer_id buffer = (buffer_id)data.readInt32();
1099            OMX_U32 range_offset = data.readInt32();
1100            OMX_U32 range_length = data.readInt32();
1101            OMX_U32 flags = data.readInt32();
1102            OMX_TICKS timestamp = data.readInt64();
1103            bool haveFence = data.readInt32();
1104            int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1105            reply->writeInt32(emptyBuffer(
1106                    node, buffer, range_offset, range_length, flags, timestamp, fenceFd));
1107
1108            return NO_ERROR;
1109        }
1110
1111        case GET_EXTENSION_INDEX:
1112        {
1113            CHECK_OMX_INTERFACE(IOMX, data, reply);
1114
1115            node_id node = (node_id)data.readInt32();
1116            const char *parameter_name = data.readCString();
1117
1118            if (parameter_name == NULL) {
1119                ALOGE("b/26392700");
1120                reply->writeInt32(INVALID_OPERATION);
1121                return NO_ERROR;
1122            }
1123
1124            OMX_INDEXTYPE index;
1125            status_t err = getExtensionIndex(node, parameter_name, &index);
1126
1127            reply->writeInt32(err);
1128
1129            if (err == OK) {
1130                reply->writeInt32(index);
1131            }
1132
1133            return OK;
1134        }
1135
1136        default:
1137            return BBinder::onTransact(code, data, reply, flags);
1138    }
1139}
1140
1141////////////////////////////////////////////////////////////////////////////////
1142
1143class BpOMXObserver : public BpInterface<IOMXObserver> {
1144public:
1145    BpOMXObserver(const sp<IBinder> &impl)
1146        : BpInterface<IOMXObserver>(impl) {
1147    }
1148
1149    virtual void onMessages(const std::list<omx_message> &messages) {
1150        Parcel data, reply;
1151        std::list<omx_message>::const_iterator it = messages.cbegin();
1152        bool first = true;
1153        while (it != messages.cend()) {
1154            const omx_message &msg = *it++;
1155            if (first) {
1156                data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
1157                data.writeInt32(msg.node);
1158                first = false;
1159            }
1160            data.writeInt32(msg.fenceFd >= 0);
1161            if (msg.fenceFd >= 0) {
1162                data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
1163            }
1164            data.writeInt32(msg.type);
1165            data.write(&msg.u, sizeof(msg.u));
1166            ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
1167        }
1168        if (!first) {
1169            data.writeInt32(-1); // mark end
1170            remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
1171        }
1172    }
1173};
1174
1175IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
1176
1177status_t BnOMXObserver::onTransact(
1178    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
1179    switch (code) {
1180        case OBSERVER_ON_MSG:
1181        {
1182            CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
1183            IOMX::node_id node = data.readInt32();
1184            std::list<omx_message> messages;
1185            status_t err = FAILED_TRANSACTION; // must receive at least one message
1186            do {
1187                int haveFence = data.readInt32();
1188                if (haveFence < 0) { // we use -1 to mark end of messages
1189                    break;
1190                }
1191                omx_message msg;
1192                msg.node = node;
1193                msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1194                msg.type = (typeof(msg.type))data.readInt32();
1195                err = data.read(&msg.u, sizeof(msg.u));
1196                ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg));
1197                messages.push_back(msg);
1198            } while (err == OK);
1199
1200            if (err == OK) {
1201                onMessages(messages);
1202            }
1203
1204            return err;
1205        }
1206
1207        default:
1208            return BBinder::onTransact(code, data, reply, flags);
1209    }
1210}
1211
1212}  // namespace android
1213