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