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: 55 BpMediaPlayer(const sp<IBinder>& impl) 56 : BpInterface<IMediaPlayer>(impl) 57 { 58 } 59 60 // disconnect from media player service 61 void disconnect() 62 { 63 Parcel data, reply; 64 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 65 remote()->transact(DISCONNECT, data, &reply); 66 } 67 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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