Merge "st-hal: Add feature flag for daemon support"
diff --git a/sound_trigger_hw.c b/sound_trigger_hw.c
index 74ac639..3073a17 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__);
 }
@@ -1069,6 +1107,7 @@
         st_session_disable_device(p_ses);
     }
     sthw_extn_lpma_notify_event(LPMA_EVENT_DISABLE_DEVICE);
+    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);
@@ -1264,16 +1303,9 @@
     pthread_mutex_unlock(&stdev->lock);
 }
 
-static int stdev_get_properties(const struct sound_trigger_hw_device *dev,
-    struct sound_trigger_properties *properties)
+static void get_base_properties(struct sound_trigger_device *stdev)
 {
-    struct sound_trigger_device *stdev = (struct sound_trigger_device *)dev;
-
-    ALOGI("%s", __func__);
-    if (properties == NULL) {
-        ALOGE("%s: NULL properties", __func__);
-        return -EINVAL;
-    }
+    ALOGI("%s: enter", __func__);
 
     stdev->hw_properties->concurrent_capture = stdev->conc_capture_supported;
 
@@ -1301,8 +1333,24 @@
            stdev->hw_properties->capture_transition,
            stdev->hw_properties->concurrent_capture);
 
-    memcpy(properties, stdev->hw_properties,
+    memset(&hw_properties_extended, 0, sizeof(hw_properties_extended));
+    memcpy(&hw_properties_extended.base, stdev->hw_properties,
            sizeof(struct sound_trigger_properties));
+}
+
+static int stdev_get_properties(const struct sound_trigger_hw_device *dev,
+    struct sound_trigger_properties *properties)
+{
+    struct sound_trigger_device *stdev = (struct sound_trigger_device *)dev;
+
+    ALOGI("%s", __func__);
+    if (properties == NULL) {
+        ALOGE("%s: NULL properties", __func__);
+        return -EINVAL;
+    }
+
+    get_base_properties(stdev);
+    memcpy(properties, &hw_properties_extended.base, sizeof(struct sound_trigger_properties));
     hw_properties_extended.header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_0;
     return 0;
 }
