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