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/IMediaPlayer.h>
     25 #include <media/IStreamSource.h>
     26 
     27 #include <gui/ISurfaceTexture.h>
     28 #include <utils/String8.h>
     29 
     30 namespace android {
     31 
     32 enum {
     33     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     34     SET_DATA_SOURCE_URL,
     35     SET_DATA_SOURCE_FD,
     36     SET_DATA_SOURCE_STREAM,
     37     PREPARE_ASYNC,
     38     START,
     39     STOP,
     40     IS_PLAYING,
     41     PAUSE,
     42     SEEK_TO,
     43     GET_CURRENT_POSITION,
     44     GET_DURATION,
     45     RESET,
     46     SET_AUDIO_STREAM_TYPE,
     47     SET_LOOPING,
     48     SET_VOLUME,
     49     INVOKE,
     50     SET_METADATA_FILTER,
     51     GET_METADATA,
     52     SET_AUX_EFFECT_SEND_LEVEL,
     53     ATTACH_AUX_EFFECT,
     54     SET_VIDEO_SURFACETEXTURE,
     55     SET_PARAMETER,
     56     GET_PARAMETER,
     57     SET_RETRANSMIT_ENDPOINT,
     58     SET_NEXT_PLAYER,
     59 };
     60 
     61 class BpMediaPlayer: public BpInterface<IMediaPlayer>
     62 {
     63 public:
     64     BpMediaPlayer(const sp<IBinder>& impl)
     65         : BpInterface<IMediaPlayer>(impl)
     66     {
     67     }
     68 
     69     // disconnect from media player service
     70     void disconnect()
     71     {
     72         Parcel data, reply;
     73         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
     74         remote()->transact(DISCONNECT, data, &reply);
     75     }
     76 
     77     status_t setDataSource(const char* url,
     78             const KeyedVector<String8, String8>* headers)
     79     {
     80         Parcel data, reply;
     81         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
     82         data.writeCString(url);
     83         if (headers == NULL) {
     84             data.writeInt32(0);
     85         } else {
     86             // serialize the headers
     87             data.writeInt32(headers->size());
     88             for (size_t i = 0; i < headers->size(); ++i) {
     89                 data.writeString8(headers->keyAt(i));
     90                 data.writeString8(headers->valueAt(i));
     91             }
     92         }
     93         remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
     94         return reply.readInt32();
     95     }
     96 
     97     status_t setDataSource(int fd, int64_t offset, int64_t length) {
     98         Parcel data, reply;
     99         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    100         data.writeFileDescriptor(fd);
    101         data.writeInt64(offset);
    102         data.writeInt64(length);
    103         remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
    104         return reply.readInt32();
    105     }
    106 
    107     status_t setDataSource(const sp<IStreamSource> &source) {
    108         Parcel data, reply;
    109         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    110         data.writeStrongBinder(source->asBinder());
    111         remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
    112         return reply.readInt32();
    113     }
    114 
    115     // pass the buffered ISurfaceTexture to the media player service
    116     status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
    117     {
    118         Parcel data, reply;
    119         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    120         sp<IBinder> b(surfaceTexture->asBinder());
    121         data.writeStrongBinder(b);
    122         remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
    123         return reply.readInt32();
    124     }
    125 
    126     status_t prepareAsync()
    127     {
    128         Parcel data, reply;
    129         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    130         remote()->transact(PREPARE_ASYNC, data, &reply);
    131         return reply.readInt32();
    132     }
    133 
    134     status_t start()
    135     {
    136         Parcel data, reply;
    137         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    138         remote()->transact(START, data, &reply);
    139         return reply.readInt32();
    140     }
    141 
    142     status_t stop()
    143     {
    144         Parcel data, reply;
    145         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    146         remote()->transact(STOP, data, &reply);
    147         return reply.readInt32();
    148     }
    149 
    150     status_t isPlaying(bool* state)
    151     {
    152         Parcel data, reply;
    153         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    154         remote()->transact(IS_PLAYING, data, &reply);
    155         *state = reply.readInt32();
    156         return reply.readInt32();
    157     }
    158 
    159     status_t pause()
    160     {
    161         Parcel data, reply;
    162         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    163         remote()->transact(PAUSE, data, &reply);
    164         return reply.readInt32();
    165     }
    166 
    167     status_t seekTo(int msec)
    168     {
    169         Parcel data, reply;
    170         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    171         data.writeInt32(msec);
    172         remote()->transact(SEEK_TO, data, &reply);
    173         return reply.readInt32();
    174     }
    175 
    176     status_t getCurrentPosition(int* msec)
    177     {
    178         Parcel data, reply;
    179         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    180         remote()->transact(GET_CURRENT_POSITION, data, &reply);
    181         *msec = reply.readInt32();
    182         return reply.readInt32();
    183     }
    184 
    185     status_t getDuration(int* msec)
    186     {
    187         Parcel data, reply;
    188         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    189         remote()->transact(GET_DURATION, data, &reply);
    190         *msec = reply.readInt32();
    191         return reply.readInt32();
    192     }
    193 
    194     status_t reset()
    195     {
    196         Parcel data, reply;
    197         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    198         remote()->transact(RESET, data, &reply);
    199         return reply.readInt32();
    200     }
    201 
    202     status_t setAudioStreamType(audio_stream_type_t stream)
    203     {
    204         Parcel data, reply;
    205         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    206         data.writeInt32((int32_t) stream);
    207         remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
    208         return reply.readInt32();
    209     }
    210 
    211     status_t setLooping(int loop)
    212     {
    213         Parcel data, reply;
    214         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    215         data.writeInt32(loop);
    216         remote()->transact(SET_LOOPING, data, &reply);
    217         return reply.readInt32();
    218     }
    219 
    220     status_t setVolume(float leftVolume, float rightVolume)
    221     {
    222         Parcel data, reply;
    223         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    224         data.writeFloat(leftVolume);
    225         data.writeFloat(rightVolume);
    226         remote()->transact(SET_VOLUME, data, &reply);
    227         return reply.readInt32();
    228     }
    229 
    230     status_t invoke(const Parcel& request, Parcel *reply)
    231     {
    232         // Avoid doing any extra copy. The interface descriptor should
    233         // have been set by MediaPlayer.java.
    234         return remote()->transact(INVOKE, request, reply);
    235     }
    236 
    237     status_t setMetadataFilter(const Parcel& request)
    238     {
    239         Parcel reply;
    240         // Avoid doing any extra copy of the request. The interface
    241         // descriptor should have been set by MediaPlayer.java.
    242         remote()->transact(SET_METADATA_FILTER, request, &reply);
    243         return reply.readInt32();
    244     }
    245 
    246     status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
    247     {
    248         Parcel request;
    249         request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    250         // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
    251         request.writeInt32(update_only);
    252         request.writeInt32(apply_filter);
    253         remote()->transact(GET_METADATA, request, reply);
    254         return reply->readInt32();
    255     }
    256 
    257     status_t setAuxEffectSendLevel(float level)
    258     {
    259         Parcel data, reply;
    260         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    261         data.writeFloat(level);
    262         remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
    263         return reply.readInt32();
    264     }
    265 
    266     status_t attachAuxEffect(int effectId)
    267     {
    268         Parcel data, reply;
    269         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    270         data.writeInt32(effectId);
    271         remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
    272         return reply.readInt32();
    273     }
    274 
    275     status_t setParameter(int key, const Parcel& request)
    276     {
    277         Parcel data, reply;
    278         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    279         data.writeInt32(key);
    280         if (request.dataSize() > 0) {
    281             data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
    282         }
    283         remote()->transact(SET_PARAMETER, data, &reply);
    284         return reply.readInt32();
    285     }
    286 
    287     status_t getParameter(int key, Parcel *reply)
    288     {
    289         Parcel data;
    290         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    291         data.writeInt32(key);
    292         return remote()->transact(GET_PARAMETER, data, reply);
    293     }
    294 
    295     status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
    296         Parcel data, reply;
    297         status_t err;
    298 
    299         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    300         if (NULL != endpoint) {
    301             data.writeInt32(sizeof(*endpoint));
    302             data.write(endpoint, sizeof(*endpoint));
    303         } else {
    304             data.writeInt32(0);
    305         }
    306 
    307         err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply);
    308         if (OK != err) {
    309             return err;
    310         }
    311         return reply.readInt32();
    312     }
    313 
    314     status_t setNextPlayer(const sp<IMediaPlayer>& player) {
    315         Parcel data, reply;
    316         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
    317         sp<IBinder> b(player->asBinder());
    318         data.writeStrongBinder(b);
    319         remote()->transact(SET_NEXT_PLAYER, data, &reply);
    320         return reply.readInt32();
    321     }
    322 };
    323 
    324 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
    325 
    326 // ----------------------------------------------------------------------
    327 
    328 status_t BnMediaPlayer::onTransact(
    329     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    330 {
    331     switch (code) {
    332         case DISCONNECT: {
    333             CHECK_INTERFACE(IMediaPlayer, data, reply);
    334             disconnect();
    335             return NO_ERROR;
    336         } break;
    337         case SET_DATA_SOURCE_URL: {
    338             CHECK_INTERFACE(IMediaPlayer, data, reply);
    339             const char* url = data.readCString();
    340             KeyedVector<String8, String8> headers;
    341             int32_t numHeaders = data.readInt32();
    342             for (int i = 0; i < numHeaders; ++i) {
    343                 String8 key = data.readString8();
    344                 String8 value = data.readString8();
    345                 headers.add(key, value);
    346             }
    347             reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
    348             return NO_ERROR;
    349         } break;
    350         case SET_DATA_SOURCE_FD: {
    351             CHECK_INTERFACE(IMediaPlayer, data, reply);
    352             int fd = data.readFileDescriptor();
    353             int64_t offset = data.readInt64();
    354             int64_t length = data.readInt64();
    355             reply->writeInt32(setDataSource(fd, offset, length));
    356             return NO_ERROR;
    357         }
    358         case SET_DATA_SOURCE_STREAM: {
    359             CHECK_INTERFACE(IMediaPlayer, data, reply);
    360             sp<IStreamSource> source =
    361                 interface_cast<IStreamSource>(data.readStrongBinder());
    362             reply->writeInt32(setDataSource(source));
    363             return NO_ERROR;
    364         }
    365         case SET_VIDEO_SURFACETEXTURE: {
    366             CHECK_INTERFACE(IMediaPlayer, data, reply);
    367             sp<ISurfaceTexture> surfaceTexture =
    368                     interface_cast<ISurfaceTexture>(data.readStrongBinder());
    369             reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
    370             return NO_ERROR;
    371         } break;
    372         case PREPARE_ASYNC: {
    373             CHECK_INTERFACE(IMediaPlayer, data, reply);
    374             reply->writeInt32(prepareAsync());
    375             return NO_ERROR;
    376         } break;
    377         case START: {
    378             CHECK_INTERFACE(IMediaPlayer, data, reply);
    379             reply->writeInt32(start());
    380             return NO_ERROR;
    381         } break;
    382         case STOP: {
    383             CHECK_INTERFACE(IMediaPlayer, data, reply);
    384             reply->writeInt32(stop());
    385             return NO_ERROR;
    386         } break;
    387         case IS_PLAYING: {
    388             CHECK_INTERFACE(IMediaPlayer, data, reply);
    389             bool state;
    390             status_t ret = isPlaying(&state);
    391             reply->writeInt32(state);
    392             reply->writeInt32(ret);
    393             return NO_ERROR;
    394         } break;
    395         case PAUSE: {
    396             CHECK_INTERFACE(IMediaPlayer, data, reply);
    397             reply->writeInt32(pause());
    398             return NO_ERROR;
    399         } break;
    400         case SEEK_TO: {
    401             CHECK_INTERFACE(IMediaPlayer, data, reply);
    402             reply->writeInt32(seekTo(data.readInt32()));
    403             return NO_ERROR;
    404         } break;
    405         case GET_CURRENT_POSITION: {
    406             CHECK_INTERFACE(IMediaPlayer, data, reply);
    407             int msec;
    408             status_t ret = getCurrentPosition(&msec);
    409             reply->writeInt32(msec);
    410             reply->writeInt32(ret);
    411             return NO_ERROR;
    412         } break;
    413         case GET_DURATION: {
    414             CHECK_INTERFACE(IMediaPlayer, data, reply);
    415             int msec;
    416             status_t ret = getDuration(&msec);
    417             reply->writeInt32(msec);
    418             reply->writeInt32(ret);
    419             return NO_ERROR;
    420         } break;
    421         case RESET: {
    422             CHECK_INTERFACE(IMediaPlayer, data, reply);
    423             reply->writeInt32(reset());
    424             return NO_ERROR;
    425         } break;
    426         case SET_AUDIO_STREAM_TYPE: {
    427             CHECK_INTERFACE(IMediaPlayer, data, reply);
    428             reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
    429             return NO_ERROR;
    430         } break;
    431         case SET_LOOPING: {
    432             CHECK_INTERFACE(IMediaPlayer, data, reply);
    433             reply->writeInt32(setLooping(data.readInt32()));
    434             return NO_ERROR;
    435         } break;
    436         case SET_VOLUME: {
    437             CHECK_INTERFACE(IMediaPlayer, data, reply);
    438             float leftVolume = data.readFloat();
    439             float rightVolume = data.readFloat();
    440             reply->writeInt32(setVolume(leftVolume, rightVolume));
    441             return NO_ERROR;
    442         } break;
    443         case INVOKE: {
    444             CHECK_INTERFACE(IMediaPlayer, data, reply);
    445             status_t result = invoke(data, reply);
    446             return result;
    447         } break;
    448         case SET_METADATA_FILTER: {
    449             CHECK_INTERFACE(IMediaPlayer, data, reply);
    450             reply->writeInt32(setMetadataFilter(data));
    451             return NO_ERROR;
    452         } break;
    453         case GET_METADATA: {
    454             CHECK_INTERFACE(IMediaPlayer, data, reply);
    455             bool update_only = static_cast<bool>(data.readInt32());
    456             bool apply_filter = static_cast<bool>(data.readInt32());
    457             const status_t retcode = getMetadata(update_only, apply_filter, reply);
    458             reply->setDataPosition(0);
    459             reply->writeInt32(retcode);
    460             reply->setDataPosition(0);
    461             return NO_ERROR;
    462         } break;
    463         case SET_AUX_EFFECT_SEND_LEVEL: {
    464             CHECK_INTERFACE(IMediaPlayer, data, reply);
    465             reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
    466             return NO_ERROR;
    467         } break;
    468         case ATTACH_AUX_EFFECT: {
    469             CHECK_INTERFACE(IMediaPlayer, data, reply);
    470             reply->writeInt32(attachAuxEffect(data.readInt32()));
    471             return NO_ERROR;
    472         } break;
    473         case SET_PARAMETER: {
    474             CHECK_INTERFACE(IMediaPlayer, data, reply);
    475             int key = data.readInt32();
    476 
    477             Parcel request;
    478             if (data.dataAvail() > 0) {
    479                 request.appendFrom(
    480                         const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
    481             }
    482             request.setDataPosition(0);
    483             reply->writeInt32(setParameter(key, request));
    484             return NO_ERROR;
    485         } break;
    486         case GET_PARAMETER: {
    487             CHECK_INTERFACE(IMediaPlayer, data, reply);
    488             return getParameter(data.readInt32(), reply);
    489         } break;
    490         case SET_RETRANSMIT_ENDPOINT: {
    491             CHECK_INTERFACE(IMediaPlayer, data, reply);
    492 
    493             struct sockaddr_in endpoint;
    494             int amt = data.readInt32();
    495             if (amt == sizeof(endpoint)) {
    496                 data.read(&endpoint, sizeof(struct sockaddr_in));
    497                 reply->writeInt32(setRetransmitEndpoint(&endpoint));
    498             } else {
    499                 reply->writeInt32(setRetransmitEndpoint(NULL));
    500             }
    501             return NO_ERROR;
    502         } break;
    503         case SET_NEXT_PLAYER: {
    504             CHECK_INTERFACE(IMediaPlayer, data, reply);
    505             reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
    506             return NO_ERROR;
    507         } break;
    508         default:
    509             return BBinder::onTransact(code, data, reply, flags);
    510     }
    511 }
    512 
    513 // ----------------------------------------------------------------------------
    514 
    515 }; // namespace android
    516