Merge changes from topic "enhance_hearing_aid"

* changes:
  audio: use SinkMetaData to route voice call with hearing aid.
  audio: Enhance latency and tuning in voice call with hearing aid
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index ccf922e..24d726f 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1531,7 +1531,8 @@
                                                get_voice_usecase_id_from_list(adev));
             if ((vc_usecase != NULL) &&
                 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
-                (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
+                 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
+                 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
                 in_snd_device = vc_usecase->in_snd_device;
                 out_snd_device = vc_usecase->out_snd_device;
             }
@@ -1577,8 +1578,13 @@
                         out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
                     } else if (voip_usecase) {
                         out_device = voip_usecase->stream.out->devices;
-                    } else if (adev->primary_output) {
+                    } else if (adev->primary_output &&
+                                  !adev->primary_output->standby) {
                         out_device = adev->primary_output->devices;
+                    } else {
+                        /* forcing speaker o/p device to get matching i/p pair
+                           in case o/p is not routed from same primary HAL */
+                        out_device = AUDIO_DEVICE_OUT_SPEAKER;
                     }
                 }
                 in_snd_device = platform_get_input_snd_device(adev->platform,
@@ -2234,14 +2240,19 @@
         }
         ret = 0;
     }
-
+    /* 1) media + voip output routing to handset must route media back to
+          speaker when voip stops.
+       2) trigger voip input to reroute when voip output changes to
+          hearing aid. */
     if (has_voip_usecase ||
             out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
         struct listnode *node;
         struct audio_usecase *usecase;
         list_for_each(node, &adev->usecase_list) {
             usecase = node_to_item(node, struct audio_usecase, list);
-            if (usecase->type == PCM_CAPTURE || usecase == uc_info)
+            if ((usecase->type == PCM_CAPTURE &&
+                     usecase->id != USECASE_AUDIO_RECORD_VOIP)
+                || usecase == uc_info)
                 continue;
 
             ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
@@ -4512,6 +4523,52 @@
     return -ENOSYS;
 }
 
+static void in_update_sink_metadata(struct audio_stream_in *stream,
+                                    const struct sink_metadata *sink_metadata) {
+
+    if (stream == NULL
+            || sink_metadata == NULL
+            || sink_metadata->tracks == NULL) {
+        return;
+    }
+
+    int error = 0;
+    struct stream_in *in = (struct stream_in *)stream;
+    struct audio_device *adev = in->dev;
+    audio_devices_t device = AUDIO_DEVICE_NONE;
+
+    if (sink_metadata->track_count != 0)
+        device = sink_metadata->tracks->dest_device;
+
+    lock_input_stream(in);
+    pthread_mutex_lock(&adev->lock);
+    ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
+
+    if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
+            && device != AUDIO_DEVICE_NONE
+            && adev->voice_tx_output != NULL) {
+        /* Use the rx device from afe-proxy record to route voice call because
+           there is no routing if tx device is on primary hal and rx device
+           is on other hal during voice call. */
+        adev->voice_tx_output->devices = device;
+
+        if (!voice_is_call_state_active(adev)) {
+            if (adev->mode == AUDIO_MODE_IN_CALL) {
+                adev->current_call_output = adev->voice_tx_output;
+                error = voice_start_call(adev);
+                if (error != 0)
+                    ALOGE("%s: start voice call failed %d", __func__, error);
+            }
+        } else {
+            adev->current_call_output = adev->voice_tx_output;
+            voice_update_devices_for_all_voice_usecases(adev);
+        }
+    }
+
+    pthread_mutex_unlock(&adev->lock);
+    pthread_mutex_unlock(&in->lock);
+}
+
 static int adev_open_output_stream(struct audio_hw_device *dev,
                                    audio_io_handle_t handle,
                                    audio_devices_t devices,
@@ -5479,6 +5536,7 @@
     in->stream.get_active_microphones = in_get_active_microphones;
     in->stream.set_microphone_direction = in_set_microphone_direction;
     in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
+    in->stream.update_sink_metadata = in_update_sink_metadata;
 
     in->device = devices;
     in->source = source;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index f547f1c..ecb3db7 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -295,6 +295,7 @@
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = "speaker-safe-and-bt-sco",
     [SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = "speaker-and-bt-sco-wb",
     [SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = "speaker-safe-and-bt-sco-wb",
+    [SND_DEVICE_OUT_VOICE_HEARING_AID] = "hearing-aid",
 
     /* Capture sound devices */
     [SND_DEVICE_IN_HANDSET_MIC] = "handset-mic",
@@ -374,6 +375,7 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = "camcorder-mic",
     [SND_DEVICE_IN_SPEAKER_QMIC_NS] = "quad-mic",
     [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = "quad-mic",
+    [SND_DEVICE_IN_VOICE_HEARING_AID] = "hearing-aid-mic",
 };
 
 static struct audio_effect_config \
@@ -446,6 +448,7 @@
     [SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
     [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
     [SND_DEVICE_OUT_VOICE_SPEAKER_HFP] = ACDB_ID_VOICE_SPEAKER,
+    [SND_DEVICE_OUT_VOICE_HEARING_AID] = 45,
 
     [SND_DEVICE_IN_HANDSET_MIC] = 4,
     [SND_DEVICE_IN_HANDSET_MIC_AEC] = 106,
@@ -523,6 +526,7 @@
     [SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = 61,
     [SND_DEVICE_IN_SPEAKER_QMIC_NS] = 129,
     [SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = 129,
+    [SND_DEVICE_IN_VOICE_HEARING_AID] = 44,
 };
 
 // Platform specific backend bit width table
@@ -581,6 +585,7 @@
     {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
     {TO_NAME_INDEX(SND_DEVICE_OUT_USB_HEADSET_SPEC)},
+    {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEARING_AID)},
 
     /* in */
     {TO_NAME_INDEX(SND_DEVICE_IN_HANDSET_MIC)},
@@ -657,6 +662,8 @@
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE)},
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE)},
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT)},
+    {TO_NAME_INDEX(SND_DEVICE_IN_VOICE_HEARING_AID)},
+
     /* For legacy xml file parsing */
     {TO_NAME_INDEX(SND_DEVICE_IN_CAMCORDER_MIC)},
     {TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_NS)},
