IMediaPlayer.cpp revision 6b74d671a1321a6ecc4a40b6c87beedfecc1ec44
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
30namespace android {
31
32enum {
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
61class BpMediaPlayer: public BpInterface<IMediaPlayer>
62{
63public:
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
324IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
325
326// ----------------------------------------------------------------------
327
328status_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