audio policy: fix lockup during mediaserver restart
When pre or post processing effects are applied by audio policy service
automatically there is a potential lockup if the first call into
AudioPolicyService is made while creating one of those effects.
This is because effects are created with AudioPolicyService mutex held and
effect creation calls into methods (e.g registerClient()) which also acquire
the mutex.
The fix consists in adding a new mutex to AudioPolicyEffects class and not
hold the AudioPolicyService mutex when calling methods in of class.
Bug: 17830596.
Change-Id: Ie61c3671d3147f46e99ba208f39c1a3bf180779f
diff --git a/services/audiopolicy/AudioPolicyEffects.cpp b/services/audiopolicy/AudioPolicyEffects.cpp
index c45acd0..3c1c042 100644
--- a/services/audiopolicy/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/AudioPolicyEffects.cpp
@@ -87,6 +87,7 @@
audio_source_t aliasSource = (inputSource == AUDIO_SOURCE_HOTWORD) ?
AUDIO_SOURCE_VOICE_RECOGNITION : inputSource;
+ Mutex::Autolock _l(mLock);
ssize_t index = mInputSources.indexOfKey(aliasSource);
if (index < 0) {
ALOGV("addInputEffects(): no processing needs to be attached to this source");
@@ -122,7 +123,7 @@
ALOGV("addInputEffects(): added Fx %s on source: %d", effect->mName, (int32_t)aliasSource);
inputDesc->mEffects.add(fx);
}
- setProcessorEnabled(inputDesc, true);
+ inputDesc->setProcessorEnabled(true);
return status;
}
@@ -132,6 +133,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
ssize_t index = mInputs.indexOfKey(input);
if (index < 0) {
return status;
@@ -140,7 +142,7 @@
inputDesc->mRefCount--;
ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
if (inputDesc->mRefCount == 0) {
- setProcessorEnabled(inputDesc, false);
+ inputDesc->setProcessorEnabled(false);
delete inputDesc;
mInputs.removeItemsAt(index);
ALOGV("releaseInputEffects(): all effects released");
@@ -154,6 +156,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
size_t index;
for (index = 0; index < mInputs.size(); index++) {
if (mInputs.valueAt(index)->mSessionId == audioSession) {
@@ -186,6 +189,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
size_t index;
for (index = 0; index < mOutputSessions.size(); index++) {
if (mOutputSessions.valueAt(index)->mSessionId == audioSession) {
@@ -218,6 +222,7 @@
{
status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
// create audio processors according to stream
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
@@ -254,7 +259,7 @@
procDesc->mEffects.add(fx);
}
- setProcessorEnabled(procDesc, true);
+ procDesc->setProcessorEnabled(true);
return status;
}
@@ -267,6 +272,7 @@
(void) output; // argument not used for now
(void) stream; // argument not used for now
+ Mutex::Autolock _l(mLock);
ssize_t index = mOutputSessions.indexOfKey(audioSession);
if (index < 0) {
ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
@@ -277,7 +283,7 @@
procDesc->mRefCount--;
ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d", audioSession, procDesc->mRefCount);
if (procDesc->mRefCount == 0) {
- setProcessorEnabled(procDesc, false);
+ procDesc->setProcessorEnabled(false);
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
@@ -288,11 +294,10 @@
}
-void AudioPolicyEffects::setProcessorEnabled(const EffectVector *effectVector, bool enabled)
+void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled)
{
- const Vector<sp<AudioEffect> > &fxVector = effectVector->mEffects;
- for (size_t i = 0; i < fxVector.size(); i++) {
- fxVector.itemAt(i)->setEnabled(enabled);
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ mEffects.itemAt(i)->setEnabled(enabled);
}
}
@@ -313,7 +318,7 @@
// returns the audio_source_t enum corresponding to the input source name or
// AUDIO_SOURCE_CNT is no match found
-audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
+/*static*/ audio_source_t AudioPolicyEffects::inputSourceNameToEnum(const char *name)
{
int i;
for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {