Merge 47c34c8ea639c7e2ccf6b3b361473d5c534923e4 on remote branch

Change-Id: I363d75799c91e150aa82a4fd2bf0605e1f22da40
diff --git a/sound_trigger_hw.c b/sound_trigger_hw.c
index e4772cb..4a65991 100644
--- a/sound_trigger_hw.c
+++ b/sound_trigger_hw.c
@@ -793,6 +793,21 @@
 
     if (!num_sessions) {
         stdev->session_allowed = conc_allowed;
+        /*
+         * This is needed for the following usecase:
+         *
+         * 1. LPI and NLPI have different number of MICs (different devices).
+         * 2. ST session is stopped from app and unloaded while Tx active.
+         * 3. Tx stops.
+         * 4. ST session started again from app on LPI.
+         *
+         * The device disablement is missed in step 3 because the st_session was
+         * deinitialized. Thus, it is handled here.
+         */
+        if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE &&
+            !platform_stdev_is_dedicated_sva_path(stdev->platform) &&
+            platform_stdev_backend_reset_allowed(stdev->platform))
+            platform_stdev_disable_stale_devices(stdev->platform);
         pthread_mutex_unlock(&stdev->lock);
         return;
     }
@@ -849,12 +864,26 @@
             }
         } else {
             if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE) {
+                /*
+                 * The reset_backend flag allows the backend device to be disabled. This should
+                 * only be disallowed when in non-dedicated path mode and there is an active
+                 * audio input stream.
+                 */
+                stdev->reset_backend = platform_stdev_backend_reset_allowed(stdev->platform);
+                st_hw_check_and_update_lpi(stdev, p_ses);
+                stdev->vad_enable = st_hw_check_vad_support(stdev, p_ses, stdev->lpi_enable);
+
                 list_for_each(p_ses_node, &stdev->sound_model_list) {
                     p_ses = node_to_item(p_ses_node, st_session_t, list_node);
                     ALOGD("%s:[%d] Capture device is disabled, pause SVA session",
                           __func__, p_ses->sm_handle);
                     st_session_pause(p_ses);
                 }
+                /*
+                 * This is needed when the session goes to loaded state, then
+                 * LPI/NLPI switch happens due to Rx event.
+                 */
+                platform_stdev_disable_stale_devices(stdev->platform);
                 list_for_each(p_ses_node, &stdev->sound_model_list) {
                     p_ses = node_to_item(p_ses_node, st_session_t, list_node);
                     ALOGD("%s:[%d] Capture device is disabled, resume SVA session",
@@ -922,6 +951,15 @@
             }
         }
     }
+    /*
+     * The device can be disabled within this thread upon reception of the device
+     * active event because audio hal does not enable the device until after returning
+     * from this callback. After this thread exits, device disablement will be
+     * disallowed until the device inactive event is received.
+     */
+    if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE &&
+        !platform_stdev_is_dedicated_sva_path(stdev->platform))
+        stdev->reset_backend = platform_stdev_backend_reset_allowed(stdev->platform);
     pthread_mutex_unlock(&stdev->lock);
     ALOGV("%s: Exit", __func__);
 }
@@ -2041,11 +2079,13 @@
         goto exit_1;
     }
 
+    ALOGD("%s: second state detection %s",__func__,
+             st_session->vendor_uuid_info->second_stage_supported ? "supported" : "not supported");
     /*
      * Parse second stage sound models and populate the second stage list for
      * this session.
      */
