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