Merge "Fix underruns when fast track denied due to SRC" into klp-dev
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index ad7409d..fe258ad 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -383,8 +383,6 @@
 protected:
     size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
     int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
-private:
-    bool        mDeferWake;     // whether another releaseBuffer() is expected soon
 };
 
 // Proxy used by AudioFlinger for servicing AudioTrack
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 744faee..15249a4 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -815,12 +815,29 @@
         return NO_INIT;
     }
 
+    // Not all of these values are needed under all conditions, but it is easier to get them all
+
     uint32_t afLatency;
-    if ((status = AudioSystem::getLatency(output, streamType, &afLatency)) != NO_ERROR) {
+    status = AudioSystem::getLatency(output, streamType, &afLatency);
+    if (status != NO_ERROR) {
         ALOGE("getLatency(%d) failed status %d", output, status);
         return NO_INIT;
     }
 
+    size_t afFrameCount;
+    status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
+    if (status != NO_ERROR) {
+        ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status);
+        return NO_INIT;
+    }
+
+    uint32_t afSampleRate;
+    status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate);
+    if (status != NO_ERROR) {
+        ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status);
+        return NO_INIT;
+    }
+
     // Client decides whether the track is TIMED (see below), but can only express a preference
     // for FAST.  Server will perform additional tests.
     if ((flags & AUDIO_OUTPUT_FLAG_FAST) && !(
@@ -836,6 +853,14 @@
     }
     ALOGV("createTrack_l() output %d afLatency %d", output, afLatency);
 
+    // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where
+    //  n = 1   fast track; nBuffering is ignored
+    //  n = 2   normal track, no sample rate conversion
+    //  n = 3   normal track, with sample rate conversion
+    //          (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering)
+    //  n > 3   very high latency or very small notification interval; nBuffering is ignored
+    const uint32_t nBuffering = (sampleRate == afSampleRate) ? 2 : 3;
+
     mNotificationFramesAct = mNotificationFramesReq;
 
     if (!audio_is_linear_pcm(format)) {
@@ -844,13 +869,6 @@
             // Same comment as below about ignoring frameCount parameter for set()
             frameCount = sharedBuffer->size();
         } else if (frameCount == 0) {
-            size_t afFrameCount;
-            status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
-            if (status != NO_ERROR) {
-                ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType,
-                        status);
-                return NO_INIT;
-            }
             frameCount = afFrameCount;
         }
         if (mNotificationFramesAct != frameCount) {
@@ -880,26 +898,13 @@
     } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) {
 
         // FIXME move these calculations and associated checks to server
-        uint32_t afSampleRate;
-        status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate);
-        if (status != NO_ERROR) {
-            ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType,
-                    status);
-            return NO_INIT;
-        }
-        size_t afFrameCount;
-        status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
-        if (status != NO_ERROR) {
-            ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status);
-            return NO_INIT;
-        }
 
         // Ensure that buffer depth covers at least audio hardware latency
         uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
         ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d",
                 afFrameCount, minBufCount, afSampleRate, afLatency);
-        if (minBufCount <= 2) {
-            minBufCount = sampleRate == afSampleRate ? 2 : 3;
+        if (minBufCount <= nBuffering) {
+            minBufCount = nBuffering;
         }
 
         size_t minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
@@ -909,18 +914,16 @@
 
         if (frameCount == 0) {
             frameCount = minFrameCount;
-        }
-        // Make sure that application is notified with sufficient margin
-        // before underrun
-        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
-            mNotificationFramesAct = frameCount/2;
-        }
-        if (frameCount < minFrameCount) {
+        } else if (frameCount < minFrameCount) {
             // not ALOGW because it happens all the time when playing key clicks over A2DP
             ALOGV("Minimum buffer size corrected from %d to %d",
                      frameCount, minFrameCount);
             frameCount = minFrameCount;
         }
+        // Make sure that application is notified with sufficient margin before underrun
+        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
+            mNotificationFramesAct = frameCount/nBuffering;
+        }
 
     } else {
         // For fast tracks, the frame count calculations and checks are done by server
@@ -1001,8 +1004,8 @@
             flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST);
             mFlags = flags;
             if (sharedBuffer == 0) {
-                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
-                    mNotificationFramesAct = frameCount/2;
+                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
+                    mNotificationFramesAct = frameCount/nBuffering;
                 }
             }
         }
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index e7abb40..4fd92b2 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -481,7 +481,7 @@
 ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
         size_t frameSize, bool isOut, bool clientInServer)
     : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
-      mAvailToClient(0), mFlush(0), mDeferWake(false)
+      mAvailToClient(0), mFlush(0)
 {
 }
 
@@ -559,9 +559,6 @@
             &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL;
     buffer->mNonContig = availToServer - part1;
     mUnreleased = part1;
-    // optimization to avoid waking up the client too early
-    // FIXME need to test for recording
-    mDeferWake = part1 < ask && availToServer >= ask;
     return part1 > 0 ? NO_ERROR : WOULD_BLOCK;
     }
 no_init:
@@ -607,7 +604,7 @@
         minimum = half;
     }
     // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
-    if (!mIsOut || (!mDeferWake && mAvailToClient + stepCount >= minimum)) {
+    if (!mIsOut || (mAvailToClient + stepCount >= minimum)) {
         ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
         int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
         if (!(old & CBLK_FUTEX_WAKE)) {