blob: 16ba484e2d775f1c9a7e02f7380d17f289542bb3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
John Grossman720aa282012-02-22 15:38:35 -080018#include <arpa/inet.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#include <stdint.h>
20#include <sys/types.h>
21
Mathias Agopian07952722009-05-19 19:08:10 -070022#include <binder/Parcel.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
24#include <media/IMediaPlayer.h>
Dave Burkefc301b02011-08-30 14:39:17 +010025#include <media/IStreamSource.h>
26
Glenn Kastencc562a32011-02-08 17:26:17 -080027#include <gui/ISurfaceTexture.h>
Dave Burkefc301b02011-08-30 14:39:17 +010028#include <utils/String8.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
30namespace android {
31
32enum {
33 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
Dave Burkefc301b02011-08-30 14:39:17 +010034 SET_DATA_SOURCE_URL,
35 SET_DATA_SOURCE_FD,
36 SET_DATA_SOURCE_STREAM,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 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,
Nicolas Catania20cb94e2009-05-12 23:25:55 -070048 SET_VOLUME,
49 INVOKE,
Nicolas Cataniab2c69392009-07-08 08:57:42 -070050 SET_METADATA_FILTER,
Nicolas Catania5d55c712009-07-09 09:21:33 -070051 GET_METADATA,
Eric Laurent7070b362010-07-16 07:43:46 -070052 SET_AUX_EFFECT_SEND_LEVEL,
Glenn Kastencc562a32011-02-08 17:26:17 -080053 ATTACH_AUX_EFFECT,
54 SET_VIDEO_SURFACETEXTURE,
Gloria Wangd01ec6e2011-04-25 17:28:22 -070055 SET_PARAMETER,
56 GET_PARAMETER,
John Grossman720aa282012-02-22 15:38:35 -080057 SET_RETRANSMIT_ENDPOINT,
Marco Nelissen84b83202012-02-28 16:07:44 -080058 SET_NEXT_PLAYER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059};
60
61class BpMediaPlayer: public BpInterface<IMediaPlayer>
62{
63public:
64 BpMediaPlayer(const sp<IBinder>& impl)
65 : BpInterface<IMediaPlayer>(impl)
66 {
67 }
68
69 // disconnect from media player service
70 void disconnect()
71 {
72 Parcel data, reply;
73 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
74 remote()->transact(DISCONNECT, data, &reply);
75 }
76
Dave Burkefc301b02011-08-30 14:39:17 +010077 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
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
107 status_t setDataSource(const sp<IStreamSource> &source) {
108 Parcel data, reply;
109 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
110 data.writeStrongBinder(source->asBinder());
Glenn Kasten27f4bbb2011-09-07 14:40:23 -0700111 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
Dave Burkefc301b02011-08-30 14:39:17 +0100112 return reply.readInt32();
113 }
114
Glenn Kastencc562a32011-02-08 17:26:17 -0800115 // pass the buffered ISurfaceTexture to the media player service
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 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
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
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
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
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
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
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
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
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
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800202 status_t setAudioStreamType(audio_stream_type_t stream)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 {
204 Parcel data, reply;
205 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800206 data.writeInt32((int32_t) stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
208 return reply.readInt32();
209 }
210
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
220 status_t setVolume(float leftVolume, float rightVolume)
221 {
222 Parcel data, reply;
Dave Sparks81494192009-05-26 14:39:29 -0700223 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 data.writeFloat(leftVolume);
225 data.writeFloat(rightVolume);
226 remote()->transact(SET_VOLUME, data, &reply);
227 return reply.readInt32();
228 }
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700229
230 status_t invoke(const Parcel& request, Parcel *reply)
James Dong4edf1d12011-04-06 18:29:01 -0700231 {
232 // Avoid doing any extra copy. The interface descriptor should
233 // have been set by MediaPlayer.java.
Nicolas Catania5d55c712009-07-09 09:21:33 -0700234 return remote()->transact(INVOKE, request, reply);
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700235 }
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700236
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 }
Nicolas Catania5d55c712009-07-09 09:21:33 -0700245
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 }
Andreas Huberfbb38852010-02-12 12:35:58 -0800256
Eric Laurent7070b362010-07-16 07:43:46 -0700257 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
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 }
Glenn Kastencc562a32011-02-08 17:26:17 -0800274
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700275 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
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
John Grossman720aa282012-02-22 15:38:35 -0800295 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 }
Marco Nelissen84b83202012-02-28 16:07:44 -0800311 return reply.readInt32();
312 }
John Grossman720aa282012-02-22 15:38:35 -0800313
Marco Nelissen84b83202012-02-28 16:07:44 -0800314 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);
John Grossman720aa282012-02-22 15:38:35 -0800320 return reply.readInt32();
321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322};
323
nikodcd810d2009-06-22 08:49:52 -0700324IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325
326// ----------------------------------------------------------------------
327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328status_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;
Dave Burkefc301b02011-08-30 14:39:17 +0100337 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 }
Glenn Kastencc562a32011-02-08 17:26:17 -0800365 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 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);
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800428 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 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: {
Dave Sparks81494192009-05-26 14:39:29 -0700437 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wang8f164fe2011-08-01 14:01:29 -0700438 float leftVolume = data.readFloat();
439 float rightVolume = data.readFloat();
440 reply->writeInt32(setVolume(leftVolume, rightVolume));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 return NO_ERROR;
442 } break;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700443 case INVOKE: {
444 CHECK_INTERFACE(IMediaPlayer, data, reply);
James Dong4edf1d12011-04-06 18:29:01 -0700445 status_t result = invoke(data, reply);
446 return result;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700447 } break;
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700448 case SET_METADATA_FILTER: {
449 CHECK_INTERFACE(IMediaPlayer, data, reply);
450 reply->writeInt32(setMetadataFilter(data));
451 return NO_ERROR;
452 } break;
Nicolas Catania5d55c712009-07-09 09:21:33 -0700453 case GET_METADATA: {
454 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wang8f164fe2011-08-01 14:01:29 -0700455 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);
Nicolas Catania5d55c712009-07-09 09:21:33 -0700458 reply->setDataPosition(0);
459 reply->writeInt32(retcode);
460 reply->setDataPosition(0);
461 return NO_ERROR;
462 } break;
Eric Laurent7070b362010-07-16 07:43:46 -0700463 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;
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700473 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;
John Grossman720aa282012-02-22 15:38:35 -0800490 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 }
Marco Nelissen84b83202012-02-28 16:07:44 -0800501 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())));
John Grossman720aa282012-02-22 15:38:35 -0800506 return NO_ERROR;
507 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 default:
509 return BBinder::onTransact(code, data, reply, flags);
510 }
511}
512
513// ----------------------------------------------------------------------------
514
515}; // namespace android