From 51bd12c20d5b0d4667299e87ba2e9a3317e81828 Mon Sep 17 00:00:00 2001
From: Fevax <fer.vonarx@gmail.com>
Date: Wed, 15 Mar 2017 10:56:39 -0300
Subject: [PATCH] audio: add support for bluetooth wideband voice calls

Change-Id: I02bf23a83c52389cc02ba1f61572eb651418fe24
---
 audio/audio_hw.c                 | 16 +++++++++++-----
 audio/audio_hw.h                 |  3 +++
 audio/mixer_paths_0.xml.template |  8 ++++++++
 audio/voice.c                    | 23 ++++++++++++++++++++---
 4 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 076a469..2f8ce97 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -312,6 +312,7 @@ static const char * const device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_OUT_HDMI] = "hdmi",
     [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
     [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
+    [SND_DEVICE_OUT_BT_SCO_WB] = "bt-sco-headset-wb",
 
     /* Capture sound devices */
     [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
@@ -329,6 +330,7 @@ static const char * const device_table[SND_DEVICE_MAX] = {
     [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
     [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
     [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
+    [SND_DEVICE_IN_BT_SCO_MIC_WB] = "bt-sco-mic-wb",
     [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
     [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
     [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
@@ -531,6 +533,8 @@ static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devic
         if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
             devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
             snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
+        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
+            snd_device = SND_DEVICE_OUT_BT_SCO;
         } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
             snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
         } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -541,6 +545,8 @@ static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devic
             if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
                 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
                 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
+            } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
+                snd_device = SND_DEVICE_OUT_BT_SCO_WB;
             } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
                 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
             } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -548,10 +554,6 @@ static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devic
             }
         }
 
-        if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
-            snd_device = SND_DEVICE_OUT_BT_SCO;
-        }
-
         if (snd_device != SND_DEVICE_NONE) {
             goto exit;
         }
@@ -660,7 +662,11 @@ static snd_device_t get_input_snd_device(struct audio_device *adev, audio_device
             snd_device = SND_DEVICE_IN_VOICE_MIC;
 
             if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
-                snd_device = SND_DEVICE_IN_BT_SCO_MIC;
+                if (voice_session_uses_wideband(adev->voice.session)) {
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC_WB;
+                } else {
+                    snd_device = SND_DEVICE_IN_BT_SCO_MIC;
+                }
             } else if (voice_session_uses_twomic(adev->voice.session)) {
                 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
             }
diff --git a/audio/audio_hw.h b/audio/audio_hw.h
index ca90fef..3bafff2 100644
--- a/audio/audio_hw.h
+++ b/audio/audio_hw.h
@@ -76,6 +76,7 @@ enum {
     SND_DEVICE_OUT_HDMI,
     SND_DEVICE_OUT_SPEAKER_AND_HDMI,
     SND_DEVICE_OUT_BT_SCO,
+    SND_DEVICE_OUT_BT_SCO_WB,
     SND_DEVICE_OUT_END,
 
     /*
@@ -99,6 +100,7 @@ enum {
     SND_DEVICE_IN_VOICE_HEADSET_MIC_WB,
     SND_DEVICE_IN_HDMI_MIC,
     SND_DEVICE_IN_BT_SCO_MIC,
+    SND_DEVICE_IN_BT_SCO_MIC_WB,
     SND_DEVICE_IN_CAMCORDER_MIC,
     SND_DEVICE_IN_VOICE_REC_HEADSET_MIC,
     SND_DEVICE_IN_VOICE_REC_MIC,
@@ -131,6 +133,7 @@ enum {
 #define SCO_PERIOD_COUNT 2
 #define SCO_DEFAULT_CHANNEL_COUNT 2
 #define SCO_DEFAULT_SAMPLING_RATE 8000
+#define SCO_WB_SAMPLING_RATE 16000
 #define SCO_START_THRESHOLD 335
 #define SCO_STOP_THRESHOLD 336
 #define SCO_AVAILABLE_MIN 1
diff --git a/audio/mixer_paths_0.xml.template b/audio/mixer_paths_0.xml.template
index 7753896..4db9540 100644
--- a/audio/mixer_paths_0.xml.template
+++ b/audio/mixer_paths_0.xml.template
@@ -68,6 +68,10 @@
         <!-- Empty path -->
     </path>
 
+    <path name="bt-sco-headset-wb">
+        <!-- Empty path -->
+    </path>
+
     <!-- ########## Capture ########## -->
 
     <path name="earpiece-mic">
@@ -124,6 +128,10 @@
         <!-- Empty path -->
     </path>
 
+    <path name="bt-sco-mic-wb">
+        <!-- Empty path -->
+    </path>
+
     <path name="voice-rec-headset-mic">
         <!-- Empty path -->
     </path>
diff --git a/audio/voice.c b/audio/voice.c
index 824724a..ce981c5 100644
--- a/audio/voice.c
+++ b/audio/voice.c
@@ -62,6 +62,15 @@ struct pcm_config pcm_config_voice_sco = {
     .format = PCM_FORMAT_S16_LE,
 };
 
+/* SCO WB and NB uses 8kHz for now, 16kHz it's on TO DO*/
+struct pcm_config pcm_config_voice_sco_wb = {
+    .channels = 1,
+    .rate = SCO_DEFAULT_SAMPLING_RATE,
+    .period_size = SCO_PERIOD_SIZE,
+    .period_count = SCO_PERIOD_COUNT,
+    .format = PCM_FORMAT_S16_LE,
+};
+
 /* Prototypes */
 int start_voice_call(struct audio_device *adev);
 int stop_voice_call(struct audio_device *adev);
@@ -150,6 +159,8 @@ static void stop_voice_session_bt_sco(struct voice_session *session) {
 /* must be called with the hw device mutex locked, OK to hold other mutexes */
 void start_voice_session_bt_sco(struct voice_session *session)
 {
+    struct pcm_config *voice_sco_config;
+
     if (session->pcm_sco_rx != NULL || session->pcm_sco_tx != NULL) {
         ALOGW("%s: SCO PCMs already open!\n", __func__);
         return;
@@ -157,12 +168,18 @@ void start_voice_session_bt_sco(struct voice_session *session)
 
     ALOGV("%s: Opening SCO PCMs", __func__);
 
-    /* TODO: Add wideband support */
+    if (session->wb_amr_type >= 1) {
+        ALOGV("%s: pcm_config wideband", __func__);
+        voice_sco_config = &pcm_config_voice_sco_wb;
+    } else {
+        ALOGV("%s: pcm_config narrowband", __func__);
+        voice_sco_config = &pcm_config_voice_sco;
+    }
 
     session->pcm_sco_rx = pcm_open(SOUND_CARD,
                                    SOUND_PLAYBACK_SCO_DEVICE,
                                    PCM_OUT|PCM_MONOTONIC,
-                                   &pcm_config_voice_sco);
+                                   voice_sco_config);
     if (session->pcm_sco_rx != NULL && !pcm_is_ready(session->pcm_sco_rx)) {
         ALOGE("%s: cannot open PCM SCO RX stream: %s",
               __func__, pcm_get_error(session->pcm_sco_rx));
@@ -172,7 +189,7 @@ void start_voice_session_bt_sco(struct voice_session *session)
     session->pcm_sco_tx = pcm_open(SOUND_CARD,
                                    SOUND_CAPTURE_SCO_DEVICE,
                                    PCM_IN|PCM_MONOTONIC,
-                                   &pcm_config_voice_sco);
+                                   voice_sco_config);
     if (session->pcm_sco_tx && !pcm_is_ready(session->pcm_sco_tx)) {
         ALOGE("%s: cannot open PCM SCO TX stream: %s",
               __func__, pcm_get_error(session->pcm_sco_tx));
-- 
2.20.1