Merge "Merge dup code at thread entry and param change"
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f94ab84..2f49808 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1464,7 +1464,8 @@
         mMasterVolume(audioFlinger->masterVolumeSW_l()),
         mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
         // mMixerStatus
-        mPrevMixerStatus(MIXER_IDLE)
+        mPrevMixerStatus(MIXER_IDLE),
+        standbyDelay(AudioFlinger::mStandbyTimeInNsecs)
 {
     snprintf(mName, kNameLength, "AudioOut_%X", id);
 
@@ -1997,14 +1998,8 @@
     Vector< sp<Track> > tracksToRemove;
 
     standbyTime = systemTime();
-    mixBufferSize = mFrameCount * mFrameSize;
 
     // MIXER
-    // 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
-    // increase threshold again due to low power audio mode. The way this warning threshold is
-    // calculated and its usefulness should be reconsidered anyway.
-    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
     nsecs_t lastWarning = 0;
 if (mType == MIXER) {
     longStandbyExit = false;
@@ -2014,8 +2009,7 @@
     // FIXME could this be made local to while loop?
     writeFrames = 0;
 
-    activeSleepTime = activeSleepTimeUs();
-    idleSleepTime = idleSleepTimeUs();
+    cacheParameters_l();
     sleepTime = idleSleepTime;
 
 if (mType == MIXER) {
@@ -2025,13 +2019,6 @@
     // MIXER
     CpuStats cpuStats;
 
-    // DIRECT
-if (mType == DIRECT) {
-    // use shorter standby delay as on normal output to release
-    // hardware resources as soon as possible
-    standbyDelay = microseconds(activeSleepTime*2);
-}
-
     acquireWakeLock();
 
     while (!exitPending())
@@ -2050,25 +2037,7 @@
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
-                mixBufferSize = mFrameCount * mFrameSize;
-
-if (mType == MIXER) {
-                // 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
-                // increase threshold again due to low power audio mode. The way this warning
-                // threshold is calculated and its usefulness should be reconsidered anyway.
-                maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
-}
-
-                updateWaitTime_l();
-
-                activeSleepTime = activeSleepTimeUs();
-                idleSleepTime = idleSleepTimeUs();
-
-if (mType == DIRECT) {
-                standbyDelay = microseconds(activeSleepTime*2);
-}
-
+                cacheParameters_l();
             }
 
             saveOutputTracks();
@@ -2103,19 +2072,11 @@
 
                     checkSilentMode_l();
 
-if (mType == MIXER || mType == DUPLICATING) {
-                    standbyTime = systemTime() + mStandbyTimeInNsecs;
-}
-
-if (mType == DIRECT) {
                     standbyTime = systemTime() + standbyDelay;
-}
-
                     sleepTime = idleSleepTime;
-
-if (mType == MIXER) {
-                    sleepTimeShift = 0;
-}
+                    if (mType == MIXER) {
+                        sleepTimeShift = 0;
+                    }
 
                     continue;
                 }
@@ -2261,7 +2222,7 @@
         sleepTimeShift--;
     }
     sleepTime = 0;
-    standbyTime = systemTime() + mStandbyTimeInNsecs;
+    standbyTime = systemTime() + standbyDelay;
     //TODO: delay standby when effects have a tail
 }
 
@@ -2548,6 +2509,32 @@
     return mixerStatus;
 }
 
+/*
+The derived values that are cached:
+ - mixBufferSize from frame count * frame size
+ - activeSleepTime from activeSleepTimeUs()
+ - idleSleepTime from idleSleepTimeUs()
+ - standbyDelay from mActiveSleepTimeUs (DIRECT only)
+ - maxPeriod from frame count and sample rate (MIXER only)
+
+The parameters that affect these derived values are:
+ - frame count
+ - frame size
+ - sample rate
+ - device type: A2DP or not
+ - device latency
+ - format: PCM or not
+ - active sleep time
+ - idle sleep time
+*/
+
+void AudioFlinger::PlaybackThread::cacheParameters_l()
+{
+    mixBufferSize = mFrameCount * mFrameSize;
+    activeSleepTime = activeSleepTimeUs();
+    idleSleepTime = idleSleepTimeUs();
+}
+
 void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
 {
     ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
@@ -2718,6 +2705,17 @@
     return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
 }
 
