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