• 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             KeyedVector<String8, String8> headers;
448             int32_t numHeaders = data.readInt32();
449             for (int i = 0; i < numHeaders; ++i) {
450                 String8 key = data.readString8();
451                 String8 value = data.readString8();
452                 headers.add(key, value);
453             }
454             reply->writeInt32(setDataSource(
455                         httpService, url, numHeaders > 0 ? &headers : NULL));
456             return NO_ERROR;
457         } break;
458         case SET_DATA_SOURCE_FD: {
459             CHECK_INTERFACE(IMediaPlayer, data, reply);
460             int fd = data.readFileDescriptor();
461             int64_t offset = data.readInt64();
462             int64_t length = data.readInt64();
463             reply->writeInt32(setDataSource(fd, offset, length));
464             return NO_ERROR;
465         }
466         case SET_DATA_SOURCE_STREAM: {
467             CHECK_INTERFACE(IMediaPlayer, data, reply);
468             sp<IStreamSource> source =
469                 interface_cast<IStreamSource>(data.readStrongBinder());
470             reply->writeInt32(setDataSource(source));
471             return NO_ERROR;
472         }
473         case SET_DATA_SOURCE_CALLBACK: {
474             CHECK_INTERFACE(IMediaPlayer, data, reply);
475             sp<IDataSource> source =
476                 interface_cast<IDataSource>(data.readStrongBinder());
477             reply->writeInt32(setDataSource(source));
478             return NO_ERROR;
479         }
480         case SET_VIDEO_SURFACETEXTURE: {
481             CHECK_INTERFACE(IMediaPlayer, data, reply);
482             sp<IGraphicBufferProducer> bufferProducer =
483                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
484             reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
485             return NO_ERROR;
486         } break;
487         case PREPARE_ASYNC: {
488             CHECK_INTERFACE(IMediaPlayer, data, reply);
489             reply->writeInt32(prepareAsync());
490             return NO_ERROR;
491         } break;
492         case START: {
493             CHECK_INTERFACE(IMediaPlayer, data, reply);
494             reply->writeInt32(start());
495             return NO_ERROR;
496         } break;
497         case STOP: {
498             CHECK_INTERFACE(IMediaPlayer, data, reply);
499             reply->writeInt32(stop());
500             return NO_ERROR;
501         } break;
502         case IS_PLAYING: {
503             CHECK_INTERFACE(IMediaPlayer, data, reply);
504             bool state;
505             status_t ret = isPlaying(&state);
506             reply->writeInt32(state);
507             reply->writeInt32(ret);
508             return NO_ERROR;
509         } break;
510         case SET_PLAYBACK_SETTINGS: {
511             CHECK_INTERFACE(IMediaPlayer, data, reply);
512             AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
513             rate.mSpeed = data.readFloat();
514             rate.mPitch = data.readFloat();
515             rate.mFallbackMode = (AudioTimestretchFallbackMode)data.readInt32();
516             rate.mStretchMode = (AudioTimestretchStretchMode)data.readInt32();
517             reply->writeInt32(setPlaybackSettings(rate));
518             return NO_ERROR;
519         } break;
520         case GET_PLAYBACK_SETTINGS: {
521             CHECK_INTERFACE(IMediaPlayer, data, reply);
522             AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
523             status_t err = getPlaybackSettings(&rate);
524             reply->writeInt32(err);
525             if (err == OK) {
526                 reply->writeFloat(rate.mSpeed);
527                 reply->writeFloat(rate.mPitch);
528                 reply->writeInt32((int32_t)rate.mFallbackMode);
529                 reply->writeInt32((int32_t)rate.mStretchMode);
530             }
531             return NO_ERROR;
532         } break;
533         case SET_SYNC_SETTINGS: {
534             CHECK_INTERFACE(IMediaPlayer, data, reply);
535             AVSyncSettings sync;
536             sync.mSource = (AVSyncSource)data.readInt32();
537             sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)data.readInt32();
538             sync.mTolerance = data.readFloat();
539             float videoFpsHint = data.readFloat();
540             reply->writeInt32(setSyncSettings(sync, videoFpsHint));
541             return NO_ERROR;
542         } break;
543         case GET_SYNC_SETTINGS: {
544             CHECK_INTERFACE(IMediaPlayer, data, reply);
545             AVSyncSettings sync;
546             float videoFps;
547             status_t err = getSyncSettings(&sync, &videoFps);
548             reply->writeInt32(err);
549             if (err == OK) {
550                 reply->writeInt32((int32_t)sync.mSource);
551                 reply->writeInt32((int32_t)sync.mAudioAdjustMode);
552                 reply->writeFloat(sync.mTolerance);
553                 reply->writeFloat(videoFps);
554             }
555             return NO_ERROR;
556         } break;
557         case PAUSE: {
558             CHECK_INTERFACE(IMediaPlayer, data, reply);
559             reply->writeInt32(pause());
560             return NO_ERROR;
561         } break;
562         case SEEK_TO: {
563             CHECK_INTERFACE(IMediaPlayer, data, reply);
564             reply->writeInt32(seekTo(data.readInt32()));
565             return NO_ERROR;
566         } break;
567         case GET_CURRENT_POSITION: {
568             CHECK_INTERFACE(IMediaPlayer, data, reply);
569             int msec = 0;
570             status_t ret = getCurrentPosition(&msec);
571             reply->writeInt32(msec);
572             reply->writeInt32(ret);
573             return NO_ERROR;
574         } break;
575         case GET_DURATION: {
576             CHECK_INTERFACE(IMediaPlayer, data, reply);
577             int msec = 0;
578             status_t ret = getDuration(&msec);
579             reply->writeInt32(msec);
580             reply->writeInt32(ret);
581             return NO_ERROR;
582         } break;
583         case RESET: {
584             CHECK_INTERFACE(IMediaPlayer, data, reply);
585             reply->writeInt32(reset());
586             return NO_ERROR;
587         } break;
588         case SET_AUDIO_STREAM_TYPE: {
589             CHECK_INTERFACE(IMediaPlayer, data, reply);
590             reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
591             return NO_ERROR;
592         } break;
593         case SET_LOOPING: {
594             CHECK_INTERFACE(IMediaPlayer, data, reply);
595             reply->writeInt32(setLooping(data.readInt32()));
596             return NO_ERROR;
597         } break;
598         case SET_VOLUME: {
599             CHECK_INTERFACE(IMediaPlayer, data, reply);
600             float leftVolume = data.readFloat();
601             float rightVolume = data.readFloat();
602             reply->writeInt32(setVolume(leftVolume, rightVolume));
603             return NO_ERROR;
604         } break;
605         case INVOKE: {
606             CHECK_INTERFACE(IMediaPlayer, data, reply);
607             status_t result = invoke(data, reply);
608             return result;
609         } break;
610         case SET_METADATA_FILTER: {
611             CHECK_INTERFACE(IMediaPlayer, data, reply);
612             reply->writeInt32(setMetadataFilter(data));
613             return NO_ERROR;
614         } break;
615         case GET_METADATA: {
616             CHECK_INTERFACE(IMediaPlayer, data, reply);
617             bool update_only = static_cast<bool>(data.readInt32());
618             bool apply_filter = static_cast<bool>(data.readInt32());
619             const status_t retcode = getMetadata(update_only, apply_filter, reply);
620             reply->setDataPosition(0);
621             reply->writeInt32(retcode);
622             reply->setDataPosition(0);
623             return NO_ERROR;
624         } break;
625         case SET_AUX_EFFECT_SEND_LEVEL: {
626             CHECK_INTERFACE(IMediaPlayer, data, reply);
627             reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
628             return NO_ERROR;
629         } break;
630         case ATTACH_AUX_EFFECT: {
631             CHECK_INTERFACE(IMediaPlayer, data, reply);
632             reply->writeInt32(attachAuxEffect(data.readInt32()));
633             return NO_ERROR;
634         } break;
635         case SET_PARAMETER: {
636             CHECK_INTERFACE(IMediaPlayer, data, reply);
637             int key = data.readInt32();
638 
639             Parcel request;
640             if (data.dataAvail() > 0) {
641                 request.appendFrom(
642                         const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
643             }
644             request.setDataPosition(0);
645             reply->writeInt32(setParameter(key, request));
646             return NO_ERROR;
647         } break;
648         case GET_PARAMETER: {
649             CHECK_INTERFACE(IMediaPlayer, data, reply);
650             return getParameter(data.readInt32(), reply);
651         } break;
652         case SET_RETRANSMIT_ENDPOINT: {
653             CHECK_INTERFACE(IMediaPlayer, data, reply);
654 
655             struct sockaddr_in endpoint;
656             memset(&endpoint, 0, sizeof(endpoint));
657             int amt = data.readInt32();
658             if (amt == sizeof(endpoint)) {
659                 data.read(&endpoint, sizeof(struct sockaddr_in));
660                 reply->writeInt32(setRetransmitEndpoint(&endpoint));
661             } else {
662                 reply->writeInt32(setRetransmitEndpoint(NULL));
663             }
664 
665             return NO_ERROR;
666         } break;
667         case GET_RETRANSMIT_ENDPOINT: {
668             CHECK_INTERFACE(IMediaPlayer, data, reply);
669 
670             struct sockaddr_in endpoint;
671             memset(&endpoint, 0, sizeof(endpoint));
672             status_t res = getRetransmitEndpoint(&endpoint);
673 
674             reply->writeInt32(res);
675             reply->write(&endpoint, sizeof(endpoint));
676 
677             return NO_ERROR;
678         } break;
679         case SET_NEXT_PLAYER: {
680             CHECK_INTERFACE(IMediaPlayer, data, reply);
681             reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
682 
683             return NO_ERROR;
684         } break;
685         default:
686             return BBinder::onTransact(code, data, reply, flags);
687     }
688 }
689 
690 // ----------------------------------------------------------------------------
691 
692 } // namespace android
693