blob: 36a9efe4a15776048fc1ed756515d5a6446ad218 [file] [log] [blame]
The Android Open Source Project89fa4ad2009-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 Grossman68f09452012-02-22 15:38:35 -080018#include <arpa/inet.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080019#include <stdint.h>
20#include <sys/types.h>
21
Mathias Agopian75624082009-05-19 19:08:10 -070022#include <binder/Parcel.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080023
24#include <media/IMediaPlayer.h>
Dave Burked681bbb2011-08-30 14:39:17 +010025#include <media/IStreamSource.h>
26
Mathias Agopian3cf61352010-02-09 17:46:37 -080027#include <surfaceflinger/ISurface.h>
Andreas Huber5daeb122010-08-16 08:49:37 -070028#include <surfaceflinger/Surface.h>
Glenn Kasten11731182011-02-08 17:26:17 -080029#include <gui/ISurfaceTexture.h>
Dave Burked681bbb2011-08-30 14:39:17 +010030#include <utils/String8.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080031
32namespace android {
33
34enum {
35 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
Dave Burked681bbb2011-08-30 14:39:17 +010036 SET_DATA_SOURCE_URL,
37 SET_DATA_SOURCE_FD,
38 SET_DATA_SOURCE_STREAM,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080039 PREPARE_ASYNC,
40 START,
41 STOP,
42 IS_PLAYING,
43 PAUSE,
44 SEEK_TO,
45 GET_CURRENT_POSITION,
46 GET_DURATION,
47 RESET,
48 SET_AUDIO_STREAM_TYPE,
49 SET_LOOPING,
Nicolas Catania1d187f12009-05-12 23:25:55 -070050 SET_VOLUME,
51 INVOKE,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070052 SET_METADATA_FILTER,
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -070053 GET_METADATA,
Eric Laurent2beeb502010-07-16 07:43:46 -070054 SET_AUX_EFFECT_SEND_LEVEL,
Glenn Kasten11731182011-02-08 17:26:17 -080055 ATTACH_AUX_EFFECT,
56 SET_VIDEO_SURFACETEXTURE,
Gloria Wang4f9e47f2011-04-25 17:28:22 -070057 SET_PARAMETER,
58 GET_PARAMETER,
John Grossman68f09452012-02-22 15:38:35 -080059 SET_RETRANSMIT_ENDPOINT,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080060};
61
62class BpMediaPlayer: public BpInterface<IMediaPlayer>
63{
64public:
65 BpMediaPlayer(const sp<IBinder>& impl)
66 : BpInterface<IMediaPlayer>(impl)
67 {
68 }
69
70 // disconnect from media player service
71 void disconnect()
72 {
73 Parcel data, reply;
74 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
75 remote()->transact(DISCONNECT, data, &reply);
76 }
77
Dave Burked681bbb2011-08-30 14:39:17 +010078 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
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
108 status_t setDataSource(const sp<IStreamSource> &source) {
109 Parcel data, reply;
110 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
111 data.writeStrongBinder(source->asBinder());
Glenn Kasten8d655102011-09-07 14:40:23 -0700112 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
Dave Burked681bbb2011-08-30 14:39:17 +0100113 return reply.readInt32();
114 }
115
Glenn Kasten11731182011-02-08 17:26:17 -0800116 // pass the buffered ISurfaceTexture to the media player service
117 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
118 {
119 Parcel data, reply;
120 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
121 sp<IBinder> b(surfaceTexture->asBinder());
122 data.writeStrongBinder(b);
123 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
124 return reply.readInt32();
125 }
126
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800127 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
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
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
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
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
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
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
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
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
203 status_t setAudioStreamType(int type)
204 {
205 Parcel data, reply;
206 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
207 data.writeInt32(type);
208 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
209 return reply.readInt32();
210 }
211
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
221 status_t setVolume(float leftVolume, float rightVolume)
222 {
223 Parcel data, reply;
Dave Sparks172fb9a2009-05-26 14:39:29 -0700224 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800225 data.writeFloat(leftVolume);
226 data.writeFloat(rightVolume);
227 remote()->transact(SET_VOLUME, data, &reply);
228 return reply.readInt32();
229 }
Nicolas Catania1d187f12009-05-12 23:25:55 -0700230
231 status_t invoke(const Parcel& request, Parcel *reply)
James Dong040e4a12011-04-06 18:29:01 -0700232 {
233 // Avoid doing any extra copy. The interface descriptor should
234 // have been set by MediaPlayer.java.
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700235 return remote()->transact(INVOKE, request, reply);
Nicolas Catania1d187f12009-05-12 23:25:55 -0700236 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700237
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 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700246
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 }
Andreas Huber4e92c7e2010-02-12 12:35:58 -0800257
Eric Laurent2beeb502010-07-16 07:43:46 -0700258 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
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 }
Glenn Kasten11731182011-02-08 17:26:17 -0800275
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700276 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
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
John Grossman68f09452012-02-22 15:38:35 -0800296 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
297 Parcel data, reply;
298 status_t err;
299
300 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
301 if (NULL != endpoint) {
302 data.writeInt32(sizeof(*endpoint));
303 data.write(endpoint, sizeof(*endpoint));
304 } else {
305 data.writeInt32(0);
306 }
307
308 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply);
309 if (OK != err) {
310 return err;
311 }
312
313 return reply.readInt32();
314 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800315};
316
niko56f0cc52009-06-22 08:49:52 -0700317IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800318
319// ----------------------------------------------------------------------
320
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800321status_t BnMediaPlayer::onTransact(
322 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
323{
324 switch(code) {
325 case DISCONNECT: {
326 CHECK_INTERFACE(IMediaPlayer, data, reply);
327 disconnect();
328 return NO_ERROR;
329 } break;
Dave Burked681bbb2011-08-30 14:39:17 +0100330 case SET_DATA_SOURCE_URL: {
331 CHECK_INTERFACE(IMediaPlayer, data, reply);
332 const char* url = data.readCString();
333 KeyedVector<String8, String8> headers;
334 int32_t numHeaders = data.readInt32();
335 for (int i = 0; i < numHeaders; ++i) {
336 String8 key = data.readString8();
337 String8 value = data.readString8();
338 headers.add(key, value);
339 }
340 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
341 return NO_ERROR;
342 } break;
343 case SET_DATA_SOURCE_FD: {
344 CHECK_INTERFACE(IMediaPlayer, data, reply);
345 int fd = data.readFileDescriptor();
346 int64_t offset = data.readInt64();
347 int64_t length = data.readInt64();
348 reply->writeInt32(setDataSource(fd, offset, length));
349 return NO_ERROR;
350 }
351 case SET_DATA_SOURCE_STREAM: {
352 CHECK_INTERFACE(IMediaPlayer, data, reply);
353 sp<IStreamSource> source =
354 interface_cast<IStreamSource>(data.readStrongBinder());
355 reply->writeInt32(setDataSource(source));
356 return NO_ERROR;
357 }
Glenn Kasten11731182011-02-08 17:26:17 -0800358 case SET_VIDEO_SURFACETEXTURE: {
359 CHECK_INTERFACE(IMediaPlayer, data, reply);
360 sp<ISurfaceTexture> surfaceTexture =
361 interface_cast<ISurfaceTexture>(data.readStrongBinder());
362 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
363 return NO_ERROR;
364 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800365 case PREPARE_ASYNC: {
366 CHECK_INTERFACE(IMediaPlayer, data, reply);
367 reply->writeInt32(prepareAsync());
368 return NO_ERROR;
369 } break;
370 case START: {
371 CHECK_INTERFACE(IMediaPlayer, data, reply);
372 reply->writeInt32(start());
373 return NO_ERROR;
374 } break;
375 case STOP: {
376 CHECK_INTERFACE(IMediaPlayer, data, reply);
377 reply->writeInt32(stop());
378 return NO_ERROR;
379 } break;
380 case IS_PLAYING: {
381 CHECK_INTERFACE(IMediaPlayer, data, reply);
382 bool state;
383 status_t ret = isPlaying(&state);
384 reply->writeInt32(state);
385 reply->writeInt32(ret);
386 return NO_ERROR;
387 } break;
388 case PAUSE: {
389 CHECK_INTERFACE(IMediaPlayer, data, reply);
390 reply->writeInt32(pause());
391 return NO_ERROR;
392 } break;
393 case SEEK_TO: {
394 CHECK_INTERFACE(IMediaPlayer, data, reply);
395 reply->writeInt32(seekTo(data.readInt32()));
396 return NO_ERROR;
397 } break;
398 case GET_CURRENT_POSITION: {
399 CHECK_INTERFACE(IMediaPlayer, data, reply);
400 int msec;
401 status_t ret = getCurrentPosition(&msec);
402 reply->writeInt32(msec);
403 reply->writeInt32(ret);
404 return NO_ERROR;
405 } break;
406 case GET_DURATION: {
407 CHECK_INTERFACE(IMediaPlayer, data, reply);
408 int msec;
409 status_t ret = getDuration(&msec);
410 reply->writeInt32(msec);
411 reply->writeInt32(ret);
412 return NO_ERROR;
413 } break;
414 case RESET: {
415 CHECK_INTERFACE(IMediaPlayer, data, reply);
416 reply->writeInt32(reset());
417 return NO_ERROR;
418 } break;
419 case SET_AUDIO_STREAM_TYPE: {
420 CHECK_INTERFACE(IMediaPlayer, data, reply);
421 reply->writeInt32(setAudioStreamType(data.readInt32()));
422 return NO_ERROR;
423 } break;
424 case SET_LOOPING: {
425 CHECK_INTERFACE(IMediaPlayer, data, reply);
426 reply->writeInt32(setLooping(data.readInt32()));
427 return NO_ERROR;
428 } break;
429 case SET_VOLUME: {
Dave Sparks172fb9a2009-05-26 14:39:29 -0700430 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700431 float leftVolume = data.readFloat();
432 float rightVolume = data.readFloat();
433 reply->writeInt32(setVolume(leftVolume, rightVolume));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800434 return NO_ERROR;
435 } break;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700436 case INVOKE: {
437 CHECK_INTERFACE(IMediaPlayer, data, reply);
James Dong040e4a12011-04-06 18:29:01 -0700438 status_t result = invoke(data, reply);
439 return result;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700440 } break;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700441 case SET_METADATA_FILTER: {
442 CHECK_INTERFACE(IMediaPlayer, data, reply);
443 reply->writeInt32(setMetadataFilter(data));
444 return NO_ERROR;
445 } break;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700446 case GET_METADATA: {
447 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700448 bool update_only = static_cast<bool>(data.readInt32());
449 bool apply_filter = static_cast<bool>(data.readInt32());
450 const status_t retcode = getMetadata(update_only, apply_filter, reply);
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700451 reply->setDataPosition(0);
452 reply->writeInt32(retcode);
453 reply->setDataPosition(0);
454 return NO_ERROR;
455 } break;
Eric Laurent2beeb502010-07-16 07:43:46 -0700456 case SET_AUX_EFFECT_SEND_LEVEL: {
457 CHECK_INTERFACE(IMediaPlayer, data, reply);
458 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
459 return NO_ERROR;
460 } break;
461 case ATTACH_AUX_EFFECT: {
462 CHECK_INTERFACE(IMediaPlayer, data, reply);
463 reply->writeInt32(attachAuxEffect(data.readInt32()));
464 return NO_ERROR;
465 } break;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700466 case SET_PARAMETER: {
467 CHECK_INTERFACE(IMediaPlayer, data, reply);
468 int key = data.readInt32();
469
470 Parcel request;
471 if (data.dataAvail() > 0) {
472 request.appendFrom(
473 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
474 }
475 request.setDataPosition(0);
476 reply->writeInt32(setParameter(key, request));
477 return NO_ERROR;
478 } break;
479 case GET_PARAMETER: {
480 CHECK_INTERFACE(IMediaPlayer, data, reply);
481 return getParameter(data.readInt32(), reply);
482 } break;
John Grossman68f09452012-02-22 15:38:35 -0800483 case SET_RETRANSMIT_ENDPOINT: {
484 CHECK_INTERFACE(IMediaPlayer, data, reply);
485
486 struct sockaddr_in endpoint;
487 int amt = data.readInt32();
488 if (amt == sizeof(endpoint)) {
489 data.read(&endpoint, sizeof(struct sockaddr_in));
490 reply->writeInt32(setRetransmitEndpoint(&endpoint));
491 } else {
492 reply->writeInt32(setRetransmitEndpoint(NULL));
493 }
494
495 return NO_ERROR;
496 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800497 default:
498 return BBinder::onTransact(code, data, reply, flags);
499 }
500}
501
502// ----------------------------------------------------------------------------
503
504}; // namespace android