Merge "fix fallout from binderizing BufferQueues consumer side"
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 6d778dd..1379379 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -415,6 +415,13 @@
     virtual void        framesReadyIsCalledByMultipleThreads() { }
 
     bool     setStreamEndDone();    // and return previous value
+
+    // Add to the tally of underrun frames, and inform client of underrun
+    virtual void        tallyUnderrunFrames(uint32_t frameCount);
+
+    // Return the total number of frames which AudioFlinger desired but were unavailable,
+    // and thus which resulted in an underrun.
+    virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
 };
 
 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
@@ -429,6 +436,8 @@
     virtual void        framesReadyIsCalledByMultipleThreads();
     virtual status_t    obtainBuffer(Buffer* buffer);
     virtual void        releaseBuffer(Buffer* buffer);
+    virtual void        tallyUnderrunFrames(uint32_t frameCount);
+    virtual uint32_t    getUnderrunFrames() const { return 0; }
 
 private:
     ssize_t             pollPosition(); // poll for state queue update, and return current position
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 3b7616f..e7abb40 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -661,6 +661,14 @@
     return old;
 }
 
+void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
+{
+    mCblk->u.mStreaming.mUnderrunFrames += frameCount;
+
+    // FIXME also wake futex so that underrun is noticed more quickly
+    (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+}
+
 // ---------------------------------------------------------------------------
 
 StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
@@ -817,6 +825,17 @@
     buffer->mNonContig = 0;
 }
 
+void StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
+{
+    // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks,
+    // we don't have a location to count underrun frames.  The underrun frame counter
+    // only exists in AudioTrackSharedStreaming.  Fortunately, underruns are not
+    // possible for static buffer tracks other than at end of buffer, so this is not a loss.
+
+    // FIXME also wake futex so that underrun is noticed more quickly
+    (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+}
+
 // ---------------------------------------------------------------------------
 
 }   // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 628f5af..5600411c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -140,7 +140,6 @@
                                     // but the slot is only used if track is active
     FastTrackUnderruns  mObservedUnderruns; // Most recently observed value of
                                     // mFastMixerDumpState.mTracks[mFastIndex].mUnderruns
-    uint32_t            mUnderrunCount; // Counter of total number of underruns, never reset
     volatile float      mCachedVolume;  // combined master volume and stream type volume;
                                         // 'volatile' means accessed without lock or
                                         // barrier, but is read/written atomically
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 17fbd72..f0c27c3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2739,8 +2739,10 @@
             track->mObservedUnderruns = underruns;
             // don't count underruns that occur while stopping or pausing
             // or stopped which can occur when flush() is called while active
-            if (!(track->isStopping() || track->isPausing() || track->isStopped())) {
-                track->mUnderrunCount += recentUnderruns;
+            if (!(track->isStopping() || track->isPausing() || track->isStopped()) &&
+                    recentUnderruns > 0) {
+                // FIXME fast mixer will pull & mix partial buffers, but we count as a full underrun
+                track->mAudioTrackServerProxy->tallyUnderrunFrames(recentUnderruns * mFrameCount);
             }
 
             // This is similar to the state machine for normal tracks,
@@ -3056,12 +3058,8 @@
                 mixerStatus = MIXER_TRACKS_READY;
             }
         } else {
-            // only implemented for normal tracks, not fast tracks
             if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
-                // we missed desiredFrames whatever the actual number of frames missing was
-                cblk->u.mStreaming.mUnderrunFrames += desiredFrames;
-                // FIXME also wake futex so that underrun is noticed more quickly
-                (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags);
+                track->mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
             }
             // clear effect chain input buffer if an active track underruns to avoid sending
             // previous audio buffer again to effects
@@ -3086,7 +3084,6 @@
                     tracksToRemove->add(track);
                 }
             } else {
-                track->mUnderrunCount++;
                 // No buffers for this track. Give it a few chances to
                 // fill a buffer, then remove it from active list.
                 if (--(track->mRetryCount) <= 0) {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 1f75468..e676365 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -316,7 +316,6 @@
     mPresentationCompleteFrames(0),
     mFlags(flags),
     mFastIndex(-1),
-    mUnderrunCount(0),
     mCachedVolume(1.0),
     mIsInvalid(false),
     mAudioTrackServerProxy(NULL),
@@ -389,7 +388,7 @@
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
     result.append("   Name Client Type Fmt Chn mask Session fCount S F SRate  "
-                  "L dB  R dB    Server Main buf  Aux Buf Flags Underruns\n");
+                  "L dB  R dB    Server Main buf  Aux Buf Flags UndFrmCnt\n");
 }
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
@@ -470,7 +469,7 @@
             (int)mMainBuffer,
             (int)mAuxBuffer,
             mCblk->mFlags,
-            mUnderrunCount,
+            mAudioTrackServerProxy->getUnderrunFrames(),
             nowInUnderrun);
 }
 
@@ -489,10 +488,7 @@
     buffer->frameCount = buf.mFrameCount;
     buffer->raw = buf.mRaw;
     if (buf.mFrameCount == 0) {
-        // only implemented so far for normal tracks, not fast tracks
-        mCblk->u.mStreaming.mUnderrunFrames += desiredFrames;
-        // FIXME also wake futex so that underrun is noticed more quickly
-        (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+        mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
     }
     return status;
 }