From aaa44478a373232d8416657035a9020f9c7aa7c3 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 12 Sep 2014 17:41:50 -0700 Subject: 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 --- services/audioflinger/Tracks.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'services/audioflinger/Tracks.cpp') diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 6cbab04..c0a75b9 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -96,7 +96,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mServerProxy(NULL), mId(android_atomic_inc(&nextTrackId)), mTerminated(false), - mType(type) + mType(type), + mThreadIoHandle(thread->id()) { // if the caller is us, trust the specified uid if (IPCThreadState::self()->getCallingPid() != getpid_cached || clientUid == -1) { @@ -482,14 +483,15 @@ void AudioFlinger::PlaybackThread::Track::destroy() // this Track with its member mTrack. sp keep(this); { // scope for mLock + bool wasActive = false; sp thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); - bool wasActive = playbackThread->destroyTrack_l(this); - if (isExternalTrack() && !wasActive) { - AudioSystem::releaseOutput(thread->id()); - } + wasActive = playbackThread->destroyTrack_l(this); + } + if (isExternalTrack() && !wasActive) { + AudioSystem::releaseOutput(mThreadIoHandle); } } } @@ -2050,7 +2052,7 @@ void AudioFlinger::RecordThread::RecordTrack::stop() if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); if (recordThread->stop(this) && isExternalTrack()) { - AudioSystem::stopInput(recordThread->id(), (audio_session_t)mSessionId); + AudioSystem::stopInput(mThreadIoHandle, (audio_session_t)mSessionId); } } } @@ -2060,14 +2062,14 @@ void AudioFlinger::RecordThread::RecordTrack::destroy() // see comments at AudioFlinger::PlaybackThread::Track::destroy() sp keep(this); { + if (isExternalTrack()) { + if (mState == ACTIVE || mState == RESUMING) { + AudioSystem::stopInput(mThreadIoHandle, (audio_session_t)mSessionId); + } + AudioSystem::releaseInput(mThreadIoHandle, (audio_session_t)mSessionId); + } sp thread = mThread.promote(); if (thread != 0) { - if (isExternalTrack()) { - if (mState == ACTIVE || mState == RESUMING) { - AudioSystem::stopInput(thread->id(), (audio_session_t)mSessionId); - } - AudioSystem::releaseInput(thread->id(), (audio_session_t)mSessionId); - } Mutex::Autolock _l(thread->mLock); RecordThread *recordThread = (RecordThread *) thread.get(); recordThread->destroyTrack_l(this); -- cgit v1.1