AudioFlinger: more fixes for offload audio lost

mStandby being false was not a reliable indication that
something had been written to audio HAL.

Considering the last track in mActiveTracks vector as the
latest activated track was wrong as this is a SortedVector.

Bug: 11247103.
Change-Id: I397d011c5afcdd779def3fe25aaae7669a472cfc
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ae059fb..9d705f2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -272,6 +272,7 @@
         // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, and mFormat are
         // set by PlaybackThread::readOutputParameters() or RecordThread::readInputParameters()
         mParamStatus(NO_ERROR),
+        //FIXME: mStandby should be true here. Is this some kind of hack?
         mStandby(false), mOutDevice(outDevice), mInDevice(inDevice),
         mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
         // mName will be set by concrete (non-virtual) subclass
@@ -1461,6 +1462,7 @@
         mActiveTracks.add(track);
         mWakeLockUids.add(track->uid());
         mActiveTracksGeneration++;
+        mLatestActiveTrack = track;
         sp<EffectChain> chain = getEffectChain_l(track->sessionId());
         if (chain != 0) {
             ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -1934,7 +1936,7 @@
 
     mNumWrites++;
     mInWrite = false;
-
+    mStandby = false;
     return bytesWritten;
 }
 
@@ -2357,7 +2359,6 @@
                 }
 }
 
-                mStandby = false;
             } else {
                 usleep(sleepTime);
             }
@@ -3605,6 +3606,12 @@
 
         Track* const track = t.get();
         audio_track_cblk_t* cblk = track->cblk();
+        // Only consider last track started for volume and mixer state control.
+        // In theory an older track could underrun and restart after the new one starts
+        // but as we only care about the transition phase between two tracks on a
+        // direct output, it is not a problem to ignore the underrun case.
+        sp<Track> l = mLatestActiveTrack.promote();
+        bool last = l.get() == track;
 
         // The first time a track is added we wait
         // for all its buffers to be filled before processing it
@@ -3614,11 +3621,6 @@
         } else {
             minFrames = 1;
         }
-        // Only consider last track started for volume and mixer state control.
-        // This is the last entry in mActiveTracks unless a track underruns.
-        // As we only care about the transition phase between two tracks on a
-        // direct output, it is not a problem to ignore the underrun case.
-        bool last = (i == (count - 1));
 
         if ((track->framesReady() >= minFrames) && track->isReady() &&
                 !track->isPaused() && !track->isTerminated())
@@ -3645,7 +3647,7 @@
         } else {
             // clear effect chain input buffer if the last active track started underruns
             // to avoid sending previous audio buffer again to effects
-            if (!mEffectChains.isEmpty() && (i == (count -1))) {
+            if (!mEffectChains.isEmpty() && last) {
                 mEffectChains[0]->clearInputBuffer();
             }
 
@@ -3657,7 +3659,8 @@
                 // TODO: implement behavior for compressed audio
                 size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
                 size_t framesWritten = mBytesWritten / mFrameSize;
-                if (mStandby || track->presentationComplete(framesWritten, audioHALFrames)) {
+                if (mStandby || !last ||
+                        track->presentationComplete(framesWritten, audioHALFrames)) {
                     if (track->isStopped()) {
                         track->reset();
                     }
@@ -3933,6 +3936,8 @@
         mPausedBytesRemaining(0),
         mPreviousTrack(NULL)
 {
+    //FIXME: mStandby should be set to true by ThreadBase constructor
+    mStandby = true;
 }
 
 void AudioFlinger::OffloadThread::threadLoop_exit()
@@ -3969,8 +3974,15 @@
         }
         Track* const track = t.get();
         audio_track_cblk_t* cblk = track->cblk();
+        // Only consider last track started for volume and mixer state control.
+        // In theory an older track could underrun and restart after the new one starts
+        // but as we only care about the transition phase between two tracks on a
+        // direct output, it is not a problem to ignore the underrun case.
+        sp<Track> l = mLatestActiveTrack.promote();
+        bool last = l.get() == track;
+
         if (mPreviousTrack != NULL) {
-            if (t.get() != mPreviousTrack) {
+            if (track != mPreviousTrack) {
                 // Flush any data still being written from last track
                 mBytesRemaining = 0;
                 if (mPausedBytesRemaining) {
@@ -3985,8 +3997,7 @@
                 }
             }
         }
-        mPreviousTrack = t.get();
-        bool last = (i == (count - 1));
+        mPreviousTrack = track;
         if (track->isPausing()) {
             track->setPaused();
             if (last) {
@@ -4096,7 +4107,7 @@
     // If a flush is pending and a track is active but the HW is not paused, force a HW pause
     // before flush and then resume HW. This can happen in case of pause/flush/resume
     // if resume is received before pause is executed.
-    if (doHwPause || (mFlushPending && !mHwPaused && (count != 0))) {
+    if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
         mOutput->stream->pause(mOutput->stream);
         if (!doHwPause) {
             doHwResume = true;
@@ -4106,7 +4117,7 @@
         flushHw_l();
         mFlushPending = false;
     }
-    if (doHwResume) {
+    if (!mStandby && doHwResume) {
         mOutput->stream->resume(mOutput->stream);
     }
 
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 81804c2..a0b53cb 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -501,6 +501,7 @@
     SortedVector< wp<Track> >       mActiveTracks;  // FIXME check if this could be sp<>
     SortedVector<int>               mWakeLockUids;
     int                             mActiveTracksGeneration;
+    wp<Track>                       mLatestActiveTrack; // latest track added to mActiveTracks
 
     // Allocate a track name for a given channel mask.
     //   Returns name >= 0 if successful, -1 on failure.