Soundtrigger service: fix cross deadlock with audio policy service Do not hold Module mutex when calling into audio policy manager to avoid cross deadlock with audio poicy service mutex: Audio policy manager can call into sound trigger service with its mutex held in methods like stopInput(). Regression introduced by fix for b/64340921 commit f759b8c4 Bug: 64340921 Bug: 67310830 Test: repro steps in b/67310830 Merged-In: Ie50b2e7c55fe9828a3fd8de6b31eb4a492791583 Change-Id: Ie50b2e7c55fe9828a3fd8de6b31eb4a492791583 (cherry picked from commit 98647879efd7fd85c57399037a2cf330726b0a09)
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp index eebc487..c6dcd01 100644 --- a/services/soundtrigger/SoundTriggerHwService.cpp +++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -505,6 +505,8 @@ if (!captureHotwordAllowed()) { return; } + Vector<audio_session_t> releasedSessions; + { AutoMutex lock(mLock); for (size_t i = 0; i < mModels.size(); i++) { @@ -514,9 +516,16 @@ mHwDevice->stop_recognition(mHwDevice, model->mHandle); } mHwDevice->unload_sound_model(mHwDevice, model->mHandle); + releasedSessions.add(model->mCaptureSession); } mModels.clear(); } + + for (size_t i = 0; i < releasedSessions.size(); i++) { + // do not call AudioSystem methods with mLock held + AudioSystem::releaseSoundTriggerSession(releasedSessions[i]); + } + if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); } @@ -558,33 +567,43 @@ return BAD_VALUE; } - AutoMutex lock(mLock); - - if (mModels.size() >= mDescriptor.properties.max_sound_models) { - ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded", - mDescriptor.properties.max_sound_models); - return INVALID_OPERATION; - } - - status_t status = mHwDevice->load_sound_model(mHwDevice, sound_model, - SoundTriggerHwService::soundModelCallback, - this, handle); - - if (status != NO_ERROR) { - return status; - } audio_session_t session; audio_io_handle_t ioHandle; audio_devices_t device; - - status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); + // do not call AudioSystem methods with mLock held + status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); if (status != NO_ERROR) { return status; } - sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); - mModels.replaceValueFor(*handle, model); + { + AutoMutex lock(mLock); + if (mModels.size() >= mDescriptor.properties.max_sound_models) { + ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded", + mDescriptor.properties.max_sound_models); + status = INVALID_OPERATION; + goto exit; + } + + status_t status = mHwDevice->load_sound_model(mHwDevice, + sound_model, + SoundTriggerHwService::soundModelCallback, + this, + handle); + if (status != NO_ERROR) { + goto exit; + } + + sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); + mModels.replaceValueFor(*handle, model); + } + +exit: + if (status != NO_ERROR) { + // do not call AudioSystem methods with mLock held + AudioSystem::releaseSoundTriggerSession(session); + } return status; } @@ -594,25 +613,26 @@ if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } + status_t status; + audio_session_t session; - AutoMutex lock(mLock); - return unloadSoundModel_l(handle); -} - -status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle) -{ - ssize_t index = mModels.indexOfKey(handle); - if (index < 0) { - return BAD_VALUE; + { + AutoMutex lock(mLock); + ssize_t index = mModels.indexOfKey(handle); + if (index < 0) { + return BAD_VALUE; + } + sp<Model> model = mModels.valueAt(index); + mModels.removeItem(handle); + if (model->mState == Model::STATE_ACTIVE) { + mHwDevice->stop_recognition(mHwDevice, model->mHandle); + model->mState = Model::STATE_IDLE; + } + status = mHwDevice->unload_sound_model(mHwDevice, handle); + session = model->mCaptureSession; } - sp<Model> model = mModels.valueAt(index); - mModels.removeItem(handle); - if (model->mState == Model::STATE_ACTIVE) { - mHwDevice->stop_recognition(mHwDevice, model->mHandle); - model->mState = Model::STATE_IDLE; - } - AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); - return mHwDevice->unload_sound_model(mHwDevice, handle); + AudioSystem::releaseSoundTriggerSession(session); + return status; } status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h index 2619a5f..d05dacd 100644 --- a/services/soundtrigger/SoundTriggerHwService.h +++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -141,9 +141,6 @@ private: - status_t unloadSoundModel_l(sound_model_handle_t handle); - - Mutex mLock; wp<SoundTriggerHwService> mService; struct sound_trigger_hw_device* mHwDevice;