Merge "audio: enable waves effect on usb headset"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7661e58..5af3897 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1286,6 +1286,44 @@
     return false;
 }
 
+struct stream_in *adev_get_active_input(const struct audio_device *adev)
+{
+    struct listnode *node;
+    struct stream_in *last_active_in = NULL;
+
+    /* Get last added active input.
+     * TODO: We may use a priority mechanism to pick highest priority active source */
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
+            last_active_in =  usecase->stream.in;
+        }
+    }
+
+    return last_active_in;
+}
+
+struct stream_in *get_voice_communication_input(const struct audio_device *adev)
+{
+    struct listnode *node;
+
+    /* First check active inputs with voice communication source and then
+     * any input if audio mode is in communication */
+    list_for_each(node, &adev->usecase_list)
+    {
+        struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
+        if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
+            usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+            return usecase->stream.in;
+        }
+    }
+    if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+        return adev_get_active_input(adev);
+    }
+    return NULL;
+}
+
 int select_devices(struct audio_device *adev,
                    audio_usecase_t uc_id)
 {
@@ -1310,7 +1348,9 @@
         (usecase->type == PCM_HFP_CALL)) {
         out_snd_device = platform_get_output_snd_device(adev->platform,
                                                         usecase->stream.out->devices);
-        in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
+        in_snd_device = platform_get_input_snd_device(adev->platform,
+                                                      NULL,
+                                                      usecase->stream.out->devices);
         usecase->devices = usecase->stream.out->devices;
     } else {
         /*
@@ -1342,6 +1382,7 @@
             in_snd_device = SND_DEVICE_NONE;
             if (out_snd_device == SND_DEVICE_NONE) {
                 struct stream_out *voip_out = adev->primary_output;
+                struct stream_in *voip_in = get_voice_communication_input(adev);
 
                 out_snd_device = platform_get_output_snd_device(adev->platform,
                                             usecase->stream.out->devices);
@@ -1349,11 +1390,8 @@
                 if (voip_usecase)
                     voip_out = voip_usecase->stream.out;
 
-                if (usecase->stream.out == voip_out &&
-                        adev->active_input &&
-                        (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
-                            adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
-                    select_devices(adev, adev->active_input->usecase);
+                if (usecase->stream.out == voip_out && voip_in != NULL) {
+                    select_devices(adev, voip_in->usecase);
                 }
             }
         } else if (usecase->type == PCM_CAPTURE) {
@@ -1361,9 +1399,9 @@
             out_snd_device = SND_DEVICE_NONE;
             if (in_snd_device == SND_DEVICE_NONE) {
                 audio_devices_t out_device = AUDIO_DEVICE_NONE;
-                if (adev->active_input &&
-                        (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
-                            adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
+                struct stream_in *voip_in = get_voice_communication_input(adev);
+
+                if (voip_in != NULL) {
 
                     struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
                                                              USECASE_AUDIO_PLAYBACK_VOIP);
@@ -1377,7 +1415,9 @@
                         out_device = adev->primary_output->devices;
                     }
                 }
-                in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
+                in_snd_device = platform_get_input_snd_device(adev->platform,
+                                                              usecase->stream.in,
+                                                              out_device);
             }
         }
     }
@@ -1534,17 +1574,6 @@
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
           in->usecase, use_case_table[in->usecase]);
 
-    if (adev->active_input) {
-        if (adev->active_input->usecase == in->usecase) {
-            adev->active_input = NULL;
-        } else {
-            ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
-                __func__,
-                use_case_table[adev->active_input->usecase],
-                use_case_table[in->usecase]);
-        }
-    }
-
     uc_info = get_usecase_from_list(adev, in->usecase);
     if (uc_info == NULL) {
         ALOGE("%s: Could not find the usecase (%d) in the list",
@@ -1602,7 +1631,6 @@
         goto error_config;
     }
 
-    adev->active_input = in;
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
     uc_info->id = in->usecase;
     uc_info->type = PCM_CAPTURE;
@@ -1692,7 +1720,6 @@
     audio_extn_perf_lock_release();
 
 error_config:
-    adev->active_input = NULL;
     ALOGW("%s: exit: status(%d)", __func__, ret);
     return ret;
 }
@@ -5429,13 +5456,10 @@
             uc_info.id = audio_usecase;
             uc_info.type = usecase_type;
             if (dir) {
-                adev->active_input = ∈
                 memset(&in, 0, sizeof(in));
                 in.device = audio_device;
                 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                 uc_info.stream.in = ∈
-            }  else {
-                adev->active_input = NULL;
             }
             memset(&out, 0, sizeof(out));
             out.devices = audio_device; /* only field needed in select_devices */
@@ -5469,7 +5493,6 @@
             list_remove(&uc_info.list);
         }
     }