-    if (sml_version == SML_MODEL_V3) {
+    if (sml_version == SML_MODEL_V3 && st_session->vendor_uuid_info->second_stage_supported) {
         status = check_and_configure_second_stage_models(st_session, sm_payload,
             num_models, phrase_sm->phrases[0].recognition_mode);
         if (status) {
diff --git a/sound_trigger_platform.c b/sound_trigger_platform.c
index cefc47e..032617b 100644
--- a/sound_trigger_platform.c
+++ b/sound_trigger_platform.c
@@ -2,7 +2,7 @@
  *
  * This file contains the platform specific functionality.
  *
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -128,6 +128,7 @@
 #define ST_PARAM_KEY_KW_START_TOLERANCE "kw_start_tolerance"
 #define ST_PARAM_KEY_KW_END_TOLERANCE "kw_end_tolerance"
 #define ST_PARAM_KEY_EXECUTION_TYPE "execution_type"
+#define ST_PARAM_KEY_SECOND_STAGE_SUPPORTED "second_stage_supported"
 #define ST_PARAM_KEY_EVENT_TIMESTAMP_MODE "event_timestamp_mode"
 #define ST_PARAM_KEY_BACKEND_PORT_NAME "backend_port_name"
 #define ST_PARAM_KEY_BACKEND_DAI_NAME "backend_dai_name"
@@ -2658,6 +2659,21 @@
         }
     }
 
+    err = str_parms_get_str(parms, ST_PARAM_KEY_SECOND_STAGE_SUPPORTED,
+                            str_value, sizeof(str_value));
+    //By default set to true
+    sm_info->second_stage_supported = true;
+    if (err >= 0) {
+        str_parms_del(parms, ST_PARAM_KEY_SECOND_STAGE_SUPPORTED);
+        if (!strcmp(str_value, "true")) {
+           sm_info->second_stage_supported = true;
+        } else if (!strcmp(str_value, "false")) {
+           sm_info->second_stage_supported = false;
+        } else {
+            ALOGE("%s: invalid second stage support value set: %s", __func__, str_value);
+        }
+    }
+
     err = str_parms_get_str(parms, ST_PARAM_KEY_APP_TYPE,
                             str_value, sizeof(str_value));
     if (err >= 0) {
@@ -3797,6 +3813,22 @@
     return true;
 }
 
+bool platform_stdev_backend_reset_allowed
+(
+    void *platform
+)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    sound_trigger_device_t *stdev = my_data->stdev;
+
+    if (stdev->conc_capture_supported &&
+        stdev->tx_concurrency_active > 0 &&
+        !platform_stdev_is_dedicated_sva_path(platform))
+        return false;
+    else
+        return true;
+}
+
 static int platform_stdev_get_device_sample_rate
 (
    struct platform_data *my_data,
@@ -4582,6 +4614,17 @@
     return get_st_device(platform, v_info, device, exec_mode, false);
 }
 
