am 20398fac: Merge "audioflinger: reduce sleep time to avoid underrun" into ics-mr1

* commit '20398fac99ff78cb3ec3dd122930e45d409e0524':
  audioflinger: reduce sleep time to avoid underrun
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 780c0d2..aea31a8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -89,6 +89,12 @@
 
 static const nsecs_t kSetParametersTimeout = seconds(2);
 
+// minimum sleep time for the mixer thread loop when tracks are active but in underrun
+static const uint32_t kMinThreadSleepTimeUs = 5000;
+// maximum divider applied to the active sleep time in the mixer thread loop
+static const uint32_t kMaxThreadSleepTimeShift = 2;
+
+
 // ----------------------------------------------------------------------------
 
 static bool recordingAllowed() {
@@ -1846,6 +1852,7 @@
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
+    uint32_t sleepTimeShift = 0;
     Vector< sp<EffectChain> > effectChains;
 #ifdef DEBUG_CPU_USAGE
     ThreadCpuUsage cpu;
@@ -1937,6 +1944,7 @@
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
                     sleepTime = idleSleepTime;
+                    sleepTimeShift = 0;
                     continue;
                 }
             }
@@ -1953,6 +1961,10 @@
             // mix buffers...
             mAudioMixer->process();
             sleepTime = 0;
+            // increase sleep time progressively when application underrun condition clears
+            if (sleepTimeShift > 0) {
+                sleepTimeShift--;
+            }
             standbyTime = systemTime() + kStandbyTimeInNsecs;
             //TODO: delay standby when effects have a tail
         } else {
@@ -1960,7 +1972,17 @@
             // buffer size, then write 0s to the output
             if (sleepTime == 0) {
                 if (mixerStatus == MIXER_TRACKS_ENABLED) {
-                    sleepTime = activeSleepTime;
+                    sleepTime = activeSleepTime >> sleepTimeShift;
+                    if (sleepTime < kMinThreadSleepTimeUs) {
+                        sleepTime = kMinThreadSleepTimeUs;
+                    }
+                    // reduce sleep time in case of consecutive application underruns to avoid
+                    // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
+                    // duration we would end up writing less data than needed by the audio HAL if
+                    // the condition persists.
+                    if (sleepTimeShift < kMaxThreadSleepTimeShift) {
+                        sleepTimeShift++;
+                    }
                 } else {
                     sleepTime = idleSleepTime;
                 }