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;