am 7f8f7585: am fd477974: AudioFlinger: more fixes for offload audio lost

* commit '7f8f758506a95d6fe5c0e52aa7b5ef82fb18861a':
  AudioFlinger: more fixes for offload audio lost
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ff7ccac..ef90952 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -272,6 +272,7 @@
         // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, mFormat, mBufferSize
         // 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
@@ -1468,6 +1469,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(),
@@ -1942,7 +1944,7 @@
 
     mNumWrites++;
     mInWrite = false;
-
+    mStandby = false;
     return bytesWritten;
 }
 
@@ -2365,7 +2367,6 @@
                 }
 }
 
-                mStandby = false;
             } else {
                 usleep(sleepTime);
             }
@@ -3615,6 +3616,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
@@ -3624,11 +3631,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())
@@ -3655,7 +3657,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();
             }
 
@@ -3667,7 +3669,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();
                     }
@@ -3943,6 +3946,8 @@
         mPausedBytesRemaining(0),
         mPreviousTrack(NULL)
 {
+    //FIXME: mStandby should be set to true by ThreadBase constructor
+    mStandby = true;
 }
 
 void AudioFlinger::OffloadThread::threadLoop_exit()
@@ -3979,8 +3984,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) {
@@ -3995,8 +4007,7 @@
                 }
             }
         }
-        mPreviousTrack = t.get();
-        bool last = (i == (count - 1));
+        mPreviousTrack = track;
         if (track->isPausing()) {
             track->setPaused();
             if (last) {
@@ -4106,7 +4117,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;
@@ -4116,7 +4127,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 2b4c9fd..8a859f5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -503,6 +503,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.