Loading services/audioflinger/AudioFlinger.cpp +78 −9 Original line number Diff line number Diff line Loading @@ -1993,9 +1993,12 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l() bool AudioFlinger::MixerThread::threadLoop() { // DirectOutputThread has single trackToRemove instead of Vector Vector< sp<Track> > tracksToRemove; // DirectOutputThread has activeTrack here 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 // increase threshold again due to low power audio mode. The way this warning threshold is Loading @@ -2003,18 +2006,25 @@ bool AudioFlinger::MixerThread::threadLoop() nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15; nsecs_t lastWarning = 0; bool longStandbyExit = false; uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; uint32_t sleepTimeShift = 0; Vector< sp<EffectChain> > effectChains; CpuStats cpuStats; // DirectOutputThread has shorter standbyDelay acquireWakeLock(); while (!exitPending()) { cpuStats.sample(); // DirectOutputThread has rampVolume, leftVol, rightVol processConfigEvents(); mixer_state mixerStatus = MIXER_IDLE; Loading @@ -2024,13 +2034,16 @@ bool AudioFlinger::MixerThread::threadLoop() if (checkForNewParameters_l()) { 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 // 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; activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); // DirectOutputThread updates standbyDelay also } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -2136,6 +2149,9 @@ bool AudioFlinger::MixerThread::threadLoop() // only process effects if we're going to write if (sleepTime == 0) { // DirectOutputThread adds applyVolume here for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } Loading @@ -2146,14 +2162,16 @@ bool AudioFlinger::MixerThread::threadLoop() // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { // FIXME Only in MixerThread, and rewrite to reduce number of system calls mLastWriteTime = systemTime(); mInWrite = true; mBytesWritten += mixBufferSize; int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize); if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; // Only in MixerThread: start of write blocked detection nsecs_t now = systemTime(); nsecs_t delta = now - mLastWriteTime; if (!mStandby && delta > maxPeriod) { Loading @@ -2167,12 +2185,14 @@ bool AudioFlinger::MixerThread::threadLoop() longStandbyExit = true; } } // end of write blocked detection mStandby = false; } else { usleep(sleepTime); } // finally let go of all our tracks, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. tracksToRemove.clear(); Loading @@ -2182,6 +2202,7 @@ bool AudioFlinger::MixerThread::threadLoop() effectChains.clear(); } // put output stream into standby mode if (!mStandby) { mOutput->stream->common.standby(&mOutput->stream->common); } Loading Loading @@ -2706,13 +2727,21 @@ void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t ri bool AudioFlinger::DirectOutputThread::threadLoop() { // MixerThread has Vector instead of single trackToRemove sp<Track> trackToRemove; // MixerThread does not have activeTrack here sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // MixerThread has relaxed timing: maxPeriod, lastWarning, longStandbyExit uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; // MixerThread has sleepTimeShift and cpuStats // use shorter standby delay as on normal output to release // hardware resources as soon as possible nsecs_t standbyDelay = microseconds(activeSleepTime*2); Loading @@ -2721,9 +2750,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop() while (!exitPending()) { // MixerThread has cpuStats.sample() bool rampVolume; uint16_t leftVol; uint16_t rightVol; Vector< sp<EffectChain> > effectChains; processConfigEvents(); Loading @@ -2735,6 +2767,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount * mFrameSize; // different calculations here standbyDelay = microseconds(activeSleepTime*2); activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); standbyDelay = microseconds(activeSleepTime*2); Loading @@ -2743,7 +2779,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // put audio hardware into standby after short delay if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) || mSuspended)) { // wait until we have something to do... if (!mStandby) { ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended); mOutput->stream->common.standby(&mOutput->stream->common); Loading @@ -2758,19 +2793,27 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (exitPending()) break; releaseWakeLock_l(); // wait until we have something to do... ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid()); mWaitWorkCV.wait(mLock); ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); // MixerThread has "mPrevMixerStatus = MIXER_IDLE" checkSilentMode_l(); // MixerThread has different standbyDelay standbyTime = systemTime() + standbyDelay; sleepTime = idleSleepTime; // MixerThread has "sleepTimeShift = 0" continue; } } // MixerThread has "mixerStatus = prepareTracks_l(...)" // equivalent to MixerThread's lockEffectChains_l, but without the lock // FIXME - is it OK to omit the lock here? effectChains = mEffectChains; // find out which tracks need to be processed Loading Loading @@ -2939,9 +2982,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // only process effects if we're going to write if (sleepTime == 0) { // MixerThread does not have applyVolume if (mixerStatus == MIXER_TRACKS_READY) { applyVolume(leftVol, rightVol, rampVolume); } for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } Loading @@ -2959,12 +3005,15 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; // MixerThread has write blocked detection here mStandby = false; } else { usleep(sleepTime); } // finally let go of removed track, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. trackToRemove.clear(); Loading @@ -2975,6 +3024,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() effectChains.clear(); } // put output stream into standby mode if (!mStandby) { mOutput->stream->common.standby(&mOutput->stream->common); } Loading Loading @@ -3100,8 +3150,11 @@ bool AudioFlinger::DuplicatingThread::threadLoop() Vector< sp<Track> > tracksToRemove; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // Only in DuplicatingThread SortedVector< sp<OutputTrack> > outputTracks; uint32_t writeFrames = 0; uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; Loading @@ -3111,6 +3164,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop() while (!exitPending()) { // MixerThread has cpuStats.sample processConfigEvents(); mixer_state mixerStatus = MIXER_IDLE; Loading @@ -3120,13 +3175,17 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount * mFrameSize; // Only in DuplicatingThread updateWaitTime(); activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; // Only in DuplicatingThread for (size_t i = 0; i < mOutputTracks.size(); i++) { outputTracks.add(mOutputTracks[i]); } Loading @@ -3135,6 +3194,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) || mSuspended)) { if (!mStandby) { // DuplicatingThread implements standby by stopping all tracks for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->stop(); } Loading @@ -3156,10 +3216,12 @@ bool AudioFlinger::DuplicatingThread::threadLoop() ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); // MixerThread has "mPrevMixerStatus = MIXER_IDLE" checkSilentMode_l(); standbyTime = systemTime() + mStandbyTimeInNsecs; sleepTime = idleSleepTime; // MixerThread has sleepTimeShift continue; } } Loading @@ -3172,6 +3234,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() lockEffectChains_l(effectChains); } // Duplicating Thread is completely different here if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) { // mix buffers... if (outputsReady(outputTracks)) { Loading Loading @@ -3223,11 +3286,14 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } mStandby = false; mBytesWritten += mixBufferSize; // MixerThread has write blocked detection here } else { usleep(sleepTime); } // finally let go of all our tracks, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. tracksToRemove.clear(); Loading @@ -3238,6 +3304,9 @@ bool AudioFlinger::DuplicatingThread::threadLoop() effectChains.clear(); } // MixerThread and DirectOutpuThread have standby here, // but for DuplicatingThread this is handled by the outputTracks releaseWakeLock(); ALOGV("Thread %p type %d exiting", this, mType); Loading Loading
services/audioflinger/AudioFlinger.cpp +78 −9 Original line number Diff line number Diff line Loading @@ -1993,9 +1993,12 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l() bool AudioFlinger::MixerThread::threadLoop() { // DirectOutputThread has single trackToRemove instead of Vector Vector< sp<Track> > tracksToRemove; // DirectOutputThread has activeTrack here 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 // increase threshold again due to low power audio mode. The way this warning threshold is Loading @@ -2003,18 +2006,25 @@ bool AudioFlinger::MixerThread::threadLoop() nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15; nsecs_t lastWarning = 0; bool longStandbyExit = false; uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; uint32_t sleepTimeShift = 0; Vector< sp<EffectChain> > effectChains; CpuStats cpuStats; // DirectOutputThread has shorter standbyDelay acquireWakeLock(); while (!exitPending()) { cpuStats.sample(); // DirectOutputThread has rampVolume, leftVol, rightVol processConfigEvents(); mixer_state mixerStatus = MIXER_IDLE; Loading @@ -2024,13 +2034,16 @@ bool AudioFlinger::MixerThread::threadLoop() if (checkForNewParameters_l()) { 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 // 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; activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); // DirectOutputThread updates standbyDelay also } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; Loading Loading @@ -2136,6 +2149,9 @@ bool AudioFlinger::MixerThread::threadLoop() // only process effects if we're going to write if (sleepTime == 0) { // DirectOutputThread adds applyVolume here for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } Loading @@ -2146,14 +2162,16 @@ bool AudioFlinger::MixerThread::threadLoop() // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { // FIXME Only in MixerThread, and rewrite to reduce number of system calls mLastWriteTime = systemTime(); mInWrite = true; mBytesWritten += mixBufferSize; int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize); if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; // Only in MixerThread: start of write blocked detection nsecs_t now = systemTime(); nsecs_t delta = now - mLastWriteTime; if (!mStandby && delta > maxPeriod) { Loading @@ -2167,12 +2185,14 @@ bool AudioFlinger::MixerThread::threadLoop() longStandbyExit = true; } } // end of write blocked detection mStandby = false; } else { usleep(sleepTime); } // finally let go of all our tracks, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. tracksToRemove.clear(); Loading @@ -2182,6 +2202,7 @@ bool AudioFlinger::MixerThread::threadLoop() effectChains.clear(); } // put output stream into standby mode if (!mStandby) { mOutput->stream->common.standby(&mOutput->stream->common); } Loading Loading @@ -2706,13 +2727,21 @@ void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t ri bool AudioFlinger::DirectOutputThread::threadLoop() { // MixerThread has Vector instead of single trackToRemove sp<Track> trackToRemove; // MixerThread does not have activeTrack here sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // MixerThread has relaxed timing: maxPeriod, lastWarning, longStandbyExit uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; // MixerThread has sleepTimeShift and cpuStats // use shorter standby delay as on normal output to release // hardware resources as soon as possible nsecs_t standbyDelay = microseconds(activeSleepTime*2); Loading @@ -2721,9 +2750,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop() while (!exitPending()) { // MixerThread has cpuStats.sample() bool rampVolume; uint16_t leftVol; uint16_t rightVol; Vector< sp<EffectChain> > effectChains; processConfigEvents(); Loading @@ -2735,6 +2767,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount * mFrameSize; // different calculations here standbyDelay = microseconds(activeSleepTime*2); activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); standbyDelay = microseconds(activeSleepTime*2); Loading @@ -2743,7 +2779,6 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // put audio hardware into standby after short delay if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) || mSuspended)) { // wait until we have something to do... if (!mStandby) { ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended); mOutput->stream->common.standby(&mOutput->stream->common); Loading @@ -2758,19 +2793,27 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (exitPending()) break; releaseWakeLock_l(); // wait until we have something to do... ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid()); mWaitWorkCV.wait(mLock); ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); // MixerThread has "mPrevMixerStatus = MIXER_IDLE" checkSilentMode_l(); // MixerThread has different standbyDelay standbyTime = systemTime() + standbyDelay; sleepTime = idleSleepTime; // MixerThread has "sleepTimeShift = 0" continue; } } // MixerThread has "mixerStatus = prepareTracks_l(...)" // equivalent to MixerThread's lockEffectChains_l, but without the lock // FIXME - is it OK to omit the lock here? effectChains = mEffectChains; // find out which tracks need to be processed Loading Loading @@ -2939,9 +2982,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop() // only process effects if we're going to write if (sleepTime == 0) { // MixerThread does not have applyVolume if (mixerStatus == MIXER_TRACKS_READY) { applyVolume(leftVol, rightVol, rampVolume); } for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } Loading @@ -2959,12 +3005,15 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (bytesWritten < 0) mBytesWritten -= mixBufferSize; mNumWrites++; mInWrite = false; // MixerThread has write blocked detection here mStandby = false; } else { usleep(sleepTime); } // finally let go of removed track, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. trackToRemove.clear(); Loading @@ -2975,6 +3024,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() effectChains.clear(); } // put output stream into standby mode if (!mStandby) { mOutput->stream->common.standby(&mOutput->stream->common); } Loading Loading @@ -3100,8 +3150,11 @@ bool AudioFlinger::DuplicatingThread::threadLoop() Vector< sp<Track> > tracksToRemove; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // Only in DuplicatingThread SortedVector< sp<OutputTrack> > outputTracks; uint32_t writeFrames = 0; uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; Loading @@ -3111,6 +3164,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop() while (!exitPending()) { // MixerThread has cpuStats.sample processConfigEvents(); mixer_state mixerStatus = MIXER_IDLE; Loading @@ -3120,13 +3175,17 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (checkForNewParameters_l()) { mixBufferSize = mFrameCount * mFrameSize; // Only in DuplicatingThread updateWaitTime(); activeSleepTime = activeSleepTimeUs(); idleSleepTime = idleSleepTimeUs(); } const SortedVector< wp<Track> >& activeTracks = mActiveTracks; // Only in DuplicatingThread for (size_t i = 0; i < mOutputTracks.size(); i++) { outputTracks.add(mOutputTracks[i]); } Loading @@ -3135,6 +3194,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) || mSuspended)) { if (!mStandby) { // DuplicatingThread implements standby by stopping all tracks for (size_t i = 0; i < outputTracks.size(); i++) { outputTracks[i]->stop(); } Loading @@ -3156,10 +3216,12 @@ bool AudioFlinger::DuplicatingThread::threadLoop() ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); // MixerThread has "mPrevMixerStatus = MIXER_IDLE" checkSilentMode_l(); standbyTime = systemTime() + mStandbyTimeInNsecs; sleepTime = idleSleepTime; // MixerThread has sleepTimeShift continue; } } Loading @@ -3172,6 +3234,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() lockEffectChains_l(effectChains); } // Duplicating Thread is completely different here if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) { // mix buffers... if (outputsReady(outputTracks)) { Loading Loading @@ -3223,11 +3286,14 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } mStandby = false; mBytesWritten += mixBufferSize; // MixerThread has write blocked detection here } else { usleep(sleepTime); } // finally let go of all our tracks, without the lock held // finally let go of removed track(s), without the lock held // since we can't guarantee the destructors won't acquire that // same lock. tracksToRemove.clear(); Loading @@ -3238,6 +3304,9 @@ bool AudioFlinger::DuplicatingThread::threadLoop() effectChains.clear(); } // MixerThread and DirectOutpuThread have standby here, // but for DuplicatingThread this is handled by the outputTracks releaseWakeLock(); ALOGV("Thread %p type %d exiting", this, mType); Loading