• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params,
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> &params,
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