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