hal: notify listen while enabling/disabling snd device

Listen needs be stopped when audio capture is active. Also
Listen needs to be started again after audio capture becomes
inactive. Stop and start listen based on audio capture device.

Change-Id: I05ca7cccd59b43a163604881bd9c6ee10cc8fba3
Depends-on: 510494
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 7d04c6d..904152f 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -95,7 +95,7 @@
 
 #ifndef AUDIO_LISTEN_ENABLED
 
-#define audio_extn_listen_init(adev)                            (0)
+#define audio_extn_listen_init(adev, snd_card)                  (0)
 #define audio_extn_listen_deinit(adev)                          (0)
 #define audio_extn_listen_update_status(uc_info, event)         (0)
 #define audio_extn_listen_set_parameters(adev, parms)           (0)
@@ -103,17 +103,17 @@
 #else
 
 enum listen_event_type {
-    LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE,
-    LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE,
+    LISTEN_EVENT_SND_DEVICE_FREE,
+    LISTEN_EVENT_SND_DEVICE_BUSY
 };
 typedef enum listen_event_type listen_event_type_t;
 
-int audio_extn_listen_init(struct audio_device *adev);
+int audio_extn_listen_init(struct audio_device *adev, unsigned int snd_card);
 void audio_extn_listen_deinit(struct audio_device *adev);
-void audio_extn_listen_update_status(struct audio_usecase *uc_info,
-        listen_event_type_t event);
+void audio_extn_listen_update_status(snd_device_t snd_device,
+                                     listen_event_type_t event);
 void audio_extn_listen_set_parameters(struct audio_device *adev,
-                                        struct str_parms *parms);
+                                      struct str_parms *parms);
 
 #endif /* AUDIO_LISTEN_ENABLED */
 
diff --git a/hal/audio_extn/listen.c b/hal/audio_extn/listen.c
index 14a427b..65c0ae6 100644
--- a/hal/audio_extn/listen.c
+++ b/hal/audio_extn/listen.c
@@ -27,7 +27,7 @@
  *
  */
 #define LOG_TAG "listen_hal_loader"
-#define LOG_NDEBUG 0
+/* #define LOG_NDEBUG 0 */
 /* #define LOG_NDDEBUG 0 */
 #include <stdbool.h>
 #include <stdlib.h>
@@ -59,7 +59,8 @@
 }
 
 
-typedef int (*create_listen_hw_t)();
+typedef int (*create_listen_hw_t)(unsigned int snd_card,
+                                  struct audio_route *audio_route);
 typedef void (*destroy_listen_hw_t)();
 
 typedef int (*open_listen_session_t)(struct audio_hw_device *,
@@ -93,15 +94,25 @@
 
 static struct listen_audio_device *listen_dev;
 
-void audio_extn_listen_update_status(struct audio_usecase *uc_info,
+void audio_extn_listen_update_status(snd_device_t snd_device,
                                     listen_event_type_t event)
 {
+    if (!platform_listen_update_status(snd_device)) {
+        ALOGV("%s(): no need to notify listen. device = %s. Event = %u",
+                __func__, platform_get_snd_device_name(snd_device), event);
+        return;
+    }
+
     if (listen_dev) {
-        ALOGI("%s(): current active device =  %s. Event = %u", __func__,
-                platform_get_snd_device_name(uc_info->in_snd_device),
-                event);
-        if (uc_info->in_snd_device != SND_DEVICE_IN_CAPTURE_FM)
-            listen_dev->notify_event(event);
+        ALOGI("%s(): %s listen. current active device = %s. Event = %u",
+                __func__,
+                (event == LISTEN_EVENT_SND_DEVICE_BUSY) ? "stop" : "start",
+                platform_get_snd_device_name(snd_device), event);
+
+            if (event == LISTEN_EVENT_SND_DEVICE_FREE)
+                   listen_dev->notify_event(AUDIO_CAPTURE_INACTIVE);
+            else if (event == LISTEN_EVENT_SND_DEVICE_BUSY)
+                   listen_dev->notify_event(AUDIO_CAPTURE_ACTIVE);
     }
 }
 
@@ -111,7 +122,7 @@
     return;
 }
 
-int audio_extn_listen_init(struct audio_device *adev)
+int audio_extn_listen_init(struct audio_device *adev, unsigned int snd_card)
 {
     int ret;
     void *lib_handle;
@@ -165,7 +176,7 @@
         LISTEN_LOAD_SYMBOLS(listen_dev, notify_event,
                 listen_notify_event_t, listen_hw_notify_event);
 
-        listen_dev->create_listen_hw();
+        listen_dev->create_listen_hw(snd_card, adev->audio_route);
     }
     return 0;
 }
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 5537115..df040e2 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -271,6 +271,9 @@
             adev->snd_dev_ref_cnt[snd_device]--;
             return -EINVAL;
         }
