Improvements for issue 2197683:	English IME key-press latency is noticeably higher on passion than sholes

This change goes with a kernel driver change that reduces the audio buffer size from 4800 bytes (~27ms) to 3072 bytes (~17ms).
- The AudioFlinger modifcations in change 0bca68cfff161abbc992fec82dc7c88079dd1a36 have been removed: the short sleep period was counter productive when the AudioTrack is using the call back thread as it causes to many preemptions.
- AudioFlinger mixer thread now detects long standby exit time and in this case anticipates start by writing 0s as soon as a track is enabled even if not ready for mixing.
- AudioTrack::start() is modified to start call back thread before starting the IAudioTrack so that thread startup time is masked by IAudioTrack start and mixer thread wakeup time.
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index ebd470f4..d918998 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1185,7 +1185,6 @@
     mFrameSize = mOutput->frameSize();
     mFrameCount = mOutput->bufferSize() / mFrameSize;
 
-    mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
     // FIXME - Current mixer implementation only supports stereo output: Always
     // Allocate a stereo buffer even if HW output is mono.
     if (mMixBuffer != NULL) delete mMixBuffer;
@@ -1215,23 +1214,25 @@
 
 bool AudioFlinger::MixerThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount * mFrameSize;
     // FIXME: Relaxed timing because of a certain device that can't meet latency
     // Should be reduced to 2x after the vendor fixes the driver issue
     nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
     nsecs_t lastWarning = 0;
+    bool longStandbyExit = false;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for mLock
 
             Mutex::Autolock _l(mLock);
@@ -1241,7 +1242,8 @@
                 // FIXME: Relaxed timing because of a certain device that can't meet latency
                 // Should be reduced to 2x after the vendor fixes the driver issue
                 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1277,15 +1279,15 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
        }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
@@ -1294,15 +1296,22 @@
             // If no tracks are ready, sleep once for the duration of an output
             // buffer size, then write 0s to the output
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
-            } else if (mBytesWritten != 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0 ||
+                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
+                LOGV("NO DATA READY, %p", this);
                 memset (curBuf, 0, mixBufferSize);
                 sleepTime = 0;
+                LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
             }
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1312,7 +1321,6 @@
             if (bytesWritten > 0) mBytesWritten += bytesWritten;
             mNumWrites++;
             mInWrite = false;
-            mStandby = false;
             nsecs_t now = systemTime();
             nsecs_t delta = now - mLastWriteTime;
             if (delta > maxPeriod) {
@@ -1322,7 +1330,11 @@
                             ns2ms(delta), mNumDelayedWrites, this);
                     lastWarning = now;
                 }
+                if (mStandby) {
+                    longStandbyExit = true;
+                }
             }
+            mStandby = false;
         } else {
             usleep(sleepTime);
         }
@@ -1342,10 +1354,10 @@
 }
 
 // prepareTracks_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
 {
 
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     // find out which tracks need to be processed
     size_t count = activeTracks.size();
     for (size_t i=0 ; i<count ; i++) {
@@ -1415,7 +1427,7 @@
 
             // reset retry count
             track->mRetryCount = kMaxTrackRetries;
-            enabledTracks++;
+            mixerStatus = MIXER_TRACKS_READY;
         } else {
             //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
             if (track->isStopped()) {
@@ -1432,16 +1444,11 @@
                 if (--(track->mRetryCount) <= 0) {
                     LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                     tracksToRemove->add(track);
+                } else if (mixerStatus != MIXER_TRACKS_READY) {
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
-                // For tracks using static shared memory buffer, make sure that we have
-                // written enough data to audio hardware before disabling the track
-                // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                // don't care about code removing track from active list above.
-                if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                } else {
-                    enabledTracks++;
-                }
+
+                mAudioMixer->disable(AudioMixer::MIXING);
             }
         }
     }
@@ -1459,7 +1466,7 @@
         }
     }
 
-    return enabledTracks;
+    return mixerStatus;
 }
 
 void AudioFlinger::MixerThread::getTracks(
@@ -1621,14 +1628,14 @@
     return NO_ERROR;
 }
 
-uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
 {
-    uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-    // Add some margin with regard to scheduling precision
-    if (time > 10000) {
-        time -= 10000;
-    }
-    return time;
+    return (uint32_t)(mOutput->latency() * 1000) / 2;
+}
+
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+{
+    return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
 }
 
 // ----------------------------------------------------------------------------
