audioflinger: Handle pause /resume in stopping state

-Pre-requisite:
 Perform seek on the clip. After seek the data remaining till EOS
 is little more than the driver and common block buffering.
-Framework state:
 Offload thread is waiting for signal from the HAL for a free
 buffer. Audio Player calls sink stop on reaching EOS. Audio
 track is waiting on obtain buffer for a free space in common
 block to send the last buffer. The track is moved to stopping
 state as input EOS is reached.
-Issue:
 Perform pause/ resume in this state(STOPPING), Audio playback
 does not resume.
-Fix
 Ensure resume is called in stopping state if frames ready is
 greater than zero.

Bug: 12870871

Change-Id: Ib1378c4ee5ce4bea655691e93de0775f7b1d2804
Signed-off-by: Glenn Kasten <gkasten@google.com>
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index b5e763d..e9c6834 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -96,6 +96,8 @@
     void reset();
     bool isFlushPending() const { return mFlushHwPending; }
     void flushAck();
+    bool isResumePending();
+    void resumeAck();
 
     bool isOutputTrack() const {
         return (mStreamType == AUDIO_STREAM_CNT);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 12d453e..e90ebd1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4230,8 +4230,8 @@
                 track->mFillingUpStatus = Track::FS_ACTIVE;
                 // make sure processVolume_l() will apply new volume even if 0
                 mLeftVolFloat = mRightVolFloat = -1.0;
-                if (track->mState == TrackBase::RESUMING) {
-                    track->mState = TrackBase::ACTIVE;
+                if (track->isResumePending()) {
+                    track->resumeAck();
                     if (last) {
                         if (mPausedBytesRemaining) {
                             // Need to continue write that was interrupted
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f19cd88..c90bae0 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -567,7 +567,12 @@
 
 // Don't call for fast tracks; the framesReady() could result in priority inversion
 bool AudioFlinger::PlaybackThread::Track::isReady() const {
-    if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing() || isStopping()) {
+    if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
+        return true;
+    }
+
+    if (isStopping() && framesReady() > 0) {
+        mFillingUpStatus = FS_FILLED;
         return true;
     }
 
@@ -604,7 +609,10 @@
         // here the track could be either new, or restarted
         // in both cases "unstop" the track
 
-        if (state == PAUSED) {
+        // initial state-stopping. next state-pausing.
+        // What if resume is called ?
+
+        if (state == PAUSED || state == PAUSING) {
             if (mResumeToStopping) {
                 // happened we need to resume to STOPPING_1
                 mState = TrackBase::STOPPING_1;
@@ -991,6 +999,29 @@
     }
 }
 
+//To be called with thread lock held
+bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+
+    if (mState == RESUMING)
+        return true;
+    /* Resume is pending if track was stopping before pause was called */
+    if (mState == STOPPING_1 &&
+        mResumeToStopping)
+        return true;
+
+    return false;
+}
+
+//To be called with thread lock held
+void AudioFlinger::PlaybackThread::Track::resumeAck() {
+
+
+    if (mState == RESUMING)
+        mState = ACTIVE;
+    // Other possibility of  pending resume is stopping_1 state
+    // Do not update the state from stopping as this prevents
+    //drain being called.
+}
 // ----------------------------------------------------------------------------
 
 sp<AudioFlinger::PlaybackThread::TimedTrack>