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