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