Skip to content

Commit 71c4496

Browse files
author
Eric Laurent
committed
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 19ddf0e and 8a04fe0 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
1 parent 3938e4f commit 71c4496

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

services/audioflinger/AudioFlinger.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,7 +1832,7 @@ uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
18321832

18331833
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
18341834
: PlaybackThread(audioFlinger, output, id, device),
1835-
mAudioMixer(0)
1835+
mAudioMixer(0), mPrevMixerStatus(MIXER_IDLE)
18361836
{
18371837
mType = ThreadBase::MIXER;
18381838
mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
@@ -1945,6 +1945,7 @@ bool AudioFlinger::MixerThread::threadLoop()
19451945
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
19461946
acquireWakeLock_l();
19471947

1948+
mPrevMixerStatus = MIXER_IDLE;
19481949
if (mMasterMute == false) {
19491950
char value[PROPERTY_VALUE_MAX];
19501951
property_get("ro.audio.silent", value, "0");
@@ -2103,11 +2104,11 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
21032104
// make sure that we have enough frames to mix one full buffer.
21042105
// enforce this condition only once to enable draining the buffer in case the client
21052106
// app does not call stop() and relies on underrun to stop:
2106-
// hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed
2107+
// hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
21072108
// during last round
21082109
uint32_t minFrames = 1;
21092110
if (!track->isStopped() && !track->isPausing() &&
2110-
(track->mRetryCount >= kMaxTrackRetries)) {
2111+
(mPrevMixerStatus == MIXER_TRACKS_READY)) {
21112112
if (t->sampleRate() == (int)mSampleRate) {
21122113
minFrames = mFrameCount;
21132114
} else {
@@ -2229,7 +2230,13 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
22292230

22302231
// reset retry count
22312232
track->mRetryCount = kMaxTrackRetries;
2232-
mixerStatus = MIXER_TRACKS_READY;
2233+
// If one track is ready, set the mixer ready if:
2234+
// - the mixer was not ready during previous round OR
2235+
// - no other track is not ready
2236+
if (mPrevMixerStatus != MIXER_TRACKS_READY ||
2237+
mixerStatus != MIXER_TRACKS_ENABLED) {
2238+
mixerStatus = MIXER_TRACKS_READY;
2239+
}
22332240
} else {
22342241
//LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
22352242
if (track->isStopped()) {
@@ -2247,7 +2254,11 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
22472254
tracksToRemove->add(track);
22482255
// indicate to client process that the track was disabled because of underrun
22492256
android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
2250-
} else if (mixerStatus != MIXER_TRACKS_READY) {
2257+
// If one track is not ready, mark the mixer also not ready if:
2258+
// - the mixer was ready during previous round OR
2259+
// - no other track is ready
2260+
} else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
2261+
mixerStatus != MIXER_TRACKS_READY) {
22512262
mixerStatus = MIXER_TRACKS_ENABLED;
22522263
}
22532264
}
@@ -2281,6 +2292,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
22812292
memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
22822293
}
22832294

2295+
mPrevMixerStatus = mixerStatus;
22842296
return mixerStatus;
22852297
}
22862298

@@ -3016,6 +3028,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
30163028
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
30173029
acquireWakeLock_l();
30183030

3031+
mPrevMixerStatus = MIXER_IDLE;
30193032
if (mMasterMute == false) {
30203033
char value[PROPERTY_VALUE_MAX];
30213034
property_get("ro.audio.silent", value, "0");

services/audioflinger/AudioFlinger.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,9 @@ class AudioFlinger :
836836
virtual uint32_t idleSleepTimeUs();
837837
virtual uint32_t suspendSleepTimeUs();
838838

839-
AudioMixer* mAudioMixer;
839+
AudioMixer* mAudioMixer;
840+
uint32_t mPrevMixerStatus; // previous status (mixer_state) returned by
841+
// prepareTracks_l()
840842
};
841843

842844
class DirectOutputThread : public PlaybackThread {

0 commit comments

Comments
 (0)