@@ -1510,8 +1558,8 @@
 
 static bool compare_recognition_config
 (
-   const struct sound_trigger_recognition_config *current_config,
-   struct sound_trigger_recognition_config *new_config
+   const struct sound_trigger_recognition_config *new_config,
+   struct sound_trigger_recognition_config *current_config
 )
 {
     unsigned int i = 0, j = 0;
@@ -1533,7 +1581,6 @@
         (current_config->capture_requested != new_config->capture_requested) ||
         (current_config->num_phrases != new_config->num_phrases) ||
         (current_config->data_size != new_config->data_size) ||
-        (current_config->data_offset != new_config->data_offset) ||
         (hw_properties_extended.header.version == SOUND_TRIGGER_DEVICE_API_VERSION_1_3 &&
          memcmp((char *) current_config + current_config->data_offset,
                (char *) new_config + sizeof(struct sound_trigger_recognition_config) +
@@ -2739,11 +2786,8 @@
 
     stdev = (struct sound_trigger_device *)dev;
     prop_hdr = (struct sound_trigger_properties_header *)&hw_properties_extended;
-    status = stdev_get_properties(dev, &hw_properties_extended.base);
-    if (status) {
-        ALOGW("%s: Failed to initialize the stdev properties", __func__);
-        return NULL;
-    }
+    get_base_properties(stdev);
+
     hw_properties_extended.header.size = sizeof(struct sound_trigger_properties_extended_1_3);
     hw_properties_extended.audio_capabilities = 0;
     hw_properties_extended.header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3;
@@ -2772,7 +2816,7 @@
                 goto exit_2;
             }
 
-            st_session->f_stage_version = ST_MODULE_TYPE_CUSTOM;
+            st_session->f_stage_version = ST_MODULE_TYPE_GMM;
             st_session->vendor_uuid_info = v_info;
             handle = android_atomic_inc(&stdev->session_id);
 
@@ -2953,7 +2997,13 @@
     stdev_ref_cnt++;
     pthread_mutex_unlock(&stdev_init_lock);
 
+    get_base_properties(stdev);
+    hw_properties_extended.header.size = sizeof(struct sound_trigger_properties_extended_1_3);
+    hw_properties_extended.audio_capabilities = 0;
+    hw_properties_extended.header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3;
+
     ATRACE_END();
+    ALOGD("%s: Exit ", __func__);
     return 0;
 
 exit_1:
@@ -3290,6 +3340,15 @@
         handle_screen_status_change(config);
         break;
 
+    case AUDIO_EVENT_ROUTE_INIT_DONE:
+        if (!config) {
+            ALOGE("%s: NULL config for AUDIO_EVENT_ROUTE_INIT_DONE", __func__);
+            ret = -EINVAL;
+            break;
+        }
+        stdev->audio_route = config->u.audio_route;
+        break;
+
     default:
         ALOGW("%s: Unknown event %d", __func__, event);
         break;
diff --git a/sound_trigger_hw.h b/sound_trigger_hw.h
index 85b33eb..01feae9 100644
--- a/sound_trigger_hw.h
+++ b/sound_trigger_hw.h
@@ -261,6 +261,7 @@
     bool screen_off;
     bool barge_in_mode;
     int ec_reset_pending_cnt;
+    bool shared_mixer;
 };
 
 typedef struct sound_trigger_device sound_trigger_device_t;
diff --git a/sound_trigger_platform.c b/sound_trigger_platform.c
old mode 100644
new mode 100755
index cefc47e..3a0f668
--- a/sound_trigger_platform.c
+++ b/sound_trigger_platform.c
@@ -59,6 +59,7 @@
 #include <cutils/str_parms.h>
 #include <cutils/properties.h>
 #include <cutils/trace.h>
+#include <cutils/bitops.h>
 #include <dlfcn.h>
 #include <expat.h>
 #include <errno.h>
@@ -2541,8 +2542,7 @@
         return -ENOMEM;
     }
 
-    if (my_data->xml_version > PLATFORM_XML_VERSION_0x0105)
-        list_init(&lsm_params->module_params_list);
+    list_init(&lsm_params->module_params_list);
 
     list_add_tail(&sm_info->lsm_usecase_list, &lsm_params->list_node);
 
@@ -3797,6 +3797,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,
@@ -4097,12 +4113,16 @@
 
     snd_card_name = mixer_get_name(stdev->mixer);
 
-    query_stdev_platform(my_data, snd_card_name, mixer_path_xml);
-    stdev->audio_route = audio_route_init(snd_card_num, mixer_path_xml);
-    if (!stdev->audio_route) {
-        ALOGE("%s: ERROR. Failed to init audio route controls, aborting.",
-                __func__);
-        goto cleanup;
+    stdev->shared_mixer =
+        property_get_bool("persist.vendor.audio.shared_mixer.enabled", false);
+    if (!stdev->shared_mixer) {
+        query_stdev_platform(my_data, snd_card_name, mixer_path_xml);
+        stdev->audio_route = audio_route_init(snd_card_num, mixer_path_xml);
+        if (!stdev->audio_route) {
+            ALOGE("%s: ERROR. Failed to init audio route controls, aborting.",
+                    __func__);
+            goto cleanup;
+        }
     }
     stdev->snd_card = snd_card_num;
 
@@ -5005,8 +5025,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,56 +5036,70 @@
         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;
         }
