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             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