audio policy: fix output session effect leak
Clean up session effects in releaseOutput in case stopOutput
is not received before release.
Bug: 124689305
Test: start/stop cast screen while playing music
Change-Id: Ie0588dd3336d56d34c2d717268fcd0918cbf5717
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b8036bb..2eb272e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -225,6 +225,21 @@
return result;
}
+void AudioPolicyService::getPlaybackClientAndEffects(audio_port_handle_t portId,
+ sp<AudioPlaybackClient>& client,
+ sp<AudioPolicyEffects>& effects,
+ const char *context)
+{
+ Mutex::Autolock _l(mLock);
+ const ssize_t index = mAudioPlaybackClients.indexOfKey(portId);
+ if (index < 0) {
+ ALOGE("%s AudioTrack client not found for portId %d", context, portId);
+ return;
+ }
+ client = mAudioPlaybackClients.valueAt(index);
+ effects = mAudioPolicyEffects;
+}
+
status_t AudioPolicyService::startOutput(audio_port_handle_t portId)
{
if (mAudioPolicyManager == NULL) {
@@ -233,16 +248,9 @@
ALOGV("startOutput()");
sp<AudioPlaybackClient> client;
sp<AudioPolicyEffects>audioPolicyEffects;
- {
- Mutex::Autolock _l(mLock);
- const ssize_t index = mAudioPlaybackClients.indexOfKey(portId);
- if (index < 0) {
- ALOGE("%s AudioTrack client not found for portId %d", __FUNCTION__, portId);
- return INVALID_OPERATION;
- }
- client = mAudioPlaybackClients.valueAt(index);
- audioPolicyEffects = mAudioPolicyEffects;
- }
+
+ getPlaybackClientAndEffects(portId, client, audioPolicyEffects, __func__);
+
if (audioPolicyEffects != 0) {
// create audio processors according to stream
status_t status = audioPolicyEffects->addOutputSessionEffects(
@@ -275,17 +283,9 @@
ALOGV("doStopOutput");
sp<AudioPlaybackClient> client;
sp<AudioPolicyEffects>audioPolicyEffects;
- {
- Mutex::Autolock _l(mLock);
- const ssize_t index = mAudioPlaybackClients.indexOfKey(portId);
- if (index < 0) {
- ALOGE("%s AudioTrack client not found for portId %d", __FUNCTION__, portId);
- return INVALID_OPERATION;
- }
- client = mAudioPlaybackClients.valueAt(index);
- audioPolicyEffects = mAudioPolicyEffects;
- }
+ getPlaybackClientAndEffects(portId, client, audioPolicyEffects, __func__);
+
if (audioPolicyEffects != 0) {
// release audio processors from the stream
status_t status = audioPolicyEffects->releaseOutputSessionEffects(
@@ -315,13 +315,17 @@
void AudioPolicyService::doReleaseOutput(audio_port_handle_t portId)
{
ALOGV("doReleaseOutput from tid %d", gettid());
- Mutex::Autolock _l(mLock);
- const ssize_t index = mAudioPlaybackClients.indexOfKey(portId);
- if (index < 0) {
- ALOGE("%s AudioTrack client not found for portId %d", __FUNCTION__, portId);
- return;
+ sp<AudioPlaybackClient> client;
+ sp<AudioPolicyEffects> audioPolicyEffects;
+
+ getPlaybackClientAndEffects(portId, client, audioPolicyEffects, __func__);
+
+ if (audioPolicyEffects != 0 && client->active) {
+ // clean up effects if output was not stopped before being released
+ audioPolicyEffects->releaseOutputSessionEffects(
+ client->io, client->stream, client->session);
}
- sp<AudioPlaybackClient> client = mAudioPlaybackClients.valueAt(index);
+ Mutex::Autolock _l(mLock);
mAudioPlaybackClients.removeItem(portId);
// called from internal thread: no need to clear caller identity