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