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/AudioResamplerPublic.h> 25#include <media/AVSyncSettings.h> 26 27#include <media/IDataSource.h> 28#include <media/IMediaHTTPService.h> 29#include <media/IMediaPlayer.h> 30#include <media/IStreamSource.h> 31 32#include <gui/IGraphicBufferProducer.h> 33#include <utils/String8.h> 34 35namespace android { 36 37enum { 38 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 39 SET_DATA_SOURCE_URL, 40 SET_DATA_SOURCE_FD, 41 SET_DATA_SOURCE_STREAM, 42 SET_DATA_SOURCE_CALLBACK, 43 PREPARE_ASYNC, 44 START, 45 STOP, 46 IS_PLAYING, 47 SET_PLAYBACK_SETTINGS, 48 GET_PLAYBACK_SETTINGS, 49 SET_SYNC_SETTINGS, 50 GET_SYNC_SETTINGS, 51 PAUSE, 52 SEEK_TO, 53 GET_CURRENT_POSITION, 54 GET_DURATION, 55 RESET, 56 SET_AUDIO_STREAM_TYPE, 57 SET_LOOPING, 58 SET_VOLUME, 59 INVOKE, 60 SET_METADATA_FILTER, 61 GET_METADATA, 62 SET_AUX_EFFECT_SEND_LEVEL, 63 ATTACH_AUX_EFFECT, 64 SET_VIDEO_SURFACETEXTURE, 65 SET_PARAMETER, 66 GET_PARAMETER, 67 SET_RETRANSMIT_ENDPOINT, 68 GET_RETRANSMIT_ENDPOINT, 69 SET_NEXT_PLAYER, 70}; 71 72class BpMediaPlayer: public BpInterface<IMediaPlayer> 73{ 74public: 75 BpMediaPlayer(const sp<IBinder>& impl) 76 : BpInterface<IMediaPlayer>(impl) 77 { 78 } 79 80 // disconnect from media player service 81 void disconnect() 82 { 83 Parcel data, reply; 84 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 85 remote()->transact(DISCONNECT, data, &reply); 86 } 87 88 status_t setDataSource( 89 const sp<IMediaHTTPService> &httpService, 90 const char* url, 91 const KeyedVector<String8, String8>* headers) 92 { 93 Parcel data, reply; 94 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 95 data.writeInt32(httpService != NULL); 96 if (httpService != NULL) { 97 data.writeStrongBinder(IInterface::asBinder(httpService)); 98 } 99 data.writeCString(url); 100 if (headers == NULL) { 101 data.writeInt32(0); 102 } else { 103 // serialize the headers 104 data.writeInt32(headers->size()); 105 for (size_t i = 0; i < headers->size(); ++i) { 106 data.writeString8(headers->keyAt(i)); 107 data.writeString8(headers->valueAt(i)); 108 } 109 } 110 remote()->transact(SET_DATA_SOURCE_URL, data, &reply); 111 return reply.readInt32(); 112 } 113 114 status_t setDataSource(int fd, int64_t offset, int64_t length) { 115 Parcel data, reply; 116 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 117 data.writeFileDescriptor(fd); 118 data.writeInt64(offset); 119 data.writeInt64(length); 120 remote()->transact(SET_DATA_SOURCE_FD, data, &reply); 121 return reply.readInt32(); 122 } 123 124 status_t setDataSource(const sp<IStreamSource> &source) { 125 Parcel data, reply; 126 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 127 data.writeStrongBinder(IInterface::asBinder(source)); 128 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); 129 return reply.readInt32(); 130 } 131 132 status_t setDataSource(const sp<IDataSource> &source) { 133 Parcel data, reply; 134 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 135 data.writeStrongBinder(IInterface::asBinder(source)); 136 remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply); 137 return reply.readInt32(); 138 } 139 140 // pass the buffered IGraphicBufferProducer to the media player service 141 status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer) 142 { 143 Parcel data, reply; 144 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 145 sp<IBinder> b(IInterface::asBinder(bufferProducer)); 146 data.writeStrongBinder(b); 147 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); 148 return reply.readInt32(); 149 } 150 151 status_t prepareAsync() 152 { 153 Parcel data, reply; 154 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 155 remote()->transact(PREPARE_ASYNC, data, &reply); 156 return reply.readInt32(); 157 } 158 159 status_t start() 160 { 161 Parcel data, reply; 162 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 163 remote()->transact(START, data, &reply); 164 return reply.readInt32(); 165 } 166 167 status_t stop() 168 { 169 Parcel data, reply; 170 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 171 remote()->transact(STOP, data, &reply); 172 return reply.readInt32(); 173 } 174 175 status_t isPlaying(bool* state) 176 { 177 Parcel data, reply; 178 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 179 remote()->transact(IS_PLAYING, data, &reply); 180 *state = reply.readInt32(); 181 return reply.readInt32(); 182 } 183 184 status_t setPlaybackSettings(const AudioPlaybackRate& rate) 185 { 186 Parcel data, reply; 187 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 188 data.writeFloat(rate.mSpeed); 189 data.writeFloat(rate.mPitch); 190 data.writeInt32((int32_t)rate.mFallbackMode); 191 data.writeInt32((int32_t)rate.mStretchMode); 192 remote()->transact(SET_PLAYBACK_SETTINGS, data, &reply); 193 return reply.readInt32(); 194 } 195 196 status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) 197 { 198 Parcel data, reply; 199 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 200 remote()->transact(GET_PLAYBACK_SETTINGS, data, &reply); 201 status_t err = reply.readInt32(); 202 if (err == OK) { 203 *rate = AUDIO_PLAYBACK_RATE_DEFAULT; 204 rate->mSpeed = reply.readFloat(); 205 rate->mPitch = reply.readFloat(); 206 rate->mFallbackMode = (AudioTimestretchFallbackMode)reply.readInt32(); 207 rate->mStretchMode = (AudioTimestretchStretchMode)reply.readInt32(); 208 } 209 return err; 210 } 211 212 status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) 213 { 214 Parcel data, reply; 215 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 216 data.writeInt32((int32_t)sync.mSource); 217 data.writeInt32((int32_t)sync.mAudioAdjustMode); 218 data.writeFloat(sync.mTolerance); 219 data.writeFloat(videoFpsHint); 220 remote()->transact(SET_SYNC_SETTINGS, data, &reply); 221 return reply.readInt32(); 222 } 223 224 status_t getSyncSettings(AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) 225 { 226 Parcel data, reply; 227 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 228 remote()->transact(GET_SYNC_SETTINGS, data, &reply); 229 status_t err = reply.readInt32(); 230 if (err == OK) { 231 AVSyncSettings settings; 232 settings.mSource = (AVSyncSource)reply.readInt32(); 233 settings.mAudioAdjustMode = (AVSyncAudioAdjustMode)reply.readInt32(); 234 settings.mTolerance = reply.readFloat(); 235 *sync = settings; 236 *videoFps = reply.readFloat(); 237 } 238 return err; 239 } 240 241 status_t pause() 242 { 243 Parcel data, reply; 244 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 245 remote()->transact(PAUSE, data, &reply); 246 return reply.readInt32(); 247 } 248 249 status_t seekTo(int msec) 250 { 251 Parcel data, reply; 252 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 253 data.writeInt32(msec); 254 remote()->transact(SEEK_TO, data, &reply); 255 return reply.readInt32(); 256 } 257 258 status_t getCurrentPosition(int* msec) 259 { 260 Parcel data, reply; 261 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 262 remote()->transact(GET_CURRENT_POSITION, data, &reply); 263 *msec = reply.readInt32(); 264 return reply.readInt32(); 265 } 266 267 status_t getDuration(int* msec) 268 { 269 Parcel data, reply; 270 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 271 remote()->transact(GET_DURATION, data, &reply); 272 *msec = reply.readInt32(); 273 return reply.readInt32(); 274 } 275 276 status_t reset() 277 { 278 Parcel data, reply; 279 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 280 remote()->transact(RESET, data, &reply); 281 return reply.readInt32(); 282 } 283 284 status_t setAudioStreamType(audio_stream_type_t stream) 285 { 286 Parcel data, reply; 287 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 288 data.writeInt32((int32_t) stream); 289 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 290 return reply.readInt32(); 291 } 292 293 status_t setLooping(int loop) 294 { 295 Parcel data, reply; 296 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 297 data.writeInt32(loop); 298 remote()->transact(SET_LOOPING, data, &reply); 299 return reply.readInt32(); 300 } 301 302 status_t setVolume(float leftVolume, float rightVolume) 303 { 304 Parcel data, reply; 305 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 306 data.writeFloat(leftVolume); 307 data.writeFloat(rightVolume); 308 remote()->transact(SET_VOLUME, data, &reply); 309 return reply.readInt32(); 310 } 311 312 status_t invoke(const Parcel& request, Parcel *reply) 313 { 314 // Avoid doing any extra copy. The interface descriptor should 315 // have been set by MediaPlayer.java. 316 return remote()->transact(INVOKE, request, reply); 317 } 318 319 status_t setMetadataFilter(const Parcel& request) 320 { 321 Parcel reply; 322 // Avoid doing any extra copy of the request. The interface 323 // descriptor should have been set by MediaPlayer.java. 324 remote()->transact(SET_METADATA_FILTER, request, &reply); 325 return reply.readInt32(); 326 } 327 328 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 329 { 330 Parcel request; 331 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 332 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 333 request.writeInt32(update_only); 334 request.writeInt32(apply_filter); 335 remote()->transact(GET_METADATA, request, reply); 336 return reply->readInt32(); 337 } 338 339 status_t setAuxEffectSendLevel(float level) 340 { 341 Parcel data, reply; 342 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 343 data.writeFloat(level); 344 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 345 return reply.readInt32(); 346 } 347 348 status_t attachAuxEffect(int effectId) 349 { 350 Parcel data, reply; 351 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 352 data.writeInt32(effectId); 353 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 354 return reply.readInt32(); 355 } 356 357 status_t setParameter(int key, const Parcel& request) 358 { 359 Parcel data, reply; 360 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 361 data.writeInt32(key); 362 if (request.dataSize() > 0) { 363 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize()); 364 } 365 remote()->transact(SET_PARAMETER, data, &reply); 366 return reply.readInt32(); 367 } 368 369 status_t getParameter(int key, Parcel *reply) 370 { 371 Parcel data; 372 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 373 data.writeInt32(key); 374 return remote()->transact(GET_PARAMETER, data, reply); 375 } 376 377 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) 378 { 379 Parcel data, reply; 380 status_t err; 381 382 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 383 if (NULL != endpoint) { 384 data.writeInt32(sizeof(*endpoint)); 385 data.write(endpoint, sizeof(*endpoint)); 386 } else { 387 data.writeInt32(0); 388 } 389 390 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply); 391 if (OK != err) { 392 return err; 393 } 394 return reply.readInt32(); 395 } 396 397 status_t setNextPlayer(const sp<IMediaPlayer>& player) { 398 Parcel data, reply; 399 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 400 sp<IBinder> b(IInterface::asBinder(player)); 401 data.writeStrongBinder(b); 402 remote()->transact(SET_NEXT_PLAYER, data, &reply); 403 return reply.readInt32(); 404 } 405 406 status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) 407 { 408 Parcel data, reply; 409 status_t err; 410 411 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 412 err = remote()->transact(GET_RETRANSMIT_ENDPOINT, data, &reply); 413 414 if ((OK != err) || (OK != (err = reply.readInt32()))) { 415 return err; 416 } 417 418 data.read(endpoint, sizeof(*endpoint)); 419 420 return err; 421 } 422}; 423 424IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 425 426// ---------------------------------------------------------------------- 427 428status_t BnMediaPlayer::onTransact( 429 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 430{ 431 switch (code) { 432 case DISCONNECT: { 433 CHECK_INTERFACE(IMediaPlayer, data, reply); 434 disconnect(); 435 return NO_ERROR; 436 } break; 437 case SET_DATA_SOURCE_URL: { 438 CHECK_INTERFACE(IMediaPlayer, data, reply); 439 440 sp<IMediaHTTPService> httpService; 441 if (data.readInt32()) { 442 httpService = 443 interface_cast<IMediaHTTPService>(data.readStrongBinder()); 444 } 445 446 const char* url = data.readCString(); 447 if (url == NULL) { 448 reply->writeInt32(BAD_VALUE); 449 return NO_ERROR; 450 } 451 KeyedVector<String8, String8> headers; 452 int32_t numHeaders = data.readInt32(); 453 for (int i = 0; i < numHeaders; ++i) { 454 String8 key = data.readString8(); 455 String8 value = data.readString8(); 456 headers.add(key, value); 457 } 458 reply->writeInt32(setDataSource( 459 httpService, url, numHeaders > 0 ? &headers : NULL)); 460 return NO_ERROR; 461 } break; 462 case SET_DATA_SOURCE_FD: { 463 CHECK_INTERFACE(IMediaPlayer, data, reply); 464 int fd = data.readFileDescriptor(); 465 int64_t offset = data.readInt64(); 466 int64_t length = data.readInt64(); 467 reply->writeInt32(setDataSource(fd, offset, length)); 468 return NO_ERROR; 469 } 470 case SET_DATA_SOURCE_STREAM: { 471 CHECK_INTERFACE(IMediaPlayer, data, reply); 472 sp<IStreamSource> source = 473 interface_cast<IStreamSource>(data.readStrongBinder()); 474 if (source == NULL) { 475 reply->writeInt32(BAD_VALUE); 476 } else { 477 reply->writeInt32(setDataSource(source)); 478 } 479 return NO_ERROR; 480 } 481 case SET_DATA_SOURCE_CALLBACK: { 482 CHECK_INTERFACE(IMediaPlayer, data, reply); 483 sp<IDataSource> source = 484 interface_cast<IDataSource>(data.readStrongBinder()); 485 if (source == NULL) { 486 reply->writeInt32(BAD_VALUE); 487 } else { 488 reply->writeInt32(setDataSource(source)); 489 } 490 return NO_ERROR; 491 } 492 case SET_VIDEO_SURFACETEXTURE: { 493 CHECK_INTERFACE(IMediaPlayer, data, reply); 494 sp<IGraphicBufferProducer> bufferProducer = 495 interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); 496 reply->writeInt32(setVideoSurfaceTexture(bufferProducer)); 497 return NO_ERROR; 498 } break; 499 case PREPARE_ASYNC: { 500 CHECK_INTERFACE(IMediaPlayer, data, reply); 501 reply->writeInt32(prepareAsync()); 502 return NO_ERROR; 503 } break; 504 case START: { 505 CHECK_INTERFACE(IMediaPlayer, data, reply); 506 reply->writeInt32(start()); 507 return NO_ERROR; 508 } break; 509 case STOP: { 510 CHECK_INTERFACE(IMediaPlayer, data, reply); 511 reply->writeInt32(stop()); 512 return NO_ERROR; 513 } break; 514 case IS_PLAYING: { 515 CHECK_INTERFACE(IMediaPlayer, data, reply); 516 bool state; 517 status_t ret = isPlaying(&state); 518 reply->writeInt32(state); 519 reply->writeInt32(ret); 520 return NO_ERROR; 521 } break; 522 case SET_PLAYBACK_SETTINGS: { 523 CHECK_INTERFACE(IMediaPlayer, data, reply); 524 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT; 525 rate.mSpeed = data.readFloat(); 526 rate.mPitch = data.readFloat(); 527 rate.mFallbackMode = (AudioTimestretchFallbackMode)data.readInt32(); 528 rate.mStretchMode = (AudioTimestretchStretchMode)data.readInt32(); 529 reply->writeInt32(setPlaybackSettings(rate)); 530 return NO_ERROR; 531 } break; 532 case GET_PLAYBACK_SETTINGS: { 533 CHECK_INTERFACE(IMediaPlayer, data, reply); 534 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT; 535 status_t err = getPlaybackSettings(&rate); 536 reply->writeInt32(err); 537 if (err == OK) { 538 reply->writeFloat(rate.mSpeed); 539 reply->writeFloat(rate.mPitch); 540 reply->writeInt32((int32_t)rate.mFallbackMode); 541 reply->writeInt32((int32_t)rate.mStretchMode); 542 } 543 return NO_ERROR; 544 } break; 545 case SET_SYNC_SETTINGS: { 546 CHECK_INTERFACE(IMediaPlayer, data, reply); 547 AVSyncSettings sync; 548 sync.mSource = (AVSyncSource)data.readInt32(); 549 sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)data.readInt32(); 550 sync.mTolerance = data.readFloat(); 551 float videoFpsHint = data.readFloat(); 552 reply->writeInt32(setSyncSettings(sync, videoFpsHint)); 553 return NO_ERROR; 554 } break; 555 case GET_SYNC_SETTINGS: { 556 CHECK_INTERFACE(IMediaPlayer, data, reply); 557 AVSyncSettings sync; 558 float videoFps; 559 status_t err = getSyncSettings(&sync, &videoFps); 560 reply->writeInt32(err); 561 if (err == OK) { 562 reply->writeInt32((int32_t)sync.mSource); 563 reply->writeInt32((int32_t)sync.mAudioAdjustMode); 564 reply->writeFloat(sync.mTolerance); 565 reply->writeFloat(videoFps); 566 } 567 return NO_ERROR; 568 } break; 569 case PAUSE: { 570 CHECK_INTERFACE(IMediaPlayer, data, reply); 571 reply->writeInt32(pause()); 572 return NO_ERROR; 573 } break; 574 case SEEK_TO: { 575 CHECK_INTERFACE(IMediaPlayer, data, reply); 576 reply->writeInt32(seekTo(data.readInt32())); 577 return NO_ERROR; 578 } break; 579 case GET_CURRENT_POSITION: { 580 CHECK_INTERFACE(IMediaPlayer, data, reply); 581 int msec = 0; 582 status_t ret = getCurrentPosition(&msec); 583 reply->writeInt32(msec); 584 reply->writeInt32(ret); 585 return NO_ERROR; 586 } break; 587 case GET_DURATION: { 588 CHECK_INTERFACE(IMediaPlayer, data, reply); 589 int msec = 0; 590 status_t ret = getDuration(&msec); 591 reply->writeInt32(msec); 592 reply->writeInt32(ret); 593 return NO_ERROR; 594 } break; 595 case RESET: { 596 CHECK_INTERFACE(IMediaPlayer, data, reply); 597 reply->writeInt32(reset()); 598 return NO_ERROR; 599 } break; 600 case SET_AUDIO_STREAM_TYPE: { 601 CHECK_INTERFACE(IMediaPlayer, data, reply); 602 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32())); 603 return NO_ERROR; 604 } break; 605 case SET_LOOPING: { 606 CHECK_INTERFACE(IMediaPlayer, data, reply); 607 reply->writeInt32(setLooping(data.readInt32())); 608 return NO_ERROR; 609 } break; 610 case SET_VOLUME: { 611 CHECK_INTERFACE(IMediaPlayer, data, reply); 612 float leftVolume = data.readFloat(); 613 float rightVolume = data.readFloat(); 614 reply->writeInt32(setVolume(leftVolume, rightVolume)); 615 return NO_ERROR; 616 } break; 617 case INVOKE: { 618 CHECK_INTERFACE(IMediaPlayer, data, reply); 619 status_t result = invoke(data, reply); 620 return result; 621 } break; 622 case SET_METADATA_FILTER: { 623 CHECK_INTERFACE(IMediaPlayer, data, reply); 624 reply->writeInt32(setMetadataFilter(data)); 625 return NO_ERROR; 626 } break; 627 case GET_METADATA: { 628 CHECK_INTERFACE(IMediaPlayer, data, reply); 629 bool update_only = static_cast<bool>(data.readInt32()); 630 bool apply_filter = static_cast<bool>(data.readInt32()); 631 const status_t retcode = getMetadata(update_only, apply_filter, reply); 632 reply->setDataPosition(0); 633 reply->writeInt32(retcode); 634 reply->setDataPosition(0); 635 return NO_ERROR; 636 } break; 637 case SET_AUX_EFFECT_SEND_LEVEL: { 638 CHECK_INTERFACE(IMediaPlayer, data, reply); 639 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 640 return NO_ERROR; 641 } break; 642 case ATTACH_AUX_EFFECT: { 643 CHECK_INTERFACE(IMediaPlayer, data, reply); 644 reply->writeInt32(attachAuxEffect(data.readInt32())); 645 return NO_ERROR; 646 } break; 647 case SET_PARAMETER: { 648 CHECK_INTERFACE(IMediaPlayer, data, reply); 649 int key = data.readInt32(); 650 651 Parcel request; 652 if (data.dataAvail() > 0) { 653 request.appendFrom( 654 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail()); 655 } 656 request.setDataPosition(0); 657 reply->writeInt32(setParameter(key, request)); 658 return NO_ERROR; 659 } break; 660 case GET_PARAMETER: { 661 CHECK_INTERFACE(IMediaPlayer, data, reply); 662 return getParameter(data.readInt32(), reply); 663 } break; 664 case SET_RETRANSMIT_ENDPOINT: { 665 CHECK_INTERFACE(IMediaPlayer, data, reply); 666 667 struct sockaddr_in endpoint; 668 memset(&endpoint, 0, sizeof(endpoint)); 669 int amt = data.readInt32(); 670 if (amt == sizeof(endpoint)) { 671 data.read(&endpoint, sizeof(struct sockaddr_in)); 672 reply->writeInt32(setRetransmitEndpoint(&endpoint)); 673 } else { 674 reply->writeInt32(setRetransmitEndpoint(NULL)); 675 } 676 677 return NO_ERROR; 678 } break; 679 case GET_RETRANSMIT_ENDPOINT: { 680 CHECK_INTERFACE(IMediaPlayer, data, reply); 681 682 struct sockaddr_in endpoint; 683 memset(&endpoint, 0, sizeof(endpoint)); 684 status_t res = getRetransmitEndpoint(&endpoint); 685 686 reply->writeInt32(res); 687 reply->write(&endpoint, sizeof(endpoint)); 688 689 return NO_ERROR; 690 } break; 691 case SET_NEXT_PLAYER: { 692 CHECK_INTERFACE(IMediaPlayer, data, reply); 693 reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder()))); 694 695 return NO_ERROR; 696 } break; 697 default: 698 return BBinder::onTransact(code, data, reply, flags); 699 } 700} 701 702// ---------------------------------------------------------------------------- 703 704} // namespace android 705