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