blob: 50a41ca153eed8eb5eaf8dbf90e96946405bbf46 [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
18#include <stdint.h>
19#include <sys/types.h>
20
Mathias Agopian75624082009-05-19 19:08:10 -070021#include <binder/Parcel.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080022
23#include <media/IMediaPlayer.h>
Dave Burked681bbb2011-08-30 14:39:17 +010024#include <media/IStreamSource.h>
25
Mathias Agopian3cf61352010-02-09 17:46:37 -080026#include <surfaceflinger/ISurface.h>
Andreas Huber5daeb122010-08-16 08:49:37 -070027#include <surfaceflinger/Surface.h>
Glenn Kasten11731182011-02-08 17:26:17 -080028#include <gui/ISurfaceTexture.h>
Dave Burked681bbb2011-08-30 14:39:17 +010029#include <utils/String8.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080030
31namespace android {
32
33enum {
34 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
Dave Burked681bbb2011-08-30 14:39:17 +010035 SET_DATA_SOURCE_URL,
36 SET_DATA_SOURCE_FD,
37 SET_DATA_SOURCE_STREAM,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080038 SET_VIDEO_SURFACE,
39 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,
The Android Open Source Project89fa4ad2009-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 Burked681bbb2011-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 Kasten8d655102011-09-07 14:40:23 -0700111 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
Dave Burked681bbb2011-08-30 14:39:17 +0100112 return reply.readInt32();
113 }
114
Glenn Kasten11731182011-02-08 17:26:17 -0800115 // pass the buffered Surface to the media player service
Andreas Huber5daeb122010-08-16 08:49:37 -0700116 status_t setVideoSurface(const sp<Surface>& surface)
117 {
118 Parcel data, reply;
119 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
120 Surface::writeToParcel(surface, &data);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800121 remote()->transact(SET_VIDEO_SURFACE, data, &reply);
122 return reply.readInt32();
123 }
124
Glenn Kasten11731182011-02-08 17:26:17 -0800125 // pass the buffered ISurfaceTexture to the media player service
126 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
127 {
128 Parcel data, reply;
129 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
130 sp<IBinder> b(surfaceTexture->asBinder());
131 data.writeStrongBinder(b);
132 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
133 return reply.readInt32();
134 }
135
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800136 status_t prepareAsync()
137 {
138 Parcel data, reply;
139 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
140 remote()->transact(PREPARE_ASYNC, data, &reply);
141 return reply.readInt32();
142 }
143
144 status_t start()
145 {
146 Parcel data, reply;
147 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
148 remote()->transact(START, data, &reply);
149 return reply.readInt32();
150 }
151
152 status_t stop()
153 {
154 Parcel data, reply;
155 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
156 remote()->transact(STOP, data, &reply);
157 return reply.readInt32();
158 }
159
160 status_t isPlaying(bool* state)
161 {
162 Parcel data, reply;
163 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
164 remote()->transact(IS_PLAYING, data, &reply);
165 *state = reply.readInt32();
166 return reply.readInt32();
167 }
168
169 status_t pause()
170 {
171 Parcel data, reply;
172 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
173 remote()->transact(PAUSE, data, &reply);
174 return reply.readInt32();
175 }
176
177 status_t seekTo(int msec)
178 {
179 Parcel data, reply;
180 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
181 data.writeInt32(msec);
182 remote()->transact(SEEK_TO, data, &reply);
183 return reply.readInt32();
184 }
185
186 status_t getCurrentPosition(int* msec)
187 {
188 Parcel data, reply;
189 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
190 remote()->transact(GET_CURRENT_POSITION, data, &reply);
191 *msec = reply.readInt32();
192 return reply.readInt32();
193 }
194
195 status_t getDuration(int* msec)
196 {
197 Parcel data, reply;
198 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
199 remote()->transact(GET_DURATION, data, &reply);
200 *msec = reply.readInt32();
201 return reply.readInt32();
202 }
203
204 status_t reset()
205 {
206 Parcel data, reply;
207 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
208 remote()->transact(RESET, data, &reply);
209 return reply.readInt32();
210 }
211
212 status_t setAudioStreamType(int type)
213 {
214 Parcel data, reply;
215 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
216 data.writeInt32(type);
217 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
218 return reply.readInt32();
219 }
220
221 status_t setLooping(int loop)
222 {
223 Parcel data, reply;
224 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
225 data.writeInt32(loop);
226 remote()->transact(SET_LOOPING, data, &reply);
227 return reply.readInt32();
228 }
229
230 status_t setVolume(float leftVolume, float rightVolume)
231 {
232 Parcel data, reply;
Dave Sparks172fb9a2009-05-26 14:39:29 -0700233 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800234 data.writeFloat(leftVolume);
235 data.writeFloat(rightVolume);
236 remote()->transact(SET_VOLUME, data, &reply);
237 return reply.readInt32();
238 }
Nicolas Catania1d187f12009-05-12 23:25:55 -0700239
240 status_t invoke(const Parcel& request, Parcel *reply)
James Dong040e4a12011-04-06 18:29:01 -0700241 {
242 // Avoid doing any extra copy. The interface descriptor should
243 // have been set by MediaPlayer.java.
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700244 return remote()->transact(INVOKE, request, reply);
Nicolas Catania1d187f12009-05-12 23:25:55 -0700245 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700246
247 status_t setMetadataFilter(const Parcel& request)
248 {
249 Parcel reply;
250 // Avoid doing any extra copy of the request. The interface
251 // descriptor should have been set by MediaPlayer.java.
252 remote()->transact(SET_METADATA_FILTER, request, &reply);
253 return reply.readInt32();
254 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700255
256 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
257 {
258 Parcel request;
259 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
260 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
261 request.writeInt32(update_only);
262 request.writeInt32(apply_filter);
263 remote()->transact(GET_METADATA, request, reply);
264 return reply->readInt32();
265 }
Andreas Huber4e92c7e2010-02-12 12:35:58 -0800266
Eric Laurent2beeb502010-07-16 07:43:46 -0700267 status_t setAuxEffectSendLevel(float level)
268 {
269 Parcel data, reply;
270 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
271 data.writeFloat(level);
272 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
273 return reply.readInt32();
274 }
275
276 status_t attachAuxEffect(int effectId)
277 {
278 Parcel data, reply;
279 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
280 data.writeInt32(effectId);
281 remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
282 return reply.readInt32();
283 }
Glenn Kasten11731182011-02-08 17:26:17 -0800284
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700285 status_t setParameter(int key, const Parcel& request)
286 {
287 Parcel data, reply;
288 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
289 data.writeInt32(key);
290 if (request.dataSize() > 0) {
291 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
292 }
293 remote()->transact(SET_PARAMETER, data, &reply);
294 return reply.readInt32();
295 }
296
297 status_t getParameter(int key, Parcel *reply)
298 {
299 Parcel data;
300 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
301 data.writeInt32(key);
302 return remote()->transact(GET_PARAMETER, data, reply);
303 }
304
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800305};
306
niko56f0cc52009-06-22 08:49:52 -0700307IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800308
309// ----------------------------------------------------------------------
310
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800311status_t BnMediaPlayer::onTransact(
312 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
313{
314 switch(code) {
315 case DISCONNECT: {
316 CHECK_INTERFACE(IMediaPlayer, data, reply);
317 disconnect();
318 return NO_ERROR;
319 } break;
Dave Burked681bbb2011-08-30 14:39:17 +0100320 case SET_DATA_SOURCE_URL: {
321 CHECK_INTERFACE(IMediaPlayer, data, reply);
322 const char* url = data.readCString();
323 KeyedVector<String8, String8> headers;
324 int32_t numHeaders = data.readInt32();
325 for (int i = 0; i < numHeaders; ++i) {
326 String8 key = data.readString8();
327 String8 value = data.readString8();
328 headers.add(key, value);
329 }
330 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
331 return NO_ERROR;
332 } break;
333 case SET_DATA_SOURCE_FD: {
334 CHECK_INTERFACE(IMediaPlayer, data, reply);
335 int fd = data.readFileDescriptor();
336 int64_t offset = data.readInt64();
337 int64_t length = data.readInt64();
338 reply->writeInt32(setDataSource(fd, offset, length));
339 return NO_ERROR;
340 }
341 case SET_DATA_SOURCE_STREAM: {
342 CHECK_INTERFACE(IMediaPlayer, data, reply);
343 sp<IStreamSource> source =
344 interface_cast<IStreamSource>(data.readStrongBinder());
345 reply->writeInt32(setDataSource(source));
346 return NO_ERROR;
347 }
Andreas Huber5daeb122010-08-16 08:49:37 -0700348 case SET_VIDEO_SURFACE: {
349 CHECK_INTERFACE(IMediaPlayer, data, reply);
350 sp<Surface> surface = Surface::readFromParcel(data);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800351 reply->writeInt32(setVideoSurface(surface));
352 return NO_ERROR;
353 } break;
Glenn Kasten11731182011-02-08 17:26:17 -0800354 case SET_VIDEO_SURFACETEXTURE: {
355 CHECK_INTERFACE(IMediaPlayer, data, reply);
356 sp<ISurfaceTexture> surfaceTexture =
357 interface_cast<ISurfaceTexture>(data.readStrongBinder());
358 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
359 return NO_ERROR;
360 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800361 case PREPARE_ASYNC: {
362 CHECK_INTERFACE(IMediaPlayer, data, reply);
363 reply->writeInt32(prepareAsync());
364 return NO_ERROR;
365 } break;
366 case START: {
367 CHECK_INTERFACE(IMediaPlayer, data, reply);
368 reply->writeInt32(start());
369 return NO_ERROR;
370 } break;
371 case STOP: {
372 CHECK_INTERFACE(IMediaPlayer, data, reply);
373 reply->writeInt32(stop());
374 return NO_ERROR;
375 } break;
376 case IS_PLAYING: {
377 CHECK_INTERFACE(IMediaPlayer, data, reply);
378 bool state;
379 status_t ret = isPlaying(&state);
380 reply->writeInt32(state);
381 reply->writeInt32(ret);
382 return NO_ERROR;
383 } break;
384 case PAUSE: {
385 CHECK_INTERFACE(IMediaPlayer, data, reply);
386 reply->writeInt32(pause());
387 return NO_ERROR;
388 } break;
389 case SEEK_TO: {
390 CHECK_INTERFACE(IMediaPlayer, data, reply);
391 reply->writeInt32(seekTo(data.readInt32()));
392 return NO_ERROR;
393 } break;
394 case GET_CURRENT_POSITION: {
395 CHECK_INTERFACE(IMediaPlayer, data, reply);
396 int msec;
397 status_t ret = getCurrentPosition(&msec);
398 reply->writeInt32(msec);
399 reply->writeInt32(ret);
400 return NO_ERROR;
401 } break;
402 case GET_DURATION: {
403 CHECK_INTERFACE(IMediaPlayer, data, reply);
404 int msec;
405 status_t ret = getDuration(&msec);
406 reply->writeInt32(msec);
407 reply->writeInt32(ret);
408 return NO_ERROR;
409 } break;
410 case RESET: {
411 CHECK_INTERFACE(IMediaPlayer, data, reply);
412 reply->writeInt32(reset());
413 return NO_ERROR;
414 } break;
415 case SET_AUDIO_STREAM_TYPE: {
416 CHECK_INTERFACE(IMediaPlayer, data, reply);
417 reply->writeInt32(setAudioStreamType(data.readInt32()));
418 return NO_ERROR;
419 } break;
420 case SET_LOOPING: {
421 CHECK_INTERFACE(IMediaPlayer, data, reply);
422 reply->writeInt32(setLooping(data.readInt32()));
423 return NO_ERROR;
424 } break;
425 case SET_VOLUME: {
Dave Sparks172fb9a2009-05-26 14:39:29 -0700426 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700427 float leftVolume = data.readFloat();
428 float rightVolume = data.readFloat();
429 reply->writeInt32(setVolume(leftVolume, rightVolume));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800430 return NO_ERROR;
431 } break;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700432 case INVOKE: {
433 CHECK_INTERFACE(IMediaPlayer, data, reply);
James Dong040e4a12011-04-06 18:29:01 -0700434 status_t result = invoke(data, reply);
435 return result;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700436 } break;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700437 case SET_METADATA_FILTER: {
438 CHECK_INTERFACE(IMediaPlayer, data, reply);
439 reply->writeInt32(setMetadataFilter(data));
440 return NO_ERROR;
441 } break;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700442 case GET_METADATA: {
443 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700444 bool update_only = static_cast<bool>(data.readInt32());
445 bool apply_filter = static_cast<bool>(data.readInt32());
446 const status_t retcode = getMetadata(update_only, apply_filter, reply);
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700447 reply->setDataPosition(0);
448 reply->writeInt32(retcode);
449 reply->setDataPosition(0);
450 return NO_ERROR;
451 } break;
Eric Laurent2beeb502010-07-16 07:43:46 -0700452 case SET_AUX_EFFECT_SEND_LEVEL: {
453 CHECK_INTERFACE(IMediaPlayer, data, reply);
454 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
455 return NO_ERROR;
456 } break;
457 case ATTACH_AUX_EFFECT: {
458 CHECK_INTERFACE(IMediaPlayer, data, reply);
459 reply->writeInt32(attachAuxEffect(data.readInt32()));
460 return NO_ERROR;
461 } break;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700462 case SET_PARAMETER: {
463 CHECK_INTERFACE(IMediaPlayer, data, reply);
464 int key = data.readInt32();
465
466 Parcel request;
467 if (data.dataAvail() > 0) {
468 request.appendFrom(
469 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
470 }
471 request.setDataPosition(0);
472 reply->writeInt32(setParameter(key, request));
473 return NO_ERROR;
474 } break;
475 case GET_PARAMETER: {
476 CHECK_INTERFACE(IMediaPlayer, data, reply);
477 return getParameter(data.readInt32(), reply);
478 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800479 default:
480 return BBinder::onTransact(code, data, reply, flags);
481 }
482}
483
484// ----------------------------------------------------------------------------
485
486}; // namespace android