From 2774144fa8283f1a7b43e17a53c97dec0c366dd3 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 17 Jan 2012 19:20:12 -0800 Subject: [PATCH] AudioFlinger: mix track only when really ready (2) This problem due to the way audio buffers are mixed when low power mode is active was addressed by commits 19ddf0eb and 8a04fe03 but only partially. As a matter of fact, when more than one audio track is playing, the problem is still present. This is most noticeable when playing music with screen off and a notification or navigation instruction is played: in this case, the music or notification is likely to skip. The fix consists in declaring the mixer ready if all active tracks are ready. Previous behavior was to declare ready if at least one track was ready. To avoid that one application failing to fill the track buffer blocks other tracks indefinitely, this condition is respected only if the mixer was ready in the previous round. Issue 5799167. Change-Id: Iabd4ca08d3d45f563d9824c8a03c2c68a43ae179 --- services/audioflinger/AudioFlinger.cpp | 23 ++++++++++++++++++----- services/audioflinger/AudioFlinger.h | 4 +++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 060a632202..133dabdfc5 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1832,7 +1832,7 @@ uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() AudioFlinger::MixerThread::MixerThread(const sp& audioFlinger, AudioStreamOut* output, int id, uint32_t device) : PlaybackThread(audioFlinger, output, id, device), - mAudioMixer(0) + mAudioMixer(0), mPrevMixerStatus(MIXER_IDLE) { mType = ThreadBase::MIXER; mAudioMixer = new AudioMixer(mFrameCount, mSampleRate); @@ -1945,6 +1945,7 @@ bool AudioFlinger::MixerThread::threadLoop() LOGV("MixerThread %p TID %d waking up\n", this, gettid()); acquireWakeLock_l(); + mPrevMixerStatus = MIXER_IDLE; if (mMasterMute == false) { char value[PROPERTY_VALUE_MAX]; property_get("ro.audio.silent", value, "0"); @@ -2103,11 +2104,11 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wpmRetryCount >= kMaxTrackRetries) meaning the track was mixed + // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed // during last round uint32_t minFrames = 1; if (!track->isStopped() && !track->isPausing() && - (track->mRetryCount >= kMaxTrackRetries)) { + (mPrevMixerStatus == MIXER_TRACKS_READY)) { if (t->sampleRate() == (int)mSampleRate) { minFrames = mFrameCount; } else { @@ -2229,7 +2230,13 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wpmRetryCount = kMaxTrackRetries; - mixerStatus = MIXER_TRACKS_READY; + // If one track is ready, set the mixer ready if: + // - the mixer was not ready during previous round OR + // - no other track is not ready + if (mPrevMixerStatus != MIXER_TRACKS_READY || + mixerStatus != MIXER_TRACKS_ENABLED) { + mixerStatus = MIXER_TRACKS_READY; + } } else { //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this); if (track->isStopped()) { @@ -2247,7 +2254,11 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wpadd(track); // indicate to client process that the track was disabled because of underrun android_atomic_or(CBLK_DISABLED_ON, &cblk->flags); - } else if (mixerStatus != MIXER_TRACKS_READY) { + // If one track is not ready, mark the mixer also not ready if: + // - the mixer was ready during previous round OR + // - no other track is ready + } else if (mPrevMixerStatus == MIXER_TRACKS_READY || + mixerStatus != MIXER_TRACKS_READY) { mixerStatus = MIXER_TRACKS_ENABLED; } } @@ -2281,6 +2292,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp