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