audio policy: update spatializer policy

Modify the rules to open and close the spatializer output
to address more scenarios:
- more than one spatializer output profile available
- some devices only reachable via a spatializer output profile

The spatializer outputs are opened and closed like other outputs
and a logic evaluates the best output when getSpatializerOutput()
is called

Bug: 188502620
Test: make
Change-Id: Id336e5c38a398525b3fab406cedce8a010d6c854
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 56c472b..de71a00 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -366,41 +366,51 @@
 void AudioPolicyService::onCheckSpatializer()
 {
     Mutex::Autolock _l(mLock);
-    mOutputCommandThread->checkSpatializerCommand();
+    onCheckSpatializer_l();
+}
+
+void AudioPolicyService::onCheckSpatializer_l()
+{
+    if (mSpatializer != nullptr) {
+        mOutputCommandThread->checkSpatializerCommand();
+    }
 }
 
 void AudioPolicyService::doOnCheckSpatializer()
 {
-    sp<Spatializer> spatializer;
-    {
-        Mutex::Autolock _l(mLock);
-        spatializer = mSpatializer;
+    Mutex::Autolock _l(mLock);
 
-        if (spatializer != nullptr) {
-            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-            if (spatializer->getLevel() != media::SpatializationLevel::NONE
-                && spatializer->getOutput() == AUDIO_IO_HANDLE_NONE) {
-                const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
-                audio_config_base_t config = spatializer->getAudioInConfig();
-                status_t status =
-                        mAudioPolicyManager->getSpatializerOutput(&config, &attr, &output);
-                if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
-                    return;
-                }
-                mLock.unlock();
-                status = spatializer->attachOutput(output);
+    if (mSpatializer != nullptr) {
+        if (mSpatializer->getLevel() != media::SpatializationLevel::NONE) {
+            audio_io_handle_t currentOutput = mSpatializer->getOutput();
+            audio_io_handle_t newOutput;
+            const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
+            audio_config_base_t config = mSpatializer->getAudioInConfig();
+            status_t status =
+                    mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
+
+            if (status == NO_ERROR && currentOutput == newOutput) {
+                return;
+            }
+            mLock.unlock();
+            // It is OK to call detachOutput() is none is already attached.
+            mSpatializer->detachOutput();
+            if (status != NO_ERROR || newOutput == AUDIO_IO_HANDLE_NONE) {
                 mLock.lock();
-                if (status != NO_ERROR) {
-                    mAudioPolicyManager->releaseSpatializerOutput(output);
-                }
-            } else if (spatializer->getLevel() == media::SpatializationLevel::NONE
-                                   && spatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
-                mLock.unlock();
-                output = spatializer->detachOutput();
-                mLock.lock();
-                if (output != AUDIO_IO_HANDLE_NONE) {
-                    mAudioPolicyManager->releaseSpatializerOutput(output);
-                }
+                return;
+            }
+            status = mSpatializer->attachOutput(newOutput);
+            mLock.lock();
+            if (status != NO_ERROR) {
+                mAudioPolicyManager->releaseSpatializerOutput(newOutput);
+            }
+        } else if (mSpatializer->getLevel() == media::SpatializationLevel::NONE
+                               && mSpatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
+            mLock.unlock();
+            audio_io_handle_t output = mSpatializer->detachOutput();
+            mLock.lock();
+            if (output != AUDIO_IO_HANDLE_NONE) {
+                mAudioPolicyManager->releaseSpatializerOutput(output);
             }
         }
     }