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