diff options
author | Eric Laurent <elaurent@google.com> | 2014-09-12 17:41:50 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-09-15 09:31:31 -0700 |
commit | aaa44478a373232d8416657035a9020f9c7aa7c3 (patch) | |
tree | 95a4724c0d7ebbe065551f0aeaf5d65283ab3e04 /services/audioflinger/Effects.cpp | |
parent | f0b31e6333839972afb2e374f6d8824180d29fc2 (diff) | |
download | frameworks_av-aaa44478a373232d8416657035a9020f9c7aa7c3.zip frameworks_av-aaa44478a373232d8416657035a9020f9c7aa7c3.tar.gz frameworks_av-aaa44478a373232d8416657035a9020f9c7aa7c3.tar.bz2 |
audioflinger: fix pre processing effect leak
When a capture thread was closed, the effects attached to this thread
were left dangling and the associated effect chain destroyed.
When their last client was disconnected, the effects were not released
properly from the effect library because the destruction process could
not be completed without the effect being attached to a thread.
A similar problem prevented a RecordTrack to be properly released if
its client was destroyed after the capture thread.
The fix consists in allowing the effect or record track to be properly
released even if its parent thread cannot be promoted.
Also save any effect chain still present on a closed capture thread
in case a new client wants to reuse the effects on the same session later.
Bug: 17110064.
Change-Id: I5cd644daa357afd1f3548f9bcb28e6152d95fdb8
Diffstat (limited to 'services/audioflinger/Effects.cpp')
-rw-r--r-- | services/audioflinger/Effects.cpp | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 365f271..15f1f23 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -68,7 +68,8 @@ AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, mStatus(NO_INIT), mState(IDLE), // mMaxDisableWaitCnt is set by configure() and not used before then // mDisableWaitCnt is set by process() and updateState() and not used before then - mSuspended(false) + mSuspended(false), + mAudioFlinger(thread->mAudioFlinger) { ALOGV("Constructor %p", this); int lStatus; @@ -197,9 +198,19 @@ size_t AudioFlinger::EffectModule::disconnect(EffectHandle *handle, bool unpinIf // destructor before we exit sp<EffectModule> keep(this); { - sp<ThreadBase> thread = mThread.promote(); - if (thread != 0) { - thread->disconnectEffect(keep, handle, unpinIfLast); + if (removeHandle(handle) == 0) { + if (!isPinned() || unpinIfLast) { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + Mutex::Autolock _l(thread->mLock); + thread->removeEffect_l(this); + } + sp<AudioFlinger> af = mAudioFlinger.promote(); + if (af != 0) { + af->updateOrphanEffectChains(this); + } + AudioSystem::unregisterEffect(mId); + } } } return mHandles.size(); @@ -1911,4 +1922,13 @@ bool AudioFlinger::EffectChain::isNonOffloadableEnabled() return false; } +void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread) +{ + Mutex::Autolock _l(mLock); + mThread = thread; + for (size_t i = 0; i < mEffects.size(); i++) { + mEffects[i]->setThread(thread); + } +} + }; // namespace android |