diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 110 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 23 |
2 files changed, 81 insertions, 52 deletions
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 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge 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 @@ bool AudioFlinger::PlaybackThread::threadLoop() 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 @@ if (mType == MIXER) { // 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 @@ if (mType == MIXER) { // 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 @@ if (mType == MIXER) { 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 @@ if (mType == DIRECT) { 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 @@ void AudioFlinger::MixerThread::threadLoop_mix() sleepTimeShift--; } sleepTime = 0; - standbyTime = systemTime() + mStandbyTimeInNsecs; + standbyTime = systemTime() + standbyDelay; //TODO: delay standby when effects have a tail } @@ -2548,6 +2509,32 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac 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 @@ uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() 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 @@ uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() 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_sleepTime() 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 @@ uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() 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 @@ private: 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 @@ protected: 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 @@ public: 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 @@ public: // 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ private: 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: |