Merge "qahw: test: Enhance and add new functionality to playback test app"
diff --git a/configs/msmcobalt/audio_policy.conf b/configs/msmcobalt/audio_policy.conf
index 70ab311..59fa525 100644
--- a/configs/msmcobalt/audio_policy.conf
+++ b/configs/msmcobalt/audio_policy.conf
@@ -102,7 +102,7 @@
       }
       surround_sound {
         sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
-        channel_masks AUDIO_CHANNEL_IN_5POINT1|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK|AUDIO_CHANNEL_INDEX_MASK_3|AUDIO_CHANNEL_INDEX_MASK_4
+        channel_masks AUDIO_CHANNEL_IN_5POINT1|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK|AUDIO_CHANNEL_INDEX_MASK_3|AUDIO_CHANNEL_INDEX_MASK_4|AUDIO_CHANNEL_INDEX_MASK_6
         formats AUDIO_FORMAT_PCM_16_BIT
         devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC
       }
diff --git a/configs/msmcobalt/audio_policy_configuration.xml b/configs/msmcobalt/audio_policy_configuration.xml
index 66b7d17..7ef79d1 100644
--- a/configs/msmcobalt/audio_policy_configuration.xml
+++ b/configs/msmcobalt/audio_policy_configuration.xml
@@ -176,7 +176,7 @@
                 <mixPort name="surround_sound" role="sink">
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
-                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1"/>
+                             channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4,AUDIO_CHANNEL_IN_5POINT1,AUDIO_CHANNEL_INDEX_MASK_6"/>
                 </mixPort>
                 <mixPort name="record_24" role="sink">
                     <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 022a3c0..8bfea9a 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -435,6 +435,48 @@
     return BAD_VALUE;
 }
 
+bool AudioPolicyManagerCustom::isInvalidationOfMusicStreamNeeded(routing_strategy strategy)
+{
+    if (strategy == STRATEGY_MEDIA) {
+        for (size_t i = 0; i < mOutputs.size(); i++) {
+            sp<SwAudioOutputDescriptor> newOutputDesc = mOutputs.valueAt(i);
+            if (newOutputDesc->mFormat == AUDIO_FORMAT_DSD)
+                return false;
+        }
+    }
+    return true;
+}
+
+void AudioPolicyManagerCustom::checkOutputForStrategy(routing_strategy strategy)
+{
+    audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);
+    audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/);
+    SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mOutputs);
+    SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
+
+    // also take into account external policy-related changes: add all outputs which are
+    // associated with policies in the "before" and "after" output vectors
+    ALOGV("checkOutputForStrategy(): policy related outputs");
+    for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
+        const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
+        if (desc != 0 && desc->mPolicyMix != NULL) {
+            srcOutputs.add(desc->mIoHandle);
+            ALOGV(" previous outputs: adding %d", desc->mIoHandle);
+        }
+    }
+    for (size_t i = 0 ; i < mOutputs.size() ; i++) {
+        const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+        if (desc != 0 && desc->mPolicyMix != NULL) {
+            dstOutputs.add(desc->mIoHandle);
+            ALOGV(" new outputs: adding %d", desc->mIoHandle);
+        }
+    }
+
+    if (!vectorsEqual(srcOutputs,dstOutputs) && isInvalidationOfMusicStreamNeeded(strategy)) {
+        AudioPolicyManager::checkOutputForStrategy(strategy);
+    }
+}
+
 // This function checks for the parameters which can be offloaded.
 // This can be enhanced depending on the capability of the DSP and policy
 // of the system.
@@ -2189,40 +2231,6 @@
     ALOGD("USE_XML_AUDIO_POLICY_CONF is FALSE");
 #endif
 
-    //TODO: Check the new logic to parse policy conf and update the below code
-    //      Need this when SSR encoding is enabled
-    char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
-    bool prop_ssr_enabled = false;
-
-    if (property_get("ro.qc.sdk.audio.ssr", ssr_enabled, NULL)) {
-        prop_ssr_enabled = atoi(ssr_enabled) || !strncmp("true", ssr_enabled, 4);
-    }
-
-    for (size_t i = 0; i < mHwModules.size(); i++) {
-        ALOGV("Hw module %zu", i);
-        for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
-            const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
-            AudioProfileVector profiles = inProfile->getAudioProfiles();
-            for (size_t k = 0; k < profiles.size(); k++){
-                ChannelsVector channels = profiles[k]->getChannels();
-                for (size_t x = 0; x < channels.size(); x++) {
-                    audio_channel_mask_t channelMask = channels[x];
-                    ALOGV("Channel Mask %x size %zu", channelMask,
-                         channels.size());
-                    if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
-                        if (!prop_ssr_enabled) {
-                            ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
-                                " input profile as SSR(surround sound record)"
-                                " is not supported on this chipset variant");
-                            channels.removeItemsAt(x, 1);
-                            ALOGV("Channel Mask size now %zu",
-                                channels.size());
-                        }
-                    }
-                }
-            }
-        }
-    }
 #ifdef RECORD_PLAY_CONCURRENCY
     mIsInputRequestOnProgress = false;
 #endif
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index deef57d..00da599 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -96,6 +96,14 @@
         // see getDeviceForStrategy() for the use of fromCache parameter
         audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
                                            bool fromCache);
+
+        // avoid invalidation for active music stream on  previous outputs
+        // which is supported on the new device.
+        bool isInvalidationOfMusicStreamNeeded(routing_strategy strategy);
+
+        // Must be called before updateDevicesAndOutputs()
+        void checkOutputForStrategy(routing_strategy strategy);
+
         // returns true if given output is direct output
         bool isDirectOutput(audio_io_handle_t output);
 
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index e1dd026..7b60248 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -697,24 +697,31 @@
     struct listnode *node = NULL;
     vol_listener_context_t *context = NULL;
     vol_listener_context_t *recv_contex = (vol_listener_context_t *)handle;
-    int status = -1;
+    int status = -EINVAL;
     bool recompute_flag = false;
     int active_stream_count = 0;
+    uint32_t session_id;
+    uint32_t stream_type;
+    effect_uuid_t uuid;
+
     ALOGV("%s context %p", __func__, handle);
-    if (recv_contex == NULL || recv_contex->desc == NULL) {
-        ALOGE("%s: Got invalid handle while release, DO NOTHING ", __func__);
+
+    if (recv_contex == NULL) {
         return status;
     }
-
     pthread_mutex_lock(&vol_listner_init_lock);
+    session_id = recv_contex->session_id;
+    stream_type = recv_contex->stream_type;
+    uuid = recv_contex->desc->uuid;
 
     // check if the handle/context provided is valid
     list_for_each(node, &vol_effect_list) {
         context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
-        if ((memcmp(&(context->desc->uuid), &(recv_contex->desc->uuid), sizeof(effect_uuid_t)) == 0)
-            && (context->session_id == recv_contex->session_id)
-            && (context->stream_type == recv_contex->stream_type)) {
+        if ((memcmp(&(context->desc->uuid), &uuid, sizeof(effect_uuid_t)) == 0)
+            && (context->session_id == session_id)
+            && (context->stream_type == stream_type)) {
             ALOGV("--- Found something to remove ---");
+            list_remove(node);
             PRINT_STREAM_TYPE(context->stream_type);
             if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
                 recompute_flag = true;
@@ -730,6 +737,8 @@
 
     if (status != 0) {
         ALOGE("something wrong ... <<<--- Found NOTHING to remove ... ???? --->>>>>");
+        pthread_mutex_unlock(&vol_listner_init_lock);
+        return status;
     }
 
     // if there are no active streams, reset cal and volume level