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