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