1 /*
2 **
3 ** Copyright 2008, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include <arpa/inet.h>
19 #include <stdint.h>
20 #include <sys/types.h>
21
22 #include <binder/Parcel.h>
23
24 #include <media/AudioResamplerPublic.h>
25 #include <media/AVSyncSettings.h>
26
27 #include <media/IDataSource.h>
28 #include <media/IMediaHTTPService.h>
29 #include <media/IMediaPlayer.h>
30 #include <media/IStreamSource.h>
31
32 #include <gui/IGraphicBufferProducer.h>
33 #include <utils/String8.h>
34
35 namespace android {
36
37 enum {
38 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
39 SET_DATA_SOURCE_URL,
40 SET_DATA_SOURCE_FD,
41 SET_DATA_SOURCE_STREAM,
42 SET_DATA_SOURCE_CALLBACK,
43 PREPARE_ASYNC,
44 START,
45 STOP,
46 IS_PLAYING,
47 SET_PLAYBACK_SETTINGS,
48 GET_PLAYBACK_SETTINGS,
49 SET_SYNC_SETTINGS,
50 GET_SYNC_SETTINGS,
51 PAUSE,
52 SEEK_TO,
53 GET_CURRENT_POSITION,
54 GET_DURATION,
55 RESET,
56 SET_AUDIO_STREAM_TYPE,
57 SET_LOOPING,
58 SET_VOLUME,
59 INVOKE,
60 SET_METADATA_FILTER,
61 GET_METADATA,
62 SET_AUX_EFFECT_SEND_LEVEL,
63 ATTACH_AUX_EFFECT,
64 SET_VIDEO_SURFACETEXTURE,
65 SET_PARAMETER,
66 GET_PARAMETER,
67 SET_RETRANSMIT_ENDPOINT,
68 GET_RETRANSMIT_ENDPOINT,
69 SET_NEXT_PLAYER,
70 };
71
72 class BpMediaPlayer: public BpInterface<IMediaPlayer>
73 {
74 public:
BpMediaPlayer(const sp<IBinder> & impl)75 BpMediaPlayer(const sp<IBinder>& impl)
76 : BpInterface<IMediaPlayer>(impl)
77 {
78 }
79
80 // disconnect from media player service
disconnect()81 void disconnect()
82 {
83 Parcel data, reply;
84 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
85 remote()->transact(DISCONNECT, data, &reply);
86 }
87
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)88 status_t setDataSource(
89 const sp<IMediaHTTPService> &httpService,
90 const char* url,
91 const KeyedVector<String8, String8>* headers)
92 {
93 Parcel data, reply;
94 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
95 data.writeInt32(httpService != NULL);
96 if (httpService != NULL) {
97 data.writeStrongBinder(IInterface::asBinder(httpService));
98 }
99 data.writeCString(url);
100 if (headers == NULL) {
101 data.writeInt32(0);
102 } else {
103 // serialize the headers
104 data.writeInt32(headers->size());
105 for (size_t i = 0; i < headers->size(); ++i) {
106 data.writeString8(headers->keyAt(i));
107 data.writeString8(headers->valueAt(i));
108 }
109 }
110 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
111 return reply.readInt32();
112 }
113
setDataSource(int fd,int64_t offset,int64_t length)114 status_t setDataSource(int fd, int64_t offset, int64_t length) {
115 Parcel data, reply;
116 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
117 data.writeFileDescriptor(fd);
118 data.writeInt64(offset);
119 data.writeInt64(length);
120 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
121 return reply.readInt32();
122 }
123
setDataSource(const sp<IStreamSource> & source)124 status_t setDataSource(const sp<IStreamSource> &source) {
125 Parcel data, reply;
126 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
127 data.writeStrongBinder(IInterface::asBinder(source));
128 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
129 return reply.readInt32();
130 }
131
setDataSource(const sp<IDataSource> & source)132 status_t setDataSource(const sp<IDataSource> &source) {
133 Parcel data, reply;
134 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
135 data.writeStrongBinder(IInterface::asBinder(source));
136 remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
137 return reply.readInt32();
138 }
139
140 // pass the buffered IGraphicBufferProducer to the media player service
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)141 status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer)
142 {
143 Parcel data, reply;
144 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
145 sp<IBinder> b(IInterface::asBinder(bufferProducer));
146 data.writeStrongBinder(b);
147 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
148 return reply.readInt32();
149 }
150
prepareAsync()151 status_t prepareAsync()
152 {
153 Parcel data, reply;
154 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
155 remote()->transact(PREPARE_ASYNC, data, &reply);
156 return reply.readInt32();
157 }
158
start()159 status_t start()
160 {
161 Parcel data, reply;
162 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
163 remote()->transact(START, data, &reply);
164 return reply.readInt32();
165 }
166
stop()167 status_t stop()
168 {
169 Parcel data, reply;
170 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
171 remote()->transact(STOP, data, &reply);
172 return reply.readInt32();
173 }
174
isPlaying(bool * state)175 status_t isPlaying(bool* state)
176 {
177 Parcel data, reply;
178 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
179 remote()->transact(IS_PLAYING, data, &reply);
180 *state = reply.readInt32();
181 return reply.readInt32();
182 }
183
setPlaybackSettings(const AudioPlaybackRate & rate)184 status_t setPlaybackSettings(const AudioPlaybackRate& rate)
185 {
186 Parcel data, reply;
187 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
188 data.writeFloat(rate.mSpeed);
189 data.writeFloat(rate.mPitch);
190 data.writeInt32((int32_t)rate.mFallbackMode);
191 data.writeInt32((int32_t)rate.mStretchMode);
192 remote()->transact(SET_PLAYBACK_SETTINGS, data, &reply);
193 return reply.readInt32();
194 }
195
getPlaybackSettings(AudioPlaybackRate * rate)196 status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
197 {
198 Parcel data, reply;
199 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
200 remote()->transact(GET_PLAYBACK_SETTINGS, data, &reply);
201 status_t err = reply.readInt32();
202 if (err == OK) {
203 *rate = AUDIO_PLAYBACK_RATE_DEFAULT;
204 rate->mSpeed = reply.readFloat();
205 rate->mPitch = reply.readFloat();
206 rate->mFallbackMode = (AudioTimestretchFallbackMode)reply.readInt32();
207 rate->mStretchMode = (AudioTimestretchStretchMode)reply.readInt32();
208 }
209 return err;
210 }
211
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)212 status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
213 {
214 Parcel data, reply;
215 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
216 data.writeInt32((int32_t)sync.mSource);
217 data.writeInt32((int32_t)sync.mAudioAdjustMode);
218 data.writeFloat(sync.mTolerance);
219 data.writeFloat(videoFpsHint);
220 remote()->transact(SET_SYNC_SETTINGS, data, &reply);
221 return reply.readInt32();
222 }
223
getSyncSettings(AVSyncSettings * sync,float * videoFps)224 status_t getSyncSettings(AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
225 {
226 Parcel data, reply;
227 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
228 remote()->transact(GET_SYNC_SETTINGS, data, &reply);
229 status_t err = reply.readInt32();
230 if (err == OK) {
231 AVSyncSettings settings;
232 settings.mSource = (AVSyncSource)reply.readInt32();
233 settings.mAudioAdjustMode = (AVSyncAudioAdjustMode)reply.readInt32();
234 settings.mTolerance = reply.readFloat();
235 *sync = settings;
236 *videoFps = reply.readFloat();
237 }
238 return err;
239 }
240
pause()241 status_t pause()
242 {
243 Parcel data, reply;
244 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
245 remote()->transact(PAUSE, data, &reply);
246 return reply.readInt32();
247 }
248
seekTo(int msec)249 status_t seekTo(int msec)
250 {
251 Parcel data, reply;
252 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
253 data.writeInt32(msec);
254 remote()->transact(SEEK_TO, data, &reply);
255 return reply.readInt32();
256 }
257
getCurrentPosition(int * msec)258 status_t getCurrentPosition(int* msec)
259 {
260 Parcel data, reply;
261 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
262 remote()->transact(GET_CURRENT_POSITION, data, &reply);
263 *msec = reply.readInt32();
264 return reply.readInt32();
265 }
266
getDuration(int * msec)267 status_t getDuration(int* msec)
268 {
269 Parcel data, reply;
270 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
271 remote()->transact(GET_DURATION, data, &reply);
272 *msec = reply.readInt32();
273 return reply.readInt32();
274 }
275
reset()276 status_t reset()
277 {
278 Parcel data, reply;
279 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
280 remote()->transact(RESET, data, &reply);
281 return reply.readInt32();
282 }
283
setAudioStreamType(audio_stream_type_t stream)284 status_t setAudioStreamType(audio_stream_type_t stream)
285 {
286 Parcel data, reply;
287 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
288 data.writeInt32((int32_t) stream);
289 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
290 return reply.readInt32();
291 }
292
setLooping(int loop)293 status_t setLooping(int loop)
294 {
295 Parcel data, reply;
296 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
297 data.writeInt32(loop);
298 remote()->transact(SET_LOOPING, data, &reply);
299 return reply.readInt32();
300 }
301
setVolume(float leftVolume,float rightVolume)302 status_t setVolume(float leftVolume, float rightVolume)
303 {
304 Parcel data, reply;
305 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
306 data.writeFloat(leftVolume);
307 data.writeFloat(rightVolume);
308 remote()->transact(SET_VOLUME, data, &reply);
309 return reply.readInt32();
310 }
311
invoke(const Parcel & request,Parcel * reply)312 status_t invoke(const Parcel& request, Parcel *reply)
313 {
314 // Avoid doing any extra copy. The interface descriptor should
315 // have been set by MediaPlayer.java.
316 return remote()->transact(INVOKE, request, reply);
317 }
318
setMetadataFilter(const Parcel & request)319 status_t setMetadataFilter(const Parcel& request)
320 {
321 Parcel reply;
322 // Avoid doing any extra copy of the request. The interface
323 // descriptor should have been set by MediaPlayer.java.
324 remote()->transact(SET_METADATA_FILTER, request, &reply);
325 return reply.readInt32();
326 }
327
getMetadata(bool update_only,bool apply_filter,Parcel * reply)328 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
329 {
330 Parcel request;
331 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
332 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
333 request.writeInt32(update_only);
334 request.writeInt32(apply_filter);
335 remote()->transact(GET_METADATA, request, reply);
336 return reply->readInt32();
337 }
338
setAuxEffectSendLevel(float level)339 status_t setAuxEffectSendLevel(float level)
340 {
341 Parcel data, reply;
342 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
343 data.writeFloat(level);
344 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
345 return reply.readInt32();
346 }
347
attachAuxEffect(int effectId)348 status_t attachAuxEffect(int effectId)
349 {
350 Parcel data, reply;
351 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
352 data.writeInt32(effectId);
353 remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
354 return reply.readInt32();
355 }
356
setParameter(int key,const Parcel & request)357 status_t setParameter(int key, const Parcel& request)
358 {
359 Parcel data, reply;
360 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
361 data.writeInt32(key);
362 if (request.dataSize() > 0) {
363 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
364 }
365 remote()->transact(SET_PARAMETER, data, &reply);
366 return reply.readInt32();
367 }
368
getParameter(int key,Parcel * reply)369 status_t getParameter(int key, Parcel *reply)
370 {
371 Parcel data;
372 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
373 data.writeInt32(key);
374 return remote()->transact(GET_PARAMETER, data, reply);
375 }
376
setRetransmitEndpoint(const struct sockaddr_in * endpoint)377 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint)
378 {
379 Parcel data, reply;
380 status_t err;
381
382 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
383 if (NULL != endpoint) {
384 data.writeInt32(sizeof(*endpoint));
385 data.write(endpoint, sizeof(*endpoint));
386 } else {
387 data.writeInt32(0);
388 }
389
390 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply);
391 if (OK != err) {
392 return err;
393 }
394 return reply.readInt32();
395 }
396
setNextPlayer(const sp<IMediaPlayer> & player)397 status_t setNextPlayer(const sp<IMediaPlayer>& player) {
398 Parcel data, reply;
399 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
400 sp<IBinder> b(IInterface::asBinder(player));
401 data.writeStrongBinder(b);
402 remote()->transact(SET_NEXT_PLAYER, data, &reply);
403 return reply.readInt32();
404 }
405
getRetransmitEndpoint(struct sockaddr_in * endpoint)406 status_t getRetransmitEndpoint(struct sockaddr_in* endpoint)
407 {
408 Parcel data, reply;
409 status_t err;
410
411 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
412 err = remote()->transact(GET_RETRANSMIT_ENDPOINT, data, &reply);
413
414 if ((OK != err) || (OK != (err = reply.readInt32()))) {
415 return err;
416 }
417
418 data.read(endpoint, sizeof(*endpoint));
419
420 return err;
421 }
422 };
423
424 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
425
426 // ----------------------------------------------------------------------
427
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)428 status_t BnMediaPlayer::onTransact(
429 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
430 {
431 switch (code) {
432 case DISCONNECT: {
433 CHECK_INTERFACE(IMediaPlayer, data, reply);
434 disconnect();
435 return NO_ERROR;
436 } break;
437 case SET_DATA_SOURCE_URL: {
438 CHECK_INTERFACE(IMediaPlayer, data, reply);
439
440 sp<IMediaHTTPService> httpService;
441 if (data.readInt32()) {
442 httpService =
443 interface_cast<IMediaHTTPService>(data.readStrongBinder());
444 }
445
446 const char* url = data.readCString();
447 if (url == NULL) {
448 reply->writeInt32(BAD_VALUE);
449 return NO_ERROR;
450 }
451 KeyedVector<String8, String8> headers;
452 int32_t numHeaders = data.readInt32();
453 for (int i = 0; i < numHeaders; ++i) {
454 String8 key = data.readString8();
455 String8 value = data.readString8();
456 headers.add(key, value);
457 }
458 reply->writeInt32(setDataSource(
459 httpService, url, numHeaders > 0 ? &headers : NULL));
460 return NO_ERROR;
461 } break;
462 case SET_DATA_SOURCE_FD: {
463 CHECK_INTERFACE(IMediaPlayer, data, reply);
464 int fd = data.readFileDescriptor();
465 int64_t offset = data.readInt64();
466 int64_t length = data.readInt64();
467 reply->writeInt32(setDataSource(fd, offset, length));
468 return NO_ERROR;
469 }
470 case SET_DATA_SOURCE_STREAM: {
471 CHECK_INTERFACE(IMediaPlayer, data, reply);
472 sp<IStreamSource> source =
473 interface_cast<IStreamSource>(data.readStrongBinder());
474 if (source == NULL) {
475 reply->writeInt32(BAD_VALUE);
476 } else {
477 reply->writeInt32(setDataSource(source));
478 }
479 return NO_ERROR;
480 }
481 case SET_DATA_SOURCE_CALLBACK: {
482 CHECK_INTERFACE(IMediaPlayer, data, reply);
483 sp<IDataSource> source =
484 interface_cast<IDataSource>(data.readStrongBinder());
485 if (source == NULL) {
486 reply->writeInt32(BAD_VALUE);
487 } else {
488 reply->writeInt32(setDataSource(source));
489 }
490 return NO_ERROR;
491 }
492 case SET_VIDEO_SURFACETEXTURE: {
493 CHECK_INTERFACE(IMediaPlayer, data, reply);
494 sp<IGraphicBufferProducer> bufferProducer =
495 interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
496 reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
497 return NO_ERROR;
498 } break;
499 case PREPARE_ASYNC: {
500 CHECK_INTERFACE(IMediaPlayer, data, reply);
501 reply->writeInt32(prepareAsync());
502 return NO_ERROR;
503 } break;
504 case START: {
505 CHECK_INTERFACE(IMediaPlayer, data, reply);
506 reply->writeInt32(start());
507 return NO_ERROR;
508 } break;
509 case STOP: {
510 CHECK_INTERFACE(IMediaPlayer, data, reply);
511 reply->writeInt32(stop());
512 return NO_ERROR;
513 } break;
514 case IS_PLAYING: {
515 CHECK_INTERFACE(IMediaPlayer, data, reply);
516 bool state;
517 status_t ret = isPlaying(&state);
518 reply->writeInt32(state);
519 reply->writeInt32(ret);
520 return NO_ERROR;
521 } break;
522 case SET_PLAYBACK_SETTINGS: {
523 CHECK_INTERFACE(IMediaPlayer, data, reply);
524 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
525 rate.mSpeed = data.readFloat();
526 rate.mPitch = data.readFloat();
527 rate.mFallbackMode = (AudioTimestretchFallbackMode)data.readInt32();
528 rate.mStretchMode = (AudioTimestretchStretchMode)data.readInt32();
529 reply->writeInt32(setPlaybackSettings(rate));
530 return NO_ERROR;
531 } break;
532 case GET_PLAYBACK_SETTINGS: {
533 CHECK_INTERFACE(IMediaPlayer, data, reply);
534 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
535 status_t err = getPlaybackSettings(&rate);
536 reply->writeInt32(err);
537 if (err == OK) {
538 reply->writeFloat(rate.mSpeed);
539 reply->writeFloat(rate.mPitch);
540 reply->writeInt32((int32_t)rate.mFallbackMode);
541 reply->writeInt32((int32_t)rate.mStretchMode);
542 }
543 return NO_ERROR;
544 } break;
545 case SET_SYNC_SETTINGS: {
546 CHECK_INTERFACE(IMediaPlayer, data, reply);
547 AVSyncSettings sync;
548 sync.mSource = (AVSyncSource)data.readInt32();
549 sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)data.readInt32();
550 sync.mTolerance = data.readFloat();
551 float videoFpsHint = data.readFloat();
552 reply->writeInt32(setSyncSettings(sync, videoFpsHint));
553 return NO_ERROR;
554 } break;
555 case GET_SYNC_SETTINGS: {
556 CHECK_INTERFACE(IMediaPlayer, data, reply);
557 AVSyncSettings sync;
558 float videoFps;
559 status_t err = getSyncSettings(&sync, &videoFps);
560 reply->writeInt32(err);
561 if (err == OK) {
562 reply->writeInt32((int32_t)sync.mSource);
563 reply->writeInt32((int32_t)sync.mAudioAdjustMode);
564 reply->writeFloat(sync.mTolerance);
565 reply->writeFloat(videoFps);
566 }
567 return NO_ERROR;
568 } break;
569 case PAUSE: {
570 CHECK_INTERFACE(IMediaPlayer, data, reply);
571 reply->writeInt32(pause());
572 return NO_ERROR;
573 } break;
574 case SEEK_TO: {
575 CHECK_INTERFACE(IMediaPlayer, data, reply);
576 reply->writeInt32(seekTo(data.readInt32()));
577 return NO_ERROR;
578 } break;
579 case GET_CURRENT_POSITION: {
580 CHECK_INTERFACE(IMediaPlayer, data, reply);
581 int msec = 0;
582 status_t ret = getCurrentPosition(&msec);
583 reply->writeInt32(msec);
584 reply->writeInt32(ret);
585 return NO_ERROR;
586 } break;
587 case GET_DURATION: {
588 CHECK_INTERFACE(IMediaPlayer, data, reply);
589 int msec = 0;
590 status_t ret = getDuration(&msec);
591 reply->writeInt32(msec);
592 reply->writeInt32(ret);
593 return NO_ERROR;
594 } break;
595 case RESET: {
596 CHECK_INTERFACE(IMediaPlayer, data, reply);
597 reply->writeInt32(reset());
598 return NO_ERROR;
599 } break;
600 case SET_AUDIO_STREAM_TYPE: {
601 CHECK_INTERFACE(IMediaPlayer, data, reply);
602 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
603 return NO_ERROR;
604 } break;
605 case SET_LOOPING: {
606 CHECK_INTERFACE(IMediaPlayer, data, reply);
607 reply->writeInt32(setLooping(data.readInt32()));
608 return NO_ERROR;
609 } break;
610 case SET_VOLUME: {
611 CHECK_INTERFACE(IMediaPlayer, data, reply);
612 float leftVolume = data.readFloat();
613 float rightVolume = data.readFloat();
614 reply->writeInt32(setVolume(leftVolume, rightVolume));
615 return NO_ERROR;
616 } break;
617 case INVOKE: {
618 CHECK_INTERFACE(IMediaPlayer, data, reply);
619 status_t result = invoke(data, reply);
620 return result;
621 } break;
622 case SET_METADATA_FILTER: {
623 CHECK_INTERFACE(IMediaPlayer, data, reply);
624 reply->writeInt32(setMetadataFilter(data));
625 return NO_ERROR;
626 } break;
627 case GET_METADATA: {
628 CHECK_INTERFACE(IMediaPlayer, data, reply);
629 bool update_only = static_cast<bool>(data.readInt32());
630 bool apply_filter = static_cast<bool>(data.readInt32());
631 const status_t retcode = getMetadata(update_only, apply_filter, reply);
632 reply->setDataPosition(0);
633 reply->writeInt32(retcode);
634 reply->setDataPosition(0);
635 return NO_ERROR;
636 } break;
637 case SET_AUX_EFFECT_SEND_LEVEL: {
638 CHECK_INTERFACE(IMediaPlayer, data, reply);
639 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
640 return NO_ERROR;
641 } break;
642 case ATTACH_AUX_EFFECT: {
643 CHECK_INTERFACE(IMediaPlayer, data, reply);
644 reply->writeInt32(attachAuxEffect(data.readInt32()));
645 return NO_ERROR;
646 } break;
647 case SET_PARAMETER: {
648 CHECK_INTERFACE(IMediaPlayer, data, reply);
649 int key = data.readInt32();
650
651 Parcel request;
652 if (data.dataAvail() > 0) {
653 request.appendFrom(
654 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
655 }
656 request.setDataPosition(0);
657 reply->writeInt32(setParameter(key, request));
658 return NO_ERROR;
659 } break;
660 case GET_PARAMETER: {
661 CHECK_INTERFACE(IMediaPlayer, data, reply);
662 return getParameter(data.readInt32(), reply);
663 } break;
664 case SET_RETRANSMIT_ENDPOINT: {
665 CHECK_INTERFACE(IMediaPlayer, data, reply);
666
667 struct sockaddr_in endpoint;
668 memset(&endpoint, 0, sizeof(endpoint));
669 int amt = data.readInt32();
670 if (amt == sizeof(endpoint)) {
671 data.read(&endpoint, sizeof(struct sockaddr_in));
672 reply->writeInt32(setRetransmitEndpoint(&endpoint));
673 } else {
674 reply->writeInt32(setRetransmitEndpoint(NULL));
675 }
676
677 return NO_ERROR;
678 } break;
679 case GET_RETRANSMIT_ENDPOINT: {
680 CHECK_INTERFACE(IMediaPlayer, data, reply);
681
682 struct sockaddr_in endpoint;
683 memset(&endpoint, 0, sizeof(endpoint));
684 status_t res = getRetransmitEndpoint(&endpoint);
685
686 reply->writeInt32(res);
687 reply->write(&endpoint, sizeof(endpoint));
688
689 return NO_ERROR;
690 } break;
691 case SET_NEXT_PLAYER: {
692 CHECK_INTERFACE(IMediaPlayer, data, reply);
693 reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
694
695 return NO_ERROR;
696 } break;
697 default:
698 return BBinder::onTransact(code, data, reply, flags);
699 }
700 }
701
702 // ----------------------------------------------------------------------------
703
704 } // namespace android
705