blob: 4661af6c1f016910437f5df96ade705a9937edb1 [file] [log] [blame]
Andreas Hubere46b7be2009-07-14 16:56:47 -07001//#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>
Andreas Huber1de13162009-07-31 11:52:50 -07008#include <ui/ISurface.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -07009
10namespace android {
11
12enum {
13 CONNECT = IBinder::FIRST_CALL_TRANSACTION,
14 LIST_NODES,
15 ALLOCATE_NODE,
16 FREE_NODE,
17 SEND_COMMAND,
18 GET_PARAMETER,
19 SET_PARAMETER,
20 USE_BUFFER,
21 ALLOC_BUFFER,
22 ALLOC_BUFFER_WITH_BACKUP,
23 FREE_BUFFER,
24 OBSERVE_NODE,
25 FILL_BUFFER,
26 EMPTY_BUFFER,
Andreas Huber1de13162009-07-31 11:52:50 -070027 CREATE_RENDERER,
Andreas Hubere46b7be2009-07-14 16:56:47 -070028 OBSERVER_ON_MSG,
Andreas Huber1de13162009-07-31 11:52:50 -070029 RENDERER_RENDER,
Andreas Hubere46b7be2009-07-14 16:56:47 -070030};
31
32static void *readVoidStar(const Parcel *parcel) {
33 // FIX if sizeof(void *) != sizeof(int32)
34 return (void *)parcel->readInt32();
35}
36
37static void writeVoidStar(void *x, Parcel *parcel) {
38 // FIX if sizeof(void *) != sizeof(int32)
39 parcel->writeInt32((int32_t)x);
40}
41
42class BpOMX : public BpInterface<IOMX> {
43public:
44 BpOMX(const sp<IBinder> &impl)
45 : BpInterface<IOMX>(impl) {
46 }
47
48#if IOMX_USES_SOCKETS
49 virtual status_t connect(int *sd) {
50 Parcel data, reply;
51 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
52 remote()->transact(CONNECT, data, &reply);
53
54 status_t err = reply.readInt32();
55 if (err == OK) {
56 *sd = dup(reply.readFileDescriptor());
57 } else {
58 *sd = -1;
59 }
60
61 return reply.readInt32();
62 }
63#endif
64
65 virtual status_t list_nodes(List<String8> *list) {
66 list->clear();
67
68 Parcel data, reply;
69 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
70 remote()->transact(LIST_NODES, data, &reply);
71
72 int32_t n = reply.readInt32();
73 for (int32_t i = 0; i < n; ++i) {
74 String8 s = reply.readString8();
75
76 list->push_back(s);
77 }
78
79 return OK;
80 }
81
82 virtual status_t allocate_node(const char *name, node_id *node) {
83 Parcel data, reply;
84 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
85 data.writeCString(name);
86 remote()->transact(ALLOCATE_NODE, data, &reply);
87
88 status_t err = reply.readInt32();
89 if (err == OK) {
90 *node = readVoidStar(&reply);
91 } else {
92 *node = 0;
93 }
94
95 return err;
96 }
97
98 virtual status_t free_node(node_id node) {
99 Parcel data, reply;
100 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
101 writeVoidStar(node, &data);
102 remote()->transact(FREE_NODE, data, &reply);
103
104 return reply.readInt32();
105 }
106
107 virtual status_t send_command(
108 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
109 Parcel data, reply;
110 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
111 writeVoidStar(node, &data);
112 data.writeInt32(cmd);
113 data.writeInt32(param);
114 remote()->transact(SEND_COMMAND, data, &reply);
115
116 return reply.readInt32();
117 }
118
119 virtual status_t get_parameter(
120 node_id node, OMX_INDEXTYPE index,
121 void *params, size_t size) {
122 Parcel data, reply;
123 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
124 writeVoidStar(node, &data);
125 data.writeInt32(index);
126 data.writeInt32(size);
127 data.write(params, size);
128 remote()->transact(GET_PARAMETER, data, &reply);
129
130 status_t err = reply.readInt32();
131 if (err != OK) {
132 return err;
133 }
134
135 reply.read(params, size);
136
137 return OK;
138 }
139
140 virtual status_t set_parameter(
141 node_id node, OMX_INDEXTYPE index,
142 const void *params, size_t size) {
143 Parcel data, reply;
144 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
145 writeVoidStar(node, &data);
146 data.writeInt32(index);
147 data.writeInt32(size);
148 data.write(params, size);
149 remote()->transact(SET_PARAMETER, data, &reply);
150
151 return reply.readInt32();
152 }
153
154 virtual status_t use_buffer(
155 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
156 buffer_id *buffer) {
157 Parcel data, reply;
158 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
159 writeVoidStar(node, &data);
160 data.writeInt32(port_index);
161 data.writeStrongBinder(params->asBinder());
162 remote()->transact(USE_BUFFER, data, &reply);
163
164 status_t err = reply.readInt32();
165 if (err != OK) {
166 *buffer = 0;
167
168 return err;
169 }
170
171 *buffer = readVoidStar(&reply);
172
173 return err;
174 }
175
176 virtual status_t allocate_buffer(
177 node_id node, OMX_U32 port_index, size_t size,
178 buffer_id *buffer) {
179 Parcel data, reply;
180 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
181 writeVoidStar(node, &data);
182 data.writeInt32(port_index);
183 data.writeInt32(size);
184 remote()->transact(ALLOC_BUFFER, data, &reply);
185
186 status_t err = reply.readInt32();
187 if (err != OK) {
188 *buffer = 0;
189
190 return err;
191 }
192
193 *buffer = readVoidStar(&reply);
194
195 return err;
196 }
197
198 virtual status_t allocate_buffer_with_backup(
199 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
200 buffer_id *buffer) {
201 Parcel data, reply;
202 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
203 writeVoidStar(node, &data);
204 data.writeInt32(port_index);
205 data.writeStrongBinder(params->asBinder());
206 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
207
208 status_t err = reply.readInt32();
209 if (err != OK) {
210 *buffer = 0;
211
212 return err;
213 }
214
215 *buffer = readVoidStar(&reply);
216
217 return err;
218 }
219
220 virtual status_t free_buffer(
221 node_id node, OMX_U32 port_index, buffer_id buffer) {
222 Parcel data, reply;
223 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
224 writeVoidStar(node, &data);
225 data.writeInt32(port_index);
226 writeVoidStar(buffer, &data);
227 remote()->transact(FREE_BUFFER, data, &reply);
228
229 return reply.readInt32();
230 }
231
232#if !IOMX_USES_SOCKETS
233 virtual status_t observe_node(
234 node_id node, const sp<IOMXObserver> &observer) {
235 Parcel data, reply;
236 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
237 writeVoidStar(node, &data);
238 data.writeStrongBinder(observer->asBinder());
239 remote()->transact(OBSERVE_NODE, data, &reply);
240
241 return reply.readInt32();
242 }
243
244 virtual void fill_buffer(node_id node, buffer_id buffer) {
245 Parcel data, reply;
246 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
247 writeVoidStar(node, &data);
248 writeVoidStar(buffer, &data);
249 remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
250 }
251
252 virtual void empty_buffer(
253 node_id node,
254 buffer_id buffer,
255 OMX_U32 range_offset, OMX_U32 range_length,
256 OMX_U32 flags, OMX_TICKS timestamp) {
257 Parcel data, reply;
258 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
259 writeVoidStar(node, &data);
260 writeVoidStar(buffer, &data);
261 data.writeInt32(range_offset);
262 data.writeInt32(range_length);
263 data.writeInt32(flags);
264 data.writeInt64(timestamp);
265 remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
266 }
267#endif
Andreas Huber1de13162009-07-31 11:52:50 -0700268
269 virtual sp<IOMXRenderer> createRenderer(
270 const sp<ISurface> &surface,
271 const char *componentName,
272 OMX_COLOR_FORMATTYPE colorFormat,
273 size_t encodedWidth, size_t encodedHeight,
274 size_t displayWidth, size_t displayHeight) {
275 Parcel data, reply;
276 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
277
278 data.writeStrongBinder(surface->asBinder());
279 data.writeCString(componentName);
280 data.writeInt32(colorFormat);
281 data.writeInt32(encodedWidth);
282 data.writeInt32(encodedHeight);
283 data.writeInt32(displayWidth);
284 data.writeInt32(displayHeight);
285
286 remote()->transact(CREATE_RENDERER, data, &reply);
287
288 return interface_cast<IOMXRenderer>(reply.readStrongBinder());
289 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700290};
291
292IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
293
294////////////////////////////////////////////////////////////////////////////////
295
296#define CHECK_INTERFACE(interface, data, reply) \
297 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
298 LOGW("Call incorrectly routed to " #interface); \
299 return PERMISSION_DENIED; \
300 } } while (0)
301
302status_t BnOMX::onTransact(
303 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
304 switch (code) {
305#if IOMX_USES_SOCKETS
306 case CONNECT:
307 {
308 CHECK_INTERFACE(IOMX, data, reply);
309
310 int s;
311 status_t err = connect(&s);
312
313 reply->writeInt32(err);
314 if (err == OK) {
315 assert(s >= 0);
316 reply->writeDupFileDescriptor(s);
317 close(s);
318 s = -1;
319 } else {
320 assert(s == -1);
321 }
322
323 return NO_ERROR;
324 }
325#endif
326
327 case LIST_NODES:
328 {
329 CHECK_INTERFACE(IOMX, data, reply);
330
331 List<String8> list;
332 list_nodes(&list);
333
334 reply->writeInt32(list.size());
335 for (List<String8>::iterator it = list.begin();
336 it != list.end(); ++it) {
337 reply->writeString8(*it);
338 }
339
340 return NO_ERROR;
341 }
342
343 case ALLOCATE_NODE:
344 {
345 CHECK_INTERFACE(IOMX, data, reply);
346
347 node_id node;
348 status_t err = allocate_node(data.readCString(), &node);
349 reply->writeInt32(err);
350 if (err == OK) {
351 writeVoidStar(node, reply);
352 }
353
354 return NO_ERROR;
355 }
356
357 case FREE_NODE:
358 {
359 CHECK_INTERFACE(IOMX, data, reply);
360
361 node_id node = readVoidStar(&data);
362
363 reply->writeInt32(free_node(node));
364
365 return NO_ERROR;
366 }
367
368 case SEND_COMMAND:
369 {
370 CHECK_INTERFACE(IOMX, data, reply);
371
372 node_id node = readVoidStar(&data);
373
374 OMX_COMMANDTYPE cmd =
375 static_cast<OMX_COMMANDTYPE>(data.readInt32());
376
377 OMX_S32 param = data.readInt32();
378 reply->writeInt32(send_command(node, cmd, param));
379
380 return NO_ERROR;
381 }
382
383 case GET_PARAMETER:
384 {
385 CHECK_INTERFACE(IOMX, data, reply);
386
387 node_id node = readVoidStar(&data);
388 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
389
390 size_t size = data.readInt32();
391
392 // XXX I am not happy with this but Parcel::readInplace didn't work.
393 void *params = malloc(size);
394 data.read(params, size);
395
396 status_t err = get_parameter(node, index, params, size);
397
398 reply->writeInt32(err);
399
400 if (err == OK) {
401 reply->write(params, size);
402 }
403
404 free(params);
405 params = NULL;
406
407 return NO_ERROR;
408 }
409
410 case SET_PARAMETER:
411 {
412 CHECK_INTERFACE(IOMX, data, reply);
413
414 node_id node = readVoidStar(&data);
415 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
416
417 size_t size = data.readInt32();
418 void *params = const_cast<void *>(data.readInplace(size));
419
420 reply->writeInt32(set_parameter(node, index, params, size));
421
422 return NO_ERROR;
423 }
424
425 case USE_BUFFER:
426 {
427 CHECK_INTERFACE(IOMX, data, reply);
428
429 node_id node = readVoidStar(&data);
430 OMX_U32 port_index = data.readInt32();
431 sp<IMemory> params =
432 interface_cast<IMemory>(data.readStrongBinder());
433
434 buffer_id buffer;
435 status_t err = use_buffer(node, port_index, params, &buffer);
436 reply->writeInt32(err);
437
438 if (err == OK) {
439 writeVoidStar(buffer, reply);
440 }
441
442 return NO_ERROR;
443 }
444
445 case ALLOC_BUFFER:
446 {
447 CHECK_INTERFACE(IOMX, data, reply);
448
449 node_id node = readVoidStar(&data);
450 OMX_U32 port_index = data.readInt32();
451 size_t size = data.readInt32();
452
453 buffer_id buffer;
454 status_t err = allocate_buffer(node, port_index, size, &buffer);
455 reply->writeInt32(err);
456
457 if (err == OK) {
458 writeVoidStar(buffer, reply);
459 }
460
461 return NO_ERROR;
462 }
463
464 case ALLOC_BUFFER_WITH_BACKUP:
465 {
466 CHECK_INTERFACE(IOMX, data, reply);
467
468 node_id node = readVoidStar(&data);
469 OMX_U32 port_index = data.readInt32();
470 sp<IMemory> params =
471 interface_cast<IMemory>(data.readStrongBinder());
472
473 buffer_id buffer;
474 status_t err = allocate_buffer_with_backup(
475 node, port_index, params, &buffer);
476
477 reply->writeInt32(err);
478
479 if (err == OK) {
480 writeVoidStar(buffer, reply);
481 }
482
483 return NO_ERROR;
484 }
485
486 case FREE_BUFFER:
487 {
488 CHECK_INTERFACE(IOMX, data, reply);
489
490 node_id node = readVoidStar(&data);
491 OMX_U32 port_index = data.readInt32();
492 buffer_id buffer = readVoidStar(&data);
493 reply->writeInt32(free_buffer(node, port_index, buffer));
494
495 return NO_ERROR;
496 }
497
498#if !IOMX_USES_SOCKETS
499 case OBSERVE_NODE:
500 {
501 CHECK_INTERFACE(IOMX, data, reply);
502
503 node_id node = readVoidStar(&data);
504 sp<IOMXObserver> observer =
505 interface_cast<IOMXObserver>(data.readStrongBinder());
506 reply->writeInt32(observe_node(node, observer));
507
508 return NO_ERROR;
509 }
510
511 case FILL_BUFFER:
512 {
513 CHECK_INTERFACE(IOMX, data, reply);
514
515 node_id node = readVoidStar(&data);
516 buffer_id buffer = readVoidStar(&data);
517 fill_buffer(node, buffer);
518
519 return NO_ERROR;
520 }
521
522 case EMPTY_BUFFER:
523 {
524 CHECK_INTERFACE(IOMX, data, reply);
525
526 node_id node = readVoidStar(&data);
527 buffer_id buffer = readVoidStar(&data);
528 OMX_U32 range_offset = data.readInt32();
529 OMX_U32 range_length = data.readInt32();
530 OMX_U32 flags = data.readInt32();
531 OMX_TICKS timestamp = data.readInt64();
532
533 empty_buffer(
534 node, buffer, range_offset, range_length,
535 flags, timestamp);
536
537 return NO_ERROR;
538 }
539#endif
540
Andreas Huber1de13162009-07-31 11:52:50 -0700541 case CREATE_RENDERER:
542 {
543 CHECK_INTERFACE(IOMX, data, reply);
544
545 sp<ISurface> isurface =
546 interface_cast<ISurface>(data.readStrongBinder());
547
548 const char *componentName = data.readCString();
549
550 OMX_COLOR_FORMATTYPE colorFormat =
551 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
552
553 size_t encodedWidth = (size_t)data.readInt32();
554 size_t encodedHeight = (size_t)data.readInt32();
555 size_t displayWidth = (size_t)data.readInt32();
556 size_t displayHeight = (size_t)data.readInt32();
557
558 sp<IOMXRenderer> renderer =
559 createRenderer(isurface, componentName, colorFormat,
560 encodedWidth, encodedHeight,
561 displayWidth, displayHeight);
562
563 reply->writeStrongBinder(renderer->asBinder());
564
565 return OK;
566 }
567
Andreas Hubere46b7be2009-07-14 16:56:47 -0700568 default:
569 return BBinder::onTransact(code, data, reply, flags);
570 }
571}
572
573////////////////////////////////////////////////////////////////////////////////
574
575class BpOMXObserver : public BpInterface<IOMXObserver> {
576public:
577 BpOMXObserver(const sp<IBinder> &impl)
578 : BpInterface<IOMXObserver>(impl) {
579 }
580
581 virtual void on_message(const omx_message &msg) {
582 Parcel data, reply;
583 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
584 data.write(&msg, sizeof(msg));
585
586 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
587 }
588};
589
590IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
591
592status_t BnOMXObserver::onTransact(
593 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
594 switch (code) {
595 case OBSERVER_ON_MSG:
596 {
597 CHECK_INTERFACE(IOMXObserver, data, reply);
598
599 omx_message msg;
600 data.read(&msg, sizeof(msg));
601
602 // XXX Could use readInplace maybe?
603 on_message(msg);
604
605 return NO_ERROR;
606 }
607
608 default:
609 return BBinder::onTransact(code, data, reply, flags);
610 }
611}
612
Andreas Huber1de13162009-07-31 11:52:50 -0700613////////////////////////////////////////////////////////////////////////////////
614
615class BpOMXRenderer : public BpInterface<IOMXRenderer> {
616public:
617 BpOMXRenderer(const sp<IBinder> &impl)
618 : BpInterface<IOMXRenderer>(impl) {
619 }
620
621 virtual void render(IOMX::buffer_id buffer) {
622 Parcel data, reply;
623 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
624 writeVoidStar(buffer, &data);
625
626 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
627 // so that the caller knows when to recycle the buffer.
628 remote()->transact(RENDERER_RENDER, data, &reply);
629 }
630};
631
632IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
633
634status_t BnOMXRenderer::onTransact(
635 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
636 switch (code) {
637 case RENDERER_RENDER:
638 {
639 CHECK_INTERFACE(IOMXRenderer, data, reply);
640
641 IOMX::buffer_id buffer = readVoidStar(&data);
642
643 render(buffer);
644
645 return NO_ERROR;
646 }
647
648 default:
649 return BBinder::onTransact(code, data, reply, flags);
650 }
651}
652
Andreas Hubere46b7be2009-07-14 16:56:47 -0700653} // namespace android