blob: 86d65db5ddc10120f293ece0859897578e2643ae [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
Glenn Kasten11731182011-02-08 17:26:17 -080026#include <gui/ISurfaceTexture.h>
Dave Burked681bbb2011-08-30 14:39:17 +010027#include <utils/String8.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080028
29namespace android {
30
31enum {
32 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
Dave Burked681bbb2011-08-30 14:39:17 +010033 SET_DATA_SOURCE_URL,
34 SET_DATA_SOURCE_FD,
35 SET_DATA_SOURCE_STREAM,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080036 PREPARE_ASYNC,
37 START,
38 STOP,
39 IS_PLAYING,
40 PAUSE,
41 SEEK_TO,
42 GET_CURRENT_POSITION,
43 GET_DURATION,
44 RESET,
45 SET_AUDIO_STREAM_TYPE,
46 SET_LOOPING,
Nicolas Catania1d187f12009-05-12 23:25:55 -070047 SET_VOLUME,
48 INVOKE,
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -070049 SET_METADATA_FILTER,
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -070050 GET_METADATA,
Eric Laurent2beeb502010-07-16 07:43:46 -070051 SET_AUX_EFFECT_SEND_LEVEL,
Glenn Kasten11731182011-02-08 17:26:17 -080052 ATTACH_AUX_EFFECT,
53 SET_VIDEO_SURFACETEXTURE,
Gloria Wang4f9e47f2011-04-25 17:28:22 -070054 SET_PARAMETER,
55 GET_PARAMETER,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080056};
57
58class BpMediaPlayer: public BpInterface<IMediaPlayer>
59{
60public:
61 BpMediaPlayer(const sp<IBinder>& impl)
62 : BpInterface<IMediaPlayer>(impl)
63 {
64 }
65
66 // disconnect from media player service
67 void disconnect()
68 {
69 Parcel data, reply;
70 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
71 remote()->transact(DISCONNECT, data, &reply);
72 }
73
Dave Burked681bbb2011-08-30 14:39:17 +010074 status_t setDataSource(const char* url,
75 const KeyedVector<String8, String8>* headers)
76 {
77 Parcel data, reply;
78 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
79 data.writeCString(url);
80 if (headers == NULL) {
81 data.writeInt32(0);
82 } else {
83 // serialize the headers
84 data.writeInt32(headers->size());
85 for (size_t i = 0; i < headers->size(); ++i) {
86 data.writeString8(headers->keyAt(i));
87 data.writeString8(headers->valueAt(i));
88 }
89 }
90 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
91 return reply.readInt32();
92 }
93
94 status_t setDataSource(int fd, int64_t offset, int64_t length) {
95 Parcel data, reply;
96 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
97 data.writeFileDescriptor(fd);
98 data.writeInt64(offset);
99 data.writeInt64(length);
100 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
101 return reply.readInt32();
102 }
103
104 status_t setDataSource(const sp<IStreamSource> &source) {
105 Parcel data, reply;
106 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
107 data.writeStrongBinder(source->asBinder());
Glenn Kasten8d655102011-09-07 14:40:23 -0700108 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
Dave Burked681bbb2011-08-30 14:39:17 +0100109 return reply.readInt32();
110 }
111
Glenn Kasten11731182011-02-08 17:26:17 -0800112 // pass the buffered ISurfaceTexture to the media player service
113 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
114 {
115 Parcel data, reply;
116 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
117 sp<IBinder> b(surfaceTexture->asBinder());
118 data.writeStrongBinder(b);
119 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
120 return reply.readInt32();
121 }
122
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800123 status_t prepareAsync()
124 {
125 Parcel data, reply;
126 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
127 remote()->transact(PREPARE_ASYNC, data, &reply);
128 return reply.readInt32();
129 }
130
131 status_t start()
132 {
133 Parcel data, reply;
134 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
135 remote()->transact(START, data, &reply);
136 return reply.readInt32();
137 }
138
139 status_t stop()
140 {
141 Parcel data, reply;
142 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
143 remote()->transact(STOP, data, &reply);
144 return reply.readInt32();
145 }
146
147 status_t isPlaying(bool* state)
148 {
149 Parcel data, reply;
150 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
151 remote()->transact(IS_PLAYING, data, &reply);
152 *state = reply.readInt32();
153 return reply.readInt32();
154 }
155
156 status_t pause()
157 {
158 Parcel data, reply;
159 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
160 remote()->transact(PAUSE, data, &reply);
161 return reply.readInt32();
162 }
163
164 status_t seekTo(int msec)
165 {
166 Parcel data, reply;
167 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
168 data.writeInt32(msec);
169 remote()->transact(SEEK_TO, data, &reply);
170 return reply.readInt32();
171 }
172
173 status_t getCurrentPosition(int* msec)
174 {
175 Parcel data, reply;
176 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
177 remote()->transact(GET_CURRENT_POSITION, data, &reply);
178 *msec = reply.readInt32();
179 return reply.readInt32();
180 }
181
182 status_t getDuration(int* msec)
183 {
184 Parcel data, reply;
185 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
186 remote()->transact(GET_DURATION, data, &reply);
187 *msec = reply.readInt32();
188 return reply.readInt32();
189 }
190
191 status_t reset()
192 {
193 Parcel data, reply;
194 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
195 remote()->transact(RESET, data, &reply);
196 return reply.readInt32();
197 }
198
Glenn Kastenfff6d712012-01-12 16:38:12 -0800199 status_t setAudioStreamType(audio_stream_type_t stream)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800200 {
201 Parcel data, reply;
202 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
Glenn Kastenfff6d712012-01-12 16:38:12 -0800203 data.writeInt32((int32_t) stream);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800204 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
205 return reply.readInt32();
206 }
207
208 status_t setLooping(int loop)
209 {
210 Parcel data, reply;
211 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
212 data.writeInt32(loop);
213 remote()->transact(SET_LOOPING, data, &reply);
214 return reply.readInt32();
215 }
216
217 status_t setVolume(float leftVolume, float rightVolume)
218 {
219 Parcel data, reply;
Dave Sparks172fb9a2009-05-26 14:39:29 -0700220 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800221 data.writeFloat(leftVolume);
222 data.writeFloat(rightVolume);
223 remote()->transact(SET_VOLUME, data, &reply);
224 return reply.readInt32();
225 }
Nicolas Catania1d187f12009-05-12 23:25:55 -0700226
227 status_t invoke(const Parcel& request, Parcel *reply)
James Dong040e4a12011-04-06 18:29:01 -0700228 {
229 // Avoid doing any extra copy. The interface descriptor should
230 // have been set by MediaPlayer.java.
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700231 return remote()->transact(INVOKE, request, reply);
Nicolas Catania1d187f12009-05-12 23:25:55 -0700232 }
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700233
234 status_t setMetadataFilter(const Parcel& request)
235 {
236 Parcel reply;
237 // Avoid doing any extra copy of the request. The interface
238 // descriptor should have been set by MediaPlayer.java.
239 remote()->transact(SET_METADATA_FILTER, request, &reply);
240 return reply.readInt32();
241 }
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700242
243 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
244 {
245 Parcel request;
246 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
247 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
248 request.writeInt32(update_only);
249 request.writeInt32(apply_filter);
250 remote()->transact(GET_METADATA, request, reply);
251 return reply->readInt32();
252 }
Andreas Huber4e92c7e2010-02-12 12:35:58 -0800253
Eric Laurent2beeb502010-07-16 07:43:46 -0700254 status_t setAuxEffectSendLevel(float level)
255 {
256 Parcel data, reply;
257 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
258 data.writeFloat(level);
259 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
260 return reply.readInt32();
261 }
262
263 status_t attachAuxEffect(int effectId)
264 {
265 Parcel data, reply;
266 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
267 data.writeInt32(effectId);
268 remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
269 return reply.readInt32();
270 }
Glenn Kasten11731182011-02-08 17:26:17 -0800271
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700272 status_t setParameter(int key, const Parcel& request)
273 {
274 Parcel data, reply;
275 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
276 data.writeInt32(key);
277 if (request.dataSize() > 0) {
278 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
279 }
280 remote()->transact(SET_PARAMETER, data, &reply);
281 return reply.readInt32();
282 }
283
284 status_t getParameter(int key, Parcel *reply)
285 {
286 Parcel data;
287 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
288 data.writeInt32(key);
289 return remote()->transact(GET_PARAMETER, data, reply);
290 }
291
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800292};
293
niko56f0cc52009-06-22 08:49:52 -0700294IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800295
296// ----------------------------------------------------------------------
297
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800298status_t BnMediaPlayer::onTransact(
299 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
300{
301 switch(code) {
302 case DISCONNECT: {
303 CHECK_INTERFACE(IMediaPlayer, data, reply);
304 disconnect();
305 return NO_ERROR;
306 } break;
Dave Burked681bbb2011-08-30 14:39:17 +0100307 case SET_DATA_SOURCE_URL: {
308 CHECK_INTERFACE(IMediaPlayer, data, reply);
309 const char* url = data.readCString();
310 KeyedVector<String8, String8> headers;
311 int32_t numHeaders = data.readInt32();
312 for (int i = 0; i < numHeaders; ++i) {
313 String8 key = data.readString8();
314 String8 value = data.readString8();
315 headers.add(key, value);
316 }
317 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
318 return NO_ERROR;
319 } break;
320 case SET_DATA_SOURCE_FD: {
321 CHECK_INTERFACE(IMediaPlayer, data, reply);
322 int fd = data.readFileDescriptor();
323 int64_t offset = data.readInt64();
324 int64_t length = data.readInt64();
325 reply->writeInt32(setDataSource(fd, offset, length));
326 return NO_ERROR;
327 }
328 case SET_DATA_SOURCE_STREAM: {
329 CHECK_INTERFACE(IMediaPlayer, data, reply);
330 sp<IStreamSource> source =
331 interface_cast<IStreamSource>(data.readStrongBinder());
332 reply->writeInt32(setDataSource(source));
333 return NO_ERROR;
334 }
Glenn Kasten11731182011-02-08 17:26:17 -0800335 case SET_VIDEO_SURFACETEXTURE: {
336 CHECK_INTERFACE(IMediaPlayer, data, reply);
337 sp<ISurfaceTexture> surfaceTexture =
338 interface_cast<ISurfaceTexture>(data.readStrongBinder());
339 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
340 return NO_ERROR;
341 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800342 case PREPARE_ASYNC: {
343 CHECK_INTERFACE(IMediaPlayer, data, reply);
344 reply->writeInt32(prepareAsync());
345 return NO_ERROR;
346 } break;
347 case START: {
348 CHECK_INTERFACE(IMediaPlayer, data, reply);
349 reply->writeInt32(start());
350 return NO_ERROR;
351 } break;
352 case STOP: {
353 CHECK_INTERFACE(IMediaPlayer, data, reply);
354 reply->writeInt32(stop());
355 return NO_ERROR;
356 } break;
357 case IS_PLAYING: {
358 CHECK_INTERFACE(IMediaPlayer, data, reply);
359 bool state;
360 status_t ret = isPlaying(&state);
361 reply->writeInt32(state);
362 reply->writeInt32(ret);
363 return NO_ERROR;
364 } break;
365 case PAUSE: {
366 CHECK_INTERFACE(IMediaPlayer, data, reply);
367 reply->writeInt32(pause());
368 return NO_ERROR;
369 } break;
370 case SEEK_TO: {
371 CHECK_INTERFACE(IMediaPlayer, data, reply);
372 reply->writeInt32(seekTo(data.readInt32()));
373 return NO_ERROR;
374 } break;
375 case GET_CURRENT_POSITION: {
376 CHECK_INTERFACE(IMediaPlayer, data, reply);
377 int msec;
378 status_t ret = getCurrentPosition(&msec);
379 reply->writeInt32(msec);
380 reply->writeInt32(ret);
381 return NO_ERROR;
382 } break;
383 case GET_DURATION: {
384 CHECK_INTERFACE(IMediaPlayer, data, reply);
385 int msec;
386 status_t ret = getDuration(&msec);
387 reply->writeInt32(msec);
388 reply->writeInt32(ret);
389 return NO_ERROR;
390 } break;
391 case RESET: {
392 CHECK_INTERFACE(IMediaPlayer, data, reply);
393 reply->writeInt32(reset());
394 return NO_ERROR;
395 } break;
396 case SET_AUDIO_STREAM_TYPE: {
397 CHECK_INTERFACE(IMediaPlayer, data, reply);
Glenn Kastenfff6d712012-01-12 16:38:12 -0800398 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800399 return NO_ERROR;
400 } break;
401 case SET_LOOPING: {
402 CHECK_INTERFACE(IMediaPlayer, data, reply);
403 reply->writeInt32(setLooping(data.readInt32()));
404 return NO_ERROR;
405 } break;
406 case SET_VOLUME: {
Dave Sparks172fb9a2009-05-26 14:39:29 -0700407 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700408 float leftVolume = data.readFloat();
409 float rightVolume = data.readFloat();
410 reply->writeInt32(setVolume(leftVolume, rightVolume));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800411 return NO_ERROR;
412 } break;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700413 case INVOKE: {
414 CHECK_INTERFACE(IMediaPlayer, data, reply);
James Dong040e4a12011-04-06 18:29:01 -0700415 status_t result = invoke(data, reply);
416 return result;
Nicolas Catania1d187f12009-05-12 23:25:55 -0700417 } break;
Nicolas Cataniaa7e0e8b2009-07-08 08:57:42 -0700418 case SET_METADATA_FILTER: {
419 CHECK_INTERFACE(IMediaPlayer, data, reply);
420 reply->writeInt32(setMetadataFilter(data));
421 return NO_ERROR;
422 } break;
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700423 case GET_METADATA: {
424 CHECK_INTERFACE(IMediaPlayer, data, reply);
Gloria Wangde162ff2011-08-01 14:01:29 -0700425 bool update_only = static_cast<bool>(data.readInt32());
426 bool apply_filter = static_cast<bool>(data.readInt32());
427 const status_t retcode = getMetadata(update_only, apply_filter, reply);
Nicolas Catania8e1b6cc2009-07-09 09:21:33 -0700428 reply->setDataPosition(0);
429 reply->writeInt32(retcode);
430 reply->setDataPosition(0);
431 return NO_ERROR;
432 } break;
Eric Laurent2beeb502010-07-16 07:43:46 -0700433 case SET_AUX_EFFECT_SEND_LEVEL: {
434 CHECK_INTERFACE(IMediaPlayer, data, reply);
435 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
436 return NO_ERROR;
437 } break;
438 case ATTACH_AUX_EFFECT: {
439 CHECK_INTERFACE(IMediaPlayer, data, reply);
440 reply->writeInt32(attachAuxEffect(data.readInt32()));
441 return NO_ERROR;
442 } break;
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700443 case SET_PARAMETER: {
444 CHECK_INTERFACE(IMediaPlayer, data, reply);
445 int key = data.readInt32();
446
447 Parcel request;
448 if (data.dataAvail() > 0) {
449 request.appendFrom(
450 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
451 }
452 request.setDataPosition(0);
453 reply->writeInt32(setParameter(key, request));
454 return NO_ERROR;
455 } break;
456 case GET_PARAMETER: {
457 CHECK_INTERFACE(IMediaPlayer, data, reply);
458 return getParameter(data.readInt32(), reply);
459 } break;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800460 default:
461 return BBinder::onTransact(code, data, reply, flags);
462 }
463}
464
465// ----------------------------------------------------------------------------
466
467}; // namespace android