diff options
author | Eric Laurent <elaurent@google.com> | 2009-09-22 00:35:48 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2009-09-22 00:35:48 -0700 |
commit | f69a3f8dc54707e5be327e83cec742824d1ba263 (patch) | |
tree | 2f429e991d0499f5e1c176a2c7f5a46e522dff5f /libs/audioflinger | |
parent | 2e2f6b5e6866cdba632bdd599cadbf235b80546f (diff) | |
download | frameworks_base-f69a3f8dc54707e5be327e83cec742824d1ba263.zip frameworks_base-f69a3f8dc54707e5be327e83cec742824d1ba263.tar.gz frameworks_base-f69a3f8dc54707e5be327e83cec742824d1ba263.tar.bz2 |
Fix issue 2116700: Ringer screwy while connected over Bluetooth.
There was a regression introduced in AudioFlinger by change 24114 for suspended output:
The suspended output was not reading and mixing audio tracks.
When the phone is ringing, the A2DP output is suspended if the SCO headset and A2DP headset are the same. As the ringtone is played over the duplicated output, the fact that the A2DP output was not reading data was causing the hardware output to be stalled from time to time.
Diffstat (limited to 'libs/audioflinger')
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 203 |
1 files changed, 106 insertions, 97 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index e534447..6500791 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -1227,44 +1227,46 @@ bool AudioFlinger::MixerThread::threadLoop() enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); } - - // output audio to hardware - if (mSuspended) { - usleep(kMaxBufferRecoveryInUsecs); + if (LIKELY(enabledTracks)) { + // mix buffers... + mAudioMixer->process(curBuf); + sleepTime = 0; + standbyTime = systemTime() + kStandbyTimeInNsecs; } else { - if (LIKELY(enabledTracks)) { - // mix buffers... - mAudioMixer->process(curBuf); + sleepTime += kBufferRecoveryInUsecs; + if (sleepTime > kMaxBufferRecoveryInUsecs) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // There was nothing to mix this round, which means all + // active tracks were late. Sleep a little bit to give + // them another chance. If we're too late, write 0s to audio + // hardware to avoid underrun. + if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { + memset (curBuf, 0, mixBufferSize); sleepTime = 0; - standbyTime = systemTime() + kStandbyTimeInNsecs; - } else { - sleepTime += kBufferRecoveryInUsecs; - // There was nothing to mix this round, which means all - // active tracks were late. Sleep a little bit to give - // them another chance. If we're too late, write 0s to audio - // hardware to avoid underrun. - if (mBytesWritten == 0 || sleepTime < kMaxBufferRecoveryInUsecs) { - usleep(kBufferRecoveryInUsecs); - } else { - memset (curBuf, 0, mixBufferSize); - sleepTime = 0; - } } - // sleepTime == 0 means PCM data were written to mMixBuffer[] - if (sleepTime == 0) { - mLastWriteTime = systemTime(); - mInWrite = true; - int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); - if (bytesWritten > 0) mBytesWritten += bytesWritten; - mNumWrites++; - mInWrite = false; - mStandby = false; - nsecs_t delta = systemTime() - mLastWriteTime; - if (delta > maxPeriod) { - LOGW("write blocked for %llu msecs", ns2ms(delta)); - mNumDelayedWrites++; - } + } + + if (mSuspended) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // sleepTime == 0 means we must write to audio hardware + if (sleepTime == 0) { + mLastWriteTime = systemTime(); + mInWrite = true; + LOGV("mOutput->write() thread %p frames %d", this, mFrameCount); + int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize); + if (bytesWritten > 0) mBytesWritten += bytesWritten; + mNumWrites++; + mInWrite = false; + mStandby = false; + nsecs_t delta = systemTime() - mLastWriteTime; + if (delta > maxPeriod) { + LOGW("write blocked for %llu msecs, thread %p", ns2ms(delta), this); + mNumDelayedWrites++; } + } else { + usleep(sleepTime); } // finally let go of all our tracks, without the lock held @@ -1718,50 +1720,55 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } } - // output audio to hardware - if (mSuspended) { - usleep(kMaxBufferRecoveryInUsecs); - } else { - if (activeTrack != 0) { - AudioBufferProvider::Buffer buffer; - size_t frameCount = mFrameCount; - curBuf = (int8_t *)mMixBuffer; - // output audio to hardware - while(frameCount) { - buffer.frameCount = frameCount; - activeTrack->getNextBuffer(&buffer); - if (UNLIKELY(buffer.raw == 0)) { - memset(curBuf, 0, frameCount * mFrameSize); - break; - } - memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize); - frameCount -= buffer.frameCount; - curBuf += buffer.frameCount * mFrameSize; - activeTrack->releaseBuffer(&buffer); + if (activeTrack != 0) { + AudioBufferProvider::Buffer buffer; + size_t frameCount = mFrameCount; + curBuf = (int8_t *)mMixBuffer; + // output audio to hardware + while(frameCount) { + buffer.frameCount = frameCount; + activeTrack->getNextBuffer(&buffer); + if (UNLIKELY(buffer.raw == 0)) { + memset(curBuf, 0, frameCount * mFrameSize); + break; } + memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize); + frameCount -= buffer.frameCount; + curBuf += buffer.frameCount * mFrameSize; + activeTrack->releaseBuffer(&buffer); + } + sleepTime = 0; + standbyTime = systemTime() + kStandbyTimeInNsecs; + } else { + sleepTime += kBufferRecoveryInUsecs; + if (sleepTime > kMaxBufferRecoveryInUsecs) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // There was nothing to mix this round, which means all + // active tracks were late. Sleep a little bit to give + // them another chance. If we're too late, write 0s to audio + // hardware to avoid underrun. + if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs && + AudioSystem::isLinearPCM(mFormat)) { + memset (mMixBuffer, 0, mFrameCount * mFrameSize); sleepTime = 0; - standbyTime = systemTime() + kStandbyTimeInNsecs; - } else { - sleepTime += kBufferRecoveryInUsecs; - if (mBytesWritten == 0 || !AudioSystem::isLinearPCM(mFormat) || - sleepTime < kMaxBufferRecoveryInUsecs) { - usleep(kBufferRecoveryInUsecs); - } else { - memset (mMixBuffer, 0, mFrameCount * mFrameSize); - sleepTime = 0; - } } + } - // sleepTime == 0 means PCM data were written to mMixBuffer[] - if (sleepTime == 0) { - mLastWriteTime = systemTime(); - mInWrite = true; - int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); - if (bytesWritten) mBytesWritten += bytesWritten; - mNumWrites++; - mInWrite = false; - mStandby = false; - } + if (mSuspended) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // sleepTime == 0 means we must write to audio hardware + if (sleepTime == 0) { + mLastWriteTime = systemTime(); + mInWrite = true; + int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize); + if (bytesWritten) mBytesWritten += bytesWritten; + mNumWrites++; + mInWrite = false; + mStandby = false; + } else { + usleep(sleepTime); } // finally let go of removed track, without the lock held @@ -1913,38 +1920,40 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove); - } + } - bool mustSleep = true; if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); - if (!mSuspended) { - for (size_t i = 0; i < outputTracks.size(); i++) { - outputTracks[i]->write(curBuf, mFrameCount); - mustSleep = false; - } - mStandby = false; - mBytesWritten += mixBufferSize; - } + sleepTime = 0; + standbyTime = systemTime() + kStandbyTimeInNsecs; } else { - // flush remaining overflow buffers in output tracks - for (size_t i = 0; i < outputTracks.size(); i++) { - if (outputTracks[i]->isActive()) { - outputTracks[i]->write(curBuf, 0); - standbyTime = systemTime() + kStandbyTimeInNsecs; - mustSleep = false; - } + sleepTime += kBufferRecoveryInUsecs; + if (sleepTime > kMaxBufferRecoveryInUsecs) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // There was nothing to mix this round, which means all + // active tracks were late. Sleep a little bit to give + // them another chance. If we're too late, write 0s to audio + // hardware to avoid underrun. + if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) { + memset (curBuf, 0, mixBufferSize); + sleepTime = 0; } } - if (mustSleep) { -// LOGV("threadLoop() sleeping %d", sleepTime); - usleep(sleepTime); - if (sleepTime < kMaxBufferRecoveryInUsecs) { - sleepTime += kBufferRecoveryInUsecs; + + if (mSuspended) { + sleepTime = kMaxBufferRecoveryInUsecs; + } + // sleepTime == 0 means we must write to audio hardware + if (sleepTime == 0) { + for (size_t i = 0; i < outputTracks.size(); i++) { + outputTracks[i]->write(curBuf, mFrameCount); } + mStandby = false; + mBytesWritten += mixBufferSize; } else { - sleepTime = kBufferRecoveryInUsecs; + usleep(sleepTime); } // finally let go of all our tracks, without the lock held |