IMediaPlayer.cpp revision e53b9ead781c36e96d6b6f012ddffc93a3d80f0d
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 <arpa/inet.h> 19#include <stdint.h> 20#include <sys/types.h> 21 22#include <binder/Parcel.h> 23 24#include <media/IMediaPlayer.h> 25#include <media/IStreamSource.h> 26 27#include <gui/ISurfaceTexture.h> 28#include <utils/String8.h> 29 30namespace android { 31 32enum { 33 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 34 SET_DATA_SOURCE_URL, 35 SET_DATA_SOURCE_FD, 36 SET_DATA_SOURCE_STREAM, 37 PREPARE_ASYNC, 38 START, 39 STOP, 40 IS_PLAYING, 41 PAUSE, 42 SEEK_TO, 43 GET_CURRENT_POSITION, 44 GET_DURATION, 45 RESET, 46 SET_AUDIO_STREAM_TYPE, 47 SET_LOOPING, 48 SET_VOLUME, 49 INVOKE, 50 SET_METADATA_FILTER, 51 GET_METADATA, 52 SET_AUX_EFFECT_SEND_LEVEL, 53 ATTACH_AUX_EFFECT, 54 SET_VIDEO_SURFACETEXTURE, 55 SET_PARAMETER, 56 GET_PARAMETER, 57 SET_RETRANSMIT_ENDPOINT, 58}; 59 60class BpMediaPlayer: public BpInterface<IMediaPlayer> 61{ 62public: 63 BpMediaPlayer(const sp<IBinder>& impl) 64 : BpInterface<IMediaPlayer>(impl) 65 { 66 } 67 68 // disconnect from media player service 69 void disconnect() 70 { 71 Parcel data, reply; 72 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 73 remote()->transact(DISCONNECT, data, &reply); 74 } 75 76 status_t setDataSource(const char* url, 77 const KeyedVector<String8, String8>* headers) 78 { 79 Parcel data, reply; 80 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 81 data.writeCString(url); 82 if (headers == NULL) { 83 data.writeInt32(0); 84 } else { 85 // serialize the headers 86 data.writeInt32(headers->size()); 87 for (size_t i = 0; i < headers->size(); ++i) { 88 data.writeString8(headers->keyAt(i)); 89 data.writeString8(headers->valueAt(i)); 90 } 91 } 92 remote()->transact(SET_DATA_SOURCE_URL, data, &reply); 93 return reply.readInt32(); 94 } 95 96 status_t setDataSource(int fd, int64_t offset, int64_t length) { 97 Parcel data, reply; 98 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 99 data.writeFileDescriptor(fd); 100 data.writeInt64(offset); 101 data.writeInt64(length); 102 remote()->transact(SET_DATA_SOURCE_FD, data, &reply); 103 return reply.readInt32(); 104 } 105 106 status_t setDataSource(const sp<IStreamSource> &source) { 107 Parcel data, reply; 108 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 109 data.writeStrongBinder(source->asBinder()); 110 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); 111 return reply.readInt32(); 112 } 113 114 // pass the buffered ISurfaceTexture to the media player service 115 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) 116 { 117 Parcel data, reply; 118 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 119 sp<IBinder> b(surfaceTexture->asBinder()); 120 data.writeStrongBinder(b); 121 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); 122 return reply.readInt32(); 123 } 124 125 status_t prepareAsync() 126 { 127 Parcel data, reply; 128 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 129 remote()->transact(PREPARE_ASYNC, data, &reply); 130 return reply.readInt32(); 131 } 132 133 status_t start() 134 { 135 Parcel data, reply; 136 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 137 remote()->transact(START, data, &reply); 138 return reply.readInt32(); 139 } 140 141 status_t stop() 142 { 143 Parcel data, reply; 144 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 145 remote()->transact(STOP, data, &reply); 146 return reply.readInt32(); 147 } 148 149 status_t isPlaying(bool* state) 150 { 151 Parcel data, reply; 152 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 153 remote()->transact(IS_PLAYING, data, &reply); 154 *state = reply.readInt32(); 155 return reply.readInt32(); 156 } 157 158 status_t pause() 159 { 160 Parcel data, reply; 161 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 162 remote()->transact(PAUSE, data, &reply); 163 return reply.readInt32(); 164 } 165 166 status_t seekTo(int msec) 167 { 168 Parcel data, reply; 169 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 170 data.writeInt32(msec); 171 remote()->transact(SEEK_TO, data, &reply); 172 return reply.readInt32(); 173 } 174 175 status_t getCurrentPosition(int* msec) 176 { 177 Parcel data, reply; 178 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 179 remote()->transact(GET_CURRENT_POSITION, data, &reply); 180 *msec = reply.readInt32(); 181 return reply.readInt32(); 182 } 183 184 status_t getDuration(int* msec) 185 { 186 Parcel data, reply; 187 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 188 remote()->transact(GET_DURATION, data, &reply); 189 *msec = reply.readInt32(); 190 return reply.readInt32(); 191 } 192 193 status_t reset() 194 { 195 Parcel data, reply; 196 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 197 remote()->transact(RESET, data, &reply); 198 return reply.readInt32(); 199 } 200 201 status_t setAudioStreamType(audio_stream_type_t stream) 202 { 203 Parcel data, reply; 204 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 205 data.writeInt32((int32_t) stream); 206 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 207 return reply.readInt32(); 208 } 209 210 status_t setLooping(int loop) 211 { 212 Parcel data, reply; 213 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 214 data.writeInt32(loop); 215 remote()->transact(SET_LOOPING, data, &reply); 216 return reply.readInt32(); 217 } 218 219 status_t setVolume(float leftVolume, float rightVolume) 220 { 221 Parcel data, reply; 222 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 223 data.writeFloat(leftVolume); 224 data.writeFloat(rightVolume); 225 remote()->transact(SET_VOLUME, data, &reply); 226 return reply.readInt32(); 227 } 228 229 status_t invoke(const Parcel& request, Parcel *reply) 230 { 231 // Avoid doing any extra copy. The interface descriptor should 232 // have been set by MediaPlayer.java. 233 return remote()->transact(INVOKE, request, reply); 234 } 235 236 status_t setMetadataFilter(const Parcel& request) 237 { 238 Parcel reply; 239 // Avoid doing any extra copy of the request. The interface 240 // descriptor should have been set by MediaPlayer.java. 241 remote()->transact(SET_METADATA_FILTER, request, &reply); 242 return reply.readInt32(); 243 } 244 245 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 246 { 247 Parcel request; 248 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 249 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 250 request.writeInt32(update_only); 251 request.writeInt32(apply_filter); 252 remote()->transact(GET_METADATA, request, reply); 253 return reply->readInt32(); 254 } 255 256 status_t setAuxEffectSendLevel(float level) 257 { 258 Parcel data, reply; 259 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 260 data.writeFloat(level); 261 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 262 return reply.readInt32(); 263 } 264 265 status_t attachAuxEffect(int effectId) 266 { 267 Parcel data, reply; 268 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 269 data.writeInt32(effectId); 270 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 271 return reply.readInt32(); 272 } 273 274 status_t setParameter(int key, const Parcel& request) 275 { 276 Parcel data, reply; 277 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 278 data.writeInt32(key); 279 if (request.dataSize() > 0) { 280 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize()); 281 } 282 remote()->transact(SET_PARAMETER, data, &reply); 283 return reply.readInt32(); 284 } 285 286 status_t getParameter(int key, Parcel *reply) 287 { 288 Parcel data; 289 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 290 data.writeInt32(key); 291 return remote()->transact(GET_PARAMETER, data, reply); 292 } 293 294 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) { 295 Parcel data, reply; 296 status_t err; 297 298 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 299 if (NULL != endpoint) { 300 data.writeInt32(sizeof(*endpoint)); 301 data.write(endpoint, sizeof(*endpoint)); 302 } else { 303 data.writeInt32(0); 304 } 305 306 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply); 307 if (OK != err) { 308 return err; 309 } 310 311 return reply.readInt32(); 312 } 313}; 314 315IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 316 317// ---------------------------------------------------------------------- 318 319status_t BnMediaPlayer::onTransact( 320 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 321{ 322 switch (code) { 323 case DISCONNECT: { 324 CHECK_INTERFACE(IMediaPlayer, data, reply); 325 disconnect(); 326 return NO_ERROR; 327 } break; 328 case SET_DATA_SOURCE_URL: { 329 CHECK_INTERFACE(IMediaPlayer, data, reply); 330 const char* url = data.readCString(); 331 KeyedVector<String8, String8> headers; 332 int32_t numHeaders = data.readInt32(); 333 for (int i = 0; i < numHeaders; ++i) { 334 String8 key = data.readString8(); 335 String8 value = data.readString8(); 336 headers.add(key, value); 337 } 338 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL)); 339 return NO_ERROR; 340 } break; 341 case SET_DATA_SOURCE_FD: { 342 CHECK_INTERFACE(IMediaPlayer, data, reply); 343 int fd = data.readFileDescriptor(); 344 int64_t offset = data.readInt64(); 345 int64_t length = data.readInt64(); 346 reply->writeInt32(setDataSource(fd, offset, length)); 347 return NO_ERROR; 348 } 349 case SET_DATA_SOURCE_STREAM: { 350 CHECK_INTERFACE(IMediaPlayer, data, reply); 351 sp<IStreamSource> source = 352 interface_cast<IStreamSource>(data.readStrongBinder()); 353 reply->writeInt32(setDataSource(source)); 354 return NO_ERROR; 355 } 356 case SET_VIDEO_SURFACETEXTURE: { 357 CHECK_INTERFACE(IMediaPlayer, data, reply); 358 sp<ISurfaceTexture> surfaceTexture = 359 interface_cast<ISurfaceTexture>(data.readStrongBinder()); 360 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 361 return NO_ERROR; 362 } break; 363 case PREPARE_ASYNC: { 364 CHECK_INTERFACE(IMediaPlayer, data, reply); 365 reply->writeInt32(prepareAsync()); 366 return NO_ERROR; 367 } break; 368 case START: { 369 CHECK_INTERFACE(IMediaPlayer, data, reply); 370 reply->writeInt32(start()); 371 return NO_ERROR; 372 } break; 373 case STOP: { 374 CHECK_INTERFACE(IMediaPlayer, data, reply); 375 reply->writeInt32(stop()); 376 return NO_ERROR; 377 } break; 378 case IS_PLAYING: { 379 CHECK_INTERFACE(IMediaPlayer, data, reply); 380 bool state; 381 status_t ret = isPlaying(&state); 382 reply->writeInt32(state); 383 reply->writeInt32(ret); 384 return NO_ERROR; 385 } break; 386 case PAUSE: { 387 CHECK_INTERFACE(IMediaPlayer, data, reply); 388 reply->writeInt32(pause()); 389 return NO_ERROR; 390 } break; 391 case SEEK_TO: { 392 CHECK_INTERFACE(IMediaPlayer, data, reply); 393 reply->writeInt32(seekTo(data.readInt32())); 394 return NO_ERROR; 395 } break; 396 case GET_CURRENT_POSITION: { 397 CHECK_INTERFACE(IMediaPlayer, data, reply); 398 int msec; 399 status_t ret = getCurrentPosition(&msec); 400 reply->writeInt32(msec); 401 reply->writeInt32(ret); 402 return NO_ERROR; 403 } break; 404 case GET_DURATION: { 405 CHECK_INTERFACE(IMediaPlayer, data, reply); 406 int msec; 407 status_t ret = getDuration(&msec); 408 reply->writeInt32(msec); 409 reply->writeInt32(ret); 410 return NO_ERROR; 411 } break; 412 case RESET: { 413 CHECK_INTERFACE(IMediaPlayer, data, reply); 414 reply->writeInt32(reset()); 415 return NO_ERROR; 416 } break; 417 case SET_AUDIO_STREAM_TYPE: { 418 CHECK_INTERFACE(IMediaPlayer, data, reply); 419 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32())); 420 return NO_ERROR; 421 } break; 422 case SET_LOOPING: { 423 CHECK_INTERFACE(IMediaPlayer, data, reply); 424 reply->writeInt32(setLooping(data.readInt32())); 425 return NO_ERROR; 426 } break; 427 case SET_VOLUME: { 428 CHECK_INTERFACE(IMediaPlayer, data, reply); 429 float leftVolume = data.readFloat(); 430 float rightVolume = data.readFloat(); 431 reply->writeInt32(setVolume(leftVolume, rightVolume)); 432 return NO_ERROR; 433 } break; 434 case INVOKE: { 435 CHECK_INTERFACE(IMediaPlayer, data, reply); 436 status_t result = invoke(data, reply); 437 return result; 438 } break; 439 case SET_METADATA_FILTER: { 440 CHECK_INTERFACE(IMediaPlayer, data, reply); 441 reply->writeInt32(setMetadataFilter(data)); 442 return NO_ERROR; 443 } break; 444 case GET_METADATA: { 445 CHECK_INTERFACE(IMediaPlayer, data, reply); 446 bool update_only = static_cast<bool>(data.readInt32()); 447 bool apply_filter = static_cast<bool>(data.readInt32()); 448 const status_t retcode = getMetadata(update_only, apply_filter, reply); 449 reply->setDataPosition(0); 450 reply->writeInt32(retcode); 451 reply->setDataPosition(0); 452 return NO_ERROR; 453 } break; 454 case SET_AUX_EFFECT_SEND_LEVEL: { 455 CHECK_INTERFACE(IMediaPlayer, data, reply); 456 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 457 return NO_ERROR; 458 } break; 459 case ATTACH_AUX_EFFECT: { 460 CHECK_INTERFACE(IMediaPlayer, data, reply); 461 reply->writeInt32(attachAuxEffect(data.readInt32())); 462 return NO_ERROR; 463 } break; 464 case SET_PARAMETER: { 465 CHECK_INTERFACE(IMediaPlayer, data, reply); 466 int key = data.readInt32(); 467 468 Parcel request; 469 if (data.dataAvail() > 0) { 470 request.appendFrom( 471 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail()); 472 } 473 request.setDataPosition(0); 474 reply->writeInt32(setParameter(key, request)); 475 return NO_ERROR; 476 } break; 477 case GET_PARAMETER: { 478 CHECK_INTERFACE(IMediaPlayer, data, reply); 479 return getParameter(data.readInt32(), reply); 480 } break; 481 case SET_RETRANSMIT_ENDPOINT: { 482 CHECK_INTERFACE(IMediaPlayer, data, reply); 483 484 struct sockaddr_in endpoint; 485 int amt = data.readInt32(); 486 if (amt == sizeof(endpoint)) { 487 data.read(&endpoint, sizeof(struct sockaddr_in)); 488 reply->writeInt32(setRetransmitEndpoint(&endpoint)); 489 } else { 490 reply->writeInt32(setRetransmitEndpoint(NULL)); 491 } 492 493 return NO_ERROR; 494 } break; 495 default: 496 return BBinder::onTransact(code, data, reply, flags); 497 } 498} 499 500// ---------------------------------------------------------------------------- 501 502}; // namespace android 503