AudioSystem: fix cross deadlock
Do not hold gLockAPS when calling
AudioPolicyService::registerClient() in get_audio_policy_service().
registerClient() will need to acquire the AudioPolicyService mutex and
if at the same time a method called from AudioPolicyService
(with mutex held) calls back into AudioSystem and get_audio_policy_service()
a cross deadlock occurs.
Same preventive fix for get_audio_flinger().
Use a separate mutex for notification client list in AudioPolicyService.
This prevents deadlocking if registerClient() is called as a consequence of
AudioFlinger calling back into AudioPolicyManager while executing a method
with AudioPolicyService locked
Bug: 18403952.
Bug: 18450065.
Change-Id: Ia832e41aede8bc6c843fc615508fbdd74e0863b5
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index dd4067f..6a4a669 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -149,7 +149,7 @@
void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mNotificationClientsLock);
uid_t uid = IPCThreadState::self()->getCallingUid();
if (mNotificationClients.indexOfKey(uid) < 0) {
@@ -168,14 +168,17 @@
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid)
{
- Mutex::Autolock _l(mLock);
-
- mNotificationClients.removeItem(uid);
-
+ {
+ Mutex::Autolock _l(mNotificationClientsLock);
+ mNotificationClients.removeItem(uid);
+ }
#ifndef USE_LEGACY_AUDIO_POLICY
+ {
+ Mutex::Autolock _l(mLock);
if (mAudioPolicyManager) {
mAudioPolicyManager->clearAudioPatches(uid);
}
+ }
#endif
}
@@ -186,7 +189,7 @@
void AudioPolicyService::doOnAudioPortListUpdate()
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
mNotificationClients.valueAt(i)->onAudioPortListUpdate();
}
@@ -212,7 +215,7 @@
void AudioPolicyService::doOnAudioPatchListUpdate()
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
}