• 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/IGraphicBufferProducer.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     GET_RETRANSMIT_ENDPOINT,
59     SET_NEXT_PLAYER,
60 };
61 
62 class BpMediaPlayer: public BpInterface<IMediaPlayer>
63 {
64 public:
BpMediaPlayer(const sp<IBinder> & impl)65     BpMediaPlayer(const sp<IBinder>& impl)
66         : BpInterface<IMediaPlayer>(impl)
67     {
68     }
69 
70     // disconnect from media player service
disconnect()71     void disconnect()
72     {
73         Parcel data, reply;
74         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
75         remote()->transact(DISCONNECT, data, &reply);
76     }
77 
setDataSource(const char * url,const KeyedVector<String8,String8> * headers)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 
setDataSource(int fd,int64_t offset,int64_t length)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 
setDataSource(const sp<IStreamSource> & source)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 IGraphicBufferProducer to the media player service
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)117     status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer)
118     {
119         Parcel data, reply;
120         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
121         sp<IBinder> b(bufferProducer->asBinder());
122         data.writeStrongBinder(b);
123         remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
124         return reply.readInt32();
125     }
126 
prepareAsync()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 
start()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 
stop()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 
isPlaying(bool * state)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 
pause()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 
seekTo(int msec)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 
getCurrentPosition(int * msec)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 
getDuration(int * msec)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 
reset()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 
setAudioStreamType(audio_stream_type_t stream)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 
setLooping(int loop)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 
setVolume(float leftVolume,float rightVolume)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 
invoke(const Parcel & request,Parcel * reply)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 
setMetadataFilter(const Parcel & request)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 
getMetadata(bool update_only,bool apply_filter,Parcel * reply)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 
setAuxEffectSendLevel(float level)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 
attachAuxEffect(int effectId)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 
setParameter(int key,const Parcel & request)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 
getParameter(int key,Parcel * reply)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 
setRetransmitEndpoint(const struct sockaddr_in * endpoint)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 
setNextPlayer(const sp<IMediaPlayer> & player)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 
getRetransmitEndpoint(struct sockaddr_in * endpoint)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 
343 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
344 
345 // ----------------------------------------------------------------------
346 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)347 status_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<IGraphicBufferProducer> bufferProducer =
387                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
388             reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
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