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