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