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