1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "NuPlayer2Driver"
19 #include <inttypes.h>
20 #include <utils/Log.h>
21 #include <cutils/properties.h>
22 
23 #include "NuPlayer2Driver.h"
24 
25 #include "NuPlayer2.h"
26 #include "NuPlayer2Source.h"
27 
28 #include <media/DataSourceDesc.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/ALooper.h>
31 #include <media/stagefright/foundation/AUtils.h>
32 #include <media/stagefright/foundation/ByteUtils.h>
33 #include <media/stagefright/MediaClock.h>
34 #include <media/stagefright/MetaData.h>
35 #include <media/stagefright/Utils.h>
36 
37 #include <media/IMediaAnalyticsService.h>
38 
39 static const int kDumpLockRetries = 50;
40 static const int kDumpLockSleepUs = 20000;
41 
42 namespace android {
43 
44 struct ParcelWrapper : public RefBase {
Createandroid::ParcelWrapper45     static sp<ParcelWrapper> Create(const Parcel *p) {
46         if (p != NULL) {
47             sp<ParcelWrapper> pw = new ParcelWrapper();
48             if (pw->appendFrom(p) == OK) {
49                 return pw;
50             }
51         }
52         return NULL;
53     }
54 
getParcelandroid::ParcelWrapper55     const Parcel *getParcel() {
56         return mParcel;
57     }
58 
59 protected:
~ParcelWrapperandroid::ParcelWrapper60     virtual ~ParcelWrapper() {
61         if (mParcel != NULL) {
62             delete mParcel;
63         }
64     }
65 
66 private:
ParcelWrapperandroid::ParcelWrapper67     ParcelWrapper()
68         : mParcel(NULL) { }
69 
appendFromandroid::ParcelWrapper70     status_t appendFrom(const Parcel *p) {
71         if (mParcel == NULL) {
72             mParcel = new Parcel;
73         }
74         return mParcel->appendFrom(p, 0 /* start */, p->dataSize());
75     }
76 
77     Parcel *mParcel;
78 };
79 
80 // key for media statistics
81 static const char *kKeyPlayer = "nuplayer";
82 // attrs for media statistics
83     // NB: these are matched with public Java API constants defined
84     // in frameworks/base/media/java/android/media/MediaPlayer2.java
85     // These must be kept synchronized with the constants there.
86 static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
87 static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
88 static const char *kPlayerWidth = "android.media.mediaplayer.width";
89 static const char *kPlayerHeight = "android.media.mediaplayer.height";
90 static const char *kPlayerFrames = "android.media.mediaplayer.frames";
91 static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
92 static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
93 static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
94 static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
95 static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
96 static const char *kPlayerError = "android.media.mediaplayer.err";
97 static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
98 
99 // NB: These are not yet exposed as public Java API constants.
100 static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
101 static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
102 //
103 static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
104 static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
105 static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
106 
107 
NuPlayer2Driver(pid_t pid,uid_t uid)108 NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
109     : mState(STATE_IDLE),
110       mAsyncResult(UNKNOWN_ERROR),
111       mSrcId(0),
112       mSetSurfaceInProgress(false),
113       mDurationUs(-1),
114       mPositionUs(-1),
115       mSeekInProgress(false),
116       mPlayingTimeUs(0),
117       mRebufferingTimeUs(0),
118       mRebufferingEvents(0),
119       mRebufferingAtExit(false),
120       mLooper(new ALooper),
121       mNuPlayer2Looper(new ALooper),
122       mMediaClock(new MediaClock),
123       mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
124       mPlayerFlags(0),
125       mAnalyticsItem(NULL),
126       mClientUid(uid),
127       mAtEOS(false),
128       mLooping(false),
129       mAutoLoop(false) {
130     ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
131     mLooper->setName("NuPlayer2Driver Looper");
132     mNuPlayer2Looper->setName("NuPlayer2 Looper");
133 
134     mMediaClock->init();
135 
136     // set up an analytics record
137     mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
138     mAnalyticsItem->setUid(mClientUid);
139 
140     mNuPlayer2Looper->start(
141             false, /* runOnCallingThread */
142             true,  /* canCallJava */
143             PRIORITY_AUDIO);
144 
145     mNuPlayer2Looper->registerHandler(mPlayer);
146 
147     mPlayer->setDriver(this);
148 }
149 
~NuPlayer2Driver()150 NuPlayer2Driver::~NuPlayer2Driver() {
151     ALOGV("~NuPlayer2Driver(%p)", this);
152     mNuPlayer2Looper->stop();
153     mLooper->stop();
154 
155     // finalize any pending metrics, usually a no-op.
156     updateMetrics("destructor");
157     logMetrics("destructor");
158 
159     if (mAnalyticsItem != NULL) {
160         delete mAnalyticsItem;
161         mAnalyticsItem = NULL;
162     }
163 }
164 
initCheck()165 status_t NuPlayer2Driver::initCheck() {
166     mLooper->start(
167             false, /* runOnCallingThread */
168             true,  /* canCallJava */
169             PRIORITY_AUDIO);
170 
171     mLooper->registerHandler(this);
172     return OK;
173 }
174 
setDataSource(const sp<DataSourceDesc> & dsd)175 status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
176     ALOGV("setDataSource(%p)", this);
177     Mutex::Autolock autoLock(mLock);
178 
179     if (mState != STATE_IDLE) {
180         return INVALID_OPERATION;
181     }
182 
183     mSrcId = dsd->mId;
184     mState = STATE_SET_DATASOURCE_PENDING;
185 
186     mPlayer->setDataSourceAsync(dsd);
187 
188     while (mState == STATE_SET_DATASOURCE_PENDING) {
189         mCondition.wait(mLock);
190     }
191 
192     return mAsyncResult;
193 }
194 
prepareNextDataSource(const sp<DataSourceDesc> & dsd)195 status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
196     ALOGV("prepareNextDataSource(%p)", this);
197     Mutex::Autolock autoLock(mLock);
198 
199     mPlayer->prepareNextDataSourceAsync(dsd);
200 
201     return OK;
202 }
203 
playNextDataSource(int64_t srcId)204 status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
205     ALOGV("playNextDataSource(%p)", this);
206     Mutex::Autolock autoLock(mLock);
207 
208     mSrcId = srcId;
209     mPlayer->playNextDataSource(srcId);
210 
211     return OK;
212 }
213 
setVideoSurfaceTexture(const sp<ANativeWindowWrapper> & nww)214 status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
215     ALOGV("setVideoSurfaceTexture(%p)", this);
216     Mutex::Autolock autoLock(mLock);
217 
218     if (mSetSurfaceInProgress) {
219         return INVALID_OPERATION;
220     }
221 
222     switch (mState) {
223         case STATE_SET_DATASOURCE_PENDING:
224         case STATE_RESET_IN_PROGRESS:
225             return INVALID_OPERATION;
226 
227         default:
228             break;
229     }
230 
231     mSetSurfaceInProgress = true;
232 
233     mPlayer->setVideoSurfaceTextureAsync(nww);
234 
235     while (mSetSurfaceInProgress) {
236         mCondition.wait(mLock);
237     }
238 
239     return OK;
240 }
241 
getBufferingSettings(BufferingSettings * buffering)242 status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
243     ALOGV("getBufferingSettings(%p)", this);
244     {
245         Mutex::Autolock autoLock(mLock);
246         if (mState == STATE_IDLE) {
247             return INVALID_OPERATION;
248         }
249     }
250 
251     return mPlayer->getBufferingSettings(buffering);
252 }
253 
setBufferingSettings(const BufferingSettings & buffering)254 status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
255     ALOGV("setBufferingSettings(%p)", this);
256     {
257         Mutex::Autolock autoLock(mLock);
258         if (mState == STATE_IDLE) {
259             return INVALID_OPERATION;
260         }
261     }
262 
263     return mPlayer->setBufferingSettings(buffering);
264 }
265 
prepareAsync()266 status_t NuPlayer2Driver::prepareAsync() {
267     ALOGV("prepareAsync(%p)", this);
268     Mutex::Autolock autoLock(mLock);
269 
270     switch (mState) {
271         case STATE_UNPREPARED:
272             mState = STATE_PREPARING;
273             mPlayer->prepareAsync();
274             return OK;
275         case STATE_STOPPED:
276             // this is really just paused. handle as seek to start
277             mAtEOS = false;
278             mState = STATE_STOPPED_AND_PREPARING;
279             mPlayer->seekToAsync(0, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
280                     true /* needNotify */);
281             return OK;
282         default:
283             return INVALID_OPERATION;
284     };
285 }
286 
start()287 status_t NuPlayer2Driver::start() {
288     ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
289     Mutex::Autolock autoLock(mLock);
290     return start_l();
291 }
292 
start_l()293 status_t NuPlayer2Driver::start_l() {
294     switch (mState) {
295         case STATE_PAUSED:
296         case STATE_STOPPED_AND_PREPARED:
297         case STATE_PREPARED:
298         {
299             mPlayer->start();
300 
301             // fall through
302         }
303 
304         case STATE_RUNNING:
305         {
306             if (mAtEOS) {
307                 mPlayer->seekToAsync(0);
308                 mAtEOS = false;
309                 mPositionUs = -1;
310             }
311             break;
312         }
313 
314         default:
315             return INVALID_OPERATION;
316     }
317 
318     mState = STATE_RUNNING;
319 
320     return OK;
321 }
322 
stop()323 status_t NuPlayer2Driver::stop() {
324     ALOGD("stop(%p)", this);
325     Mutex::Autolock autoLock(mLock);
326 
327     switch (mState) {
328         case STATE_RUNNING:
329             mPlayer->pause();
330             // fall through
331 
332         case STATE_PAUSED:
333             mState = STATE_STOPPED;
334             //notifyListener_l(MEDIA2_STOPPED);
335             break;
336 
337         case STATE_PREPARED:
338         case STATE_STOPPED:
339         case STATE_STOPPED_AND_PREPARING:
340         case STATE_STOPPED_AND_PREPARED:
341             mState = STATE_STOPPED;
342             break;
343 
344         default:
345             return INVALID_OPERATION;
346     }
347 
348     return OK;
349 }
350 
pause()351 status_t NuPlayer2Driver::pause() {
352     ALOGD("pause(%p)", this);
353     // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
354     // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
355     // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
356     // getCurrentPosition here.
357     int64_t unused;
358     getCurrentPosition(&unused);
359 
360     Mutex::Autolock autoLock(mLock);
361 
362     switch (mState) {
363         case STATE_PAUSED:
364         case STATE_PREPARED:
365             return OK;
366 
367         case STATE_RUNNING:
368             mState = STATE_PAUSED;
369             mPlayer->pause();
370             break;
371 
372         default:
373             return INVALID_OPERATION;
374     }
375 
376     return OK;
377 }
378 
isPlaying()379 bool NuPlayer2Driver::isPlaying() {
380     return mState == STATE_RUNNING && !mAtEOS;
381 }
382 
setPlaybackSettings(const AudioPlaybackRate & rate)383 status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
384     status_t err = mPlayer->setPlaybackSettings(rate);
385     if (err == OK) {
386         // try to update position
387         int64_t unused;
388         getCurrentPosition(&unused);
389         Mutex::Autolock autoLock(mLock);
390         if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
391             mState = STATE_PAUSED;
392         } else if (rate.mSpeed != 0.f
393                 && (mState == STATE_PAUSED
394                     || mState == STATE_STOPPED_AND_PREPARED
395                     || mState == STATE_PREPARED)) {
396             err = start_l();
397         }
398     }
399     return err;
400 }
401 
getPlaybackSettings(AudioPlaybackRate * rate)402 status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
403     return mPlayer->getPlaybackSettings(rate);
404 }
405 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)406 status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
407     return mPlayer->setSyncSettings(sync, videoFpsHint);
408 }
409 
getSyncSettings(AVSyncSettings * sync,float * videoFps)410 status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
411     return mPlayer->getSyncSettings(sync, videoFps);
412 }
413 
seekTo(int64_t msec,MediaPlayer2SeekMode mode)414 status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
415     ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
416     Mutex::Autolock autoLock(mLock);
417 
418     int64_t seekTimeUs = msec * 1000ll;
419 
420     switch (mState) {
421         case STATE_PREPARED:
422         case STATE_STOPPED_AND_PREPARED:
423         case STATE_PAUSED:
424         case STATE_RUNNING:
425         {
426             mAtEOS = false;
427             mSeekInProgress = true;
428             mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
429             break;
430         }
431 
432         default:
433             return INVALID_OPERATION;
434     }
435 
436     mPositionUs = seekTimeUs;
437     return OK;
438 }
439 
getCurrentPosition(int64_t * msec)440 status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
441     int64_t tempUs = 0;
442     {
443         Mutex::Autolock autoLock(mLock);
444         if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
445             tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
446             *msec = divRound(tempUs, (int64_t)(1000));
447             return OK;
448         }
449     }
450 
451     status_t ret = mPlayer->getCurrentPosition(&tempUs);
452 
453     Mutex::Autolock autoLock(mLock);
454     // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
455     // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
456     // position value that's different the seek to position.
457     if (ret != OK) {
458         tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
459     } else {
460         mPositionUs = tempUs;
461     }
462     *msec = divRound(tempUs, (int64_t)(1000));
463     return OK;
464 }
465 
getDuration(int64_t * msec)466 status_t NuPlayer2Driver::getDuration(int64_t *msec) {
467     Mutex::Autolock autoLock(mLock);
468 
469     if (mDurationUs < 0) {
470         return UNKNOWN_ERROR;
471     }
472 
473     *msec = (mDurationUs + 500ll) / 1000;
474 
475     return OK;
476 }
477 
updateMetrics(const char * where)478 void NuPlayer2Driver::updateMetrics(const char *where) {
479     if (where == NULL) {
480         where = "unknown";
481     }
482     ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
483 
484     // gather the final stats for this record
485     Vector<sp<AMessage>> trackStats;
486     mPlayer->getStats(&trackStats);
487 
488     if (trackStats.size() > 0) {
489         for (size_t i = 0; i < trackStats.size(); ++i) {
490             const sp<AMessage> &stats = trackStats.itemAt(i);
491 
492             AString mime;
493             stats->findString("mime", &mime);
494 
495             AString name;
496             stats->findString("component-name", &name);
497 
498             if (mime.startsWith("video/")) {
499                 int32_t width, height;
500                 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
501                 if (!name.empty()) {
502                     mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
503                 }
504 
505                 if (stats->findInt32("width", &width)
506                         && stats->findInt32("height", &height)) {
507                     mAnalyticsItem->setInt32(kPlayerWidth, width);
508                     mAnalyticsItem->setInt32(kPlayerHeight, height);
509                 }
510 
511                 int64_t numFramesTotal = 0;
512                 int64_t numFramesDropped = 0;
513                 stats->findInt64("frames-total", &numFramesTotal);
514                 stats->findInt64("frames-dropped-output", &numFramesDropped);
515 
516                 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
517                 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
518 
519 
520             } else if (mime.startsWith("audio/")) {
521                 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
522                 if (!name.empty()) {
523                     mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
524                 }
525             }
526         }
527     }
528 
529     // always provide duration and playing time, even if they have 0/unknown values.
530 
531     // getDuration() uses mLock for mutex -- careful where we use it.
532     int64_t duration_ms = -1;
533     getDuration(&duration_ms);
534     mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
535 
536     mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
537 
538     if (mRebufferingEvents != 0) {
539         mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
540         mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
541         mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
542     }
543 
544     mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
545 }
546 
547 
logMetrics(const char * where)548 void NuPlayer2Driver::logMetrics(const char *where) {
549     if (where == NULL) {
550         where = "unknown";
551     }
552     ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
553 
554     if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
555         return;
556     }
557 
558     // log only non-empty records
559     // we always updateMetrics() before we get here
560     // and that always injects 3 fields (duration, playing time, and
561     // datasource) into the record.
562     // So the canonical "empty" record has 3 elements in it.
563     if (mAnalyticsItem->count() > 3) {
564 
565         mAnalyticsItem->selfrecord();
566 
567         // re-init in case we prepare() and start() again.
568         delete mAnalyticsItem ;
569         mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
570         if (mAnalyticsItem) {
571             mAnalyticsItem->setUid(mClientUid);
572         }
573     } else {
574         ALOGV("did not have anything to record");
575     }
576 }
577 
reset()578 status_t NuPlayer2Driver::reset() {
579     ALOGD("reset(%p) at state %d", this, mState);
580 
581     updateMetrics("reset");
582     logMetrics("reset");
583 
584     Mutex::Autolock autoLock(mLock);
585 
586     switch (mState) {
587         case STATE_IDLE:
588             return OK;
589 
590         case STATE_SET_DATASOURCE_PENDING:
591         case STATE_RESET_IN_PROGRESS:
592             return INVALID_OPERATION;
593 
594         case STATE_PREPARING:
595         {
596             notifyListener_l(mSrcId, MEDIA2_PREPARED);
597             break;
598         }
599 
600         default:
601             break;
602     }
603 
604     if (mState != STATE_STOPPED) {
605         // notifyListener_l(MEDIA2_STOPPED);
606     }
607 
608     mState = STATE_RESET_IN_PROGRESS;
609     mPlayer->resetAsync();
610 
611     while (mState == STATE_RESET_IN_PROGRESS) {
612         mCondition.wait(mLock);
613     }
614 
615     mDurationUs = -1;
616     mPositionUs = -1;
617     mLooping = false;
618     mPlayingTimeUs = 0;
619     mRebufferingTimeUs = 0;
620     mRebufferingEvents = 0;
621     mRebufferingAtExit = false;
622 
623     return OK;
624 }
625 
notifyAt(int64_t mediaTimeUs)626 status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
627     ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
628     return mPlayer->notifyAt(mediaTimeUs);
629 }
630 
setLooping(int loop)631 status_t NuPlayer2Driver::setLooping(int loop) {
632     mLooping = loop != 0;
633     return OK;
634 }
635 
invoke(const Parcel & request,Parcel * reply)636 status_t NuPlayer2Driver::invoke(const Parcel &request, Parcel *reply) {
637     if (reply == NULL) {
638         ALOGE("reply is a NULL pointer");
639         return BAD_VALUE;
640     }
641 
642     int32_t methodId;
643     status_t ret = request.readInt32(&methodId);
644     if (ret != OK) {
645         ALOGE("Failed to retrieve the requested method to invoke, err(%d)", ret);
646         return ret;
647     }
648 
649     switch (methodId) {
650         case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
651         {
652             int mode = request.readInt32();
653             return mPlayer->setVideoScalingMode(mode);
654         }
655 
656         case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
657         {
658             return mPlayer->getTrackInfo(reply);
659         }
660 
661         case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
662         {
663             int trackIndex = request.readInt32();
664             int64_t msec = 0;
665             // getCurrentPosition should always return OK
666             getCurrentPosition(&msec);
667             return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
668         }
669 
670         case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
671         {
672             int trackIndex = request.readInt32();
673             return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
674         }
675 
676         case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
677         {
678             int32_t type = request.readInt32();
679             return mPlayer->getSelectedTrack(type, reply);
680         }
681 
682         default:
683         {
684             return INVALID_OPERATION;
685         }
686     }
687 }
688 
setAudioSink(const sp<AudioSink> & audioSink)689 void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
690     mPlayer->setAudioSink(audioSink);
691     mAudioSink = audioSink;
692 }
693 
setParameter(int,const Parcel &)694 status_t NuPlayer2Driver::setParameter(
695         int /* key */, const Parcel & /* request */) {
696     return INVALID_OPERATION;
697 }
698 
getParameter(int key,Parcel * reply)699 status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
700 
701     if (key == FOURCC('m','t','r','X')) {
702         // mtrX -- a play on 'metrics' (not matrix)
703         // gather current info all together, parcel it, and send it back
704         updateMetrics("api");
705         mAnalyticsItem->writeToParcel(reply);
706         return OK;
707     }
708 
709     return INVALID_OPERATION;
710 }
711 
getMetadata(const media::Metadata::Filter &,Parcel * records)712 status_t NuPlayer2Driver::getMetadata(
713         const media::Metadata::Filter& /* ids */, Parcel *records) {
714     Mutex::Autolock autoLock(mLock);
715 
716     using media::Metadata;
717 
718     Metadata meta(records);
719 
720     meta.appendBool(
721             Metadata::kPauseAvailable,
722             mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
723 
724     meta.appendBool(
725             Metadata::kSeekBackwardAvailable,
726             mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
727 
728     meta.appendBool(
729             Metadata::kSeekForwardAvailable,
730             mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
731 
732     meta.appendBool(
733             Metadata::kSeekAvailable,
734             mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
735 
736     return OK;
737 }
738 
notifyResetComplete(int64_t)739 void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
740     ALOGD("notifyResetComplete(%p)", this);
741     Mutex::Autolock autoLock(mLock);
742 
743     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
744     mState = STATE_IDLE;
745     mCondition.broadcast();
746 }
747 
notifySetSurfaceComplete(int64_t)748 void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
749     ALOGV("notifySetSurfaceComplete(%p)", this);
750     Mutex::Autolock autoLock(mLock);
751 
752     CHECK(mSetSurfaceInProgress);
753     mSetSurfaceInProgress = false;
754 
755     mCondition.broadcast();
756 }
757 
notifyDuration(int64_t,int64_t durationUs)758 void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
759     Mutex::Autolock autoLock(mLock);
760     mDurationUs = durationUs;
761 }
762 
notifyMorePlayingTimeUs(int64_t,int64_t playingUs)763 void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
764     Mutex::Autolock autoLock(mLock);
765     mPlayingTimeUs += playingUs;
766 }
767 
notifyMoreRebufferingTimeUs(int64_t,int64_t rebufferingUs)768 void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
769     Mutex::Autolock autoLock(mLock);
770     mRebufferingTimeUs += rebufferingUs;
771     mRebufferingEvents++;
772 }
773 
notifyRebufferingWhenExit(int64_t,bool status)774 void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
775     Mutex::Autolock autoLock(mLock);
776     mRebufferingAtExit = status;
777 }
778 
notifySeekComplete(int64_t srcId)779 void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
780     ALOGV("notifySeekComplete(%p)", this);
781     Mutex::Autolock autoLock(mLock);
782     mSeekInProgress = false;
783     notifySeekComplete_l(srcId);
784 }
785 
notifySeekComplete_l(int64_t srcId)786 void NuPlayer2Driver::notifySeekComplete_l(int64_t srcId) {
787     bool wasSeeking = true;
788     if (mState == STATE_STOPPED_AND_PREPARING) {
789         wasSeeking = false;
790         mState = STATE_STOPPED_AND_PREPARED;
791         mCondition.broadcast();
792     } else if (mState == STATE_STOPPED) {
793         // no need to notify listener
794         return;
795     }
796     notifyListener_l(srcId, wasSeeking ? MEDIA2_SEEK_COMPLETE : MEDIA2_PREPARED);
797 }
798 
dump(int fd,const Vector<String16> &) const799 status_t NuPlayer2Driver::dump(
800         int fd, const Vector<String16> & /* args */) const {
801 
802     Vector<sp<AMessage> > trackStats;
803     mPlayer->getStats(&trackStats);
804 
805     AString logString(" NuPlayer2\n");
806     char buf[256] = {0};
807 
808     bool locked = false;
809     for (int i = 0; i < kDumpLockRetries; ++i) {
810         if (mLock.tryLock() == NO_ERROR) {
811             locked = true;
812             break;
813         }
814         usleep(kDumpLockSleepUs);
815     }
816 
817     if (locked) {
818         snprintf(buf, sizeof(buf), "  state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
819                 mState, mAtEOS, mLooping, mAutoLoop);
820         mLock.unlock();
821     } else {
822         snprintf(buf, sizeof(buf), "  NPD(%p) lock is taken\n", this);
823     }
824     logString.append(buf);
825 
826     for (size_t i = 0; i < trackStats.size(); ++i) {
827         const sp<AMessage> &stats = trackStats.itemAt(i);
828 
829         AString mime;
830         if (stats->findString("mime", &mime)) {
831             snprintf(buf, sizeof(buf), "  mime(%s)\n", mime.c_str());
832             logString.append(buf);
833         }
834 
835         AString name;
836         if (stats->findString("component-name", &name)) {
837             snprintf(buf, sizeof(buf), "    decoder(%s)\n", name.c_str());
838             logString.append(buf);
839         }
840 
841         if (mime.startsWith("video/")) {
842             int32_t width, height;
843             if (stats->findInt32("width", &width)
844                     && stats->findInt32("height", &height)) {
845                 snprintf(buf, sizeof(buf), "    resolution(%d x %d)\n", width, height);
846                 logString.append(buf);
847             }
848 
849             int64_t numFramesTotal = 0;
850             int64_t numFramesDropped = 0;
851 
852             stats->findInt64("frames-total", &numFramesTotal);
853             stats->findInt64("frames-dropped-output", &numFramesDropped);
854             snprintf(buf, sizeof(buf), "    numFramesTotal(%lld), numFramesDropped(%lld), "
855                      "percentageDropped(%.2f%%)\n",
856                      (long long)numFramesTotal,
857                      (long long)numFramesDropped,
858                      numFramesTotal == 0
859                             ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
860             logString.append(buf);
861         }
862     }
863 
864     ALOGI("%s", logString.c_str());
865 
866     if (fd >= 0) {
867         FILE *out = fdopen(dup(fd), "w");
868         fprintf(out, "%s", logString.c_str());
869         fclose(out);
870         out = NULL;
871     }
872 
873     return OK;
874 }
875 
onMessageReceived(const sp<AMessage> & msg)876 void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
877     switch (msg->what()) {
878         case kWhatNotifyListener: {
879             int64_t srcId;
880             int32_t msgId;
881             int32_t ext1 = 0;
882             int32_t ext2 = 0;
883             CHECK(msg->findInt64("srcId", &srcId));
884             CHECK(msg->findInt32("messageId", &msgId));
885             msg->findInt32("ext1", &ext1);
886             msg->findInt32("ext2", &ext2);
887             sp<ParcelWrapper> in;
888             sp<RefBase> obj;
889             if (msg->findObject("parcel", &obj) && obj != NULL) {
890                 in = static_cast<ParcelWrapper *>(obj.get());
891             }
892             sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getParcel()));
893             break;
894         }
895         default:
896             break;
897     }
898 }
899 
notifyListener(int64_t srcId,int msg,int ext1,int ext2,const Parcel * in)900 void NuPlayer2Driver::notifyListener(
901         int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
902     Mutex::Autolock autoLock(mLock);
903     notifyListener_l(srcId, msg, ext1, ext2, in);
904 }
905 
notifyListener_l(int64_t srcId,int msg,int ext1,int ext2,const Parcel * in)906 void NuPlayer2Driver::notifyListener_l(
907         int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
908     ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
909             this, (long long)srcId, msg, ext1, ext2,
910             (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
911     if (srcId == mSrcId) {
912         switch (msg) {
913             case MEDIA2_PLAYBACK_COMPLETE:
914             {
915                 if (mState != STATE_RESET_IN_PROGRESS) {
916                     if (mAutoLoop) {
917                         audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
918                         if (mAudioSink != NULL) {
919                             streamType = mAudioSink->getAudioStreamType();
920                         }
921                         if (streamType == AUDIO_STREAM_NOTIFICATION) {
922                             ALOGW("disabling auto-loop for notification");
923                             mAutoLoop = false;
924                         }
925                     }
926                     if (mLooping || mAutoLoop) {
927                         mPlayer->seekToAsync(0);
928                         if (mAudioSink != NULL) {
929                             // The renderer has stopped the sink at the end in order to play out
930                             // the last little bit of audio. In looping mode, we need to restart it.
931                             mAudioSink->start();
932                         }
933                         // don't send completion event when looping
934                         return;
935                     }
936                     if (property_get_bool("persist.debug.sf.stats", false)) {
937                         Vector<String16> args;
938                         dump(-1, args);
939                     }
940                     mPlayer->pause();
941                     mState = STATE_PAUSED;
942                 }
943                 // fall through
944             }
945 
946             case MEDIA2_ERROR:
947             {
948                 // when we have an error, add it to the analytics for this playback.
949                 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
950                 // [test against msg is due to fall through from previous switch value]
951                 if (msg == MEDIA2_ERROR) {
952                     mAnalyticsItem->setInt32(kPlayerError, ext1);
953                     if (ext2 != 0) {
954                         mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
955                     }
956                     mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
957                 }
958                 mAtEOS = true;
959                 break;
960             }
961 
962             default:
963                 break;
964         }
965     }
966 
967     sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
968     notify->setInt64("srcId", srcId);
969     notify->setInt32("messageId", msg);
970     notify->setInt32("ext1", ext1);
971     notify->setInt32("ext2", ext2);
972     notify->setObject("parcel", ParcelWrapper::Create(in));
973     notify->post();
974 }
975 
notifySetDataSourceCompleted(int64_t,status_t err)976 void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
977     Mutex::Autolock autoLock(mLock);
978 
979     CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
980 
981     mAsyncResult = err;
982     mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
983     mCondition.broadcast();
984 }
985 
notifyPrepareCompleted(int64_t srcId,status_t err)986 void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
987     ALOGV("notifyPrepareCompleted %d", err);
988 
989     Mutex::Autolock autoLock(mLock);
990 
991     if (srcId != mSrcId) {
992         if (err == OK) {
993             notifyListener_l(srcId, MEDIA2_PREPARED);
994         } else {
995             notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
996         }
997         return;
998     }
999 
1000     if (mState != STATE_PREPARING) {
1001         // We were preparing asynchronously when the client called
1002         // reset(), we sent a premature "prepared" notification and
1003         // then initiated the reset. This notification is stale.
1004         CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
1005         return;
1006     }
1007 
1008     CHECK_EQ(mState, STATE_PREPARING);
1009 
1010     mAsyncResult = err;
1011 
1012     if (err == OK) {
1013         // update state before notifying client, so that if client calls back into NuPlayer2Driver
1014         // in response, NuPlayer2Driver has the right state
1015         mState = STATE_PREPARED;
1016         notifyListener_l(srcId, MEDIA2_PREPARED);
1017     } else {
1018         mState = STATE_UNPREPARED;
1019         notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
1020     }
1021 
1022     sp<MetaData> meta = mPlayer->getFileMeta();
1023     int32_t loop;
1024     if (meta != NULL
1025             && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
1026         mAutoLoop = true;
1027     }
1028 
1029     mCondition.broadcast();
1030 }
1031 
notifyFlagsChanged(int64_t,uint32_t flags)1032 void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
1033     Mutex::Autolock autoLock(mLock);
1034 
1035     mPlayerFlags = flags;
1036 }
1037 
1038 // Modular DRM
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)1039 status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
1040 {
1041     ALOGV("prepareDrm(%p) state: %d", this, mState);
1042 
1043     // leaving the state verification for mediaplayer.cpp
1044     status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
1045 
1046     ALOGV("prepareDrm ret: %d", ret);
1047 
1048     return ret;
1049 }
1050 
releaseDrm()1051 status_t NuPlayer2Driver::releaseDrm()
1052 {
1053     ALOGV("releaseDrm(%p) state: %d", this, mState);
1054 
1055     // leaving the state verification for mediaplayer.cpp
1056     status_t ret = mPlayer->releaseDrm();
1057 
1058     ALOGV("releaseDrm ret: %d", ret);
1059 
1060     return ret;
1061 }
1062 
stateString(State state)1063 std::string NuPlayer2Driver::stateString(State state) {
1064     const char *rval = NULL;
1065     char rawbuffer[16];  // allows "%d"
1066 
1067     switch (state) {
1068         case STATE_IDLE: rval = "IDLE"; break;
1069         case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1070         case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1071         case STATE_PREPARING: rval = "PREPARING"; break;
1072         case STATE_PREPARED: rval = "PREPARED"; break;
1073         case STATE_RUNNING: rval = "RUNNING"; break;
1074         case STATE_PAUSED: rval = "PAUSED"; break;
1075         case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
1076         case STATE_STOPPED: rval = "STOPPED"; break;
1077         case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
1078         case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
1079         default:
1080             // yes, this buffer is shared and vulnerable to races
1081             snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1082             rval = rawbuffer;
1083             break;
1084     }
1085 
1086     return rval;
1087 }
1088 
1089 }  // namespace android
1090