From 0c5bf19e1535772bf837800536a2dbb25790964e Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 18 Jan 2011 13:50:39 -0800 Subject: Fix issue 3305305. The problem is that when the voice search tone is started, audio capture is still active and the output stream write function needs to place the input stream in standby to reconfigure the kernel driver. To do so it has to acquire the input stream mutex but as the input stream thread holds the lock most of the time while sleeping in the driver waiting for more data, this is very difficult and can take several seconds. The fix consists in forcing a sleep in the next read() when another function needs to acquire the input stream lock. The same change is done for output stream write() function. Also removed the workaround for issue 3201189 in setMode() (thread priority bump) as this change addresses the same problem. Change-Id: I3a5e672717752f83dfedce822a18748b165b0a5a --- libaudio/AudioHardware.cpp | 66 +++++++++++++++++++++++++++++++++++++--------- libaudio/AudioHardware.h | 12 ++++++--- 2 files changed, 62 insertions(+), 16 deletions(-) (limited to 'libaudio') diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp index 4cca932..585bb71 100644 --- a/libaudio/AudioHardware.cpp +++ b/libaudio/AudioHardware.cpp @@ -312,17 +312,13 @@ status_t AudioHardware::setMode(int mode) sp spIn; status_t status; - // bump thread priority to speed up mutex acquisition - int priority = getpriority(PRIO_PROCESS, 0); - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_URGENT_AUDIO); - // Mutex acquisition order is always out -> in -> hw AutoMutex lock(mLock); spOut = mOutput; while (spOut != 0) { if (!spOut->checkStandby()) { - int cnt = spOut->standbyCnt(); + int cnt = spOut->prepareLock(); mLock.unlock(); spOut->lock(); mLock.lock(); @@ -341,7 +337,7 @@ status_t AudioHardware::setMode(int mode) spIn = getActiveInput_l(); while (spIn != 0) { - int cnt = spIn->standbyCnt(); + int cnt = spIn->prepareLock(); mLock.unlock(); spIn->lock(); mLock.lock(); @@ -355,8 +351,6 @@ status_t AudioHardware::setMode(int mode) } // spIn is not 0 here only if the input is active - setpriority(PRIO_PROCESS, 0, priority); - int prevMode = mMode; status = AudioHardwareBase::setMode(mode); LOGV("setMode() : new %d, old %d", mMode, prevMode); @@ -924,7 +918,7 @@ AudioHardware::AudioStreamOutALSA::AudioStreamOutALSA() : mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0), mStandby(true), mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS), mSampleRate(AUDIO_HW_OUT_SAMPLERATE), mBufferSize(AUDIO_HW_OUT_PERIOD_BYTES), - mDriverOp(DRV_NONE), mStandbyCnt(0) + mDriverOp(DRV_NONE), mStandbyCnt(0), mSleepReq(false) { } @@ -979,6 +973,12 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte if (mHardware == NULL) return NO_INIT; + if (mSleepReq) { + // 10ms are always shorter than the time to reconfigure the audio path + // which is the only condition when mSleepReq would be true. + usleep(10000); + } + { // scope for the lock AutoMutex lock(mLock); @@ -991,7 +991,7 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte sp spIn = mHardware->getActiveInput_l(); while (spIn != 0) { - int cnt = spIn->standbyCnt(); + int cnt = spIn->prepareLock(); mHardware->lock().unlock(); // Mutex acquisition order is always out -> in -> hw spIn->lock(); @@ -1216,6 +1216,24 @@ status_t AudioHardware::AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrame return INVALID_OPERATION; } +int AudioHardware::AudioStreamOutALSA::prepareLock() +{ + // request sleep next time write() is called so that caller can acquire + // mLock + mSleepReq = true; + return mStandbyCnt; +} + +void AudioHardware::AudioStreamOutALSA::lock() +{ + mLock.lock(); + mSleepReq = false; +} + +void AudioHardware::AudioStreamOutALSA::unlock() { + mLock.unlock(); +} + //------------------------------------------------------------------------------ // AudioStreamInALSA //------------------------------------------------------------------------------ @@ -1225,7 +1243,7 @@ AudioHardware::AudioStreamInALSA::AudioStreamInALSA() : mStandby(true), mDevices(0), mChannels(AUDIO_HW_IN_CHANNELS), mChannelCount(1), mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_PERIOD_BYTES), mDownSampler(NULL), mReadStatus(NO_ERROR), mDriverOp(DRV_NONE), - mStandbyCnt(0) + mStandbyCnt(0), mSleepReq(false) { } @@ -1297,6 +1315,12 @@ ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes) if (mHardware == NULL) return NO_INIT; + if (mSleepReq) { + // 10ms are always shorter than the time to reconfigure the audio path + // which is the only condition when mSleepReq would be true. + usleep(10000); + } + { // scope for the lock AutoMutex lock(mLock); @@ -1309,7 +1333,7 @@ ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes) sp spOut = mHardware->output(); while (spOut != 0) { if (!spOut->checkStandby()) { - int cnt = spOut->standbyCnt(); + int cnt = spOut->prepareLock(); mHardware->lock().unlock(); mLock.unlock(); // Mutex acquisition order is always out -> in -> hw @@ -1635,6 +1659,24 @@ size_t AudioHardware::AudioStreamInALSA::getBufferSize(uint32_t sampleRate, int return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / ratio ; } +int AudioHardware::AudioStreamInALSA::prepareLock() +{ + // request sleep next time read() is called so that caller can acquire + // mLock + mSleepReq = true; + return mStandbyCnt; +} + +void AudioHardware::AudioStreamInALSA::lock() +{ + mLock.lock(); + mSleepReq = false; +} + +void AudioHardware::AudioStreamInALSA::unlock() { + mLock.unlock(); +} + //------------------------------------------------------------------------------ // DownSampler //------------------------------------------------------------------------------ diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h index 1379495..a2c47bd 100644 --- a/libaudio/AudioHardware.h +++ b/libaudio/AudioHardware.h @@ -203,8 +203,9 @@ private: status_t open_l(); int standbyCnt() { return mStandbyCnt; } - void lock() { mLock.lock(); } - void unlock() { mLock.unlock(); } + int prepareLock(); + void lock(); + void unlock(); private: @@ -222,6 +223,7 @@ private: // trace driver operations for dump int mDriverOp; int mStandbyCnt; + bool mSleepReq; }; class DownSampler; @@ -316,8 +318,9 @@ private: virtual status_t getNextBuffer(BufferProvider::Buffer* buffer); virtual void releaseBuffer(BufferProvider::Buffer* buffer); - void lock() { mLock.lock(); } - void unlock() { mLock.unlock(); } + int prepareLock(); + void lock(); + void unlock(); private: Mutex mLock; @@ -339,6 +342,7 @@ private: // trace driver operations for dump int mDriverOp; int mStandbyCnt; + bool mSleepReq; }; }; -- cgit v1.1