NuPlayerRenderer: allow flush() to be called multiple times.

Also fix racing condition on accessing some members.

Bug: 16982307
Bug: 13133027
Change-Id: I0d4a605146e24ad7396a07369d501593cad73f41
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 3640038..8391b9e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -93,10 +93,14 @@
     {
         Mutex::Autolock autoLock(mFlushLock);
         if (audio) {
-            CHECK(!mFlushingAudio);
+            if (mFlushingAudio) {
+                return;
+            }
             mFlushingAudio = true;
         } else {
-            CHECK(!mFlushingVideo);
+            if (mFlushingVideo) {
+                return;
+            }
             mFlushingVideo = true;
         }
     }
@@ -115,6 +119,14 @@
     mSyncQueues = false;
 }
 
+void NuPlayer::Renderer::signalAudioSinkChanged() {
+    (new AMessage(kWhatAudioSinkChanged, id()))->post();
+}
+
+void NuPlayer::Renderer::signalDisableOffloadAudio() {
+    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
+}
+
 void NuPlayer::Renderer::pause() {
     (new AMessage(kWhatPause, id()))->post();
 }
@@ -251,14 +263,6 @@
     msg->post(delayUs);
 }
 
-void NuPlayer::Renderer::signalAudioSinkChanged() {
-    (new AMessage(kWhatAudioSinkChanged, id()))->post();
-}
-
-void NuPlayer::Renderer::signalDisableOffloadAudio() {
-    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
-}
-
 void NuPlayer::Renderer::prepareForMediaRenderingStart() {
     mAudioRenderingStartGeneration = mAudioQueueGeneration;
     mVideoRenderingStartGeneration = mVideoQueueGeneration;
@@ -716,6 +720,15 @@
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
+    {
+        Mutex::Autolock autoLock(mFlushLock);
+        if (audio) {
+            mFlushingAudio = false;
+        } else {
+            mFlushingVideo = false;
+        }
+    }
+
     // If we're currently syncing the queues, i.e. dropping audio while
     // aligning the first audio/video buffer times and only one of the
     // two queues has data, we may starve that queue by not requesting
@@ -734,17 +747,18 @@
         {
             Mutex::Autolock autoLock(mLock);
             flushQueue(&mAudioQueue);
+
+            ++mAudioQueueGeneration;
+            prepareForMediaRenderingStart();
+
+            if (offloadingAudio()) {
+                mFirstAudioTimeUs = -1;
+            }
         }
 
-        Mutex::Autolock autoLock(mFlushLock);
-        mFlushingAudio = false;
-
         mDrainAudioQueuePending = false;
-        ++mAudioQueueGeneration;
 
-        prepareForMediaRenderingStart();
         if (offloadingAudio()) {
-            mFirstAudioTimeUs = -1;
             mAudioSink->pause();
             mAudioSink->flush();
             mAudioSink->start();
@@ -752,9 +766,6 @@
     } else {
         flushQueue(&mVideoQueue);
 
-        Mutex::Autolock autoLock(mFlushLock);
-        mFlushingVideo = false;
-
         mDrainVideoQueuePending = false;
         ++mVideoQueueGeneration;
 
@@ -852,13 +863,15 @@
 void NuPlayer::Renderer::onPause() {
     CHECK(!mPaused);
 
+    {
+        Mutex::Autolock autoLock(mLock);
+        ++mAudioQueueGeneration;
+        ++mVideoQueueGeneration;
+        prepareForMediaRenderingStart();
+    }
+
     mDrainAudioQueuePending = false;
-    ++mAudioQueueGeneration;
-
     mDrainVideoQueuePending = false;
-    ++mVideoQueueGeneration;
-
-    prepareForMediaRenderingStart();
 
     if (mHasAudio) {
         mAudioSink->pause();
@@ -895,7 +908,12 @@
     uint32_t numFramesPlayed;
     CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
 
-    int64_t currentPositionUs = mFirstAudioTimeUs
+    int64_t firstAudioTimeUs;
+    {
+        Mutex::Autolock autoLock(mLock);
+        firstAudioTimeUs = mFirstAudioTimeUs;
+    }
+    int64_t currentPositionUs = firstAudioTimeUs
             + (numFramesPlayed * mAudioSink->msecsPerFrame()) * 1000ll;
 
     mAudioSink->stop();