audio policy: remove effects before releasing input
modify releaseInput() implementation so that effects added by policy
rules are removed before closing the input stream to avoid
failure to destroy the effect chain
make sure that orphan effect chains are checked when an EffectHandle is
disconnected after thread destruction.
Test: make and run Hangouts
Bug: 32707507
Change-Id: I7833b4c5e42c0057a4477eb4485a20dd26ca2f90
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index ad4e97b..128eaba 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -207,6 +207,24 @@
return NULL;
}
+// unsafe method called when the effect parent thread has been destroyed
+ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
+{
+ ALOGV("disconnect() %p handle %p", this, handle);
+ Mutex::Autolock _l(mLock);
+ ssize_t numHandles = removeHandle_l(handle);
+ if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
+ AudioSystem::unregisterEffect(mId);
+ sp<AudioFlinger> af = mAudioFlinger.promote();
+ if (af != 0) {
+ mLock.unlock();
+ af->updateOrphanEffectChains(this);
+ mLock.lock();
+ }
+ }
+ return numHandles;
+}
+
bool AudioFlinger::EffectModule::updateState() {
Mutex::Autolock _l(mLock);
@@ -1260,6 +1278,13 @@
}
if (thread != 0) {
thread->disconnectEffectHandle(this, unpinIfLast);
+ } else {
+ ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
+ // try to cleanup as much as we can
+ sp<EffectModule> effect = mEffect.promote();
+ if (effect != 0) {
+ effect->disconnectHandle(this, unpinIfLast);
+ }
}
if (mClient != 0) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index d745121..dc29ce0 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -95,6 +95,7 @@
const wp<ThreadBase>& thread() { return mThread; }
status_t addHandle(EffectHandle *handle);
+ ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
ssize_t removeHandle(EffectHandle *handle);
ssize_t removeHandle_l(EffectHandle *handle);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 53c54bb..0c23080 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -400,7 +400,6 @@
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
- mAudioPolicyManager->releaseInput(input, session);
audioPolicyEffects = mAudioPolicyEffects;
}
if (audioPolicyEffects != 0) {
@@ -410,6 +409,10 @@
ALOGW("Failed to release effects on input %d", input);
}
}
+ {
+ Mutex::Autolock _l(mLock);
+ mAudioPolicyManager->releaseInput(input, session);
+ }
}
status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,