Add OnMediaTimeDiscontinuity notification

Test: MediaPlayerTest
Bug: 63934228
Change-Id: I7efb58d00dc86b17b9d97775d1a2672e40e841d3
diff --git a/media/libmedia/include/media/mediaplayer.h b/media/libmedia/include/media/mediaplayer.h
index c4dbf42..2335c5a 100644
--- a/media/libmedia/include/media/mediaplayer.h
+++ b/media/libmedia/include/media/mediaplayer.h
@@ -59,6 +59,7 @@
     MEDIA_SUBTITLE_DATA     = 201,
     MEDIA_META_DATA         = 202,
     MEDIA_DRM_INFO          = 210,
+    MEDIA_TIME_DISCONTINUITY = 211,
     MEDIA_AUDIO_ROUTING_CHANGED = 10000,
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index bd83c6d..14ffb1d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -220,8 +220,11 @@
     mUID = uid;
 }
 
-void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
+void NuPlayer::init(const wp<NuPlayerDriver> &driver) {
     mDriver = driver;
+
+    sp<AMessage> notify = new AMessage(kWhatMediaClockNotify, this);
+    mMediaClock->setNotificationMessage(notify);
 }
 
 void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
@@ -1425,6 +1428,24 @@
             break;
         }
 
+        case kWhatMediaClockNotify:
+        {
+            ALOGV("kWhatMediaClockNotify");
+            int64_t anchorMediaUs, anchorRealUs;
+            float playbackRate;
+            CHECK(msg->findInt64("anchor-media-us", &anchorMediaUs));
+            CHECK(msg->findInt64("anchor-real-us", &anchorRealUs));
+            CHECK(msg->findFloat("playback-rate", &playbackRate));
+
+            Parcel in;
+            in.writeInt64(anchorMediaUs);
+            in.writeInt64(anchorRealUs);
+            in.writeFloat(playbackRate);
+
+            notifyListener(MEDIA_TIME_DISCONTINUITY, 0, 0, &in);
+            break;
+        }
+
         default:
             TRESPASS();
             break;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 9481234..3a7ef4e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -39,7 +39,7 @@
 
     void setUID(uid_t uid);
 
-    void setDriver(const wp<NuPlayerDriver> &driver);
+    void init(const wp<NuPlayerDriver> &driver);
 
     void setDataSourceAsync(const sp<IStreamSource> &source);
 
@@ -158,6 +158,7 @@
         kWhatSetBufferingSettings       = 'sBuS',
         kWhatPrepareDrm                 = 'pDrm',
         kWhatReleaseDrm                 = 'rDrm',
+        kWhatMediaClockNotify           = 'mckN',
     };
 
     wp<NuPlayerDriver> mDriver;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 731fdba..63c887b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -104,7 +104,7 @@
 
     mLooper->registerHandler(mPlayer);
 
-    mPlayer->setDriver(this);
+    mPlayer->init(this);
 }
 
 NuPlayerDriver::~NuPlayerDriver() {
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 15843a2..41dbfd4 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -70,11 +70,9 @@
         it->mNotify->post();
         it = mTimers.erase(it);
     }
-    mAnchorTimeMediaUs = -1;
-    mAnchorTimeRealUs = -1;
     mMaxTimeMediaUs = INT64_MAX;
     mStartingTimeMediaUs = -1;
-    mPlaybackRate = 1.0;
+    updateAnchorTimesAndPlaybackRate_l(-1, -1, 1.0);
     ++mGeneration;
 }
 
@@ -85,8 +83,7 @@
 
 void MediaClock::clearAnchor() {
     Mutex::Autolock autoLock(mLock);
-    mAnchorTimeMediaUs = -1;
-    mAnchorTimeRealUs = -1;
+    updateAnchorTimesAndPlaybackRate_l(-1, -1, mPlaybackRate);
 }
 
 void MediaClock::updateAnchor(
@@ -118,8 +115,7 @@
             return;
         }
     }
-    mAnchorTimeRealUs = nowUs;
-    mAnchorTimeMediaUs = nowMediaUs;
+    updateAnchorTimesAndPlaybackRate_l(nowMediaUs, nowUs, mPlaybackRate);
 
     ++mGeneration;
     processTimers_l();
@@ -139,13 +135,12 @@
     }
 
     int64_t nowUs = ALooper::GetNowUs();
-    mAnchorTimeMediaUs += (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
-    if (mAnchorTimeMediaUs < 0) {
+    int64_t nowMediaUs = mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
+    if (nowMediaUs < 0) {
         ALOGW("setRate: anchor time should not be negative, set to 0.");
-        mAnchorTimeMediaUs = 0;
+        nowMediaUs = 0;
     }
-    mAnchorTimeRealUs = nowUs;
-    mPlaybackRate = rate;
+    updateAnchorTimesAndPlaybackRate_l(nowMediaUs, nowUs, rate);
 
     if (rate > 0.0) {
         ++mGeneration;
@@ -313,4 +308,31 @@
     msg->post(nextLapseRealUs);
 }
 
+void MediaClock::updateAnchorTimesAndPlaybackRate_l(int64_t anchorTimeMediaUs,
+        int64_t anchorTimeRealUs, float playbackRate) {
+    if (mAnchorTimeMediaUs != anchorTimeMediaUs
+            || mAnchorTimeRealUs != anchorTimeRealUs
+            || mPlaybackRate != playbackRate) {
+        mAnchorTimeMediaUs = anchorTimeMediaUs;
+        mAnchorTimeRealUs = anchorTimeRealUs;
+        mPlaybackRate = playbackRate;
+        notifyDiscontinuity_l();
+    }
+}
+
+void MediaClock::setNotificationMessage(const sp<AMessage> &msg) {
+    Mutex::Autolock autoLock(mLock);
+    mNotify = msg;
+}
+
+void MediaClock::notifyDiscontinuity_l() {
+    if (mNotify != nullptr) {
+        sp<AMessage> msg = mNotify->dup();
+        msg->setInt64("anchor-media-us", mAnchorTimeMediaUs);
+        msg->setInt64("anchor-real-us", mAnchorTimeRealUs);
+        msg->setFloat("playback-rate", mPlaybackRate);
+        msg->post();
+    }
+}
+
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaClock.h b/media/libstagefright/include/media/stagefright/MediaClock.h
index 7511913..3ddeb82 100644
--- a/media/libstagefright/include/media/stagefright/MediaClock.h
+++ b/media/libstagefright/include/media/stagefright/MediaClock.h
@@ -66,6 +66,8 @@
     // mediaTimeUs + (adjustRealUs / playbackRate)
     void addTimer(const sp<AMessage> &notify, int64_t mediaTimeUs, int64_t adjustRealUs = 0);
 
+    void setNotificationMessage(const sp<AMessage> &msg);
+
     void reset();
 
 protected:
@@ -92,6 +94,11 @@
 
     void processTimers_l();
 
+    void updateAnchorTimesAndPlaybackRate_l(
+            int64_t anchorTimeMediaUs, int64_t anchorTimeRealUs , float playbackRate);
+
+    void notifyDiscontinuity_l();
+
     sp<ALooper> mLooper;
     mutable Mutex mLock;
 
@@ -104,6 +111,7 @@
 
     int32_t mGeneration;
     std::list<Timer> mTimers;
+    sp<AMessage> mNotify;
 
     DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
 };