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