1 //#define LOG_NDEBUG 0
2 #define LOG_TAG "IOMX"
3 #include <utils/Log.h>
4
5 #include <binder/IMemory.h>
6 #include <binder/Parcel.h>
7 #include <media/IOMX.h>
8 #include <ui/ISurface.h>
9 #include <ui/Surface.h>
10
11 namespace android {
12
13 enum {
14 CONNECT = IBinder::FIRST_CALL_TRANSACTION,
15 LIST_NODES,
16 ALLOCATE_NODE,
17 FREE_NODE,
18 SEND_COMMAND,
19 GET_PARAMETER,
20 SET_PARAMETER,
21 GET_CONFIG,
22 SET_CONFIG,
23 USE_BUFFER,
24 ALLOC_BUFFER,
25 ALLOC_BUFFER_WITH_BACKUP,
26 FREE_BUFFER,
27 FILL_BUFFER,
28 EMPTY_BUFFER,
29 GET_EXTENSION_INDEX,
30 CREATE_RENDERER,
31 OBSERVER_ON_MSG,
32 RENDERER_RENDER,
33 };
34
createRenderer(const sp<Surface> & surface,const char * componentName,OMX_COLOR_FORMATTYPE colorFormat,size_t encodedWidth,size_t encodedHeight,size_t displayWidth,size_t displayHeight)35 sp<IOMXRenderer> IOMX::createRenderer(
36 const sp<Surface> &surface,
37 const char *componentName,
38 OMX_COLOR_FORMATTYPE colorFormat,
39 size_t encodedWidth, size_t encodedHeight,
40 size_t displayWidth, size_t displayHeight) {
41 return createRenderer(
42 surface->getISurface(),
43 componentName, colorFormat, encodedWidth, encodedHeight,
44 displayWidth, displayHeight);
45 }
46
createRendererFromJavaSurface(JNIEnv * env,jobject javaSurface,const char * componentName,OMX_COLOR_FORMATTYPE colorFormat,size_t encodedWidth,size_t encodedHeight,size_t displayWidth,size_t displayHeight)47 sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
48 JNIEnv *env, jobject javaSurface,
49 const char *componentName,
50 OMX_COLOR_FORMATTYPE colorFormat,
51 size_t encodedWidth, size_t encodedHeight,
52 size_t displayWidth, size_t displayHeight) {
53 jclass surfaceClass = env->FindClass("android/view/Surface");
54 if (surfaceClass == NULL) {
55 LOGE("Can't find android/view/Surface");
56 return NULL;
57 }
58
59 jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
60 if (surfaceID == NULL) {
61 LOGE("Can't find Surface.mSurface");
62 return NULL;
63 }
64
65 sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID);
66
67 return createRenderer(
68 surface, componentName, colorFormat, encodedWidth,
69 encodedHeight, displayWidth, displayHeight);
70 }
71
72 class BpOMX : public BpInterface<IOMX> {
73 public:
BpOMX(const sp<IBinder> & impl)74 BpOMX(const sp<IBinder> &impl)
75 : BpInterface<IOMX>(impl) {
76 }
77
listNodes(List<String8> * list)78 virtual status_t listNodes(List<String8> *list) {
79 list->clear();
80
81 Parcel data, reply;
82 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
83 remote()->transact(LIST_NODES, data, &reply);
84
85 int32_t n = reply.readInt32();
86 for (int32_t i = 0; i < n; ++i) {
87 String8 s = reply.readString8();
88
89 list->push_back(s);
90 }
91
92 return OK;
93 }
94
allocateNode(const char * name,const sp<IOMXObserver> & observer,node_id * node)95 virtual status_t allocateNode(
96 const char *name, const sp<IOMXObserver> &observer, node_id *node) {
97 Parcel data, reply;
98 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
99 data.writeCString(name);
100 data.writeStrongBinder(observer->asBinder());
101 remote()->transact(ALLOCATE_NODE, data, &reply);
102
103 status_t err = reply.readInt32();
104 if (err == OK) {
105 *node = (void*)reply.readIntPtr();
106 } else {
107 *node = 0;
108 }
109
110 return err;
111 }
112
freeNode(node_id node)113 virtual status_t freeNode(node_id node) {
114 Parcel data, reply;
115 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
116 data.writeIntPtr((intptr_t)node);
117 remote()->transact(FREE_NODE, data, &reply);
118
119 return reply.readInt32();
120 }
121
sendCommand(node_id node,OMX_COMMANDTYPE cmd,OMX_S32 param)122 virtual status_t sendCommand(
123 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
124 Parcel data, reply;
125 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
126 data.writeIntPtr((intptr_t)node);
127 data.writeInt32(cmd);
128 data.writeInt32(param);
129 remote()->transact(SEND_COMMAND, data, &reply);
130
131 return reply.readInt32();
132 }
133
getParameter(node_id node,OMX_INDEXTYPE index,void * params,size_t size)134 virtual status_t getParameter(
135 node_id node, OMX_INDEXTYPE index,
136 void *params, size_t size) {
137 Parcel data, reply;
138 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
139 data.writeIntPtr((intptr_t)node);
140 data.writeInt32(index);
141 data.writeInt32(size);
142 data.write(params, size);
143 remote()->transact(GET_PARAMETER, data, &reply);
144
145 status_t err = reply.readInt32();
146 if (err != OK) {
147 return err;
148 }
149
150 reply.read(params, size);
151
152 return OK;
153 }
154
setParameter(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)155 virtual status_t setParameter(
156 node_id node, OMX_INDEXTYPE index,
157 const void *params, size_t size) {
158 Parcel data, reply;
159 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
160 data.writeIntPtr((intptr_t)node);
161 data.writeInt32(index);
162 data.writeInt32(size);
163 data.write(params, size);
164 remote()->transact(SET_PARAMETER, data, &reply);
165
166 return reply.readInt32();
167 }
168
getConfig(node_id node,OMX_INDEXTYPE index,void * params,size_t size)169 virtual status_t getConfig(
170 node_id node, OMX_INDEXTYPE index,
171 void *params, size_t size) {
172 Parcel data, reply;
173 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
174 data.writeIntPtr((intptr_t)node);
175 data.writeInt32(index);
176 data.writeInt32(size);
177 data.write(params, size);
178 remote()->transact(GET_CONFIG, data, &reply);
179
180 status_t err = reply.readInt32();
181 if (err != OK) {
182 return err;
183 }
184
185 reply.read(params, size);
186
187 return OK;
188 }
189
setConfig(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)190 virtual status_t setConfig(
191 node_id node, OMX_INDEXTYPE index,
192 const void *params, size_t size) {
193 Parcel data, reply;
194 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
195 data.writeIntPtr((intptr_t)node);
196 data.writeInt32(index);
197 data.writeInt32(size);
198 data.write(params, size);
199 remote()->transact(SET_CONFIG, data, &reply);
200
201 return reply.readInt32();
202 }
203
useBuffer(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer)204 virtual status_t useBuffer(
205 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
206 buffer_id *buffer) {
207 Parcel data, reply;
208 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
209 data.writeIntPtr((intptr_t)node);
210 data.writeInt32(port_index);
211 data.writeStrongBinder(params->asBinder());
212 remote()->transact(USE_BUFFER, data, &reply);
213
214 status_t err = reply.readInt32();
215 if (err != OK) {
216 *buffer = 0;
217
218 return err;
219 }
220
221 *buffer = (void*)reply.readIntPtr();
222
223 return err;
224 }
225
allocateBuffer(node_id node,OMX_U32 port_index,size_t size,buffer_id * buffer)226 virtual status_t allocateBuffer(
227 node_id node, OMX_U32 port_index, size_t size,
228 buffer_id *buffer) {
229 Parcel data, reply;
230 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
231 data.writeIntPtr((intptr_t)node);
232 data.writeInt32(port_index);
233 data.writeInt32(size);
234 remote()->transact(ALLOC_BUFFER, data, &reply);
235
236 status_t err = reply.readInt32();
237 if (err != OK) {
238 *buffer = 0;
239
240 return err;
241 }
242
243 *buffer = (void*)reply.readIntPtr();
244
245 return err;
246 }
247
allocateBufferWithBackup(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer)248 virtual status_t allocateBufferWithBackup(
249 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
250 buffer_id *buffer) {
251 Parcel data, reply;
252 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
253 data.writeIntPtr((intptr_t)node);
254 data.writeInt32(port_index);
255 data.writeStrongBinder(params->asBinder());
256 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
257
258 status_t err = reply.readInt32();
259 if (err != OK) {
260 *buffer = 0;
261
262 return err;
263 }
264
265 *buffer = (void*)reply.readIntPtr();
266
267 return err;
268 }
269
freeBuffer(node_id node,OMX_U32 port_index,buffer_id buffer)270 virtual status_t freeBuffer(
271 node_id node, OMX_U32 port_index, buffer_id buffer) {
272 Parcel data, reply;
273 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
274 data.writeIntPtr((intptr_t)node);
275 data.writeInt32(port_index);
276 data.writeIntPtr((intptr_t)buffer);
277 remote()->transact(FREE_BUFFER, data, &reply);
278
279 return reply.readInt32();
280 }
281
fillBuffer(node_id node,buffer_id buffer)282 virtual status_t fillBuffer(node_id node, buffer_id buffer) {
283 Parcel data, reply;
284 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
285 data.writeIntPtr((intptr_t)node);
286 data.writeIntPtr((intptr_t)buffer);
287 remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
288
289 return reply.readInt32();
290 }
291
emptyBuffer(node_id node,buffer_id buffer,OMX_U32 range_offset,OMX_U32 range_length,OMX_U32 flags,OMX_TICKS timestamp)292 virtual status_t emptyBuffer(
293 node_id node,
294 buffer_id buffer,
295 OMX_U32 range_offset, OMX_U32 range_length,
296 OMX_U32 flags, OMX_TICKS timestamp) {
297 Parcel data, reply;
298 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
299 data.writeIntPtr((intptr_t)node);
300 data.writeIntPtr((intptr_t)buffer);
301 data.writeInt32(range_offset);
302 data.writeInt32(range_length);
303 data.writeInt32(flags);
304 data.writeInt64(timestamp);
305 remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
306
307 return reply.readInt32();
308 }
309
getExtensionIndex(node_id node,const char * parameter_name,OMX_INDEXTYPE * index)310 virtual status_t getExtensionIndex(
311 node_id node,
312 const char *parameter_name,
313 OMX_INDEXTYPE *index) {
314 Parcel data, reply;
315 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
316 data.writeIntPtr((intptr_t)node);
317 data.writeCString(parameter_name);
318
319 remote()->transact(GET_EXTENSION_INDEX, data, &reply);
320
321 status_t err = reply.readInt32();
322 if (err == OK) {
323 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
324 } else {
325 *index = OMX_IndexComponentStartUnused;
326 }
327
328 return err;
329 }
330
createRenderer(const sp<ISurface> & surface,const char * componentName,OMX_COLOR_FORMATTYPE colorFormat,size_t encodedWidth,size_t encodedHeight,size_t displayWidth,size_t displayHeight)331 virtual sp<IOMXRenderer> createRenderer(
332 const sp<ISurface> &surface,
333 const char *componentName,
334 OMX_COLOR_FORMATTYPE colorFormat,
335 size_t encodedWidth, size_t encodedHeight,
336 size_t displayWidth, size_t displayHeight) {
337 Parcel data, reply;
338 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
339
340 data.writeStrongBinder(surface->asBinder());
341 data.writeCString(componentName);
342 data.writeInt32(colorFormat);
343 data.writeInt32(encodedWidth);
344 data.writeInt32(encodedHeight);
345 data.writeInt32(displayWidth);
346 data.writeInt32(displayHeight);
347
348 remote()->transact(CREATE_RENDERER, data, &reply);
349
350 return interface_cast<IOMXRenderer>(reply.readStrongBinder());
351 }
352 };
353
354 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
355
356 ////////////////////////////////////////////////////////////////////////////////
357
358 #define CHECK_INTERFACE(interface, data, reply) \
359 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
360 LOGW("Call incorrectly routed to " #interface); \
361 return PERMISSION_DENIED; \
362 } } while (0)
363
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)364 status_t BnOMX::onTransact(
365 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
366 switch (code) {
367 case LIST_NODES:
368 {
369 CHECK_INTERFACE(IOMX, data, reply);
370
371 List<String8> list;
372 listNodes(&list);
373
374 reply->writeInt32(list.size());
375 for (List<String8>::iterator it = list.begin();
376 it != list.end(); ++it) {
377 reply->writeString8(*it);
378 }
379
380 return NO_ERROR;
381 }
382
383 case ALLOCATE_NODE:
384 {
385 CHECK_INTERFACE(IOMX, data, reply);
386
387 const char *name = data.readCString();
388
389 sp<IOMXObserver> observer =
390 interface_cast<IOMXObserver>(data.readStrongBinder());
391
392 node_id node;
393
394 status_t err = allocateNode(name, observer, &node);
395 reply->writeInt32(err);
396 if (err == OK) {
397 reply->writeIntPtr((intptr_t)node);
398 }
399
400 return NO_ERROR;
401 }
402
403 case FREE_NODE:
404 {
405 CHECK_INTERFACE(IOMX, data, reply);
406
407 node_id node = (void*)data.readIntPtr();
408
409 reply->writeInt32(freeNode(node));
410
411 return NO_ERROR;
412 }
413
414 case SEND_COMMAND:
415 {
416 CHECK_INTERFACE(IOMX, data, reply);
417
418 node_id node = (void*)data.readIntPtr();
419
420 OMX_COMMANDTYPE cmd =
421 static_cast<OMX_COMMANDTYPE>(data.readInt32());
422
423 OMX_S32 param = data.readInt32();
424 reply->writeInt32(sendCommand(node, cmd, param));
425
426 return NO_ERROR;
427 }
428
429 case GET_PARAMETER:
430 {
431 CHECK_INTERFACE(IOMX, data, reply);
432
433 node_id node = (void*)data.readIntPtr();
434 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
435
436 size_t size = data.readInt32();
437
438 // XXX I am not happy with this but Parcel::readInplace didn't work.
439 void *params = malloc(size);
440 data.read(params, size);
441
442 status_t err = getParameter(node, index, params, size);
443
444 reply->writeInt32(err);
445
446 if (err == OK) {
447 reply->write(params, size);
448 }
449
450 free(params);
451 params = NULL;
452
453 return NO_ERROR;
454 }
455
456 case SET_PARAMETER:
457 {
458 CHECK_INTERFACE(IOMX, data, reply);
459
460 node_id node = (void*)data.readIntPtr();
461 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
462
463 size_t size = data.readInt32();
464 void *params = const_cast<void *>(data.readInplace(size));
465
466 reply->writeInt32(setParameter(node, index, params, size));
467
468 return NO_ERROR;
469 }
470
471 case GET_CONFIG:
472 {
473 CHECK_INTERFACE(IOMX, data, reply);
474
475 node_id node = (void*)data.readIntPtr();
476 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
477
478 size_t size = data.readInt32();
479
480 // XXX I am not happy with this but Parcel::readInplace didn't work.
481 void *params = malloc(size);
482 data.read(params, size);
483
484 status_t err = getConfig(node, index, params, size);
485
486 reply->writeInt32(err);
487
488 if (err == OK) {
489 reply->write(params, size);
490 }
491
492 free(params);
493 params = NULL;
494
495 return NO_ERROR;
496 }
497
498 case SET_CONFIG:
499 {
500 CHECK_INTERFACE(IOMX, data, reply);
501
502 node_id node = (void*)data.readIntPtr();
503 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
504
505 size_t size = data.readInt32();
506 void *params = const_cast<void *>(data.readInplace(size));
507
508 reply->writeInt32(setConfig(node, index, params, size));
509
510 return NO_ERROR;
511 }
512
513 case USE_BUFFER:
514 {
515 CHECK_INTERFACE(IOMX, data, reply);
516
517 node_id node = (void*)data.readIntPtr();
518 OMX_U32 port_index = data.readInt32();
519 sp<IMemory> params =
520 interface_cast<IMemory>(data.readStrongBinder());
521
522 buffer_id buffer;
523 status_t err = useBuffer(node, port_index, params, &buffer);
524 reply->writeInt32(err);
525
526 if (err == OK) {
527 reply->writeIntPtr((intptr_t)buffer);
528 }
529
530 return NO_ERROR;
531 }
532
533 case ALLOC_BUFFER:
534 {
535 CHECK_INTERFACE(IOMX, data, reply);
536
537 node_id node = (void*)data.readIntPtr();
538 OMX_U32 port_index = data.readInt32();
539 size_t size = data.readInt32();
540
541 buffer_id buffer;
542 status_t err = allocateBuffer(node, port_index, size, &buffer);
543 reply->writeInt32(err);
544
545 if (err == OK) {
546 reply->writeIntPtr((intptr_t)buffer);
547 }
548
549 return NO_ERROR;
550 }
551
552 case ALLOC_BUFFER_WITH_BACKUP:
553 {
554 CHECK_INTERFACE(IOMX, data, reply);
555
556 node_id node = (void*)data.readIntPtr();
557 OMX_U32 port_index = data.readInt32();
558 sp<IMemory> params =
559 interface_cast<IMemory>(data.readStrongBinder());
560
561 buffer_id buffer;
562 status_t err = allocateBufferWithBackup(
563 node, port_index, params, &buffer);
564
565 reply->writeInt32(err);
566
567 if (err == OK) {
568 reply->writeIntPtr((intptr_t)buffer);
569 }
570
571 return NO_ERROR;
572 }
573
574 case FREE_BUFFER:
575 {
576 CHECK_INTERFACE(IOMX, data, reply);
577
578 node_id node = (void*)data.readIntPtr();
579 OMX_U32 port_index = data.readInt32();
580 buffer_id buffer = (void*)data.readIntPtr();
581 reply->writeInt32(freeBuffer(node, port_index, buffer));
582
583 return NO_ERROR;
584 }
585
586 case FILL_BUFFER:
587 {
588 CHECK_INTERFACE(IOMX, data, reply);
589
590 node_id node = (void*)data.readIntPtr();
591 buffer_id buffer = (void*)data.readIntPtr();
592 reply->writeInt32(fillBuffer(node, buffer));
593
594 return NO_ERROR;
595 }
596
597 case EMPTY_BUFFER:
598 {
599 CHECK_INTERFACE(IOMX, data, reply);
600
601 node_id node = (void*)data.readIntPtr();
602 buffer_id buffer = (void*)data.readIntPtr();
603 OMX_U32 range_offset = data.readInt32();
604 OMX_U32 range_length = data.readInt32();
605 OMX_U32 flags = data.readInt32();
606 OMX_TICKS timestamp = data.readInt64();
607
608 reply->writeInt32(
609 emptyBuffer(
610 node, buffer, range_offset, range_length,
611 flags, timestamp));
612
613 return NO_ERROR;
614 }
615
616 case GET_EXTENSION_INDEX:
617 {
618 CHECK_INTERFACE(IOMX, data, reply);
619
620 node_id node = (void*)data.readIntPtr();
621 const char *parameter_name = data.readCString();
622
623 OMX_INDEXTYPE index;
624 status_t err = getExtensionIndex(node, parameter_name, &index);
625
626 reply->writeInt32(err);
627
628 if (err == OK) {
629 reply->writeInt32(index);
630 }
631
632 return OK;
633 }
634
635 case CREATE_RENDERER:
636 {
637 CHECK_INTERFACE(IOMX, data, reply);
638
639 sp<ISurface> isurface =
640 interface_cast<ISurface>(data.readStrongBinder());
641
642 const char *componentName = data.readCString();
643
644 OMX_COLOR_FORMATTYPE colorFormat =
645 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
646
647 size_t encodedWidth = (size_t)data.readInt32();
648 size_t encodedHeight = (size_t)data.readInt32();
649 size_t displayWidth = (size_t)data.readInt32();
650 size_t displayHeight = (size_t)data.readInt32();
651
652 sp<IOMXRenderer> renderer =
653 createRenderer(isurface, componentName, colorFormat,
654 encodedWidth, encodedHeight,
655 displayWidth, displayHeight);
656
657 reply->writeStrongBinder(renderer->asBinder());
658
659 return OK;
660 }
661
662 default:
663 return BBinder::onTransact(code, data, reply, flags);
664 }
665 }
666
667 ////////////////////////////////////////////////////////////////////////////////
668
669 class BpOMXObserver : public BpInterface<IOMXObserver> {
670 public:
BpOMXObserver(const sp<IBinder> & impl)671 BpOMXObserver(const sp<IBinder> &impl)
672 : BpInterface<IOMXObserver>(impl) {
673 }
674
onMessage(const omx_message & msg)675 virtual void onMessage(const omx_message &msg) {
676 Parcel data, reply;
677 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
678 data.write(&msg, sizeof(msg));
679
680 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
681 }
682 };
683
684 IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
685
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)686 status_t BnOMXObserver::onTransact(
687 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
688 switch (code) {
689 case OBSERVER_ON_MSG:
690 {
691 CHECK_INTERFACE(IOMXObserver, data, reply);
692
693 omx_message msg;
694 data.read(&msg, sizeof(msg));
695
696 // XXX Could use readInplace maybe?
697 onMessage(msg);
698
699 return NO_ERROR;
700 }
701
702 default:
703 return BBinder::onTransact(code, data, reply, flags);
704 }
705 }
706
707 ////////////////////////////////////////////////////////////////////////////////
708
709 class BpOMXRenderer : public BpInterface<IOMXRenderer> {
710 public:
BpOMXRenderer(const sp<IBinder> & impl)711 BpOMXRenderer(const sp<IBinder> &impl)
712 : BpInterface<IOMXRenderer>(impl) {
713 }
714
render(IOMX::buffer_id buffer)715 virtual void render(IOMX::buffer_id buffer) {
716 Parcel data, reply;
717 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
718 data.writeIntPtr((intptr_t)buffer);
719
720 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
721 // so that the caller knows when to recycle the buffer.
722 remote()->transact(RENDERER_RENDER, data, &reply);
723 }
724 };
725
726 IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
727
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)728 status_t BnOMXRenderer::onTransact(
729 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
730 switch (code) {
731 case RENDERER_RENDER:
732 {
733 CHECK_INTERFACE(IOMXRenderer, data, reply);
734
735 IOMX::buffer_id buffer = (void*)data.readIntPtr();
736
737 render(buffer);
738
739 return NO_ERROR;
740 }
741
742 default:
743 return BBinder::onTransact(code, data, reply, flags);
744 }
745 }
746
747 } // namespace android
748