1 /* 2 ** 3 ** Copyright 2017, 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 //#define LOG_NDEBUG 0 19 #define LOG_TAG "MediaPlayer2Native" 20 21 #include <android/binder_ibinder.h> 22 #include <media/AudioSystem.h> 23 #include <media/DataSourceDesc.h> 24 #include <media/MemoryLeakTrackUtil.h> 25 #include <media/NdkWrapper.h> 26 #include <media/stagefright/foundation/ADebug.h> 27 #include <media/stagefright/foundation/ALooperRoster.h> 28 #include <mediaplayer2/MediaPlayer2AudioOutput.h> 29 #include <mediaplayer2/mediaplayer2.h> 30 31 #include <utils/Log.h> 32 #include <utils/SortedVector.h> 33 #include <utils/String8.h> 34 35 #include <system/audio.h> 36 #include <system/window.h> 37 38 #include <nuplayer2/NuPlayer2Driver.h> 39 40 #include <dirent.h> 41 #include <sys/stat.h> 42 43 namespace android { 44 45 extern ALooperRoster gLooperRoster; 46 47 namespace { 48 49 const int kDumpLockRetries = 50; 50 const int kDumpLockSleepUs = 20000; 51 52 class proxyListener : public MediaPlayer2InterfaceListener { 53 public: 54 proxyListener(const wp<MediaPlayer2> &player) 55 : mPlayer(player) { } 56 57 ~proxyListener() { }; 58 59 virtual void notify(int64_t srcId, int msg, int ext1, int ext2, 60 const PlayerMessage *obj) override { 61 sp<MediaPlayer2> player = mPlayer.promote(); 62 if (player != NULL) { 63 player->notify(srcId, msg, ext1, ext2, obj); 64 } 65 } 66 67 private: 68 wp<MediaPlayer2> mPlayer; 69 }; 70 71 Mutex sRecordLock; 72 SortedVector<wp<MediaPlayer2> > *sPlayers; 73 74 void ensureInit_l() { 75 if (sPlayers == NULL) { 76 sPlayers = new SortedVector<wp<MediaPlayer2> >(); 77 } 78 } 79 80 void addPlayer(const wp<MediaPlayer2>& player) { 81 Mutex::Autolock lock(sRecordLock); 82 ensureInit_l(); 83 sPlayers->add(player); 84 } 85 86 void removePlayer(const wp<MediaPlayer2>& player) { 87 Mutex::Autolock lock(sRecordLock); 88 ensureInit_l(); 89 sPlayers->remove(player); 90 } 91 92 /** 93 * The only arguments this understands right now are -c, -von and -voff, 94 * which are parsed by ALooperRoster::dump() 95 */ 96 status_t dumpPlayers(int fd, const Vector<String16>& args) { 97 const size_t SIZE = 256; 98 char buffer[SIZE]; 99 String8 result; 100 SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction. 101 102 { 103 Mutex::Autolock lock(sRecordLock); 104 ensureInit_l(); 105 for (int i = 0, n = sPlayers->size(); i < n; ++i) { 106 sp<MediaPlayer2> p = (*sPlayers)[i].promote(); 107 if (p != 0) { 108 p->dump(fd, args); 109 } 110 players.add(p); 111 } 112 } 113 114 result.append(" Files opened and/or mapped:\n"); 115 snprintf(buffer, SIZE, "/proc/%d/maps", getpid()); 116 FILE *f = fopen(buffer, "r"); 117 if (f) { 118 while (!feof(f)) { 119 fgets(buffer, SIZE, f); 120 if (strstr(buffer, " /storage/") || 121 strstr(buffer, " /system/sounds/") || 122 strstr(buffer, " /data/") || 123 strstr(buffer, " /system/media/")) { 124 result.append(" "); 125 result.append(buffer); 126 } 127 } 128 fclose(f); 129 } else { 130 result.append("couldn't open "); 131 result.append(buffer); 132 result.append("\n"); 133 } 134 135 snprintf(buffer, SIZE, "/proc/%d/fd", getpid()); 136 DIR *d = opendir(buffer); 137 if (d) { 138 struct dirent *ent; 139 while((ent = readdir(d)) != NULL) { 140 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) { 141 snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name); 142 struct stat s; 143 if (lstat(buffer, &s) == 0) { 144 if ((s.st_mode & S_IFMT) == S_IFLNK) { 145 char linkto[256]; 146 int len = readlink(buffer, linkto, sizeof(linkto)); 147 if(len > 0) { 148 if(len > 255) { 149 linkto[252] = '.'; 150 linkto[253] = '.'; 151 linkto[254] = '.'; 152 linkto[255] = 0; 153 } else { 154 linkto[len] = 0; 155 } 156 if (strstr(linkto, "/storage/") == linkto || 157 strstr(linkto, "/system/sounds/") == linkto || 158 strstr(linkto, "/data/") == linkto || 159 strstr(linkto, "/system/media/") == linkto) { 160 result.append(" "); 161 result.append(buffer); 162 result.append(" -> "); 163 result.append(linkto); 164 result.append("\n"); 165 } 166 } 167 } else { 168 result.append(" unexpected type for "); 169 result.append(buffer); 170 result.append("\n"); 171 } 172 } 173 } 174 } 175 closedir(d); 176 } else { 177 result.append("couldn't open "); 178 result.append(buffer); 179 result.append("\n"); 180 } 181 182 gLooperRoster.dump(fd, args); 183 184 bool dumpMem = false; 185 bool unreachableMemory = false; 186 for (size_t i = 0; i < args.size(); i++) { 187 if (args[i] == String16("-m")) { 188 dumpMem = true; 189 } else if (args[i] == String16("--unreachable")) { 190 unreachableMemory = true; 191 } 192 } 193 if (dumpMem) { 194 result.append("\nDumping memory:\n"); 195 std::string s = dumpMemoryAddresses(100 /* limit */); 196 result.append(s.c_str(), s.size()); 197 } 198 if (unreachableMemory) { 199 result.append("\nDumping unreachable memory:\n"); 200 // TODO - should limit be an argument parameter? 201 // TODO: enable GetUnreachableMemoryString if it's part of stable API 202 //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */); 203 //result.append(s.c_str(), s.size()); 204 } 205 206 write(fd, result.string(), result.size()); 207 return NO_ERROR; 208 } 209 210 } // anonymous namespace 211 212 //static 213 sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) { 214 sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context); 215 216 if (!player->init()) { 217 return NULL; 218 } 219 220 ALOGV("Create new player(%p)", player.get()); 221 222 addPlayer(player); 223 return player; 224 } 225 226 // static 227 status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) { 228 return dumpPlayers(fd, args); 229 } 230 231 MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) { 232 ALOGV("constructor"); 233 mSrcId = 0; 234 mLockThreadId = 0; 235 mListener = NULL; 236 mStreamType = AUDIO_STREAM_MUSIC; 237 mAudioAttributes = NULL; 238 mContext = new JObjectHolder(context); 239 mCurrentPosition = -1; 240 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 241 mSeekPosition = -1; 242 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 243 mCurrentState = MEDIA_PLAYER2_IDLE; 244 mTransitionToNext = false; 245 mLoop = false; 246 mVolume = 1.0; 247 mVideoWidth = mVideoHeight = 0; 248 mSendLevel = 0; 249 250 mPid = AIBinder_getCallingPid(); 251 mUid = AIBinder_getCallingUid(); 252 253 mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/); 254 } 255 256 MediaPlayer2::~MediaPlayer2() { 257 ALOGV("destructor"); 258 disconnect(); 259 removePlayer(this); 260 } 261 262 bool MediaPlayer2::init() { 263 // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own 264 // looper for notification. 265 return true; 266 } 267 268 void MediaPlayer2::disconnect() { 269 ALOGV("disconnect"); 270 sp<MediaPlayer2Interface> p; 271 { 272 Mutex::Autolock _l(mLock); 273 p = mPlayer; 274 mPlayer.clear(); 275 } 276 277 if (p != 0) { 278 p->setListener(NULL); 279 p->reset(); 280 } 281 282 { 283 Mutex::Autolock _l(mLock); 284 disconnectNativeWindow_l(); 285 } 286 } 287 288 void MediaPlayer2::clear_l() { 289 mCurrentPosition = -1; 290 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 291 mSeekPosition = -1; 292 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 293 mVideoWidth = mVideoHeight = 0; 294 } 295 296 status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) { 297 ALOGV("setListener"); 298 Mutex::Autolock _l(mLock); 299 mListener = listener; 300 return NO_ERROR; 301 } 302 303 status_t MediaPlayer2::getSrcId(int64_t *srcId) { 304 if (srcId == NULL) { 305 return BAD_VALUE; 306 } 307 308 Mutex::Autolock _l(mLock); 309 *srcId = mSrcId; 310 return OK; 311 } 312 313 status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) { 314 if (dsd == NULL) { 315 return BAD_VALUE; 316 } 317 // Microsecond is used in NuPlayer2. 318 if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) { 319 dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs; 320 ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs); 321 } 322 if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) { 323 dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs; 324 ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs); 325 } 326 ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId); 327 328 sp<MediaPlayer2Interface> oldPlayer; 329 330 { 331 Mutex::Autolock _l(mLock); 332 if (!((mCurrentState & MEDIA_PLAYER2_IDLE) 333 || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) { 334 ALOGE("setDataSource called in wrong state %d", mCurrentState); 335 return INVALID_OPERATION; 336 } 337 338 sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext); 339 status_t err = player->initCheck(); 340 if (err != NO_ERROR) { 341 ALOGE("Failed to create player object, initCheck failed(%d)", err); 342 return err; 343 } 344 345 clear_l(); 346 347 player->setListener(new proxyListener(this)); 348 player->setAudioSink(mAudioOutput); 349 350 err = player->setDataSource(dsd); 351 if (err != OK) { 352 ALOGE("setDataSource error: %d", err); 353 return err; 354 } 355 356 sp<MediaPlayer2Interface> oldPlayer = mPlayer; 357 mPlayer = player; 358 mSrcId = dsd->mId; 359 mCurrentState = MEDIA_PLAYER2_INITIALIZED; 360 } 361 362 if (oldPlayer != NULL) { 363 oldPlayer->setListener(NULL); 364 oldPlayer->reset(); 365 } 366 367 return OK; 368 } 369 370 status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) { 371 if (dsd == NULL) { 372 return BAD_VALUE; 373 } 374 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId); 375 376 Mutex::Autolock _l(mLock); 377 if (mPlayer == NULL) { 378 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get()); 379 return INVALID_OPERATION; 380 } 381 return mPlayer->prepareNextDataSource(dsd); 382 } 383 384 status_t MediaPlayer2::playNextDataSource(int64_t srcId) { 385 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId); 386 387 Mutex::Autolock _l(mLock); 388 if (mPlayer == NULL) { 389 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get()); 390 return INVALID_OPERATION; 391 } 392 mSrcId = srcId; 393 mTransitionToNext = true; 394 return mPlayer->playNextDataSource(srcId); 395 } 396 397 status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) { 398 Mutex::Autolock _l(mLock); 399 const bool hasBeenInitialized = 400 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) && 401 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE); 402 if ((mPlayer == NULL) || !hasBeenInitialized) { 403 ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get()); 404 return INVALID_OPERATION; 405 } 406 return mPlayer->invoke(request, reply); 407 } 408 409 void MediaPlayer2::disconnectNativeWindow_l() { 410 if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) { 411 status_t err = native_window_api_disconnect( 412 mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA); 413 414 if (err != OK) { 415 ALOGW("nativeWindowDisconnect returned an error: %s (%d)", 416 strerror(-err), err); 417 } 418 } 419 mConnectedWindow.clear(); 420 } 421 422 status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) { 423 ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow()); 424 ALOGV("setVideoSurfaceTexture(%p)", anw); 425 Mutex::Autolock _l(mLock); 426 if (mPlayer == 0) { 427 return NO_INIT; 428 } 429 430 if (anw != NULL) { 431 if (mConnectedWindow != NULL 432 && mConnectedWindow->getANativeWindow() == anw) { 433 return OK; 434 } 435 status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA); 436 437 if (err != OK) { 438 ALOGE("setVideoSurfaceTexture failed: %d", err); 439 // Note that we must do the reset before disconnecting from the ANW. 440 // Otherwise queue/dequeue calls could be made on the disconnected 441 // ANW, which may result in errors. 442 mPlayer->reset(); 443 disconnectNativeWindow_l(); 444 return err; 445 } 446 } 447 448 // Note that we must set the player's new GraphicBufferProducer before 449 // disconnecting the old one. Otherwise queue/dequeue calls could be made 450 // on the disconnected ANW, which may result in errors. 451 status_t err = mPlayer->setVideoSurfaceTexture(nww); 452 453 disconnectNativeWindow_l(); 454 455 if (err == OK) { 456 mConnectedWindow = nww; 457 mLock.unlock(); 458 } else if (anw != NULL) { 459 mLock.unlock(); 460 status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA); 461 462 if (err != OK) { 463 ALOGW("nativeWindowDisconnect returned an error: %s (%d)", 464 strerror(-err), err); 465 } 466 } 467 468 return err; 469 } 470 471 status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) { 472 ALOGV("getBufferingSettings"); 473 474 Mutex::Autolock _l(mLock); 475 if (mPlayer == 0) { 476 return NO_INIT; 477 } 478 479 status_t ret = mPlayer->getBufferingSettings(buffering); 480 if (ret == NO_ERROR) { 481 ALOGV("getBufferingSettings{%s}", buffering->toString().string()); 482 } else { 483 ALOGE("getBufferingSettings returned %d", ret); 484 } 485 return ret; 486 } 487 488 status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) { 489 ALOGV("setBufferingSettings{%s}", buffering.toString().string()); 490 491 Mutex::Autolock _l(mLock); 492 if (mPlayer == 0) { 493 return NO_INIT; 494 } 495 return mPlayer->setBufferingSettings(buffering); 496 } 497 498 status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) { 499 if (mAudioOutput != NULL) { 500 mAudioOutput->setAudioAttributes(attributes); 501 } 502 return NO_ERROR; 503 } 504 505 status_t MediaPlayer2::prepareAsync() { 506 ALOGV("prepareAsync"); 507 Mutex::Autolock _l(mLock); 508 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) { 509 if (mAudioAttributes != NULL) { 510 status_t err = setAudioAttributes_l(mAudioAttributes->getJObject()); 511 if (err != OK) { 512 return err; 513 } 514 } 515 mCurrentState = MEDIA_PLAYER2_PREPARING; 516 return mPlayer->prepareAsync(); 517 } 518 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 519 return INVALID_OPERATION; 520 } 521 522 status_t MediaPlayer2::start() { 523 ALOGV("start"); 524 525 status_t ret = NO_ERROR; 526 Mutex::Autolock _l(mLock); 527 528 mLockThreadId = getThreadId(); 529 530 if (mCurrentState & MEDIA_PLAYER2_STARTED) { 531 ret = NO_ERROR; 532 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED | 533 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) { 534 mPlayer->setLooping(mLoop); 535 536 if (mAudioOutput != 0) { 537 mAudioOutput->setVolume(mVolume); 538 } 539 540 if (mAudioOutput != 0) { 541 mAudioOutput->setAuxEffectSendLevel(mSendLevel); 542 } 543 mCurrentState = MEDIA_PLAYER2_STARTED; 544 ret = mPlayer->start(); 545 if (ret != NO_ERROR) { 546 mCurrentState = MEDIA_PLAYER2_STATE_ERROR; 547 } else { 548 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) { 549 ALOGV("playback completed immediately following start()"); 550 } 551 } 552 } else { 553 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 554 ret = INVALID_OPERATION; 555 } 556 557 mLockThreadId = 0; 558 559 return ret; 560 } 561 562 status_t MediaPlayer2::pause() { 563 ALOGV("pause"); 564 Mutex::Autolock _l(mLock); 565 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE)) 566 return NO_ERROR; 567 if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) { 568 status_t ret = mPlayer->pause(); 569 if (ret != NO_ERROR) { 570 mCurrentState = MEDIA_PLAYER2_STATE_ERROR; 571 } else { 572 mCurrentState = MEDIA_PLAYER2_PAUSED; 573 mTransitionToNext = false; 574 } 575 return ret; 576 } 577 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 578 return INVALID_OPERATION; 579 } 580 581 bool MediaPlayer2::isPlaying() { 582 Mutex::Autolock _l(mLock); 583 if (mPlayer != 0) { 584 bool temp = mPlayer->isPlaying(); 585 ALOGV("isPlaying: %d", temp); 586 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) { 587 ALOGE("internal/external state mismatch corrected"); 588 mCurrentState = MEDIA_PLAYER2_PAUSED; 589 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) { 590 ALOGE("internal/external state mismatch corrected"); 591 mCurrentState = MEDIA_PLAYER2_STARTED; 592 } 593 return temp; 594 } 595 ALOGV("isPlaying: no active player"); 596 return false; 597 } 598 599 mediaplayer2_states MediaPlayer2::getState() { 600 Mutex::Autolock _l(mLock); 601 if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) { 602 return MEDIAPLAYER2_STATE_ERROR; 603 } 604 if (mPlayer == 0 605 || (mCurrentState & 606 (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) { 607 return MEDIAPLAYER2_STATE_IDLE; 608 } 609 if (mCurrentState & MEDIA_PLAYER2_STARTED) { 610 return MEDIAPLAYER2_STATE_PLAYING; 611 } 612 if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) { 613 return MEDIAPLAYER2_STATE_PAUSED; 614 } 615 // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true 616 return MEDIAPLAYER2_STATE_PREPARED; 617 } 618 619 status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) { 620 ALOGV("setPlaybackSettings: %f %f %d %d", 621 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode); 622 // Negative speed and pitch does not make sense. Further validation will 623 // be done by the respective mediaplayers. 624 if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) { 625 return BAD_VALUE; 626 } 627 Mutex::Autolock _l(mLock); 628 if (mPlayer == 0) { 629 return INVALID_OPERATION; 630 } 631 632 status_t err = mPlayer->setPlaybackSettings(rate); 633 return err; 634 } 635 636 status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) { 637 Mutex::Autolock _l(mLock); 638 if (mPlayer == 0) { 639 return INVALID_OPERATION; 640 } 641 status_t ret = mPlayer->getPlaybackSettings(rate); 642 if (ret == NO_ERROR) { 643 ALOGV("getPlaybackSettings(%f, %f, %d, %d)", 644 rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode); 645 } else { 646 ALOGV("getPlaybackSettings returned %d", ret); 647 } 648 return ret; 649 } 650 651 status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) { 652 ALOGV("setSyncSettings: %u %u %f %f", 653 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint); 654 Mutex::Autolock _l(mLock); 655 if (mPlayer == 0) return INVALID_OPERATION; 656 return mPlayer->setSyncSettings(sync, videoFpsHint); 657 } 658 659 status_t MediaPlayer2::getSyncSettings( 660 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) { 661 Mutex::Autolock _l(mLock); 662 if (mPlayer == 0) { 663 return INVALID_OPERATION; 664 } 665 status_t ret = mPlayer->getSyncSettings(sync, videoFps); 666 if (ret == NO_ERROR) { 667 ALOGV("getSyncSettings(%u, %u, %f, %f)", 668 sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps); 669 } else { 670 ALOGV("getSyncSettings returned %d", ret); 671 } 672 return ret; 673 674 } 675 676 status_t MediaPlayer2::getVideoWidth(int *w) { 677 ALOGV("getVideoWidth"); 678 Mutex::Autolock _l(mLock); 679 if (mPlayer == 0) { 680 return INVALID_OPERATION; 681 } 682 *w = mVideoWidth; 683 return NO_ERROR; 684 } 685 686 status_t MediaPlayer2::getVideoHeight(int *h) { 687 ALOGV("getVideoHeight"); 688 Mutex::Autolock _l(mLock); 689 if (mPlayer == 0) { 690 return INVALID_OPERATION; 691 } 692 *h = mVideoHeight; 693 return NO_ERROR; 694 } 695 696 status_t MediaPlayer2::getCurrentPosition(int64_t *msec) { 697 ALOGV("getCurrentPosition"); 698 Mutex::Autolock _l(mLock); 699 if (mPlayer == 0) { 700 return INVALID_OPERATION; 701 } 702 if (mCurrentPosition >= 0) { 703 ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition); 704 *msec = mCurrentPosition; 705 return NO_ERROR; 706 } 707 status_t ret = mPlayer->getCurrentPosition(msec); 708 if (ret == NO_ERROR) { 709 ALOGV("getCurrentPosition = %lld", (long long)*msec); 710 } else { 711 ALOGE("getCurrentPosition returned %d", ret); 712 } 713 return ret; 714 } 715 716 status_t MediaPlayer2::getDuration(int64_t srcId, int64_t *msec) { 717 Mutex::Autolock _l(mLock); 718 // TODO: cache duration for currentSrcId and nextSrcId, and return correct 719 // value for nextSrcId. 720 if (srcId != mSrcId) { 721 *msec = -1; 722 return OK; 723 } 724 725 ALOGV("getDuration_l"); 726 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED | 727 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)); 728 if (mPlayer == 0 || !isValidState) { 729 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u", 730 mPlayer.get(), mCurrentState); 731 return INVALID_OPERATION; 732 } 733 int64_t durationMs; 734 status_t ret = mPlayer->getDuration(&durationMs); 735 736 if (ret == NO_ERROR) { 737 ALOGV("getDuration = %lld", (long long)durationMs); 738 } else { 739 ALOGE("getDuration returned %d", ret); 740 // Do not enter error state just because no duration was available. 741 durationMs = -1; 742 } 743 744 if (msec) { 745 *msec = durationMs; 746 } 747 return OK; 748 } 749 750 status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) { 751 ALOGV("seekTo (%lld, %d)", (long long)msec, mode); 752 if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED | 753 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) { 754 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", 755 mPlayer.get(), mCurrentState); 756 return INVALID_OPERATION; 757 } 758 if (msec < 0) { 759 ALOGW("Attempt to seek to invalid position: %lld", (long long)msec); 760 msec = 0; 761 } 762 763 int64_t durationMs; 764 status_t err = mPlayer->getDuration(&durationMs); 765 766 if (err != OK) { 767 ALOGW("Stream has no duration and is therefore not seekable."); 768 return err; 769 } 770 771 if (msec > durationMs) { 772 ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld", 773 (long long)msec, (long long)durationMs); 774 775 msec = durationMs; 776 } 777 778 // cache duration 779 mCurrentPosition = msec; 780 mCurrentSeekMode = mode; 781 if (mSeekPosition < 0) { 782 mSeekPosition = msec; 783 mSeekMode = mode; 784 return mPlayer->seekTo(msec, mode); 785 } 786 ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode); 787 return NO_ERROR; 788 } 789 790 status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) { 791 mLockThreadId = getThreadId(); 792 Mutex::Autolock _l(mLock); 793 status_t result = seekTo_l(msec, mode); 794 mLockThreadId = 0; 795 796 return result; 797 } 798 799 status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) { 800 Mutex::Autolock _l(mLock); 801 if (mPlayer != 0) { 802 return INVALID_OPERATION; 803 } 804 805 return mPlayer->notifyAt(mediaTimeUs); 806 } 807 808 status_t MediaPlayer2::reset_l() { 809 mLoop = false; 810 if (mCurrentState == MEDIA_PLAYER2_IDLE) { 811 return NO_ERROR; 812 } 813 if (mPlayer != 0) { 814 status_t ret = mPlayer->reset(); 815 if (ret != NO_ERROR) { 816 ALOGE("reset() failed with return code (%d)", ret); 817 mCurrentState = MEDIA_PLAYER2_STATE_ERROR; 818 } else { 819 mPlayer->setListener(NULL); 820 mCurrentState = MEDIA_PLAYER2_IDLE; 821 mTransitionToNext = false; 822 } 823 // setDataSource has to be called again to create a 824 // new mediaplayer. 825 mPlayer = 0; 826 return ret; 827 } 828 clear_l(); 829 return NO_ERROR; 830 } 831 832 status_t MediaPlayer2::reset() { 833 ALOGV("reset"); 834 mLockThreadId = getThreadId(); 835 Mutex::Autolock _l(mLock); 836 status_t result = reset_l(); 837 mLockThreadId = 0; 838 839 return result; 840 } 841 842 status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) { 843 ALOGV("MediaPlayer2::setAudioStreamType"); 844 Mutex::Autolock _l(mLock); 845 if (mStreamType == type) return NO_ERROR; 846 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED | 847 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) { 848 // Can't change the stream type after prepare 849 ALOGE("setAudioStream called in state %d", mCurrentState); 850 return INVALID_OPERATION; 851 } 852 // cache 853 mStreamType = type; 854 return OK; 855 } 856 857 status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) { 858 ALOGV("getAudioStreamType"); 859 Mutex::Autolock _l(mLock); 860 *type = mStreamType; 861 return OK; 862 } 863 864 status_t MediaPlayer2::setLooping(int loop) { 865 ALOGV("MediaPlayer2::setLooping"); 866 Mutex::Autolock _l(mLock); 867 mLoop = (loop != 0); 868 if (mPlayer != 0) { 869 return mPlayer->setLooping(loop); 870 } 871 return OK; 872 } 873 874 bool MediaPlayer2::isLooping() { 875 ALOGV("isLooping"); 876 Mutex::Autolock _l(mLock); 877 if (mPlayer != 0) { 878 return mLoop; 879 } 880 ALOGV("isLooping: no active player"); 881 return false; 882 } 883 884 status_t MediaPlayer2::setVolume(float volume) { 885 ALOGV("MediaPlayer2::setVolume(%f)", volume); 886 Mutex::Autolock _l(mLock); 887 mVolume = volume; 888 if (mAudioOutput != 0) { 889 mAudioOutput->setVolume(volume); 890 } 891 return OK; 892 } 893 894 status_t MediaPlayer2::setAudioSessionId(int32_t sessionId) { 895 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId); 896 Mutex::Autolock _l(mLock); 897 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) { 898 ALOGE("setAudioSessionId called in state %d", mCurrentState); 899 return INVALID_OPERATION; 900 } 901 if (sessionId < 0) { 902 return BAD_VALUE; 903 } 904 if (mAudioOutput != NULL && sessionId != mAudioOutput->getSessionId()) { 905 mAudioOutput->setSessionId(sessionId); 906 } 907 return NO_ERROR; 908 } 909 910 int32_t MediaPlayer2::getAudioSessionId() { 911 Mutex::Autolock _l(mLock); 912 if (mAudioOutput != NULL) { 913 return mAudioOutput->getSessionId(); 914 } 915 return 0; 916 } 917 918 status_t MediaPlayer2::setAuxEffectSendLevel(float level) { 919 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level); 920 Mutex::Autolock _l(mLock); 921 mSendLevel = level; 922 if (mAudioOutput != 0) { 923 return mAudioOutput->setAuxEffectSendLevel(level); 924 } 925 return OK; 926 } 927 928 status_t MediaPlayer2::attachAuxEffect(int effectId) { 929 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId); 930 Mutex::Autolock _l(mLock); 931 if (mAudioOutput == 0 || 932 (mCurrentState & MEDIA_PLAYER2_IDLE) || 933 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) { 934 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get()); 935 return INVALID_OPERATION; 936 } 937 938 return mAudioOutput->attachAuxEffect(effectId); 939 } 940 941 // always call with lock held 942 status_t MediaPlayer2::checkState_l() { 943 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED | 944 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) { 945 // Can't change the audio attributes after prepare 946 ALOGE("trying to set audio attributes called in state %d", mCurrentState); 947 return INVALID_OPERATION; 948 } 949 return OK; 950 } 951 952 status_t MediaPlayer2::setAudioAttributes(const jobject attributes) { 953 ALOGV("MediaPlayer2::setAudioAttributes"); 954 status_t status = INVALID_OPERATION; 955 Mutex::Autolock _l(mLock); 956 if (checkState_l() != OK) { 957 return status; 958 } 959 mAudioAttributes = new JObjectHolder(attributes); 960 status = setAudioAttributes_l(attributes); 961 return status; 962 } 963 964 jobject MediaPlayer2::getAudioAttributes() { 965 ALOGV("MediaPlayer2::getAudioAttributes)"); 966 Mutex::Autolock _l(mLock); 967 return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL; 968 } 969 970 status_t MediaPlayer2::getParameter(int key, Parcel *reply) { 971 ALOGV("MediaPlayer2::getParameter(%d)", key); 972 Mutex::Autolock _l(mLock); 973 if (mPlayer == NULL) { 974 ALOGV("getParameter: no active player"); 975 return INVALID_OPERATION; 976 } 977 978 status_t status = mPlayer->getParameter(key, reply); 979 if (status != OK) { 980 ALOGD("getParameter returns %d", status); 981 } 982 return status; 983 } 984 985 // for mediametrics 986 status_t MediaPlayer2::getMetrics(char **buffer, size_t *length) { 987 ALOGD("MediaPlayer2::getMetrics()"); 988 Mutex::Autolock _l(mLock); 989 if (mPlayer == NULL) { 990 ALOGV("getMetrics: no active player"); 991 return INVALID_OPERATION; 992 } 993 994 status_t status = mPlayer->getMetrics(buffer, length); 995 if (status != OK) { 996 ALOGD("getMetrics returns %d", status); 997 } 998 return status; 999 } 1000 1001 void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) { 1002 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d", 1003 (long long)srcId, msg, ext1, ext2); 1004 1005 bool send = true; 1006 bool locked = false; 1007 1008 // TODO: In the future, we might be on the same thread if the app is 1009 // running in the same process as the media server. In that case, 1010 // this will deadlock. 1011 // 1012 // The threadId hack below works around this for the care of prepare, 1013 // seekTo, start, and reset within the same process. 1014 // FIXME: Remember, this is a hack, it's not even a hack that is applied 1015 // consistently for all use-cases, this needs to be revisited. 1016 if (mLockThreadId != getThreadId()) { 1017 mLock.lock(); 1018 locked = true; 1019 } 1020 1021 // Allows calls from JNI in idle state to notify errors 1022 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) { 1023 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer", 1024 (long long)srcId, msg, ext1, ext2); 1025 if (locked) mLock.unlock(); // release the lock when done. 1026 return; 1027 } 1028 1029 switch (msg) { 1030 case MEDIA2_NOP: // interface test message 1031 break; 1032 case MEDIA2_PREPARED: 1033 ALOGV("MediaPlayer2::notify() prepared, srcId=%lld", (long long)srcId); 1034 if (srcId == mSrcId) { 1035 mCurrentState = MEDIA_PLAYER2_PREPARED; 1036 } 1037 break; 1038 case MEDIA2_DRM_INFO: 1039 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)", 1040 (long long)srcId, msg, ext1, ext2, obj); 1041 break; 1042 case MEDIA2_PLAYBACK_COMPLETE: 1043 ALOGV("playback complete"); 1044 if (mCurrentState == MEDIA_PLAYER2_IDLE) { 1045 ALOGE("playback complete in idle state"); 1046 } 1047 if (!mLoop && srcId == mSrcId) { 1048 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE; 1049 } 1050 break; 1051 case MEDIA2_ERROR: 1052 // Always log errors. 1053 // ext1: Media framework error code. 1054 // ext2: Implementation dependant error code. 1055 ALOGE("error (%d, %d)", ext1, ext2); 1056 mCurrentState = MEDIA_PLAYER2_STATE_ERROR; 1057 break; 1058 case MEDIA2_INFO: 1059 // ext1: Media framework error code. 1060 // ext2: Implementation dependant error code. 1061 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) { 1062 ALOGW("info/warning (%d, %d)", ext1, ext2); 1063 1064 if (ext1 == MEDIA2_INFO_DATA_SOURCE_START && srcId == mSrcId && mTransitionToNext) { 1065 mCurrentState = MEDIA_PLAYER2_STARTED; 1066 mTransitionToNext = false; 1067 } 1068 } 1069 break; 1070 case MEDIA2_SEEK_COMPLETE: 1071 ALOGV("Received seek complete"); 1072 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) { 1073 ALOGV("Executing queued seekTo(%lld, %d)", 1074 (long long)mCurrentPosition, mCurrentSeekMode); 1075 mSeekPosition = -1; 1076 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 1077 seekTo_l(mCurrentPosition, mCurrentSeekMode); 1078 } 1079 else { 1080 ALOGV("All seeks complete - return to regularly scheduled program"); 1081 mCurrentPosition = mSeekPosition = -1; 1082 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC; 1083 } 1084 break; 1085 case MEDIA2_BUFFERING_UPDATE: 1086 ALOGV("buffering %d", ext1); 1087 break; 1088 case MEDIA2_SET_VIDEO_SIZE: 1089 ALOGV("New video size %d x %d", ext1, ext2); 1090 mVideoWidth = ext1; 1091 mVideoHeight = ext2; 1092 break; 1093 case MEDIA2_NOTIFY_TIME: 1094 ALOGV("Received notify time message"); 1095 break; 1096 case MEDIA2_TIMED_TEXT: 1097 ALOGV("Received timed text message"); 1098 break; 1099 case MEDIA2_SUBTITLE_DATA: 1100 ALOGV("Received subtitle data message"); 1101 break; 1102 case MEDIA2_META_DATA: 1103 ALOGV("Received timed metadata message"); 1104 break; 1105 default: 1106 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); 1107 break; 1108 } 1109 1110 sp<MediaPlayer2Listener> listener = mListener; 1111 if (locked) mLock.unlock(); 1112 1113 // this prevents re-entrant calls into client code 1114 if ((listener != 0) && send) { 1115 Mutex::Autolock _l(mNotifyLock); 1116 ALOGV("callback application"); 1117 listener->notify(srcId, msg, ext1, ext2, obj); 1118 ALOGV("back from callback"); 1119 } 1120 } 1121 1122 // Modular DRM 1123 status_t MediaPlayer2::prepareDrm( 1124 int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) { 1125 // TODO change to ALOGV 1126 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid, 1127 drmSessionId.array(), drmSessionId.size()); 1128 Mutex::Autolock _l(mLock); 1129 if (mPlayer == NULL) { 1130 return NO_INIT; 1131 } 1132 1133 // Only allowed it in player's preparing/prepared state. 1134 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or 1135 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering). 1136 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener. 1137 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) { 1138 ALOGW("prepareDrm(%lld) called in non-prepare state(%d)", (long long)srcId, mCurrentState); 1139 if (srcId == mSrcId) { 1140 return INVALID_OPERATION; 1141 } 1142 } 1143 1144 if (drmSessionId.isEmpty()) { 1145 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId."); 1146 return INVALID_OPERATION; 1147 } 1148 1149 // Passing down to mediaserver mainly for creating the crypto 1150 status_t status = mPlayer->prepareDrm(srcId, uuid, drmSessionId); 1151 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status); 1152 1153 // TODO change to ALOGV 1154 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status); 1155 1156 return status; 1157 } 1158 1159 status_t MediaPlayer2::releaseDrm(int64_t srcId) { 1160 Mutex::Autolock _l(mLock); 1161 if (mPlayer == NULL) { 1162 return NO_INIT; 1163 } 1164 1165 // Not allowing releaseDrm in an active/resumable state 1166 if (mCurrentState & (MEDIA_PLAYER2_STARTED | 1167 MEDIA_PLAYER2_PAUSED | 1168 MEDIA_PLAYER2_PLAYBACK_COMPLETE | 1169 MEDIA_PLAYER2_STATE_ERROR)) { 1170 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState); 1171 return INVALID_OPERATION; 1172 } 1173 1174 status_t status = mPlayer->releaseDrm(srcId); 1175 // TODO change to ALOGV 1176 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status); 1177 if (status != OK) { 1178 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status); 1179 // Overriding to OK so the client proceed with its own cleanup 1180 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway. 1181 status = OK; 1182 } 1183 1184 return status; 1185 } 1186 1187 status_t MediaPlayer2::setPreferredDevice(jobject device) { 1188 Mutex::Autolock _l(mLock); 1189 if (mAudioOutput == NULL) { 1190 ALOGV("setPreferredDevice: audio sink not init"); 1191 return NO_INIT; 1192 } 1193 return mAudioOutput->setPreferredDevice(device); 1194 } 1195 1196 jobject MediaPlayer2::getRoutedDevice() { 1197 Mutex::Autolock _l(mLock); 1198 if (mAudioOutput == NULL) { 1199 ALOGV("getRoutedDevice: audio sink not init"); 1200 return nullptr; 1201 } 1202 return mAudioOutput->getRoutedDevice(); 1203 } 1204 1205 status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) { 1206 Mutex::Autolock _l(mLock); 1207 if (mAudioOutput == NULL) { 1208 ALOGV("addAudioDeviceCallback: player not init"); 1209 return NO_INIT; 1210 } 1211 return mAudioOutput->addAudioDeviceCallback(routingDelegate); 1212 } 1213 1214 status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) { 1215 Mutex::Autolock _l(mLock); 1216 if (mAudioOutput == NULL) { 1217 ALOGV("addAudioDeviceCallback: player not init"); 1218 return NO_INIT; 1219 } 1220 return mAudioOutput->removeAudioDeviceCallback(listener); 1221 } 1222 1223 status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) { 1224 const size_t SIZE = 256; 1225 char buffer[SIZE]; 1226 String8 result; 1227 result.append(" MediaPlayer2\n"); 1228 snprintf(buffer, 255, " pid(%d), looping(%s)\n", mPid, mLoop?"true": "false"); 1229 result.append(buffer); 1230 1231 sp<MediaPlayer2Interface> player; 1232 sp<MediaPlayer2AudioOutput> audioOutput; 1233 bool locked = false; 1234 for (int i = 0; i < kDumpLockRetries; ++i) { 1235 if (mLock.tryLock() == NO_ERROR) { 1236 locked = true; 1237 break; 1238 } 1239 usleep(kDumpLockSleepUs); 1240 } 1241 1242 if (locked) { 1243 player = mPlayer; 1244 audioOutput = mAudioOutput; 1245 mLock.unlock(); 1246 } else { 1247 result.append(" lock is taken, no dump from player and audio output\n"); 1248 } 1249 write(fd, result.string(), result.size()); 1250 1251 if (player != NULL) { 1252 player->dump(fd, args); 1253 } 1254 if (audioOutput != 0) { 1255 audioOutput->dump(fd, args); 1256 } 1257 write(fd, "\n", 1); 1258 return NO_ERROR; 1259 } 1260 1261 } // namespace android 1262