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
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 753314f..1003017 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -569,6 +569,23 @@
bool isNonOffloadableGlobalEffectEnabled_l();
void onNonOffloadableGlobalEffectEnable();
+ // Store an effect chain to mOrphanEffectChains keyed vector.
+ // Called when a thread exits and effects are still attached to it.
+ // If effects are later created on the same session, they will reuse the same
+ // effect chain and same instances in the effect library.
+ // return ALREADY_EXISTS if a chain with the same session already exists in
+ // mOrphanEffectChains. Note that this should never happen as there is only one
+ // chain for a given session and it is attached to only one thread at a time.
+ status_t putOrphanEffectChain_l(const sp<EffectChain>& chain);
+ // Get an effect chain for the specified session in mOrphanEffectChains and remove
+ // it if found. Returns 0 if not found (this is the most common case).
+ sp<EffectChain> getOrphanEffectChain_l(audio_session_t session);
+ // Called when the last effect handle on an effect instance is removed. If this
+ // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
+ // and removed from mOrphanEffectChains if it does not contain any effect.
+ // Return true if the effect was found in mOrphanEffectChains, false otherwise.
+ bool updateOrphanEffectChains(const sp<EffectModule>& effect);
+
class AudioHwDevice {
public:
enum Flags {
@@ -713,6 +730,9 @@
Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
// to be created
+ // Effect chains without a valid thread
+ DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
+
private:
sp<Client> registerPid(pid_t pid); // always returns non-0