IMediaPlayer.cpp revision 8d65510a2e9ff7b64f2f35bfe3cd745a717c9533
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 <media/IStreamSource.h> 25 26#include <surfaceflinger/ISurface.h> 27#include <surfaceflinger/Surface.h> 28#include <gui/ISurfaceTexture.h> 29#include <utils/String8.h> 30 31namespace android { 32 33enum { 34 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 35 SET_DATA_SOURCE_URL, 36 SET_DATA_SOURCE_FD, 37 SET_DATA_SOURCE_STREAM, 38 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, 50 SET_VOLUME, 51 INVOKE, 52 SET_METADATA_FILTER, 53 GET_METADATA, 54 SET_AUX_EFFECT_SEND_LEVEL, 55 ATTACH_AUX_EFFECT, 56 SET_VIDEO_SURFACETEXTURE, 57 SET_PARAMETER, 58 GET_PARAMETER, 59}; 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 77 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()); 111 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); 112 return reply.readInt32(); 113 } 114 115 // pass the buffered Surface to the media player service 116 status_t setVideoSurface(const sp<Surface>& surface) 117 { 118 Parcel data, reply; 119 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 120 Surface::writeToParcel(surface, &data); 121 remote()->transact(SET_VIDEO_SURFACE, data, &reply); 122 return reply.readInt32(); 123 } 124 125 // 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 136 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; 233 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 234 data.writeFloat(leftVolume); 235 data.writeFloat(rightVolume); 236 remote()->transact(SET_VOLUME, data, &reply); 237 return reply.readInt32(); 238 } 239 240 status_t invoke(const Parcel& request, Parcel *reply) 241 { 242 // Avoid doing any extra copy. The interface descriptor should 243 // have been set by MediaPlayer.java. 244 return remote()->transact(INVOKE, request, reply); 245 } 246 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 } 255 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 } 266 267 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 } 284 285 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 305}; 306 307IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 308 309// ---------------------------------------------------------------------- 310 311status_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; 320 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 } 348 case SET_VIDEO_SURFACE: { 349 CHECK_INTERFACE(IMediaPlayer, data, reply); 350 sp<Surface> surface = Surface::readFromParcel(data); 351 reply->writeInt32(setVideoSurface(surface)); 352 return NO_ERROR; 353 } break; 354 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; 361 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: { 426 CHECK_INTERFACE(IMediaPlayer, data, reply); 427 float leftVolume = data.readFloat(); 428 float rightVolume = data.readFloat(); 429 reply->writeInt32(setVolume(leftVolume, rightVolume)); 430 return NO_ERROR; 431 } break; 432 case INVOKE: { 433 CHECK_INTERFACE(IMediaPlayer, data, reply); 434 status_t result = invoke(data, reply); 435 return result; 436 } break; 437 case SET_METADATA_FILTER: { 438 CHECK_INTERFACE(IMediaPlayer, data, reply); 439 reply->writeInt32(setMetadataFilter(data)); 440 return NO_ERROR; 441 } break; 442 case GET_METADATA: { 443 CHECK_INTERFACE(IMediaPlayer, data, reply); 444 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); 447 reply->setDataPosition(0); 448 reply->writeInt32(retcode); 449 reply->setDataPosition(0); 450 return NO_ERROR; 451 } break; 452 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; 462 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; 479 default: 480 return BBinder::onTransact(code, data, reply, flags); 481 } 482} 483 484// ---------------------------------------------------------------------------- 485 486}; // namespace android 487