diff options
author | Android (Google) Code Review <android-gerrit@google.com> | 2009-11-12 22:53:28 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-11-12 22:53:28 -0800 |
commit | fddfb9ae03a2730ac5ce27fa4c47b7d3a0285d0f (patch) | |
tree | 3ec21d76715c79bd5faa79dcc1de9e540c8b274d /libs | |
parent | 1aa9f3cac31a7c2b50fcb3c9259cead8d638ae54 (diff) | |
parent | 059b4be2a5a5b3fd410f8263e5f5928689c97af7 (diff) | |
download | frameworks_base-fddfb9ae03a2730ac5ce27fa4c47b7d3a0285d0f.zip frameworks_base-fddfb9ae03a2730ac5ce27fa4c47b7d3a0285d0f.tar.gz frameworks_base-fddfb9ae03a2730ac5ce27fa4c47b7d3a0285d0f.tar.bz2 |
Merge change Iad79689a into eclair
* changes:
Improvements for issue 2197683: English IME key-press latency is noticeably higher on passion than sholes
Diffstat (limited to 'libs')
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 155 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.h | 18 |
2 files changed, 103 insertions, 70 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index ebd470f..d918998 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -1185,7 +1185,6 @@ void AudioFlinger::PlaybackThread::readOutputParameters() 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 @@ AudioFlinger::MixerThread::~MixerThread() 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 @@ bool AudioFlinger::MixerThread::threadLoop() // 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 @@ bool AudioFlinger::MixerThread::threadLoop() } 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 @@ bool AudioFlinger::MixerThread::threadLoop() // 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 @@ bool AudioFlinger::MixerThread::threadLoop() 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 @@ bool AudioFlinger::MixerThread::threadLoop() ns2ms(delta), mNumDelayedWrites, this); lastWarning = now; } + if (mStandby) { + longStandbyExit = true; + } } + mStandby = false; } else { usleep(sleepTime); } @@ -1342,10 +1354,10 @@ bool AudioFlinger::MixerThread::threadLoop() } // 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 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> // 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 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> 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 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> } } - return enabledTracks; + return mixerStatus; } void AudioFlinger::MixerThread::getTracks( @@ -1621,14 +1628,14 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16> 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 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread() 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 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } standbyTime = systemTime() + kStandbyTimeInNsecs; - sleepTime = 1000; + sleepTime = idleSleepTime; continue; } } @@ -1753,6 +1766,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // 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 @@ bool AudioFlinger::DirectOutputThread::threadLoop() 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 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } } - if (activeTrack != 0) { + if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) { AudioBufferProvider::Buffer buffer; size_t frameCount = mFrameCount; curBuf = (int8_t *)mMixBuffer; @@ -1812,7 +1820,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop() 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 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } if (mSuspended) { - sleepTime = maxBufferRecoveryInUsecs; + sleepTime = idleSleepTime; } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -1905,15 +1917,22 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() 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 @@ AudioFlinger::DuplicatingThread::~DuplicatingThread() 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 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } 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 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } 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 @@ private: DUPLICATING }; + enum mixer_state { + MIXER_IDLE, + MIXER_TRACKS_ENABLED, + MIXER_TRACKS_READY + }; + // playback track class Track : public TrackBase { public: @@ -530,7 +536,8 @@ private: 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 @@ private: int mNumWrites; int mNumDelayedWrites; bool mInWrite; - int mMinBytesToWrite; }; class MixerThread : public PlaybackThread { @@ -582,10 +588,11 @@ private: 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 @@ private: 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; |