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