+        audio_extn_listen_update_status(snd_device,
+                LISTEN_EVENT_SND_DEVICE_BUSY);
+
         audio_route_apply_path(adev->audio_route, device_name);
     }
     if (update_mixer)
@@ -322,6 +325,9 @@
 
         if (update_mixer)
             audio_route_update_mixer(adev->audio_route);
+
+        audio_extn_listen_update_status(snd_device,
+                                        LISTEN_EVENT_SND_DEVICE_FREE);
     }
 
     return 0;
@@ -734,9 +740,6 @@
     /* 2. Disable the tx device */
     disable_snd_device(adev, uc_info->in_snd_device, true);
 
-    audio_extn_listen_update_status(uc_info,
-            LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE);
-
     list_remove(&uc_info->list);
     free(uc_info);
 
@@ -781,9 +784,6 @@
     list_add_tail(&adev->usecase_list, &uc_info->list);
     select_devices(adev, in->usecase);
 
-    audio_extn_listen_update_status(uc_info,
-            LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE);
-
     ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
           __func__, SOUND_CARD, in->pcm_device_id, in->config.channels);
     in->pcm = pcm_open(SOUND_CARD, in->pcm_device_id,
@@ -2472,10 +2472,10 @@
     pthread_mutex_lock(&adev_init_lock);
 
     if ((--audio_device_ref_count) == 0) {
+        audio_extn_listen_deinit(adev);
         audio_route_free(adev->audio_route);
         free(adev->snd_dev_ref_cnt);
         platform_deinit(adev->platform);
-        audio_extn_listen_deinit(adev);
         free(device);
         adev = NULL;
     }
@@ -2562,7 +2562,7 @@
                                                         "visualizer_hal_stop_output");
         }
     }
-    audio_extn_listen_init(adev);
+    audio_extn_listen_init(adev, SOUND_CARD);
 
     *device = &adev->device.common;
 
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 43bef81..298c60d 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -903,3 +903,8 @@
     ALOGV("%s: input source :%d", __func__, source);
     return usecase;
 }
+
+bool platform_listen_update_status(snd_device_t snd_device)
+{
+     return false;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 1a53f32..af93782 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1403,3 +1403,14 @@
         usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
     return usecase;
 }
+
+bool platform_listen_update_status(snd_device_t snd_device)
+{
+    if ((snd_device >= SND_DEVICE_IN_BEGIN) &&
+        (snd_device < SND_DEVICE_IN_END) &&
+        (snd_device != SND_DEVICE_IN_CAPTURE_FM) &&
+        (snd_device != SND_DEVICE_IN_CAPTURE_VI_FEEDBACK))
+        return true;
+    else
+        return false;
+}
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 44ad790..a829365 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -52,4 +52,6 @@
 int64_t platform_render_latency(audio_usecase_t usecase);
 int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
 
+bool platform_listen_update_status(snd_device_t snd_device);
+
 #endif // QCOM_AUDIO_PLATFORM_API_H
diff --git a/hal/voice.c b/hal/voice.c
index dc5c417..c6c513a 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -94,9 +94,6 @@
     disable_snd_device(adev, uc_info->out_snd_device, false);
     disable_snd_device(adev, uc_info->in_snd_device, true);
 
-    audio_extn_listen_update_status(uc_info,
-            LISTEN_EVENT_AUDIO_CAPTURE_INACTIVE);
-
     list_remove(&uc_info->list);
     free(uc_info);
 
@@ -127,9 +124,6 @@
 
     select_devices(adev, usecase_id);
 
-    audio_extn_listen_update_status(uc_info,
-            LISTEN_EVENT_AUDIO_CAPTURE_ACTIVE);
-
     pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
     pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);