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