+int platform_stdev_get_device_for_cal
+(
+    void *platform,
+    struct st_vendor_info* v_info,
+    audio_devices_t device,
+    enum st_exec_mode exec_mode
+)
+{
+    return get_st_device(platform, v_info, device, exec_mode, true);
+}
+
 audio_devices_t platform_stdev_get_capture_device
 (
    void *platform
@@ -5005,8 +5048,8 @@
     if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE ||
         event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE) {
         /* handle CAPTURE_DEVICE events */
-        ALOGI("%s: Received DEVICE event, event type %d",
-              __func__, event_type);
+        ALOGI("%s: Received DEVICE event, event type %d, usecase type %d",
+              __func__, event_type, config->u.usecase.type);
         /*
          * for device status events, if:
          * 1. conc audio disabled - return with false to disable VA sessions
@@ -5016,10 +5059,30 @@
         switch (event_type) {
             case AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE:
                 stdev->tx_concurrency_active++;
+                switch (config->u.usecase.type) {
+                    case USECASE_TYPE_VOICE_CALL:
+                        stdev->conc_voice_active = true;
+                        break;
+                    case USECASE_TYPE_VOIP_CALL:
+                        stdev->conc_voip_active = true;
+                        break;
+                    default:
+                        break;
+                }
                 break;
             case AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE:
                 if (stdev->tx_concurrency_active > 0)
                     stdev->tx_concurrency_active--;
+                switch (config->u.usecase.type) {
+                    case USECASE_TYPE_VOICE_CALL:
+                        stdev->conc_voice_active = false;
+                        break;
+                    case USECASE_TYPE_VOIP_CALL:
+                        stdev->conc_voip_active = false;
+                        break;
+                    default:
+                        break;
+                }
                 break;
             default:
                 break;
@@ -5033,39 +5096,15 @@
         ALOGI("%s: Received STREAM event, event type %d, usecase type %d",
               __func__, event_type, config->u.usecase.type);
         switch (event_type) {
-        case AUDIO_EVENT_CAPTURE_STREAM_ACTIVE:
-            switch (config->u.usecase.type) {
-                case USECASE_TYPE_VOICE_CALL:
-                    stdev->conc_voice_active = true;
-                    break;
-                case USECASE_TYPE_VOIP_CALL:
-                    stdev->conc_voip_active = true;
-                    break;
-                default:
-                    break;
-            }
-            break;
-        case AUDIO_EVENT_CAPTURE_STREAM_INACTIVE:
-            switch (config->u.usecase.type) {
-                case USECASE_TYPE_VOICE_CALL:
-                    stdev->conc_voice_active = false;
-                    break;
-                case USECASE_TYPE_VOIP_CALL:
-                    stdev->conc_voip_active = false;
-                    break;
-                default:
-                    break;
-            }
-            break;
-        case AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE:
-                stdev->rx_concurrency_active++;
-            break;
-        case AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE:
-            if (stdev->rx_concurrency_active > 0)
-                stdev->rx_concurrency_active--;
-            break;
-        default:
-            break;
+            case AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE:
+                    stdev->rx_concurrency_active++;
+                break;
+            case AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE:
+                if (stdev->rx_concurrency_active > 0)
+                    stdev->rx_concurrency_active--;
+                break;
+            default:
+                break;
         }
         if (event_type == AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE ||
             event_type == AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE) {
@@ -5085,15 +5124,20 @@
     }
 
     /*
-     * Mark reset_backend as false to prevent disabling tx
-     * device when pausing VA sessions.
+     * This disablement of VOIP/Voice flags is needed for the following usecase:
+     *
+     * 1. VOIP/Voice and AR active.
+     * 2. VOIP/Voice stops - AHAL sends stream inactive events for each stream,
+     *    followed by the shared device inactive and device active events which
+     *    both have VOIP/voice usecase, followed by one stream active event for AR.
+     * 3. AR stops - stream and device inactive events with pcm capture usecase.
+     *
+     * In this usecase the VOIP/voice flags get stuck set to true, so reset them here.
      */
-    if (stdev->conc_capture_supported &&
-        stdev->tx_concurrency_active > 0 &&
-        (!platform_stdev_is_dedicated_sva_path(stdev->platform)))
-        stdev->reset_backend = false;
-    else
-        stdev->reset_backend = true;
+    if (stdev->tx_concurrency_active == 0) {
+        stdev->conc_voice_active = false;
+        stdev->conc_voip_active = false;
+    }
 
     ALOGD("%s: dedicated path %d, reset backend %d, tx %d, rx %d,"
           " concurrency session%s allowed",
@@ -5893,6 +5937,45 @@
     return app_type;
 }
 
+void platform_stdev_disable_stale_devices
+(
+    void *platform
+)
+{
+    struct platform_data *my_data = (struct platform_data *)platform;
+    sound_trigger_device_t *stdev = my_data->stdev;
+    char st_device_name[DEVICE_NAME_MAX_SIZE] = {0};
+
+    /*
+     * There can be stale devices while exec_mode is NONE with the
+     * below usecase:
+     *
+     *    1. SVA is active in non-dedicated path mode.
+     *    2. Tx starts, transitioning SVA to NLPI.
+     *    3. SVA stops and unloads, but cannot disable the BE device.
+     *    4. Tx stops - this function will get called with exec_mode NONE.
+     */
+    if (stdev->exec_mode == ST_EXEC_MODE_ADSP ||
+        (stdev->exec_mode == ST_EXEC_MODE_NONE &&
+         !stdev->is_gcs)) {
+        pthread_mutex_lock(&stdev->ref_cnt_lock);
+        for (int i = ST_DEVICE_MIN; i < ST_DEVICE_MAX; i++) {
+            if (0 < stdev->dev_enable_cnt[i]) {
+                platform_stdev_get_device_name(stdev->platform,
+                    ST_EXEC_MODE_ADSP, i, st_device_name);
+                ALOGD("%s: disable device (%x) = %s", __func__, i,
+                    st_device_name);
+                ATRACE_BEGIN("sthal: audio_route_reset_and_update_path");
+                audio_route_reset_and_update_path(stdev->audio_route,
+                                                  st_device_name);
+                ATRACE_END();
+                --(stdev->dev_enable_cnt[i]);
+            }
+        }
+        pthread_mutex_unlock(&stdev->ref_cnt_lock);
+    }
+}
+
 static void check_and_append_ec_ref_device_name
 (
     void *platform,
diff --git a/sound_trigger_platform.h b/sound_trigger_platform.h
index 1ffda2a..0ec821d 100644
--- a/sound_trigger_platform.h
+++ b/sound_trigger_platform.h
@@ -1,6 +1,6 @@
 /* sound_trigger_platform.h
  *
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -377,6 +377,7 @@
     unsigned int avail_transit_ape_phrases;
     unsigned int avail_transit_ape_users;
     st_exec_mode_config_t exec_mode_cfg;
+    bool second_stage_supported;
     bool lpi_enable;
     bool vad_enable;
     struct lab_dam_cfg_payload lab_dam_cfg_payload;
@@ -450,6 +451,14 @@
    st_exec_mode_t exec_mode
 );
 
+int platform_stdev_get_device_for_cal
+(
+   void *platform,
+   struct st_vendor_info* v_info,
+   audio_devices_t device,
+   st_exec_mode_t exec_mode
+);
+
 int platform_stdev_get_acdb_id
 (
     st_device_t st_device,
@@ -652,6 +661,11 @@
    char *use_case
 );
 
+void platform_stdev_disable_stale_devices
+(
+    void *platform
+);
+
 void platform_stdev_check_and_update_ec_ref_config
 (
    void *platform,
@@ -711,6 +725,11 @@
    void *platform
 );
 
+bool platform_stdev_backend_reset_allowed
+(
+    void *platform
+);
+
 int platform_stdev_derive_mixer_ctl_from_backend
 (
     void *platform,
diff --git a/st_hw_common.c b/st_hw_common.c
index 1255c43..97624cb 100644
--- a/st_hw_common.c
+++ b/st_hw_common.c
@@ -205,7 +205,8 @@
     }
 
     if (stdev->rx_concurrency_active || stdev->conc_voice_active ||
-        stdev->conc_voip_active) {
+        stdev->conc_voip_active ||
+        !platform_stdev_backend_reset_allowed(stdev->platform)) {
         ALOGD("%s: lpi NOT supported due to concurrency", __func__);
         return;
     }
diff --git a/st_hw_session_lsm.c b/st_hw_session_lsm.c
index 62f53d0..6198c20 100644
--- a/st_hw_session_lsm.c
+++ b/st_hw_session_lsm.c
@@ -574,6 +574,8 @@
     st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
     st_profile_type_t profile_type = get_profile_type(p_ses);
     char use_case[USECASE_STRING_SIZE];
+    audio_devices_t capture_device = 0;
+    st_device_t st_device = 0;
 
     if (enable) {
         strlcpy(use_case,
@@ -582,8 +584,11 @@
         platform_stdev_check_and_append_usecase(p_ses->stdev->platform,
                                                 use_case);
         ALOGD("%s: enable use case = %s", __func__, use_case);
+        capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
+        st_device = platform_stdev_get_device_for_cal(p_ses->stdev->platform,
+            p_ses->vendor_uuid_info, capture_device, p_ses->exec_mode);
         platform_stdev_send_stream_app_type_cfg(p_ses->stdev->platform,
-                                   p_lsm_ses->pcm_id, p_ses->st_device,
+                                   p_lsm_ses->pcm_id, st_device,
                                    p_ses->exec_mode, profile_type);
 
         platform_stdev_send_ec_ref_cfg(p_ses->stdev->platform, profile_type, true);
@@ -2174,8 +2179,10 @@
      * Custom config is mandatory for adsp multi-stage session,
      * Default config would be sent if not explicitly set from client applicaiton.
      */
-    if ((p_ses->custom_data_size && !disable_custom_config) ||
-        !list_empty(&p_ses->lsm_ss_cfg_list)) {
+    ALOGD("%s: second state detection %s",__func__,
+             p_ses->vendor_uuid_info->second_stage_supported ? "supported" : "not supported");
+    if (((p_ses->custom_data_size && !disable_custom_config) ||
+        !list_empty(&p_ses->lsm_ss_cfg_list)) && p_ses->vendor_uuid_info->second_stage_supported) {
         /* fill opaque data as custom params */
         cus_params = &param_info[param_count++];
         if (param_tag_tracker & PARAM_CUSTOM_CONFIG_BIT) {