-        if (stdev->conc_capture_supported)
-            concurrency_ses_allowed = stdev->session_allowed;
-        else if (stdev->tx_concurrency_active > 0)
+
+        /*
+         * 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->tx_concurrency_active == 0) {
+            stdev->conc_voice_active = false;
+            stdev->conc_voip_active = false;
+        }
+        if ((!stdev->conc_capture_supported &&
+             stdev->tx_concurrency_active > 0) ||
+            (stdev->conc_capture_supported &&
+             ((!stdev->conc_voice_call_supported && stdev->conc_voice_active) ||
+              (!stdev->conc_voip_call_supported && stdev->conc_voip_active))))
             concurrency_ses_allowed = false;
     } else {
         /* handle CAPTURE_STREAM events */
         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) {
@@ -5074,27 +5108,10 @@
                 num_sessions > stdev->rx_conc_max_st_ses)
                 concurrency_ses_allowed = false;
         }
-        if (concurrency_ses_allowed) {
-            if ((!stdev->conc_capture_supported &&
-                 stdev->tx_concurrency_active > 0) ||
-                (stdev->conc_capture_supported &&
-                 ((!stdev->conc_voice_call_supported && stdev->conc_voice_active) ||
-                  (!stdev->conc_voip_call_supported && stdev->conc_voip_active))))
-                concurrency_ses_allowed = false;
-        }
+        if (concurrency_ses_allowed)
+            concurrency_ses_allowed = stdev->session_allowed;
     }
 