+void AudioFlinger::MixerThread::cacheParameters_l()
+{
+    PlaybackThread::cacheParameters_l();
+
+    // 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
+    // increase threshold again due to low power audio mode. The way this warning
+    // threshold is calculated and its usefulness should be reconsidered anyway.
+    maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
+}
+
 // ----------------------------------------------------------------------------
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
@@ -3074,6 +3072,14 @@
     return time;
 }
 
+void AudioFlinger::DirectOutputThread::cacheParameters_l()
+{
+    PlaybackThread::cacheParameters_l();
+
+    // use shorter standby delay as on normal output to release
+    // hardware resources as soon as possible
+    standbyDelay = microseconds(activeSleepTime*2);
+}
 
 // ----------------------------------------------------------------------------
 
@@ -3127,7 +3133,7 @@
 
 void AudioFlinger::DuplicatingThread::threadLoop_write()
 {
-    standbyTime = systemTime() + mStandbyTimeInNsecs;
+    standbyTime = systemTime() + standbyDelay;
     for (size_t i = 0; i < outputTracks.size(); i++) {
         outputTracks[i]->write(mMixBuffer, writeFrames);
     }
@@ -3223,6 +3229,14 @@
     return (mWaitTimeMs * 1000) / 2;
 }
 
+void AudioFlinger::DuplicatingThread::cacheParameters_l()
+{
+    // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
+    updateWaitTime_l();
+
+    MixerThread::cacheParameters_l();
+}
+
 // ----------------------------------------------------------------------------
 
 // TrackBase constructor must be called with AudioFlinger::mLock held
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 38fff8c..194b826 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -222,6 +222,8 @@
     audio_hw_device_t*      findSuitableHwDev_l(uint32_t devices);
     void                    purgeStaleEffects_l();
 
+    // standby delay for MIXER and DUPLICATING playback threads is read from property
+    // ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs
     static nsecs_t          mStandbyTimeInNsecs;
 
     // Internal dump utilites.
@@ -840,9 +842,6 @@
         virtual     void        threadLoop_write();
         virtual     void        threadLoop_standby();
 
-        // Non-trivial for DUPLICATING only
-        virtual     void        updateWaitTime_l() { }
-
         // Non-trivial for DIRECT only
         virtual     void        applyVolume() { }
 
@@ -929,6 +928,9 @@
         virtual     void        saveOutputTracks() { }
         virtual     void        clearOutputTracks() { }
 
+        // Cache various calculated values, at threadLoop() entry and after a parameter change
+        virtual     void        cacheParameters_l();
+
     private:
 
         friend class AudioFlinger;
@@ -964,8 +966,11 @@
         // FIXME rename these former local variables of threadLoop to standard "m" names
         nsecs_t                         standbyTime;
         size_t                          mixBufferSize;
+
+        // cached copies of activeSleepTimeUs() and idleSleepTimeUs() made by cacheParameters_l()
         uint32_t                        activeSleepTime;
         uint32_t                        idleSleepTime;
+
         uint32_t                        sleepTime;
 
         // mixer status returned by prepareTracks_l()
@@ -976,8 +981,13 @@
         // MIXER only
         bool                            longStandbyExit;
         uint32_t                        sleepTimeShift;
-        // DIRECT only
+
+        // same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value
         nsecs_t                         standbyDelay;
+
+        // MIXER only
+        nsecs_t                         maxPeriod;
+
         // DUPLICATING only
         uint32_t                        writeFrames;
     };
@@ -1003,6 +1013,7 @@
         virtual     void        deleteTrackName_l(int name);
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
+        virtual     void        cacheParameters_l();
 
         // threadLoop snippets
         virtual     void        threadLoop_mix();
@@ -1028,6 +1039,7 @@
         virtual     uint32_t    activeSleepTimeUs();
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
+        virtual     void        cacheParameters_l();
 
         // threadLoop snippets
         virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
@@ -1075,9 +1087,12 @@
         virtual     void        threadLoop_sleepTime();
         virtual     void        threadLoop_write();
         virtual     void        threadLoop_standby();
+        virtual     void        cacheParameters_l();
 
+    private:
         // called from threadLoop, addOutputTrack, removeOutputTrack
         virtual     void        updateWaitTime_l();
+    protected:
         virtual     void        saveOutputTracks();
         virtual     void        clearOutputTracks();
     private: