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