@@ -1288,6 +1295,7 @@
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp");
     backend_tag_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP] = strdup("speaker-safe-and-bt-a2dp");
     backend_tag_table[SND_DEVICE_OUT_USB_HEADSET_SPEC] = strdup("usb-headset");
+    backend_tag_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("hearing-aid");
 
     hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX");
@@ -1336,6 +1344,11 @@
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_SCO_WB] = strdup("SLIMBUS_0_RX-and-SEC_AUX_PCM_RX");
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"),
     hw_interface_table[SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_SCO_WB] = strdup("QUAT_TDM_RX_0-and-SLIMBUS_7_RX"),
+    /* So far, primary hal doesn't support hearing aid device.
+       Need snd_device to route voice call and use specific acdb tuning.
+       Also, BT_RX is a virtual port to indicate bluetooth hearing aid. */
+    hw_interface_table[SND_DEVICE_OUT_VOICE_HEARING_AID] = strdup("BT_RX"),
+
     hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
     hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
     hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] =  strdup("USB_AUDIO_TX");
@@ -1403,6 +1416,8 @@
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_LANDSCAPE] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_INVERT_LANDSCAPE] = strdup("SLIMBUS_0_TX");
     hw_interface_table[SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT] = strdup("SLIMBUS_0_TX");
+    hw_interface_table[SND_DEVICE_IN_VOICE_HEARING_AID] = strdup("SLIMBUS_0_TX");
+
     my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
 }
 
@@ -2901,8 +2916,11 @@
                 snd_device = SND_DEVICE_OUT_VOICE_HANDSET_TMUS;
             else
                 snd_device = SND_DEVICE_OUT_VOICE_HANDSET;
-        } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX)
+        } else if (devices & AUDIO_DEVICE_OUT_TELEPHONY_TX) {
             snd_device = SND_DEVICE_OUT_VOICE_TX;
+        } else if (devices & AUDIO_DEVICE_OUT_HEARING_AID) {
+            snd_device = SND_DEVICE_OUT_VOICE_HEARING_AID;
+        }
 
         if (snd_device != SND_DEVICE_NONE) {
             goto exit;
@@ -3194,6 +3212,8 @@
                     snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
                 }
             }
+        } else if (out_device & AUDIO_DEVICE_OUT_HEARING_AID) {
+            snd_device = SND_DEVICE_IN_VOICE_HEARING_AID;
         }
     } else if (source == AUDIO_SOURCE_CAMCORDER) {
         if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 9c07c09..c2beec9 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -106,6 +106,7 @@
     SND_DEVICE_OUT_VOICE_USB_HEADSET,
     /* Specific snd_devices */
     SND_DEVICE_OUT_USB_HEADSET_SPEC,
+    SND_DEVICE_OUT_VOICE_HEARING_AID,
     SND_DEVICE_OUT_END,
 
     /*
@@ -192,6 +193,7 @@
     SND_DEVICE_IN_CAMCORDER_SELFIE_PORTRAIT,
     SND_DEVICE_IN_SPEAKER_QMIC_NS,
     SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS,
+    SND_DEVICE_IN_VOICE_HEARING_AID,
     SND_DEVICE_IN_END,
 
     SND_DEVICE_MAX = SND_DEVICE_IN_END,