blob: f586b0229a31f55de2829021028fbb70025c716b [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,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058};
59
60class BpMediaPlayer: public BpInterface<IMediaPlayer>
61{
62public:
63 BpMediaPlayer(const sp<IBinder>& impl)
64 : BpInterface<IMediaPlayer>(impl)
65 {
66 }
67
68 // disconnect from media player service
69 void disconnect()
70 {
71 Parcel data, reply;
72 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
73 remote()->transact(DISCONNECT, data, &reply);
74 }
75
Dave Burkefc301b02011-08-30 14:39:17 +010076 status_t setDataSource(const char* url,
77 const KeyedVector<String8, String8>* headers)
78 {
79 Parcel data, reply;
80 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
81 data.writeCString(url);
82 if (headers == NULL) {
83 data.writeInt32(0);
84 } else {
85 // serialize the headers
86 data.writeInt32(headers->size());
87 for (size_t i = 0; i < headers->size(); ++i) {
88 data.writeString8(headers->keyAt(i));
89 data.writeString8(headers->valueAt(i));
90 }
91 }
92 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
93 return reply.readInt32();
94 }
95
96 status_t setDataSource(int fd, int64_t offset, int64_t length) {
97 Parcel data, reply;
98 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
99 data.writeFileDescriptor(fd);
100 data.writeInt64(offset);
101 data.writeInt64(length);
102 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
103 return reply.readInt32();
104 }
105
106 status_t setDataSource(const sp<IStreamSource> &source) {
107 Parcel data, reply;
108 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
109 data.writeStrongBinder(source->asBinder());
Glenn Kasten27f4bbb2011-09-07 14:40:23 -0700110 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
Dave Burkefc301b02011-08-30 14:39:17 +0100111 return reply.readInt32();
112 }
113
Glenn Kastencc562a32011-02-08 17:26:17 -0800114 // pass the buffered ISurfaceTexture to the media player service
115 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
116 {
117 Parcel data, reply;
118 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
119 sp<IBinder> b(surfaceTexture->asBinder());
120 data.writeStrongBinder(b);
121 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
122 return reply.readInt32();
123 }
124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 status_t prepareAsync()
126 {
127 Parcel data, reply;
128 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
129 remote()->transact(PREPARE_ASYNC, data, &reply);
130 return reply.readInt32();
131 }
132
133 status_t start()
134 {
135 Parcel data, reply;
136 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
137 remote()->transact(START, data, &reply);
138 return reply.readInt32();
139 }
140
141 status_t stop()
142 {
143 Parcel data, reply;
144 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
145 remote()->transact(STOP, data, &reply);
146 return reply.readInt32();
147 }
148
149 status_t isPlaying(bool* state)
150 {
151 Parcel data, reply;
152 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
153 remote()->transact(IS_PLAYING, data, &reply);
154 *state = reply.readInt32();
155 return reply.readInt32();
156 }
157
158 status_t pause()
159 {
160 Parcel data, reply;
161 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
162 remote()->transact(PAUSE, data, &reply);
163 return reply.readInt32();
164 }
165
166 status_t seekTo(int msec)
167 {
168 Parcel data, reply;
169 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
170 data.writeInt32(msec);
171 remote()->transact(SEEK_TO, data, &reply);
172 return reply.readInt32();
173 }
174
175 status_t getCurrentPosition(int* msec)
176 {
177 Parcel data, reply;
178 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
179 remote()->transact(GET_CURRENT_POSITION, data, &reply);
180 *msec = reply.readInt32();
181 return reply.readInt32();
182 }
183
184 status_t getDuration(int* msec)
185 {
186 Parcel data, reply;
187 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
188 remote()->transact(GET_DURATION, data, &reply);
189 *msec = reply.readInt32();
190 return reply.readInt32();
191 }
192
193 status_t reset()
194 {
195 Parcel data, reply;
196 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
197 remote()->transact(RESET, data, &reply);
198 return reply.readInt32();
199 }
200
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800201 status_t setAudioStreamType(audio_stream_type_t stream)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 {
203 Parcel data, reply;
204 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800205 data.writeInt32((int32_t) stream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
207 return reply.readInt32();
208 }
209
210 status_t setLooping(int loop)
211 {
212 Parcel data, reply;
213 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
214 data.writeInt32(loop);
215 remote()->transact(SET_LOOPING, data, &reply);
216 return reply.readInt32();
217 }
218
219 status_t setVolume(float leftVolume, float rightVolume)
220 {
221 Parcel data, reply;
Dave Sparks81494192009-05-26 14:39:29 -0700222 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 data.writeFloat(leftVolume);
224 data.writeFloat(rightVolume);
225 remote()->transact(SET_VOLUME, data, &reply);
226 return reply.readInt32();
227 }
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700228
229 status_t invoke(const Parcel& request, Parcel *reply)
James Dong4edf1d12011-04-06 18:29:01 -0700230 {
231 // Avoid doing any extra copy. The interface descriptor should
232 // have been set by MediaPlayer.java.
Nicolas Catania5d55c712009-07-09 09:21:33 -0700233 return remote()->transact(INVOKE, request, reply);
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700234 }
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700235
236 status_t setMetadataFilter(const Parcel& request)
237 {
238 Parcel reply;
239 // Avoid doing any extra copy of the request. The interface
240 // descriptor should have been set by MediaPlayer.java.
241 remote()->transact(SET_METADATA_FILTER, request, &reply);
242 return reply.readInt32();
243 }
Nicolas Catania5d55c712009-07-09 09:21:33 -0700244
245 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
246 {
247 Parcel request;
248 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
249 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
250 request.writeInt32(update_only);
251 request.writeInt32(apply_filter);
252 remote()->transact(GET_METADATA, request, reply);
253 return reply->readInt32();
254 }
Andreas Huberfbb38852010-02-12 12:35:58 -0800255
Eric Laurent7070b362010-07-16 07:43:46 -0700256 status_t setAuxEffectSendLevel(float level)
257 {
258 Parcel data, reply;
259 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
260 data.writeFloat(level);
261 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
262 return reply.readInt32();
263 }
264
265 status_t attachAuxEffect(int effectId)
266 {
267 Parcel data, reply;
268 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
269 data.writeInt32(effectId);
270 remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
271 return reply.readInt32();
272 }
Glenn Kastencc562a32011-02-08 17:26:17 -0800273
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700274 status_t setParameter(int key, const Parcel& request)
275 {
276 Parcel data, reply;
277 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
278 data.writeInt32(key);
279 if (request.dataSize() > 0) {
280 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
281 }
282 remote()->transact(SET_PARAMETER, data, &reply);
283 return reply.readInt32();
284 }
285
286 status_t getParameter(int key, Parcel *reply)
287 {
288 Parcel data;
289 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
290 data.writeInt32(key);
291 return remote()->transact(GET_PARAMETER, data, reply);
292 }
293
John Grossman720aa282012-02-22 15:38:35 -0800294 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
295 Parcel data, reply;
296 status_t err;
297
298 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
299 if (NULL != endpoint) {
300 data.writeInt32(sizeof(*endpoint));
301 data.write(endpoint, sizeof(*endpoint));
302 } else {
303 data.writeInt32(0);
304 }
305
306 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply);
307 if (OK != err) {
308 return err;
309 }
310
311 return reply.readInt32();
312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313};
314
nikodcd810d2009-06-22 08:49:52 -0700315IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317// ----------------------------------------------------------------------
318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319status_t BnMediaPlayer::onTransact(
320 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
321{
Glenn Kasten18db49a2012-03-12 16:29:55 -0700322 switch (code) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 case DISCONNECT: {
324 CHECK_INTERFACE(IMediaPlayer, data, reply);
325 disconnect();
326 return NO_ERROR;
327 } break;
Dave Burkefc301b02011-08-30 14:39:17 +0100328 case SET_DATA_SOURCE_URL: {
329 CHECK_INTERFACE(IMediaPlayer, data, reply);
330 const char* url = data.readCString();
331 KeyedVector<String8, String8> headers;
332 int32_t numHeaders = data.readInt32();
333 for (int i = 0; i < numHeaders; ++i) {
334 String8 key = data.readString8();
335 String8 value = data.readString8();
336 headers.add(key, value);
337 }
338 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
339 return NO_ERROR;
340 } break;
341 case SET_DATA_SOURCE_FD: {
342 CHECK_INTERFACE(IMediaPlayer, data, reply);
343 int fd = data.readFileDescriptor();
344 int64_t offset = data.readInt64();
345 int64_t length = data.readInt64();
346 reply->writeInt32(setDataSource(fd, offset, length));
347 return NO_ERROR;
348 }
349 case SET_DATA_SOURCE_STREAM: {
350 CHECK_INTERFACE(IMediaPlayer, data, reply);
351 sp<IStreamSource> source =
352 interface_cast<IStreamSource>(data.readStrongBinder());
353 reply->writeInt32(setDataSource(source));
354 return NO_ERROR;
355 }
Glenn Kastencc562a32011-02-08 17:26:17 -0800356 case SET_VIDEO_SURFACETEXTURE: {
357 CHECK_INTERFACE(IMediaPlayer, data, reply);
358 sp<ISurfaceTexture> surfaceTexture =
359 interface_cast<ISurfaceTexture>(data.readStrongBinder());
360 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
361 return NO_ERROR;
362 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 case PREPARE_ASYNC: {
364 CHECK_INTERFACE(IMediaPlayer, data, reply);
365 reply->writeInt32(prepareAsync());
366 return NO_ERROR;
367 } break;
368 case START: {
369 CHECK_INTERFACE(IMediaPlayer, data, reply);
370 reply->writeInt32(start());
371 return NO_ERROR;
372 } break;
373 case STOP: {
374 CHECK_INTERFACE(IMediaPlayer, data, reply);
375 reply->writeInt32(stop());
376 return NO_ERROR;
377 } break;
378 case IS_PLAYING: {
379 CHECK_INTERFACE(IMediaPlayer, data, reply);
380 bool state;
381 status_t ret = isPlaying(&state);
382 reply->writeInt32(state);
383 reply->writeInt32(ret);
384 return NO_ERROR;
385 } break;
386 case PAUSE: {
387 CHECK_INTERFACE(IMediaPlayer, data, reply);
388 reply->writeInt32(pause());
389 return NO_ERROR;
390 } break;
391 case SEEK_TO: {
392 CHECK_INTERFACE(IMediaPlayer, data, reply);
393 reply->writeInt32(seekTo(data.readInt32()));
394 return NO_ERROR;
395 } break;
396 case GET_CURRENT_POSITION: {
397 CHECK_INTERFACE(IMediaPlayer, data, reply);
398 int msec;
399 status_t ret = getCurrentPosition(&msec);
400 reply->writeInt32(msec);
401 reply->writeInt32(ret);
402 return NO_ERROR;
403 } break;
404 case GET_DURATION: {
405 CHECK_INTERFACE(IMediaPlayer, data, reply);
406 int msec;
407 status_t ret = getDuration(&msec);
408 reply->writeInt32(msec);
409 reply->writeInt32(ret);
410 return NO_ERROR;
411 } break;
412 case RESET: {
413 CHECK_INTERFACE(IMediaPlayer, data, reply);
414 reply->writeInt32(reset());
415 return NO_ERROR;
416 } break;
417 case SET_AUDIO_STREAM_TYPE: {
418 CHECK_INTERFACE(IMediaPlayer, data, reply);
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800419 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 return NO_ERROR;
421 } break;
422 case SET_LOOPING: {
423 CHECK_INTERFACE(IMediaPlayer, data, reply);
424 reply->writeInt32(setLooping(data.readInt32()));
425 return NO_ERROR;
426 } break;
427 case SET_VOLUME: {
Dave Sparks81494192009-05-26 14:39:29 -0700428 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wang8f164fe2011-08-01 14:01:29 -0700429 float leftVolume = data.readFloat();
430 float rightVolume = data.readFloat();
431 reply->writeInt32(setVolume(leftVolume, rightVolume));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 return NO_ERROR;
433 } break;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700434 case INVOKE: {
435 CHECK_INTERFACE(IMediaPlayer, data, reply);
James Dong4edf1d12011-04-06 18:29:01 -0700436 status_t result = invoke(data, reply);
437 return result;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700438 } break;
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700439 case SET_METADATA_FILTER: {
440 CHECK_INTERFACE(IMediaPlayer, data, reply);
441 reply->writeInt32(setMetadataFilter(data));
442 return NO_ERROR;
443 } break;
Nicolas Catania5d55c712009-07-09 09:21:33 -0700444 case GET_METADATA: {
445 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wang8f164fe2011-08-01 14:01:29 -0700446 bool update_only = static_cast<bool>(data.readInt32());
447 bool apply_filter = static_cast<bool>(data.readInt32());
448 const status_t retcode = getMetadata(update_only, apply_filter, reply);
Nicolas Catania5d55c712009-07-09 09:21:33 -0700449 reply->setDataPosition(0);
450 reply->writeInt32(retcode);
451 reply->setDataPosition(0);
452 return NO_ERROR;
453 } break;
Eric Laurent7070b362010-07-16 07:43:46 -0700454 case SET_AUX_EFFECT_SEND_LEVEL: {
455 CHECK_INTERFACE(IMediaPlayer, data, reply);
456 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
457 return NO_ERROR;
458 } break;
459 case ATTACH_AUX_EFFECT: {
460 CHECK_INTERFACE(IMediaPlayer, data, reply);
461 reply->writeInt32(attachAuxEffect(data.readInt32()));
462 return NO_ERROR;
463 } break;
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700464 case SET_PARAMETER: {
465 CHECK_INTERFACE(IMediaPlayer, data, reply);
466 int key = data.readInt32();
467
468 Parcel request;
469 if (data.dataAvail() > 0) {
470 request.appendFrom(
471 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
472 }
473 request.setDataPosition(0);
474 reply->writeInt32(setParameter(key, request));
475 return NO_ERROR;
476 } break;
477 case GET_PARAMETER: {
478 CHECK_INTERFACE(IMediaPlayer, data, reply);
479 return getParameter(data.readInt32(), reply);
480 } break;
John Grossman720aa282012-02-22 15:38:35 -0800481 case SET_RETRANSMIT_ENDPOINT: {
482 CHECK_INTERFACE(IMediaPlayer, data, reply);
483
484 struct sockaddr_in endpoint;
485 int amt = data.readInt32();
486 if (amt == sizeof(endpoint)) {
487 data.read(&endpoint, sizeof(struct sockaddr_in));
488 reply->writeInt32(setRetransmitEndpoint(&endpoint));
489 } else {
490 reply->writeInt32(setRetransmitEndpoint(NULL));
491 }
492
493 return NO_ERROR;
494 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 default:
496 return BBinder::onTransact(code, data, reply, flags);
497 }
498}
499
500// ----------------------------------------------------------------------------
501
502}; // namespace android