audioflinger: pause HW A/V sync output when AudioTrack underruns

Do not standby, starve or feed 0s to the audio HAL on direct
output using HW A/V sync mode.

Bug: 17883772.

Change-Id: I11e6c97ec24360d75f9b602814d40a54b60cb7a7
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index dacb12c..9fccda1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4083,6 +4083,10 @@
                 track->mRetryCount = kMaxTrackRetriesDirect;
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
+                if (usesHwAvSync() && mHwPaused) {
+                    doHwResume = true;
+                    mHwPaused = false;
+                }
             }
         } else {
             // clear effect chain input buffer if the last active track started underruns
@@ -4111,9 +4115,6 @@
                         track->mState = TrackBase::STOPPED;
                     }
                     if (track->isStopped()) {
-                        if (track->mState == TrackBase::FLUSHED) {
-                            flushHw_l();
-                        }
                         track->reset();
                     }
                     tracksToRemove->add(track);
@@ -4130,6 +4131,10 @@
                     android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
                 } else if (last) {
                     mixerStatus = MIXER_TRACKS_ENABLED;
+                    if (usesHwAvSync() && !mHwPaused && !mStandby) {
+                        doHwPause = true;
+                        mHwPaused = true;
+                    }
                 }
             }
         }
@@ -4192,7 +4197,7 @@
 void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
 {
     // do not write to HAL when paused
-    if (mHwPaused) {
+    if (mHwPaused || (usesHwAvSync() && mStandby)) {
         sleepTime = idleSleepTime;
         return;
     }
@@ -4237,7 +4242,7 @@
         trackPaused = mTracks[mTracks.size() - 1]->isPaused();
     }
 
-    return !mStandby && !trackPaused;
+    return !mStandby && !(trackPaused || (usesHwAvSync() && mHwPaused));
 }
 
 // getTrackName_l() must be called with ThreadBase::mLock held
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index f5d0e27..1088843 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -710,6 +710,9 @@
                                    audio_patch_handle_t *handle);
     virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);
 
+                bool        usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL) &&
+                                                (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
+
 private:
 
     friend class AudioFlinger;      // for numerous