-    /*
-     * Mark reset_backend as false to prevent disabling tx
-     * device when pausing VA sessions.
-     */
-    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;
-
     ALOGD("%s: dedicated path %d, reset backend %d, tx %d, rx %d,"
           " concurrency session%s allowed",
           __func__, platform_stdev_is_dedicated_sva_path(stdev->platform),
@@ -5893,6 +5910,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,
@@ -5957,11 +6013,12 @@
     struct platform_data *my_data = (struct platform_data *)platform;
     sound_trigger_device_t *stdev = my_data->stdev;
     struct sound_trigger_event_info event_info = {{0}, 0};
+    bool force_reset_ec = stdev->shared_mixer;
 
     if (is_ec_profile(profile_type)) {
         event_info.st_ec_ref_enabled = enable;
         // reset the pending active EC mixer ctls first
-        if (!stdev->audio_ec_enabled) {
+        if (!stdev->audio_ec_enabled && !force_reset_ec) {
             while (stdev->ec_reset_pending_cnt > 0) {
                 audio_route_reset_and_update_path(stdev->audio_route,
                         my_data->ec_ref_mixer_path);
@@ -5982,7 +6039,7 @@
         } else {
             stdev->audio_hal_cb(ST_EVENT_UPDATE_ECHO_REF, &event_info);
             /* avoid disabling echo if audio hal has enabled echo ref */
-            if (!stdev->audio_ec_enabled) {
+            if (!stdev->audio_ec_enabled || force_reset_ec) {
                 ALOGD("%s: reset echo ref %s", __func__,
                     my_data->ec_ref_mixer_path);
                 audio_route_reset_and_update_path(stdev->audio_route,
diff --git a/sound_trigger_platform.h b/sound_trigger_platform.h
index d7e4277..1dad3b9 100755
--- a/sound_trigger_platform.h
+++ b/sound_trigger_platform.h
@@ -658,6 +658,11 @@
    char *use_case
 );
 
+void platform_stdev_disable_stale_devices
+(
+    void *platform
+);
+
 void platform_stdev_check_and_update_ec_ref_config
 (
    void *platform,
@@ -717,6 +722,11 @@
    void *platform
 );
 
+bool platform_stdev_backend_reset_allowed
+(
+    void *platform
+);
+
 int platform_stdev_derive_mixer_ctl_from_backend
 (
     void *platform,
diff --git a/sound_trigger_prop_intf.h b/sound_trigger_prop_intf.h
index 4cd599c..71b1e1b 100644
--- a/sound_trigger_prop_intf.h
+++ b/sound_trigger_prop_intf.h
@@ -73,7 +73,8 @@
     AUDIO_EVENT_BATTERY_STATUS_CHANGED,
     AUDIO_EVENT_GET_PARAM,
     AUDIO_EVENT_UPDATE_ECHO_REF,
-    AUDIO_EVENT_SCREEN_STATUS_CHANGED
+    AUDIO_EVENT_SCREEN_STATUS_CHANGED,
+    AUDIO_EVENT_ROUTE_INIT_DONE
 };
 typedef enum audio_event_type audio_event_type_t;
 
@@ -137,6 +138,7 @@
         struct audio_hal_usecase usecase;
         bool audio_ec_ref_enabled;
         struct sound_trigger_get_param_data st_get_param_data;
+        struct audio_route *audio_route;
     } u;
     struct sound_trigger_device_info device_info;
 };
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_session.c b/st_session.c
index 79268be..29bf304 100644
--- a/st_session.c
+++ b/st_session.c
@@ -184,7 +184,7 @@
             lock_status = pthread_mutex_trylock(&st_ses->lock);
         } while (lock_status && !st_ses->device_disabled &&
                  (st_ses->exec_mode != ST_EXEC_MODE_NONE) &&
-                 (st_ses->current_state != ssr_state_fn));
+                 (st_ses->current_state == active_state_fn));
 
         if (st_ses->device_disabled) {
             ALOGV("%s:[%d] device switch in progress, ignore event",
@@ -192,8 +192,8 @@
         } else if (st_ses->exec_mode == ST_EXEC_MODE_NONE) {
             ALOGV("%s:[%d] transition in progress, ignore event",
                   __func__, st_ses->sm_handle);
-        } else if (st_ses->current_state == ssr_state_fn) {
-            ALOGV("%s:[%d] SSR handling in progress, ignore event",
+        } else if (st_ses->current_state != active_state_fn) {
+            ALOGV("%s:[%d] Session not in active state, ignore event",
                   __func__, st_ses->sm_handle);
         } else if (!lock_status) {
             /*
@@ -236,20 +236,23 @@
                  (st_ses->current_state == buffering_state_fn) &&
                  !st_ses->stdev->ssr_offline_received);
 
-        if (st_ses->det_stc_ses->pending_stop)
+        if (st_ses->det_stc_ses->pending_stop) {
             ALOGV("%s:[%d] pending stop already queued, ignore event",
                 __func__, st_ses->sm_handle);
-        else if (!st_ses->det_stc_ses->detection_sent)
-            ALOGV("%s:[%d] client callback hasn't been called, ignore event",
-                __func__, st_ses->sm_handle);
-        else if (st_ses->current_state != buffering_state_fn)
+        } else if (!st_ses->det_stc_ses->detection_sent) {
+                ev.ev_id = ST_SES_EV_RESTART;
+                DISPATCH_EVENT(st_ses, ev, status);
+                ALOGV("%s:[%d] client callback hasn't been called, restart detection evt_id(%d)",
+                   __func__, st_ses->sm_handle, ev.ev_id);
+        } else if (st_ses->current_state != buffering_state_fn) {
             ALOGV("%s:[%d] session already stopped buffering, ignore event",
                 __func__, st_ses->sm_handle);
-        else if (st_ses->stdev->ssr_offline_received)
+        } else if (st_ses->stdev->ssr_offline_received) {
             ALOGV("%s:[%d] SSR handling in progress, ignore event",
                   __func__, st_ses->sm_handle);
-        else if (!lock_status)
+        } else if (!lock_status) {
             DISPATCH_EVENT(st_ses, ev, status);
+        }
 
         if (!lock_status)
             pthread_mutex_unlock(&st_ses->lock);
@@ -5537,10 +5540,13 @@
         break;
 
     case ST_SES_EV_SET_DEVICE:
-        if (!ev->payload.enable)
+        if (!ev->payload.enable) {
+            st_ses->device_disabled = true;
             status = hw_ses->fptrs->disable_device(hw_ses, true);
-        else
+        } else {
             status = hw_ses->fptrs->enable_device(hw_ses, true);
+            st_ses->device_disabled = false;
+        }
 
         if (status && st_ses->stdev->ssr_offline_received) {
             STATE_TRANSITION(st_ses, ssr_state_fn);