Merge "NuPlayerDriver: fix current position for stop and pause." into lmp-dev
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index c0091bf..60beb9d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -36,8 +36,8 @@
       mAsyncResult(UNKNOWN_ERROR),
       mDurationUs(-1),
       mPositionUs(-1),
-      mNotifyTimeRealUs(0),
-      mPauseStartedTimeUs(0),
+      mNotifyTimeRealUs(-1),
+      mPauseStartedTimeUs(-1),
       mNumFramesTotal(0),
       mNumFramesDropped(0),
       mLooper(new ALooper),
@@ -240,7 +240,14 @@
         }
 
         case STATE_RUNNING:
+        {
+            if (mAtEOS) {
+                mPlayer->seekToAsync(0);
+                mAtEOS = false;
+                mPositionUs = -1;
+            }
             break;
+        }
 
         case STATE_PAUSED:
         case STATE_STOPPED_AND_PREPARED:
@@ -255,6 +262,7 @@
     }
 
     mState = STATE_RUNNING;
+    mPauseStartedTimeUs = -1;
 
     return OK;
 }
@@ -268,7 +276,7 @@
             // fall through
 
         case STATE_PAUSED:
-            notifyListener(MEDIA_STOPPED);
+            notifyListener_l(MEDIA_STOPPED);
             // fall through
 
         case STATE_PREPARED:
@@ -281,7 +289,7 @@
         default:
             return INVALID_OPERATION;
     }
-    mPauseStartedTimeUs = ALooper::GetNowUs();
+    setPauseStartedTimeIfNeeded();
 
     return OK;
 }
@@ -295,7 +303,7 @@
             return OK;
 
         case STATE_RUNNING:
-            notifyListener(MEDIA_PAUSED);
+            notifyListener_l(MEDIA_PAUSED);
             mPlayer->pause();
             break;
 
@@ -303,7 +311,7 @@
             return INVALID_OPERATION;
     }
 
-    mPauseStartedTimeUs = ALooper::GetNowUs();
+    setPauseStartedTimeIfNeeded();
     mState = STATE_PAUSED;
 
     return OK;
@@ -334,7 +342,7 @@
         {
             mAtEOS = false;
             // seeks can take a while, so we essentially paused
-            notifyListener(MEDIA_PAUSED);
+            notifyListener_l(MEDIA_PAUSED);
             mPlayer->seekToAsync(seekTimeUs);
             break;
         }
@@ -343,6 +351,8 @@
             return INVALID_OPERATION;
     }
 
+    mPositionUs = seekTimeUs;
+    mNotifyTimeRealUs = -1;
     return OK;
 }
 
@@ -351,10 +361,11 @@
 
     if (mPositionUs < 0) {
         *msec = 0;
+    } else if (mNotifyTimeRealUs == -1) {
+        *msec = mPositionUs / 1000;
     } else {
         int64_t nowUs =
-                (mState != STATE_RUNNING ?
-                        mPauseStartedTimeUs : ALooper::GetNowUs());
+                (isPlaying() ?  ALooper::GetNowUs() : mPauseStartedTimeUs);
         *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000;
     }
 
@@ -388,7 +399,7 @@
         {
             CHECK(mIsAsyncPrepare);
 
-            notifyListener(MEDIA_PREPARED);
+            notifyListener_l(MEDIA_PREPARED);
             break;
         }
 
@@ -397,7 +408,7 @@
     }
 
     if (mState != STATE_STOPPED) {
-        notifyListener(MEDIA_STOPPED);
+        notifyListener_l(MEDIA_STOPPED);
     }
 
     mState = STATE_RESET_IN_PROGRESS;
@@ -552,10 +563,7 @@
         // no need to notify listener
         return;
     }
-    // note: notifyListener called with lock released
-    mLock.unlock();
-    notifyListener(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
-    mLock.lock();
+    notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
 }
 
 void NuPlayerDriver::notifyFrameStats(
@@ -587,11 +595,19 @@
 
 void NuPlayerDriver::notifyListener(
         int msg, int ext1, int ext2, const Parcel *in) {
+    Mutex::Autolock autoLock(mLock);
+    notifyListener_l(msg, ext1, ext2, in);
+}
+
+void NuPlayerDriver::notifyListener_l(
+        int msg, int ext1, int ext2, const Parcel *in) {
     switch (msg) {
         case MEDIA_PLAYBACK_COMPLETE:
         {
             if (mLooping) {
+                mLock.unlock();
                 mPlayer->seekToAsync(0);
+                mLock.lock();
                 break;
             }
             // fall through
@@ -600,6 +616,7 @@
         case MEDIA_ERROR:
         {
             mAtEOS = true;
+            setPauseStartedTimeIfNeeded();
             break;
         }
 
@@ -607,7 +624,9 @@
             break;
     }
 
+    mLock.unlock();
     sendEvent(msg, ext1, ext2, in);
+    mLock.lock();
 }
 
 void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
@@ -637,12 +656,12 @@
 
     if (err == OK) {
         if (mIsAsyncPrepare) {
-            notifyListener(MEDIA_PREPARED);
+            notifyListener_l(MEDIA_PREPARED);
         }
         mState = STATE_PREPARED;
     } else {
         if (mIsAsyncPrepare) {
-            notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
         }
         mState = STATE_UNPREPARED;
     }
@@ -656,4 +675,10 @@
     mPlayerFlags = flags;
 }
 
+void NuPlayerDriver::setPauseStartedTimeIfNeeded() {
+    if (mPauseStartedTimeUs == -1) {
+        mPauseStartedTimeUs = ALooper::GetNowUs();
+    }
+}
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 076493d..b0a52ad 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -120,6 +120,8 @@
     int64_t mStartupSeekTimeUs;
 
     status_t prepare_l();
+    void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
+    void setPauseStartedTimeIfNeeded();
 
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
 };