Home | History | Annotate | Download | only in libmedia
      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:
     75     BpMediaPlayer(const sp<IBinder>& impl)
     76         : BpInterface<IMediaPlayer>(impl)
     77     {
     78     }
     79 
     80     // disconnect from media player service
     81     void disconnect()
     82     {
     83         Parcel data, reply;
     84         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
     85         remote()->transact(DISCONNECT, data, &reply);
     86     }
     87 
     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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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;
    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;
    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