PatchTrack: Ensure enough data to write once

Underrun can occur for AudioPlaybackCapture
in the secondary PlaybackThread.

When the primary PlaybackThread is blocked by any reason
during playback, e.g. A2DP suspend, interceptBuffer is also
blocked and data will not be provided to the PatchRecord buffer.
But the secondary PlaybackThread is still running,
exhausting the data in the PatchTrack.

As mFillingUpStatus of the PatchTrack is still FS_ACTIVE,
the secondary PlaybackThread continues even though framesReady()
is not filled to threshold (mFrameCountToBeReady).
So, underrun happens repeatedly.

To avoid this issue, check if the PatchTrack has enough data in
releaseBuffer(); if not, change mFillingUpStatus to FS_FILLING,
and wait for the buffer to fill.

Bug: 144009535
Change-Id: Ifcbaea05228064284dfaa9b629c8860b1fbe977d
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index e4402bd..f3599c4 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1872,6 +1872,25 @@
 {
     mProxy->releaseBuffer(buffer);
     restartIfDisabled();
+
+    // Check if the PatchTrack has enough data to write once in releaseBuffer().
+    // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
+    // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
+    // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
+    if (mFillingUpStatus == FS_ACTIVE
+            && audio_is_linear_pcm(mFormat)
+            && !isOffloadedOrDirect()) {
+        if (sp<ThreadBase> thread = mThread.promote();
+            thread != 0) {
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            const size_t frameCount = playbackThread->frameCount() * sampleRate()
+                    / playbackThread->sampleRate();
+            if (framesReady() < frameCount) {
+                ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
+                mFillingUpStatus = FS_FILLING;
+            }
+        }
+    }
 }
 
 void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()