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