IOMX.cpp revision 3604cb1a5548694393c7b7a87191eb517bebaa47
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, 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.writeInt32(fenceFd >= 0);
486        if (fenceFd >= 0) {
487            data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
488        }
489        remote()->transact(EMPTY_GRAPHIC_BUFFER, data, &reply);
490
491        return reply.readInt32();
492    }
493
494    virtual status_t getExtensionIndex(
495            const char *parameter_name,
496            OMX_INDEXTYPE *index) {
497        Parcel data, reply;
498        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
499        data.writeCString(parameter_name);
500
501        remote()->transact(GET_EXTENSION_INDEX, data, &reply);
502
503        status_t err = reply.readInt32();
504        if (err == OK) {
505            *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
506        } else {
507            *index = OMX_IndexComponentStartUnused;
508        }
509
510        return err;
511    }
512
513    virtual status_t dispatchMessage(const omx_message &msg) {
514        Parcel data, reply;
515        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
516        data.writeInt32(msg.fenceFd >= 0);
517        if (msg.fenceFd >= 0) {
518            data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
519        }
520        data.writeInt32(msg.type);
521        data.write(&msg.u, sizeof(msg.u));
522
523        remote()->transact(DISPATCH_MESSAGE, data, &reply);
524
525        return reply.readInt32();
526    }
527
528    virtual status_t setQuirks(OMX_U32 quirks) {
529        Parcel data, reply;
530        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
531        data.writeInt32(quirks);
532
533        remote()->transact(SET_QUIRKS, data, &reply);
534
535        return reply.readInt32();
536    }
537};
538
539IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
540IMPLEMENT_META_INTERFACE(OMXNode, "android.hardware.IOMXNode");
541
542////////////////////////////////////////////////////////////////////////////////
543
544#define CHECK_OMX_INTERFACE(interface, data, reply) \
545        do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
546            ALOGW("Call incorrectly routed to " #interface); \
547            return PERMISSION_DENIED; \
548        } } while (0)
549
550status_t BnOMX::onTransact(
551    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
552    switch (code) {
553        case LIST_NODES:
554        {
555            CHECK_OMX_INTERFACE(IOMX, data, reply);
556
557            List<ComponentInfo> list;
558            listNodes(&list);
559
560            reply->writeInt32(list.size());
561            for (List<ComponentInfo>::iterator it = list.begin();
562                 it != list.end(); ++it) {
563                ComponentInfo &cur = *it;
564
565                reply->writeString8(cur.mName);
566                reply->writeInt32(cur.mRoles.size());
567                for (List<String8>::iterator role_it = cur.mRoles.begin();
568                     role_it != cur.mRoles.end(); ++role_it) {
569                    reply->writeString8(*role_it);
570                }
571            }
572
573            return NO_ERROR;
574        }
575
576        case ALLOCATE_NODE:
577        {
578            CHECK_OMX_INTERFACE(IOMX, data, reply);
579
580            const char *name = data.readCString();
581
582            sp<IOMXObserver> observer =
583                interface_cast<IOMXObserver>(data.readStrongBinder());
584
585            if (name == NULL || observer == NULL) {
586                ALOGE("b/26392700");
587                reply->writeInt32(INVALID_OPERATION);
588                return NO_ERROR;
589            }
590
591            sp<IOMXNode> omxNode;
592
593            status_t err = allocateNode(name, observer, &omxNode);
594
595            reply->writeInt32(err);
596            if (err == OK) {
597                reply->writeStrongBinder(IInterface::asBinder(omxNode));
598            }
599
600            return NO_ERROR;
601        }
602
603        case CREATE_INPUT_SURFACE:
604        {
605            CHECK_OMX_INTERFACE(IOMX, data, reply);
606
607            sp<IGraphicBufferProducer> bufferProducer;
608            sp<IGraphicBufferSource> bufferSource;
609            status_t err = createInputSurface(&bufferProducer, &bufferSource);
610
611            reply->writeInt32(err);
612
613            if (err == OK) {
614                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
615                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
616            }
617
618            return NO_ERROR;
619        }
620
621        default:
622            return BBinder::onTransact(code, data, reply, flags);
623    }
624}
625
626status_t BnOMXNode::onTransact(
627    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
628    switch (code) {
629        case FREE_NODE:
630        {
631            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
632
633            reply->writeInt32(freeNode());
634
635            return NO_ERROR;
636        }
637
638        case SEND_COMMAND:
639        {
640            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
641
642            OMX_COMMANDTYPE cmd =
643                static_cast<OMX_COMMANDTYPE>(data.readInt32());
644
645            OMX_S32 param = data.readInt32();
646            reply->writeInt32(sendCommand(cmd, param));
647
648            return NO_ERROR;
649        }
650
651        case GET_PARAMETER:
652        case SET_PARAMETER:
653        case GET_CONFIG:
654        case SET_CONFIG:
655        {
656            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
657
658            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
659
660            size_t size = data.readInt64();
661
662            status_t err = NOT_ENOUGH_DATA;
663            void *params = NULL;
664            size_t pageSize = 0;
665            size_t allocSize = 0;
666            bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
667            if ((isUsageBits && size < 4) || (!isUsageBits && size < 8)) {
668                // we expect the structure to contain at least the size and
669                // version, 8 bytes total
670                ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
671                android_errorWriteLog(0x534e4554, "27207275");
672            } else {
673                err = NO_MEMORY;
674                pageSize = (size_t) sysconf(_SC_PAGE_SIZE);
675                if (size > SIZE_MAX - (pageSize * 2)) {
676                    ALOGE("requested param size too big");
677                } else {
678                    allocSize = (size + pageSize * 2) & ~(pageSize - 1);
679                    params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
680                            MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
681                }
682                if (params != MAP_FAILED) {
683                    err = data.read(params, size);
684                    if (err != OK) {
685                        android_errorWriteLog(0x534e4554, "26914474");
686                    } else {
687                        err = NOT_ENOUGH_DATA;
688                        OMX_U32 declaredSize = *(OMX_U32*)params;
689                        if (index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
690                                declaredSize > size) {
691                            // the buffer says it's bigger than it actually is
692                            ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
693                            android_errorWriteLog(0x534e4554, "27207275");
694                        } else {
695                            // mark the last page as inaccessible, to avoid exploitation
696                            // of codecs that access past the end of the allocation because
697                            // they didn't check the size
698                            if (mprotect((char*)params + allocSize - pageSize, pageSize,
699                                    PROT_NONE) != 0) {
700                                ALOGE("mprotect failed: %s", strerror(errno));
701                            } else {
702                                switch (code) {
703                                    case GET_PARAMETER:
704                                        err = getParameter(index, params, size);
705                                        break;
706                                    case SET_PARAMETER:
707                                        err = setParameter(index, params, size);
708                                        break;
709                                    case GET_CONFIG:
710                                        err = getConfig(index, params, size);
711                                        break;
712                                    case SET_CONFIG:
713                                        err = setConfig(index, params, size);
714                                        break;
715                                    default:
716                                        TRESPASS();
717                                }
718                            }
719                        }
720                    }
721                } else {
722                    ALOGE("couldn't map: %s", strerror(errno));
723                }
724            }
725
726            reply->writeInt32(err);
727
728            if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
729                reply->write(params, size);
730            }
731
732            if (params) {
733                munmap(params, allocSize);
734            }
735            params = NULL;
736
737            return NO_ERROR;
738        }
739
740        case ENABLE_NATIVE_BUFFERS:
741        {
742            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
743
744            OMX_U32 port_index = data.readInt32();
745            OMX_BOOL graphic = (OMX_BOOL)data.readInt32();
746            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
747
748            status_t err = enableNativeBuffers(port_index, graphic, enable);
749            reply->writeInt32(err);
750
751            return NO_ERROR;
752        }
753
754        case GET_GRAPHIC_BUFFER_USAGE:
755        {
756            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
757
758            OMX_U32 port_index = data.readInt32();
759
760            OMX_U32 usage = 0;
761            status_t err = getGraphicBufferUsage(port_index, &usage);
762            reply->writeInt32(err);
763            reply->writeInt32(usage);
764
765            return NO_ERROR;
766        }
767
768        case USE_BUFFER:
769        {
770            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
771
772            OMX_U32 port_index = data.readInt32();
773            sp<IMemory> params =
774                interface_cast<IMemory>(data.readStrongBinder());
775            OMX_U32 allottedSize = data.readInt32();
776
777            if (params == NULL) {
778                ALOGE("b/26392700");
779                reply->writeInt32(INVALID_OPERATION);
780                return NO_ERROR;
781            }
782
783            buffer_id buffer;
784            status_t err = useBuffer(port_index, params, &buffer, allottedSize);
785            reply->writeInt32(err);
786
787            if (err == OK) {
788                reply->writeInt32((int32_t)buffer);
789            }
790
791            return NO_ERROR;
792        }
793
794        case USE_GRAPHIC_BUFFER:
795        {
796            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
797
798            OMX_U32 port_index = data.readInt32();
799            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
800            data.read(*graphicBuffer);
801
802            buffer_id buffer;
803            status_t err = useGraphicBuffer(
804                    port_index, graphicBuffer, &buffer);
805            reply->writeInt32(err);
806
807            if (err == OK) {
808                reply->writeInt32((int32_t)buffer);
809            }
810
811            return NO_ERROR;
812        }
813
814        case UPDATE_GRAPHIC_BUFFER_IN_META:
815        {
816            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
817
818            OMX_U32 port_index = data.readInt32();
819            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
820            data.read(*graphicBuffer);
821            buffer_id buffer = (buffer_id)data.readInt32();
822
823            status_t err = updateGraphicBufferInMeta(
824                    port_index, graphicBuffer, buffer);
825            reply->writeInt32(err);
826
827            return NO_ERROR;
828        }
829
830        case UPDATE_NATIVE_HANDLE_IN_META:
831        {
832            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
833
834            OMX_U32 port_index = data.readInt32();
835            native_handle *handle = NULL;
836            if (data.readInt32()) {
837                handle = data.readNativeHandle();
838            }
839            buffer_id buffer = (buffer_id)data.readInt32();
840
841            status_t err = updateNativeHandleInMeta(
842                    port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
843            reply->writeInt32(err);
844
845            return NO_ERROR;
846        }
847
848        case SET_INPUT_SURFACE:
849        {
850            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
851
852            sp<IOMXBufferSource> bufferSource =
853                    interface_cast<IOMXBufferSource>(data.readStrongBinder());
854
855            status_t err = setInputSurface(bufferSource);
856            reply->writeInt32(err);
857
858            return NO_ERROR;
859        }
860
861        case STORE_META_DATA_IN_BUFFERS:
862        {
863            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
864
865            OMX_U32 port_index = data.readInt32();
866            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
867
868            MetadataBufferType type = (MetadataBufferType)data.readInt32();
869            status_t err = storeMetaDataInBuffers(port_index, enable, &type);
870
871            reply->writeInt32(type);
872            reply->writeInt32(err);
873
874            return NO_ERROR;
875        }
876
877        case PREPARE_FOR_ADAPTIVE_PLAYBACK:
878        {
879            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
880
881            OMX_U32 port_index = data.readInt32();
882            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
883            OMX_U32 max_width = data.readInt32();
884            OMX_U32 max_height = data.readInt32();
885
886            status_t err = prepareForAdaptivePlayback(
887                    port_index, enable, max_width, max_height);
888            reply->writeInt32(err);
889
890            return NO_ERROR;
891        }
892
893        case CONFIGURE_VIDEO_TUNNEL_MODE:
894        {
895            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
896
897            OMX_U32 port_index = data.readInt32();
898            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
899            OMX_U32 audio_hw_sync = data.readInt32();
900
901            native_handle_t *sideband_handle = NULL;
902            status_t err = configureVideoTunnelMode(
903                    port_index, tunneled, audio_hw_sync, &sideband_handle);
904            reply->writeInt32(err);
905            if(err == OK){
906                reply->writeNativeHandle(sideband_handle);
907            }
908
909            return NO_ERROR;
910        }
911
912        case ALLOC_SECURE_BUFFER:
913        {
914            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
915
916            OMX_U32 port_index = data.readInt32();
917            if (!isSecure() || port_index != 0 /* kPortIndexInput */) {
918                ALOGE("b/24310423");
919                reply->writeInt32(INVALID_OPERATION);
920                return NO_ERROR;
921            }
922
923            size_t size = data.readInt64();
924
925            buffer_id buffer;
926            void *buffer_data = NULL;
927            sp<NativeHandle> native_handle;
928            status_t err = allocateSecureBuffer(
929                    port_index, size, &buffer, &buffer_data, &native_handle);
930            reply->writeInt32(err);
931
932            if (err == OK) {
933                reply->writeInt32((int32_t)buffer);
934                reply->writeInt64((uintptr_t)buffer_data);
935                if (buffer_data == NULL) {
936                    reply->writeNativeHandle(native_handle == NULL ? NULL : native_handle->handle());
937                }
938            }
939
940            return NO_ERROR;
941        }
942
943        case FREE_BUFFER:
944        {
945            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
946
947            OMX_U32 port_index = data.readInt32();
948            buffer_id buffer = (buffer_id)data.readInt32();
949            reply->writeInt32(freeBuffer(port_index, buffer));
950
951            return NO_ERROR;
952        }
953
954        case FILL_BUFFER:
955        {
956            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
957
958            buffer_id buffer = (buffer_id)data.readInt32();
959            bool haveFence = data.readInt32();
960            int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
961            reply->writeInt32(fillBuffer(buffer, fenceFd));
962
963            return NO_ERROR;
964        }
965
966        case EMPTY_BUFFER:
967        {
968            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
969
970            buffer_id buffer = (buffer_id)data.readInt32();
971            OMX_U32 range_offset = data.readInt32();
972            OMX_U32 range_length = data.readInt32();
973            OMX_U32 flags = data.readInt32();
974            OMX_TICKS timestamp = data.readInt64();
975            bool haveFence = data.readInt32();
976            int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
977            reply->writeInt32(emptyBuffer(
978                    buffer, range_offset, range_length, flags, timestamp, fenceFd));
979
980            return NO_ERROR;
981        }
982
983        case EMPTY_GRAPHIC_BUFFER:
984        {
985            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
986
987            buffer_id buffer = (buffer_id)data.readInt32();
988            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
989            data.read(*graphicBuffer);
990            OMX_U32 flags = data.readInt32();
991            OMX_TICKS timestamp = data.readInt64();
992            bool haveFence = data.readInt32();
993            int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
994            reply->writeInt32(emptyGraphicBuffer(
995                    buffer, graphicBuffer, flags, timestamp, fenceFd));
996
997            return NO_ERROR;
998        }
999
1000        case GET_EXTENSION_INDEX:
1001        {
1002            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
1003
1004            const char *parameter_name = data.readCString();
1005
1006            if (parameter_name == NULL) {
1007                ALOGE("b/26392700");
1008                reply->writeInt32(INVALID_OPERATION);
1009                return NO_ERROR;
1010            }
1011
1012            OMX_INDEXTYPE index;
1013            status_t err = getExtensionIndex(parameter_name, &index);
1014
1015            reply->writeInt32(err);
1016
1017            if (err == OK) {
1018                reply->writeInt32(index);
1019            }
1020
1021            return OK;
1022        }
1023
1024        case DISPATCH_MESSAGE:
1025        {
1026            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
1027            omx_message msg;
1028            int haveFence = data.readInt32();
1029            msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1030            msg.type = (typeof(msg.type))data.readInt32();
1031            status_t err = data.read(&msg.u, sizeof(msg.u));
1032
1033            if (err == OK) {
1034                err = dispatchMessage(msg);
1035            }
1036            reply->writeInt32(err);
1037
1038            return NO_ERROR;
1039        }
1040
1041        case SET_QUIRKS:
1042        {
1043            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
1044
1045            OMX_U32 quirks = data.readInt32();
1046
1047            reply->writeInt32(setQuirks(quirks));
1048
1049            return NO_ERROR;
1050        }
1051
1052        default:
1053            return BBinder::onTransact(code, data, reply, flags);
1054    }
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058
1059class BpOMXObserver : public BpInterface<IOMXObserver> {
1060public:
1061    explicit BpOMXObserver(const sp<IBinder> &impl)
1062        : BpInterface<IOMXObserver>(impl) {
1063    }
1064
1065    virtual void onMessages(const std::list<omx_message> &messages) {
1066        Parcel data, reply;
1067        std::list<omx_message>::const_iterator it = messages.cbegin();
1068        if (messages.empty()) {
1069            return;
1070        }
1071        data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
1072        while (it != messages.cend()) {
1073            const omx_message &msg = *it++;
1074            data.writeInt32(msg.fenceFd >= 0);
1075            if (msg.fenceFd >= 0) {
1076                data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
1077            }
1078            data.writeInt32(msg.type);
1079            data.write(&msg.u, sizeof(msg.u));
1080            ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
1081        }
1082        data.writeInt32(-1); // mark end
1083        remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
1084    }
1085};
1086
1087IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
1088
1089status_t BnOMXObserver::onTransact(
1090    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
1091    switch (code) {
1092        case OBSERVER_ON_MSG:
1093        {
1094            CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
1095            std::list<omx_message> messages;
1096            status_t err = FAILED_TRANSACTION; // must receive at least one message
1097            do {
1098                int haveFence = data.readInt32();
1099                if (haveFence < 0) { // we use -1 to mark end of messages
1100                    break;
1101                }
1102                omx_message msg;
1103                msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
1104                msg.type = (typeof(msg.type))data.readInt32();
1105                err = data.read(&msg.u, sizeof(msg.u));
1106                ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg));
1107                messages.push_back(msg);
1108            } while (err == OK);
1109
1110            if (err == OK) {
1111                onMessages(messages);
1112            }
1113
1114            return err;
1115        }
1116
1117        default:
1118            return BBinder::onTransact(code, data, reply, flags);
1119    }
1120}
1121
1122}  // namespace android
1123