1 /*
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
21 #include <binder/Parcel.h>
22
23 #include <media/IMediaPlayer.h>
24 #include <surfaceflinger/ISurface.h>
25
26 namespace android {
27
28 enum {
29 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
30 SET_VIDEO_SURFACE,
31 PREPARE_ASYNC,
32 START,
33 STOP,
34 IS_PLAYING,
35 PAUSE,
36 SEEK_TO,
37 GET_CURRENT_POSITION,
38 GET_DURATION,
39 RESET,
40 SET_AUDIO_STREAM_TYPE,
41 SET_LOOPING,
42 SET_VOLUME,
43 INVOKE,
44 SET_METADATA_FILTER,
45 GET_METADATA,
46 SUSPEND,
47 RESUME,
48 SET_AUX_EFFECT_SEND_LEVEL,
49 ATTACH_AUX_EFFECT
50 };
51
52 class BpMediaPlayer: public BpInterface<IMediaPlayer>
53 {
54 public:
BpMediaPlayer(const sp<IBinder> & impl)55 BpMediaPlayer(const sp<IBinder>& impl)
56 : BpInterface<IMediaPlayer>(impl)
57 {
58 }
59
60 // disconnect from media player service
disconnect()61 void disconnect()
62 {
63 Parcel data, reply;
64 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
65 remote()->transact(DISCONNECT, data, &reply);
66 }
67
setVideoSurface(const sp<ISurface> & surface)68 status_t setVideoSurface(const sp<ISurface>& surface)
69 {
70 Parcel data, reply;
71 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
72 data.writeStrongBinder(surface->asBinder());
73 remote()->transact(SET_VIDEO_SURFACE, data, &reply);
74 return reply.readInt32();
75 }
76
prepareAsync()77 status_t prepareAsync()
78 {
79 Parcel data, reply;
80 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
81 remote()->transact(PREPARE_ASYNC, data, &reply);
82 return reply.readInt32();
83 }
84
start()85 status_t start()
86 {
87 Parcel data, reply;
88 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
89 remote()->transact(START, data, &reply);
90 return reply.readInt32();
91 }
92
stop()93 status_t stop()
94 {
95 Parcel data, reply;
96 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
97 remote()->transact(STOP, data, &reply);
98 return reply.readInt32();
99 }
100
isPlaying(bool * state)101 status_t isPlaying(bool* state)
102 {
103 Parcel data, reply;
104 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
105 remote()->transact(IS_PLAYING, data, &reply);
106 *state = reply.readInt32();
107 return reply.readInt32();
108 }
109
pause()110 status_t pause()
111 {
112 Parcel data, reply;
113 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
114 remote()->transact(PAUSE, data, &reply);
115 return reply.readInt32();
116 }
117
seekTo(int msec)118 status_t seekTo(int msec)
119 {
120 Parcel data, reply;
121 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
122 data.writeInt32(msec);
123 remote()->transact(SEEK_TO, data, &reply);
124 return reply.readInt32();
125 }
126
getCurrentPosition(int * msec)127 status_t getCurrentPosition(int* msec)
128 {
129 Parcel data, reply;
130 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
131 remote()->transact(GET_CURRENT_POSITION, data, &reply);
132 *msec = reply.readInt32();
133 return reply.readInt32();
134 }
135
getDuration(int * msec)136 status_t getDuration(int* msec)
137 {
138 Parcel data, reply;
139 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
140 remote()->transact(GET_DURATION, data, &reply);
141 *msec = reply.readInt32();
142 return reply.readInt32();
143 }
144
reset()145 status_t reset()
146 {
147 Parcel data, reply;
148 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
149 remote()->transact(RESET, data, &reply);
150 return reply.readInt32();
151 }
152
setAudioStreamType(int type)153 status_t setAudioStreamType(int type)
154 {
155 Parcel data, reply;
156 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
157 data.writeInt32(type);
158 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
159 return reply.readInt32();
160 }
161
setLooping(int loop)162 status_t setLooping(int loop)
163 {
164 Parcel data, reply;
165 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
166 data.writeInt32(loop);
167 remote()->transact(SET_LOOPING, data, &reply);
168 return reply.readInt32();
169 }
170
setVolume(float leftVolume,float rightVolume)171 status_t setVolume(float leftVolume, float rightVolume)
172 {
173 Parcel data, reply;
174 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
175 data.writeFloat(leftVolume);
176 data.writeFloat(rightVolume);
177 remote()->transact(SET_VOLUME, data, &reply);
178 return reply.readInt32();
179 }
180
invoke(const Parcel & request,Parcel * reply)181 status_t invoke(const Parcel& request, Parcel *reply)
182 { // Avoid doing any extra copy. The interface descriptor should
183 // have been set by MediaPlayer.java.
184 return remote()->transact(INVOKE, request, reply);
185 }
186
setMetadataFilter(const Parcel & request)187 status_t setMetadataFilter(const Parcel& request)
188 {
189 Parcel reply;
190 // Avoid doing any extra copy of the request. The interface
191 // descriptor should have been set by MediaPlayer.java.
192 remote()->transact(SET_METADATA_FILTER, request, &reply);
193 return reply.readInt32();
194 }
195
getMetadata(bool update_only,bool apply_filter,Parcel * reply)196 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
197 {
198 Parcel request;
199 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
200 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
201 request.writeInt32(update_only);
202 request.writeInt32(apply_filter);
203 remote()->transact(GET_METADATA, request, reply);
204 return reply->readInt32();
205 }
206
suspend()207 status_t suspend() {
208 Parcel request;
209 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
210
211 Parcel reply;
212 remote()->transact(SUSPEND, request, &reply);
213
214 return reply.readInt32();
215 }
216
resume()217 status_t resume() {
218 Parcel request;
219 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
220
221 Parcel reply;
222 remote()->transact(RESUME, request, &reply);
223
224 return reply.readInt32();
225 }
226
setAuxEffectSendLevel(float level)227 status_t setAuxEffectSendLevel(float level)
228 {
229 Parcel data, reply;
230 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
231 data.writeFloat(level);
232 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
233 return reply.readInt32();
234 }
235
attachAuxEffect(int effectId)236 status_t attachAuxEffect(int effectId)
237 {
238 Parcel data, reply;
239 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
240 data.writeInt32(effectId);
241 remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
242 return reply.readInt32();
243 }
244 };
245
246 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
247
248 // ----------------------------------------------------------------------
249
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)250 status_t BnMediaPlayer::onTransact(
251 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
252 {
253 switch(code) {
254 case DISCONNECT: {
255 CHECK_INTERFACE(IMediaPlayer, data, reply);
256 disconnect();
257 return NO_ERROR;
258 } break;
259 case SET_VIDEO_SURFACE: {
260 CHECK_INTERFACE(IMediaPlayer, data, reply);
261 sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
262 reply->writeInt32(setVideoSurface(surface));
263 return NO_ERROR;
264 } break;
265 case PREPARE_ASYNC: {
266 CHECK_INTERFACE(IMediaPlayer, data, reply);
267 reply->writeInt32(prepareAsync());
268 return NO_ERROR;
269 } break;
270 case START: {
271 CHECK_INTERFACE(IMediaPlayer, data, reply);
272 reply->writeInt32(start());
273 return NO_ERROR;
274 } break;
275 case STOP: {
276 CHECK_INTERFACE(IMediaPlayer, data, reply);
277 reply->writeInt32(stop());
278 return NO_ERROR;
279 } break;
280 case IS_PLAYING: {
281 CHECK_INTERFACE(IMediaPlayer, data, reply);
282 bool state;
283 status_t ret = isPlaying(&state);
284 reply->writeInt32(state);
285 reply->writeInt32(ret);
286 return NO_ERROR;
287 } break;
288 case PAUSE: {
289 CHECK_INTERFACE(IMediaPlayer, data, reply);
290 reply->writeInt32(pause());
291 return NO_ERROR;
292 } break;
293 case SEEK_TO: {
294 CHECK_INTERFACE(IMediaPlayer, data, reply);
295 reply->writeInt32(seekTo(data.readInt32()));
296 return NO_ERROR;
297 } break;
298 case GET_CURRENT_POSITION: {
299 CHECK_INTERFACE(IMediaPlayer, data, reply);
300 int msec;
301 status_t ret = getCurrentPosition(&msec);
302 reply->writeInt32(msec);
303 reply->writeInt32(ret);
304 return NO_ERROR;
305 } break;
306 case GET_DURATION: {
307 CHECK_INTERFACE(IMediaPlayer, data, reply);
308 int msec;
309 status_t ret = getDuration(&msec);
310 reply->writeInt32(msec);
311 reply->writeInt32(ret);
312 return NO_ERROR;
313 } break;
314 case RESET: {
315 CHECK_INTERFACE(IMediaPlayer, data, reply);
316 reply->writeInt32(reset());
317 return NO_ERROR;
318 } break;
319 case SET_AUDIO_STREAM_TYPE: {
320 CHECK_INTERFACE(IMediaPlayer, data, reply);
321 reply->writeInt32(setAudioStreamType(data.readInt32()));
322 return NO_ERROR;
323 } break;
324 case SET_LOOPING: {
325 CHECK_INTERFACE(IMediaPlayer, data, reply);
326 reply->writeInt32(setLooping(data.readInt32()));
327 return NO_ERROR;
328 } break;
329 case SET_VOLUME: {
330 CHECK_INTERFACE(IMediaPlayer, data, reply);
331 reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
332 return NO_ERROR;
333 } break;
334 case INVOKE: {
335 CHECK_INTERFACE(IMediaPlayer, data, reply);
336 invoke(data, reply);
337 return NO_ERROR;
338 } break;
339 case SET_METADATA_FILTER: {
340 CHECK_INTERFACE(IMediaPlayer, data, reply);
341 reply->writeInt32(setMetadataFilter(data));
342 return NO_ERROR;
343 } break;
344 case SUSPEND: {
345 CHECK_INTERFACE(IMediaPlayer, data, reply);
346 reply->writeInt32(suspend());
347 return NO_ERROR;
348 } break;
349 case RESUME: {
350 CHECK_INTERFACE(IMediaPlayer, data, reply);
351 reply->writeInt32(resume());
352 return NO_ERROR;
353 } break;
354 case GET_METADATA: {
355 CHECK_INTERFACE(IMediaPlayer, data, reply);
356 const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
357 reply->setDataPosition(0);
358 reply->writeInt32(retcode);
359 reply->setDataPosition(0);
360 return NO_ERROR;
361 } break;
362 case SET_AUX_EFFECT_SEND_LEVEL: {
363 CHECK_INTERFACE(IMediaPlayer, data, reply);
364 reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
365 return NO_ERROR;
366 } break;
367 case ATTACH_AUX_EFFECT: {
368 CHECK_INTERFACE(IMediaPlayer, data, reply);
369 reply->writeInt32(attachAuxEffect(data.readInt32()));
370 return NO_ERROR;
371 } break;
372 default:
373 return BBinder::onTransact(code, data, reply, flags);
374 }
375 }
376
377 // ----------------------------------------------------------------------------
378
379 }; // namespace android
380