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