IMediaPlayer.cpp revision df712ea86e6350f7005a02ab0e1c60c28a343ed0
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 <gui/ISurfaceTexture.h> 27#include <utils/String8.h> 28 29namespace android { 30 31enum { 32 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 33 SET_DATA_SOURCE_URL, 34 SET_DATA_SOURCE_FD, 35 SET_DATA_SOURCE_STREAM, 36 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, 47 SET_VOLUME, 48 INVOKE, 49 SET_METADATA_FILTER, 50 GET_METADATA, 51 SET_AUX_EFFECT_SEND_LEVEL, 52 ATTACH_AUX_EFFECT, 53 SET_VIDEO_SURFACETEXTURE, 54 SET_PARAMETER, 55 GET_PARAMETER, 56}; 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 74 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()); 108 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); 109 return reply.readInt32(); 110 } 111 112 // 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 123 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 199 status_t setAudioStreamType(audio_stream_type_t stream) 200 { 201 Parcel data, reply; 202 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 203 data.writeInt32((int32_t) stream); 204 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; 220 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 221 data.writeFloat(leftVolume); 222 data.writeFloat(rightVolume); 223 remote()->transact(SET_VOLUME, data, &reply); 224 return reply.readInt32(); 225 } 226 227 status_t invoke(const Parcel& request, Parcel *reply) 228 { 229 // Avoid doing any extra copy. The interface descriptor should 230 // have been set by MediaPlayer.java. 231 return remote()->transact(INVOKE, request, reply); 232 } 233 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 } 242 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 } 253 254 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 } 271 272 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 292}; 293 294IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 295 296// ---------------------------------------------------------------------- 297 298status_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; 307 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 } 335 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; 342 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); 398 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32())); 399 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: { 407 CHECK_INTERFACE(IMediaPlayer, data, reply); 408 float leftVolume = data.readFloat(); 409 float rightVolume = data.readFloat(); 410 reply->writeInt32(setVolume(leftVolume, rightVolume)); 411 return NO_ERROR; 412 } break; 413 case INVOKE: { 414 CHECK_INTERFACE(IMediaPlayer, data, reply); 415 status_t result = invoke(data, reply); 416 return result; 417 } break; 418 case SET_METADATA_FILTER: { 419 CHECK_INTERFACE(IMediaPlayer, data, reply); 420 reply->writeInt32(setMetadataFilter(data)); 421 return NO_ERROR; 422 } break; 423 case GET_METADATA: { 424 CHECK_INTERFACE(IMediaPlayer, data, reply); 425 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); 428 reply->setDataPosition(0); 429 reply->writeInt32(retcode); 430 reply->setDataPosition(0); 431 return NO_ERROR; 432 } break; 433 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; 443 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; 460 default: 461 return BBinder::onTransact(code, data, reply, flags); 462 } 463} 464 465// ---------------------------------------------------------------------------- 466 467}; // namespace android 468