From 43b4dcc660e6da96285e4672ae371070ab845401 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Tue, 9 Jun 2015 16:53:44 -0700 Subject: AudioFlinger: flush stream when switching tracks For direct threads, when recycling a stream, perform a flush so that the frame position is reset. Bug: 21145353 Change-Id: I08611cd64bb249a9659c44f9e4c47e7455f4838f Signed-off-by: Phil Burk --- services/audioflinger/Threads.cpp | 62 +++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 22 deletions(-) (limited to 'services/audioflinger/Threads.cpp') diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index dc6710f..84c4fcf 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4458,6 +4458,17 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr } } +void AudioFlinger::DirectOutputThread::onAddNewTrack_l() +{ + sp previousTrack = mPreviousTrack.promote(); + sp latestTrack = mLatestActiveTrack.promote(); + + if (previousTrack != 0 && latestTrack != 0 && + (previousTrack->sessionId() != latestTrack->sessionId())) { + mFlushPending = true; + } + PlaybackThread::onAddNewTrack_l(); +} AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l( Vector< sp > *tracksToRemove @@ -4467,7 +4478,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep mixer_state mixerStatus = MIXER_IDLE; bool doHwPause = false; bool doHwResume = false; - bool flushPending = false; // find out which tracks need to be processed for (size_t i = 0; i < count; i++) { @@ -4477,6 +4487,12 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep continue; } + if (t->isInvalid()) { + ALOGW("An invalidated track shouldn't be in active list"); + tracksToRemove->add(t); + continue; + } + Track* const track = t.get(); audio_track_cblk_t* cblk = track->cblk(); // Only consider last track started for volume and mixer state control. @@ -4496,7 +4512,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep } else if (track->isFlushPending()) { track->flushAck(); if (last) { - flushPending = true; + mFlushPending = true; } } else if (track->isResumePending()) { track->resumeAck(); @@ -4537,6 +4553,21 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // compute volume for this track processVolume_l(track, last); if (last) { + sp previousTrack = mPreviousTrack.promote(); + if (previousTrack != 0) { + if (track != previousTrack.get()) { + // Flush any data still being written from last track + mBytesRemaining = 0; + // flush data already sent if changing audio session as audio + // comes from a different source. Also invalidate previous track to force a + // seek when resuming. + if (previousTrack->sessionId() != track->sessionId()) { + previousTrack->invalidate(); + } + } + } + mPreviousTrack = track; + // reset retry count track->mRetryCount = kMaxTrackRetriesDirect; mActiveTrack = t; @@ -4603,11 +4634,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep } // if an active track did not command a flush, check for pending flush on stopped tracks - if (!flushPending) { + if (!mFlushPending) { for (size_t i = 0; i < mTracks.size(); i++) { if (mTracks[i]->isFlushPending()) { mTracks[i]->flushAck(); - flushPending = true; + mFlushPending = true; } } } @@ -4617,10 +4648,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // before flush and then resume HW. This can happen in case of pause/flush/resume // if resume is received before pause is executed. if (mHwSupportsPause && !mStandby && - (doHwPause || (flushPending && !mHwPaused && (count != 0)))) { + (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) { mOutput->stream->pause(mOutput->stream); } - if (flushPending) { + if (mFlushPending) { flushHw_l(); } if (mHwSupportsPause && !mStandby && doHwResume) { @@ -4679,14 +4710,13 @@ void AudioFlinger::DirectOutputThread::threadLoop_exit() { { Mutex::Autolock _l(mLock); - bool flushPending = false; for (size_t i = 0; i < mTracks.size(); i++) { if (mTracks[i]->isFlushPending()) { mTracks[i]->flushAck(); - flushPending = true; + mFlushPending = true; } } - if (flushPending) { + if (mFlushPending) { flushHw_l(); } } @@ -4824,6 +4854,7 @@ void AudioFlinger::DirectOutputThread::flushHw_l() { mOutput->flush(); mHwPaused = false; + mFlushPending = false; } // ---------------------------------------------------------------------------- @@ -5145,7 +5176,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr } if (mFlushPending) { flushHw_l(); - mFlushPending = false; } if (!mStandby && doHwResume) { mOutput->stream->resume(mOutput->stream); @@ -5193,18 +5223,6 @@ void AudioFlinger::OffloadThread::flushHw_l() } } -void AudioFlinger::OffloadThread::onAddNewTrack_l() -{ - sp previousTrack = mPreviousTrack.promote(); - sp latestTrack = mLatestActiveTrack.promote(); - - if (previousTrack != 0 && latestTrack != 0 && - (previousTrack->sessionId() != latestTrack->sessionId())) { - mFlushPending = true; - } - PlaybackThread::onAddNewTrack_l(); -} - // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp& audioFlinger, -- cgit v1.1