@@ -1646,25 +1653,31 @@
 
 bool AudioFlinger::DirectOutputThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    uint32_t mixerStatus = MIXER_IDLE;
     sp<Track> trackToRemove;
     sp<Track> activeTrack;
     nsecs_t standbyTime = systemTime();
     int8_t *curBuf;
     size_t mixBufferSize = mFrameCount*mFrameSize;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+
 
     while (!exitPending())
     {
         processConfigEvents();
 
+        mixerStatus = MIXER_IDLE;
+
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             // put audio hardware into standby after short delay
@@ -1698,7 +1711,7 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
@@ -1753,6 +1766,7 @@
                     // reset retry count
                     track->mRetryCount = kMaxTrackRetries;
                     activeTrack = t;
+                    mixerStatus = MIXER_TRACKS_READY;
                 } else {
                     //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
                     if (track->isStopped()) {
@@ -1768,16 +1782,10 @@
                         if (--(track->mRetryCount) <= 0) {
                             LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
                             trackToRemove = track;
+                        } else {
+                            mixerStatus = MIXER_TRACKS_ENABLED;
                         }
-
-                        // For tracks using static shared memry buffer, make sure that we have
-                        // written enough data to audio hardware before disabling the track
-                        // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                        // don't care about code removing track from active list above.
-                        if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
-                            activeTrack = t;
-                        }
-                     }
+                    }
                 }
             }
 
@@ -1791,7 +1799,7 @@
             }
        }
 
-        if (activeTrack != 0) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             AudioBufferProvider::Buffer buffer;
             size_t frameCount = mFrameCount;
             curBuf = (int8_t *)mMixBuffer;
@@ -1812,7 +1820,11 @@
             standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
                 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
                 sleepTime = 0;
@@ -1820,7 +1832,7 @@
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1905,15 +1917,22 @@
     return reconfig;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
 {
     uint32_t time;
     if (AudioSystem::isLinearPCM(mFormat)) {
-        time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-        // Add some margin with regard to scheduling precision
-        if (time > 10000) {
-            time -= 10000;
-        }
+        time = (uint32_t)(mOutput->latency() * 1000) / 2;
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
     } else {
         time = 10000;
     }
@@ -1936,28 +1955,30 @@
 
 bool AudioFlinger::DuplicatingThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount*mFrameSize;
     SortedVector< sp<OutputTrack> > outputTracks;
     uint32_t writeFrames = 0;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1997,22 +2018,26 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
         }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
             writeFrames = mFrameCount;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0) {
                 // flush remaining overflow buffers in output tracks
                 for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -2026,7 +2051,7 @@
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 22d15c9..594d878 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -361,6 +361,12 @@
             DUPLICATING
         };
 
+        enum mixer_state {
+            MIXER_IDLE,
+            MIXER_TRACKS_ENABLED,
+            MIXER_TRACKS_READY
+        };
+
         // playback track
         class Track : public TrackBase {
         public:
@@ -530,7 +536,8 @@
 
         virtual int             getTrackName_l() = 0;
         virtual void            deleteTrackName_l(int name) = 0;
-        virtual uint32_t        getMaxBufferRecoveryInUsecs() = 0;
+        virtual uint32_t        activeSleepTimeUs() = 0;
+        virtual uint32_t        idleSleepTimeUs() = 0;
 
     private:
 
@@ -562,7 +569,6 @@
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
-        int                             mMinBytesToWrite;
     };
 
     class MixerThread : public PlaybackThread {
@@ -582,10 +588,11 @@
         virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
 
     protected:
-        size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
+                    uint32_t    prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
         AudioMixer*                     mAudioMixer;
     };
@@ -604,7 +611,8 @@
     protected:
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
     private:
         float mLeftVolume;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 8529a8e..cedd79d 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -318,26 +318,35 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        audio_io_handle_t output = AudioTrack::getOutput();
+        audio_io_handle_t output = getOutput();
+        AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
+        mNewPosition = mCblk->server + mUpdatePeriod;
+        mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+        mCblk->waitTimeMs = 0;
+        if (t != 0) {
+           t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+        } else {
+            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        }
+
         status_t status = mAudioTrack->start();
         if (status == DEAD_OBJECT) {
             LOGV("start() dead IAudioTrack: creating a new one");
             status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
                                  mFrameCount, mFlags, mSharedBuffer, output);
-        }
-        if (status == NO_ERROR) {
-            AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
             mNewPosition = mCblk->server + mUpdatePeriod;
             mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
             mCblk->waitTimeMs = 0;
-            if (t != 0) {
-               t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
-            } else {
-                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
-            }
-        } else {
+        }
+        if (status != NO_ERROR) {
             LOGV("start() failed");
             android_atomic_and(~1, &mActive);
+            if (t != 0) {
+                t->requestExit();
+            } else {
+                setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
+            }
+            AudioSystem::stopOutput(output, (AudioSystem::stream_type)mStreamType);
         }
     }