-    adev->active_input = NULL; /* restore adev state */
     return 0;
 }
 
@@ -5674,7 +5697,6 @@
     /* Set the default route before the PCM stream is opened */
     pthread_mutex_lock(&adev->lock);
     adev->mode = AUDIO_MODE_NORMAL;
-    adev->active_input = NULL;
     adev->primary_output = NULL;
     adev->bluetooth_nrec = true;
     adev->acdb_settings = TTY_MODE_OFF;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 447f8ca..cc24c45 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -340,7 +340,6 @@
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
     struct mixer *mixer;
     audio_mode_t mode;
-    struct stream_in *active_input;
     struct stream_out *primary_output;
     struct stream_out *voice_tx_output;
     struct stream_out *current_call_output;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 2707c89..56220e1 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1798,10 +1798,6 @@
     audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
 
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
-    int channel_count = popcount(channel_mask);
-
     ALOGV("%s: enter: output devices(%#x)", __func__, devices);
     if (devices == AUDIO_DEVICE_NONE ||
         devices & AUDIO_DEVICE_BIT_IN) {
@@ -1934,21 +1930,24 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
-    int channel_count = popcount(channel_mask);
+
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+    int channel_count = audio_channel_count_from_in_mask(channel_mask);
 
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
@@ -2043,7 +2042,7 @@
             if (channel_count == 2) {
                 snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_STEREO;
                 adev->acdb_settings |= DMIC_FLAG;
-            } else if (adev->active_input->enable_ns)
+            } else if (in->enable_ns)
                 snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
             else if (my_data->fluence_type != FLUENCE_NONE &&
                      my_data->fluence_in_voice_rec) {
@@ -2057,10 +2056,10 @@
               (mode == AUDIO_MODE_IN_COMMUNICATION)) {
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
-        if (adev->active_input) {
+        if (in) {
             if (my_data->fluence_type != FLUENCE_NONE &&
-                adev->active_input->enable_aec &&
-                adev->active_input->enable_ns) {
+                in->enable_aec &&
+                in->enable_ns) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode) {
                         if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
@@ -2085,7 +2084,7 @@
                 }
                 platform_set_echo_reference(adev, true, out_device);
             } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_aec) {
+                       in->enable_aec) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode) {
                         if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
@@ -2110,7 +2109,7 @@
                 }
                 platform_set_echo_reference(adev, true, out_device);
             } else if (my_data->fluence_type != FLUENCE_NONE &&
-                       adev->active_input->enable_ns) {
+                       in->enable_ns) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode) {
                         if (my_data->fluence_type & FLUENCE_QUAD_MIC) {
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index bd8c41c..be2b95e 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -729,21 +729,24 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
 
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+
     ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
           __func__, out_device, in_device);
     if ((out_device != AUDIO_DEVICE_NONE) && voice_is_in_call(adev)) {
@@ -827,8 +830,8 @@
             mode == AUDIO_MODE_IN_COMMUNICATION) {
         if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
-        if (adev->active_input) {
-            if (adev->active_input->enable_aec) {
+        if (in) {
+            if (in != NULL && in->enable_aec) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
                 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 6991a12..481b57d 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -915,7 +915,9 @@
 
         if (cal.dev_id) {
             if (audio_is_input_device(cal.dev_id)) {
-                cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
+                // FIXME: why pass an input device whereas
+                // platform_get_input_snd_device() expects as an output device?
+                cal.snd_dev_id = platform_get_input_snd_device(platform, NULL, cal.dev_id);
             } else {
                 cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
             }
@@ -2863,24 +2865,28 @@
     return snd_device;
 }
 
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device)
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device)
 {
     struct platform_data *my_data = (struct platform_data *)platform;
     struct audio_device *adev = my_data->adev;
-    audio_source_t  source = (adev->active_input == NULL) ?
-                                AUDIO_SOURCE_DEFAULT : adev->active_input->source;
-
-    audio_mode_t    mode   = adev->mode;
-    audio_devices_t in_device = ((adev->active_input == NULL) ?
-                                    AUDIO_DEVICE_NONE : adev->active_input->device)
-                                & ~AUDIO_DEVICE_BIT_IN;
-    audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
-                                AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
+    audio_mode_t mode = adev->mode;
     snd_device_t snd_device = SND_DEVICE_NONE;
-    int channel_count = popcount(channel_mask);
+
+    if (in == NULL) {
+        in = adev_get_active_input(adev);
+    }
+
+    audio_source_t source = (in == NULL) ? AUDIO_SOURCE_DEFAULT : in->source;
+    audio_devices_t in_device =
+        ((in == NULL) ? AUDIO_DEVICE_NONE : in->device) & ~AUDIO_DEVICE_BIT_IN;
+    audio_channel_mask_t channel_mask = (in == NULL) ? AUDIO_CHANNEL_IN_MONO : in->channel_mask;
+    int channel_count = audio_channel_count_from_in_mask(channel_mask);
 
     ALOGV("%s: enter: out_device(%#x) in_device(%#x) channel_count (%d) channel_mask (0x%x)",
           __func__, out_device, in_device, channel_count, channel_mask);
+
     if ((out_device != AUDIO_DEVICE_NONE) && (voice_is_in_call(adev) ||
         audio_extn_hfp_is_active(adev))) {
         if (adev->voice.tty_mode != TTY_MODE_OFF) {
@@ -3009,20 +3015,20 @@
             if (my_data->fluence_in_voice_rec && channel_count == 1) {
                 if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
                     (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_QMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_HANDSET_QMIC;
                 } else if ((my_data->fluence_type == FLUENCE_PRO_ENABLE) &&
                     (my_data->source_mic_type & SOURCE_THREE_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_TMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_HANDSET_TMIC;
                 } else if (((my_data->fluence_type == FLUENCE_PRO_ENABLE) ||
                     (my_data->fluence_type == FLUENCE_ENABLE)) &&
                     (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
-                    if (adev->active_input->enable_aec)
+                    if (in->enable_aec)
                         snd_device = SND_DEVICE_IN_HANDSET_DMIC_AEC;
                     else
                         snd_device = SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE;
@@ -3039,14 +3045,14 @@
                 snd_device = SND_DEVICE_IN_QUAD_MIC;
             }
             if (snd_device == SND_DEVICE_NONE) {
-                if (adev->active_input->enable_aec) {
-                    if (adev->active_input->enable_ns) {
+                if (in->enable_aec) {
+                    if (in->enable_ns) {
                         snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC_NS;
                     } else {
                         snd_device = SND_DEVICE_IN_VOICE_REC_MIC_AEC;
                     }
                     platform_set_echo_reference(adev, true, out_device);
-                } else if (adev->active_input->enable_ns) {
+                } else if (in->enable_ns) {
                     snd_device = SND_DEVICE_IN_VOICE_REC_MIC_NS;
                 } else {
                     snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
@@ -3085,9 +3091,9 @@
                 !audio_extn_usb_is_capture_supported())) {
             in_device = AUDIO_DEVICE_IN_BACK_MIC;
         }
-        if (adev->active_input) {
-            if (adev->active_input->enable_aec &&
-                    adev->active_input->enable_ns) {
+        if (in) {
+            if (in->enable_aec &&
+                    in->enable_ns) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode &&
                             my_data->fluence_in_voice_comm &&
@@ -3109,7 +3115,7 @@
                     snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
                 }
                 platform_set_echo_reference(adev, true, out_device);
-            } else if (adev->active_input->enable_aec) {
+            } else if (in->enable_aec) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode &&
                             my_data->fluence_in_voice_comm &&
@@ -3131,7 +3137,7 @@
                    snd_device = SND_DEVICE_IN_USB_HEADSET_MIC_AEC;
                }
                platform_set_echo_reference(adev, true, out_device);
-            } else if (adev->active_input->enable_ns) {
+            } else if (in->enable_ns) {
                 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                     if (my_data->fluence_in_spkr_mode &&
                             my_data->fluence_in_voice_comm &&
@@ -4748,7 +4754,7 @@
     size_t actual_mic_count = 0;
 
     snd_device_t active_input_snd_device =
-            platform_get_input_snd_device(platform, usecase->stream.in->device);
+            platform_get_input_snd_device(platform, usecase->stream.in, AUDIO_DEVICE_NONE);
     if (active_input_snd_device == SND_DEVICE_NONE) {
         ALOGI("%s: No active microphones found", __func__);
         goto end;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 8e249da..3cd2b8d 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -82,7 +82,9 @@
 int platform_get_sample_rate(void *platform, uint32_t *rate);
 int platform_set_device_mute(void *platform, bool state, char *dir);
 snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
-snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
+snd_device_t platform_get_input_snd_device(void *platform,
+                                           struct stream_in *in,
+                                           audio_devices_t out_device);
 int platform_set_hdmi_channels(void *platform, int channel_count);
 int platform_edid_get_max_channels(void *platform);
 void platform_add_operator_specific_device(snd_device_t snd_device,
@@ -182,4 +184,8 @@
 int platform_get_usb_service_interval(void *platform,
                                       bool playback,
                                       unsigned long *service_interval);
+
+/* callback functions from platform to common audio HAL */
+struct stream_in *adev_get_active_input(const struct audio_device *adev);
+
 #endif // AUDIO_PLATFORM_API_H