Home | History | Annotate | Download | only in libmediaplayer2
      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