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:
proxyListener(const wp<MediaPlayer2> & player)54     proxyListener(const wp<MediaPlayer2> &player)
55         : mPlayer(player) { }
56 
~proxyListener()57     ~proxyListener() { };
58 
notify(int64_t srcId,int msg,int ext1,int ext2,const PlayerMessage * obj)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 
ensureInit_l()74 void ensureInit_l() {
75     if (sPlayers == NULL) {
76         sPlayers = new SortedVector<wp<MediaPlayer2> >();
77     }
78 }
79 
addPlayer(const wp<MediaPlayer2> & player)80 void addPlayer(const wp<MediaPlayer2>& player) {
81     Mutex::Autolock lock(sRecordLock);
82     ensureInit_l();
83     sPlayers->add(player);
84 }
85 
removePlayer(const wp<MediaPlayer2> & player)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  */
dumpPlayers(int fd,const Vector<String16> & args)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
Create(int32_t sessionId,jobject context)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
DumpAll(int fd,const Vector<String16> & args)227 status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
228     return dumpPlayers(fd, args);
229 }
230 
MediaPlayer2(int32_t sessionId,jobject context)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 
~MediaPlayer2()256 MediaPlayer2::~MediaPlayer2() {
257     ALOGV("destructor");
258     disconnect();
259     removePlayer(this);
260 }
261 
init()262 bool MediaPlayer2::init() {
263     // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
264     // looper for notification.
265     return true;
266 }
267 
disconnect()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 
clear_l()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 
setListener(const sp<MediaPlayer2Listener> & listener)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 
getSrcId(int64_t * srcId)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 
setDataSource(const sp<DataSourceDesc> & dsd)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 
prepareNextDataSource(const sp<DataSourceDesc> & dsd)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 
playNextDataSource(int64_t srcId)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 
invoke(const PlayerMessage & request,PlayerMessage * reply)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 
disconnectNativeWindow_l()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 
setVideoSurfaceTexture(const sp<ANativeWindowWrapper> & nww)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 
getBufferingSettings(BufferingSettings * buffering)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 
setBufferingSettings(const BufferingSettings & buffering)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 
setAudioAttributes_l(const jobject attributes)498 status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
499     if (mAudioOutput != NULL) {
500         mAudioOutput->setAudioAttributes(attributes);
501     }
502     return NO_ERROR;
503 }
504 
prepareAsync()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 
start()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 
pause()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 
isPlaying()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 
getState()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 
setPlaybackSettings(const AudioPlaybackRate & rate)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 
getPlaybackSettings(AudioPlaybackRate * rate)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 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)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 
getSyncSettings(AVSyncSettings * sync,float * videoFps)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 
getVideoWidth(int * w)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 
getVideoHeight(int * h)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 
getCurrentPosition(int64_t * msec)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 
getDuration(int64_t srcId,int64_t * msec)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 
seekTo_l(int64_t msec,MediaPlayer2SeekMode mode)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 
seekTo(int64_t msec,MediaPlayer2SeekMode mode)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 
notifyAt(int64_t mediaTimeUs)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 
reset_l()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 
reset()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 
setAudioStreamType(audio_stream_type_t type)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 
getAudioStreamType(audio_stream_type_t * type)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 
setLooping(int loop)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 
isLooping()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 
setVolume(float volume)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 
setAudioSessionId(int32_t sessionId)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 
getAudioSessionId()910 int32_t MediaPlayer2::getAudioSessionId() {
911     Mutex::Autolock _l(mLock);
912     if (mAudioOutput != NULL) {
913         return mAudioOutput->getSessionId();
914     }
915     return 0;
916 }
917 
setAuxEffectSendLevel(float level)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 
attachAuxEffect(int effectId)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
checkState_l()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 
setAudioAttributes(const jobject attributes)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 
getAudioAttributes()964 jobject MediaPlayer2::getAudioAttributes() {
965     ALOGV("MediaPlayer2::getAudioAttributes)");
966     Mutex::Autolock _l(mLock);
967     return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
968 }
969 
getParameter(int key,Parcel * reply)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
getMetrics(char ** buffer,size_t * length)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 
notify(int64_t srcId,int msg,int ext1,int ext2,const PlayerMessage * obj)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
prepareDrm(int64_t srcId,const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)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 
releaseDrm(int64_t srcId)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 
setPreferredDevice(jobject device)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 
getRoutedDevice()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 
addAudioDeviceCallback(jobject routingDelegate)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 
removeAudioDeviceCallback(jobject listener)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 
dump(int fd,const Vector<String16> & args)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