Merge "Soundtrigger service: fix cross deadlock with audio policy service" into lmp-dev
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 596b23d..dda1a7b 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -497,6 +497,8 @@
     if (!captureHotwordAllowed()) {
         return;
     }
+    Vector<audio_session_t> releasedSessions;
+
     {
         AutoMutex lock(mLock);
         for (size_t i = 0; i < mModels.size(); i++) {
@@ -506,9 +508,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) {
         mClient->asBinder()->unlinkToDeath(this);
     }
@@ -550,27 +559,35 @@
         return BAD_VALUE;
     }
 
-    AutoMutex lock(mLock);
-    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);
+        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;
 }
 
@@ -580,19 +597,25 @@
     if (!captureHotwordAllowed()) {
         return PERMISSION_DENIED;
     }
+    status_t status;
+    audio_session_t session;
 
-    AutoMutex lock(mLock);
-    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);
+      }
+      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);
-    }
-    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,