IMediaPlayer.cpp revision d681bbb1767bed09415e050ba78975df214bcd68
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 return reply.readInt32(); 112 } 113 114 // pass the buffered Surface to the media player service 115 status_t setVideoSurface(const sp<Surface>& surface) 116 { 117 Parcel data, reply; 118 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 119 Surface::writeToParcel(surface, &data); 120 remote()->transact(SET_VIDEO_SURFACE, data, &reply); 121 return reply.readInt32(); 122 } 123 124 // pass the buffered ISurfaceTexture to the media player service 125 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) 126 { 127 Parcel data, reply; 128 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 129 sp<IBinder> b(surfaceTexture->asBinder()); 130 data.writeStrongBinder(b); 131 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); 132 return reply.readInt32(); 133 } 134 135 status_t prepareAsync() 136 { 137 Parcel data, reply; 138 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 139 remote()->transact(PREPARE_ASYNC, data, &reply); 140 return reply.readInt32(); 141 } 142 143 status_t start() 144 { 145 Parcel data, reply; 146 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 147 remote()->transact(START, data, &reply); 148 return reply.readInt32(); 149 } 150 151 status_t stop() 152 { 153 Parcel data, reply; 154 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 155 remote()->transact(STOP, data, &reply); 156 return reply.readInt32(); 157 } 158 159 status_t isPlaying(bool* state) 160 { 161 Parcel data, reply; 162 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 163 remote()->transact(IS_PLAYING, data, &reply); 164 *state = reply.readInt32(); 165 return reply.readInt32(); 166 } 167 168 status_t pause() 169 { 170 Parcel data, reply; 171 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 172 remote()->transact(PAUSE, data, &reply); 173 return reply.readInt32(); 174 } 175 176 status_t seekTo(int msec) 177 { 178 Parcel data, reply; 179 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 180 data.writeInt32(msec); 181 remote()->transact(SEEK_TO, data, &reply); 182 return reply.readInt32(); 183 } 184 185 status_t getCurrentPosition(int* msec) 186 { 187 Parcel data, reply; 188 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 189 remote()->transact(GET_CURRENT_POSITION, data, &reply); 190 *msec = reply.readInt32(); 191 return reply.readInt32(); 192 } 193 194 status_t getDuration(int* msec) 195 { 196 Parcel data, reply; 197 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 198 remote()->transact(GET_DURATION, data, &reply); 199 *msec = reply.readInt32(); 200 return reply.readInt32(); 201 } 202 203 status_t reset() 204 { 205 Parcel data, reply; 206 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 207 remote()->transact(RESET, data, &reply); 208 return reply.readInt32(); 209 } 210 211 status_t setAudioStreamType(int type) 212 { 213 Parcel data, reply; 214 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 215 data.writeInt32(type); 216 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 217 return reply.readInt32(); 218 } 219 220 status_t setLooping(int loop) 221 { 222 Parcel data, reply; 223 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 224 data.writeInt32(loop); 225 remote()->transact(SET_LOOPING, data, &reply); 226 return reply.readInt32(); 227 } 228 229 status_t setVolume(float leftVolume, float rightVolume) 230 { 231 Parcel data, reply; 232 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 233 data.writeFloat(leftVolume); 234 data.writeFloat(rightVolume); 235 remote()->transact(SET_VOLUME, data, &reply); 236 return reply.readInt32(); 237 } 238 239 status_t invoke(const Parcel& request, Parcel *reply) 240 { 241 // Avoid doing any extra copy. The interface descriptor should 242 // have been set by MediaPlayer.java. 243 return remote()->transact(INVOKE, request, reply); 244 } 245 246 status_t setMetadataFilter(const Parcel& request) 247 { 248 Parcel reply; 249 // Avoid doing any extra copy of the request. The interface 250 // descriptor should have been set by MediaPlayer.java. 251 remote()->transact(SET_METADATA_FILTER, request, &reply); 252 return reply.readInt32(); 253 } 254 255 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 256 { 257 Parcel request; 258 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 259 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 260 request.writeInt32(update_only); 261 request.writeInt32(apply_filter); 262 remote()->transact(GET_METADATA, request, reply); 263 return reply->readInt32(); 264 } 265 266 status_t setAuxEffectSendLevel(float level) 267 { 268 Parcel data, reply; 269 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 270 data.writeFloat(level); 271 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 272 return reply.readInt32(); 273 } 274 275 status_t attachAuxEffect(int effectId) 276 { 277 Parcel data, reply; 278 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 279 data.writeInt32(effectId); 280 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 281 return reply.readInt32(); 282 } 283 284 status_t setParameter(int key, const Parcel& request) 285 { 286 Parcel data, reply; 287 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 288 data.writeInt32(key); 289 if (request.dataSize() > 0) { 290 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize()); 291 } 292 remote()->transact(SET_PARAMETER, data, &reply); 293 return reply.readInt32(); 294 } 295 296 status_t getParameter(int key, Parcel *reply) 297 { 298 Parcel data; 299 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 300 data.writeInt32(key); 301 return remote()->transact(GET_PARAMETER, data, reply); 302 } 303 304}; 305 306IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 307 308// ---------------------------------------------------------------------- 309 310status_t BnMediaPlayer::onTransact( 311 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 312{ 313 switch(code) { 314 case DISCONNECT: { 315 CHECK_INTERFACE(IMediaPlayer, data, reply); 316 disconnect(); 317 return NO_ERROR; 318 } break; 319 case SET_DATA_SOURCE_URL: { 320 CHECK_INTERFACE(IMediaPlayer, data, reply); 321 const char* url = data.readCString(); 322 KeyedVector<String8, String8> headers; 323 int32_t numHeaders = data.readInt32(); 324 for (int i = 0; i < numHeaders; ++i) { 325 String8 key = data.readString8(); 326 String8 value = data.readString8(); 327 headers.add(key, value); 328 } 329 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL)); 330 return NO_ERROR; 331 } break; 332 case SET_DATA_SOURCE_FD: { 333 CHECK_INTERFACE(IMediaPlayer, data, reply); 334 int fd = data.readFileDescriptor(); 335 int64_t offset = data.readInt64(); 336 int64_t length = data.readInt64(); 337 reply->writeInt32(setDataSource(fd, offset, length)); 338 return NO_ERROR; 339 } 340 case SET_DATA_SOURCE_STREAM: { 341 CHECK_INTERFACE(IMediaPlayer, data, reply); 342 sp<IStreamSource> source = 343 interface_cast<IStreamSource>(data.readStrongBinder()); 344 reply->writeInt32(setDataSource(source)); 345 return NO_ERROR; 346 } 347 case SET_VIDEO_SURFACE: { 348 CHECK_INTERFACE(IMediaPlayer, data, reply); 349 sp<Surface> surface = Surface::readFromParcel(data); 350 reply->writeInt32(setVideoSurface(surface)); 351 return NO_ERROR; 352 } break; 353 case SET_VIDEO_SURFACETEXTURE: { 354 CHECK_INTERFACE(IMediaPlayer, data, reply); 355 sp<ISurfaceTexture> surfaceTexture = 356 interface_cast<ISurfaceTexture>(data.readStrongBinder()); 357 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 358 return NO_ERROR; 359 } break; 360 case PREPARE_ASYNC: { 361 CHECK_INTERFACE(IMediaPlayer, data, reply); 362 reply->writeInt32(prepareAsync()); 363 return NO_ERROR; 364 } break; 365 case START: { 366 CHECK_INTERFACE(IMediaPlayer, data, reply); 367 reply->writeInt32(start()); 368 return NO_ERROR; 369 } break; 370 case STOP: { 371 CHECK_INTERFACE(IMediaPlayer, data, reply); 372 reply->writeInt32(stop()); 373 return NO_ERROR; 374 } break; 375 case IS_PLAYING: { 376 CHECK_INTERFACE(IMediaPlayer, data, reply); 377 bool state; 378 status_t ret = isPlaying(&state); 379 reply->writeInt32(state); 380 reply->writeInt32(ret); 381 return NO_ERROR; 382 } break; 383 case PAUSE: { 384 CHECK_INTERFACE(IMediaPlayer, data, reply); 385 reply->writeInt32(pause()); 386 return NO_ERROR; 387 } break; 388 case SEEK_TO: { 389 CHECK_INTERFACE(IMediaPlayer, data, reply); 390 reply->writeInt32(seekTo(data.readInt32())); 391 return NO_ERROR; 392 } break; 393 case GET_CURRENT_POSITION: { 394 CHECK_INTERFACE(IMediaPlayer, data, reply); 395 int msec; 396 status_t ret = getCurrentPosition(&msec); 397 reply->writeInt32(msec); 398 reply->writeInt32(ret); 399 return NO_ERROR; 400 } break; 401 case GET_DURATION: { 402 CHECK_INTERFACE(IMediaPlayer, data, reply); 403 int msec; 404 status_t ret = getDuration(&msec); 405 reply->writeInt32(msec); 406 reply->writeInt32(ret); 407 return NO_ERROR; 408 } break; 409 case RESET: { 410 CHECK_INTERFACE(IMediaPlayer, data, reply); 411 reply->writeInt32(reset()); 412 return NO_ERROR; 413 } break; 414 case SET_AUDIO_STREAM_TYPE: { 415 CHECK_INTERFACE(IMediaPlayer, data, reply); 416 reply->writeInt32(setAudioStreamType(data.readInt32())); 417 return NO_ERROR; 418 } break; 419 case SET_LOOPING: { 420 CHECK_INTERFACE(IMediaPlayer, data, reply); 421 reply->writeInt32(setLooping(data.readInt32())); 422 return NO_ERROR; 423 } break; 424 case SET_VOLUME: { 425 CHECK_INTERFACE(IMediaPlayer, data, reply); 426 float leftVolume = data.readFloat(); 427 float rightVolume = data.readFloat(); 428 reply->writeInt32(setVolume(leftVolume, rightVolume)); 429 return NO_ERROR; 430 } break; 431 case INVOKE: { 432 CHECK_INTERFACE(IMediaPlayer, data, reply); 433 status_t result = invoke(data, reply); 434 return result; 435 } break; 436 case SET_METADATA_FILTER: { 437 CHECK_INTERFACE(IMediaPlayer, data, reply); 438 reply->writeInt32(setMetadataFilter(data)); 439 return NO_ERROR; 440 } break; 441 case GET_METADATA: { 442 CHECK_INTERFACE(IMediaPlayer, data, reply); 443 bool update_only = static_cast<bool>(data.readInt32()); 444 bool apply_filter = static_cast<bool>(data.readInt32()); 445 const status_t retcode = getMetadata(update_only, apply_filter, reply); 446 reply->setDataPosition(0); 447 reply->writeInt32(retcode); 448 reply->setDataPosition(0); 449 return NO_ERROR; 450 } break; 451 case SET_AUX_EFFECT_SEND_LEVEL: { 452 CHECK_INTERFACE(IMediaPlayer, data, reply); 453 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 454 return NO_ERROR; 455 } break; 456 case ATTACH_AUX_EFFECT: { 457 CHECK_INTERFACE(IMediaPlayer, data, reply); 458 reply->writeInt32(attachAuxEffect(data.readInt32())); 459 return NO_ERROR; 460 } break; 461 case SET_PARAMETER: { 462 CHECK_INTERFACE(IMediaPlayer, data, reply); 463 int key = data.readInt32(); 464 465 Parcel request; 466 if (data.dataAvail() > 0) { 467 request.appendFrom( 468 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail()); 469 } 470 request.setDataPosition(0); 471 reply->writeInt32(setParameter(key, request)); 472 return NO_ERROR; 473 } break; 474 case GET_PARAMETER: { 475 CHECK_INTERFACE(IMediaPlayer, data, reply); 476 return getParameter(data.readInt32(), reply); 477 } break; 478 default: 479 return BBinder::onTransact(code, data, reply, flags); 480 } 481} 482 483// ---------------------------------------------------------------------------- 484 485}; // namespace android 486