Audio: fix voip calls over bluetooth headset.
authorstenkinevgeniy <stenkinevgeniy@gmail.com>
Mon, 9 Jul 2018 11:20:36 +0000 (11:20 +0000)
committerSimon Shields <simon@lineageos.org>
Wed, 25 Jul 2018 07:40:56 +0000 (09:40 +0200)
Current HAL start/stop bt_sco session only for incall mode -
rewrite logic to start/stop bt session when system switch to
one of the bluetooth devices.
Move bt_sco_active and pcm_sco_rx/tx to main audio_device structure.
Remove bt_sco_capture profile.

Change-Id: I7bbe4273f759e255bb857f8292f2921df31d4b0b
Signed-off-by: stenkinevgeniy <stenkinevgeniy@gmail.com>
audio/audio_hw.c
audio/audio_hw.h
audio/voice.c
audio/voice.h

index 395cb343fccfe3cd3d755925c1afa1d27c762a50..d28dc307755710e4eb0782710fd0b5781d415336 100644 (file)
@@ -72,9 +72,7 @@ static struct pcm_device_profile pcm_device_playback = {
     .id = SOUND_PLAYBACK_DEVICE,
     .type = PCM_PLAYBACK,
     .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
-               AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|
-               AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
-               AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
+               AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
 };
 
 static struct pcm_device_profile pcm_device_deep_buffer = {
@@ -92,9 +90,7 @@ static struct pcm_device_profile pcm_device_deep_buffer = {
     .id = SOUND_DEEP_BUFFER_DEVICE,
     .type = PCM_PLAYBACK,
     .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
-               AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|
-               AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
-               AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
+               AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
 };
 
 static struct pcm_device_profile pcm_device_capture = {
@@ -112,7 +108,7 @@ static struct pcm_device_profile pcm_device_capture = {
     .card = SOUND_CARD,
     .id = SOUND_CAPTURE_DEVICE,
     .type = PCM_CAPTURE,
-    .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
+    .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
 };
 
 static struct pcm_device_profile pcm_device_capture_low_latency = {
@@ -130,32 +126,13 @@ static struct pcm_device_profile pcm_device_capture_low_latency = {
     .card = SOUND_CARD,
     .id = SOUND_CAPTURE_DEVICE,
     .type = PCM_CAPTURE_LOW_LATENCY,
-    .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
-};
-
-static struct pcm_device_profile pcm_device_capture_sco = {
-    .config = {
-        .channels = SCO_DEFAULT_CHANNEL_COUNT,
-        .rate = SCO_DEFAULT_SAMPLING_RATE,
-        .period_size = SCO_PERIOD_SIZE,
-        .period_count = SCO_PERIOD_COUNT,
-        .format = PCM_FORMAT_S16_LE,
-        .start_threshold = CAPTURE_START_THRESHOLD,
-        .stop_threshold = 0,
-        .silence_threshold = 0,
-        .avail_min = 0,
-    },
-    .card = SOUND_CARD,
-    .id = SOUND_CAPTURE_SCO_DEVICE,
-    .type = PCM_CAPTURE,
-    .devices = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
+    .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
 };
 
 static struct pcm_device_profile * const pcm_devices[] = {
     &pcm_device_playback,
     &pcm_device_capture,
     &pcm_device_capture_low_latency,
-    &pcm_device_capture_sco,
     NULL,
 };
 
@@ -2669,11 +2646,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
         }
 #endif
         if (val != SND_DEVICE_NONE) {
-            bool bt_sco_active = false;
-
-            if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
-                bt_sco_active = true;
-            }
             out->devices = val;
 
             if (!out->standby) {
@@ -2700,17 +2672,23 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
                 }
             }
 
+            /* Turn on bluetooth sco if needed */
+            if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION || adev->mode == AUDIO_MODE_IN_CALL) &&
+                (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !adev->bt_sco_active) {
+                adev->bt_sco_active = true;
+                start_voice_session_bt_sco(adev);
+            }
+            else if (!(out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && adev->bt_sco_active) {
+                adev->bt_sco_active = false;
+                stop_voice_session_bt_sco(adev);
+            }
+
             if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
                     (out == adev->primary_output)) {
                 start_voice_call(adev);
             } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
                        adev->voice.in_call &&
                        (out == adev->primary_output)) {
-                /* Turn on bluetooth if needed */
-                if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
-                    select_devices(adev, USECASE_VOICE_CALL);
-                    start_voice_session_bt_sco(adev->voice.session);
-                } else {
                     /*
                      * When we select different devices we need to restart the
                      * voice call. The modem closes the stream on its end and
@@ -2718,7 +2696,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
                      */
                     stop_voice_call(adev);
                     start_voice_call(adev);
-                }
             }
         }
 
@@ -4262,6 +4239,8 @@ static int adev_open(const hw_module_t *module, const char *name,
     adev->voice.in_call = false;
     adev->voice.bluetooth_wb = false;
 
+    adev->bt_sco_active = false;
+
     /* adev->cur_hdmi_channels = 0;  by calloc() */
     adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
     if (adev->snd_dev_ref_cnt == NULL) {
index 871c04fbea24703fe7b543603ab9a719656bfe19..7143d555b77a5df68932a6eb9cce4629569869a0 100644 (file)
@@ -381,6 +381,10 @@ struct audio_device {
     bool                    mic_mute;
     bool                    screen_off;
 
+    bool                    bt_sco_active;
+    struct pcm              *pcm_sco_rx;
+    struct pcm              *pcm_sco_tx;
+
     struct voice_data       voice;
 
     int*                    snd_dev_ref_cnt;
index a4cc03a2e77ac5cfed165c49cc5b513fcefee9d3..2219d9a4ef892bb554687563067aef51782e4204 100644 (file)
@@ -139,35 +139,35 @@ void prepare_voice_session(struct voice_session *session,
  * This must be called with the hw device mutex locked, OK to hold other
  * mutexes.
  */
-static void stop_voice_session_bt_sco(struct voice_session *session) {
+void stop_voice_session_bt_sco(struct audio_device *adev) {
     ALOGV("%s: Closing SCO PCMs", __func__);
 
-    if (session->pcm_sco_rx != NULL) {
-        pcm_stop(session->pcm_sco_rx);
-        pcm_close(session->pcm_sco_rx);
-        session->pcm_sco_rx = NULL;
+    if (adev->pcm_sco_rx != NULL) {
+        pcm_stop(adev->pcm_sco_rx);
+        pcm_close(adev->pcm_sco_rx);
+        adev->pcm_sco_rx = NULL;
     }
 
-    if (session->pcm_sco_tx != NULL) {
-        pcm_stop(session->pcm_sco_tx);
-        pcm_close(session->pcm_sco_tx);
-        session->pcm_sco_tx = NULL;
+    if (adev->pcm_sco_tx != NULL) {
+        pcm_stop(adev->pcm_sco_tx);
+        pcm_close(adev->pcm_sco_tx);
+        adev->pcm_sco_tx = NULL;
     }
 }
 
 /* must be called with the hw device mutex locked, OK to hold other mutexes */
-void start_voice_session_bt_sco(struct voice_session *session)
+void start_voice_session_bt_sco(struct audio_device *adev)
 {
     struct pcm_config *voice_sco_config;
 
-    if (session->pcm_sco_rx != NULL || session->pcm_sco_tx != NULL) {
+    if (adev->pcm_sco_rx != NULL || adev->pcm_sco_tx != NULL) {
         ALOGW("%s: SCO PCMs already open!\n", __func__);
         return;
     }
 
     ALOGV("%s: Opening SCO PCMs", __func__);
 
-    if (session->vdata->bluetooth_wb) {
+    if (adev->voice.bluetooth_wb) {
         ALOGV("%s: pcm_config wideband", __func__);
         voice_sco_config = &pcm_config_voice_sco_wb;
     } else {
@@ -175,37 +175,37 @@ void start_voice_session_bt_sco(struct voice_session *session)
         voice_sco_config = &pcm_config_voice_sco;
     }
 
-    session->pcm_sco_rx = pcm_open(SOUND_CARD,
+    adev->pcm_sco_rx = pcm_open(SOUND_CARD,
                                    SOUND_PLAYBACK_SCO_DEVICE,
                                    PCM_OUT|PCM_MONOTONIC,
                                    voice_sco_config);
-    if (session->pcm_sco_rx != NULL && !pcm_is_ready(session->pcm_sco_rx)) {
+    if (adev->pcm_sco_rx != NULL && !pcm_is_ready(adev->pcm_sco_rx)) {
         ALOGE("%s: cannot open PCM SCO RX stream: %s",
-              __func__, pcm_get_error(session->pcm_sco_rx));
+              __func__, pcm_get_error(adev->pcm_sco_rx));
         goto err_sco_rx;
     }
 
-    session->pcm_sco_tx = pcm_open(SOUND_CARD,
+    adev->pcm_sco_tx = pcm_open(SOUND_CARD,
                                    SOUND_CAPTURE_SCO_DEVICE,
                                    PCM_IN|PCM_MONOTONIC,
                                    voice_sco_config);
-    if (session->pcm_sco_tx && !pcm_is_ready(session->pcm_sco_tx)) {
+    if (adev->pcm_sco_tx && !pcm_is_ready(adev->pcm_sco_tx)) {
         ALOGE("%s: cannot open PCM SCO TX stream: %s",
-              __func__, pcm_get_error(session->pcm_sco_tx));
+              __func__, pcm_get_error(adev->pcm_sco_tx));
         goto err_sco_tx;
     }
 
-    pcm_start(session->pcm_sco_rx);
-    pcm_start(session->pcm_sco_tx);
+    pcm_start(adev->pcm_sco_rx);
+    pcm_start(adev->pcm_sco_tx);
 
     return;
 
 err_sco_tx:
-    pcm_close(session->pcm_sco_tx);
-    session->pcm_sco_tx = NULL;
+    pcm_close(adev->pcm_sco_tx);
+    adev->pcm_sco_tx = NULL;
 err_sco_rx:
-    pcm_close(session->pcm_sco_rx);
-    session->pcm_sco_rx = NULL;
+    pcm_close(adev->pcm_sco_rx);
+    adev->pcm_sco_rx = NULL;
 }
 /*
  * This function must be called with hw device mutex locked, OK to hold other
@@ -265,10 +265,6 @@ int start_voice_session(struct voice_session *session)
     pcm_start(session->pcm_voice_rx);
     pcm_start(session->pcm_voice_tx);
 
-    if (session->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
-        start_voice_session_bt_sco(session);
-    }
-
 #ifdef AUDIENCE_EARSMART_IC
     ALOGV("%s: Enabling Audience IC", __func__);
     es_start_voice_session(session);
@@ -311,10 +307,6 @@ void stop_voice_session(struct voice_session *session)
         status++;
     }
 
-    if (session->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
-        stop_voice_session_bt_sco(session);
-    }
-
 #ifdef AUDIENCE_EARSMART_IC
     ALOGV("%s: Disabling Audience IC", __func__);
     es_stop_voice_session();
index 01c6aac5714d23f3df9a70d3ac11b1d0d1d214be..c5cc2f5469f8d9d9b284679c3bc967676e018b9a 100644 (file)
@@ -25,9 +25,6 @@ struct voice_session {
     struct pcm *pcm_voice_rx;
     struct pcm *pcm_voice_tx;
 
-    struct pcm *pcm_sco_rx;
-    struct pcm *pcm_sco_tx;
-
     int wb_amr_type;
     bool two_mic_control;
     bool two_mic_disabled;
@@ -47,7 +44,8 @@ void set_voice_session_volume(struct voice_session *session, float volume);
 void set_voice_session_audio_path(struct voice_session *session);
 void set_voice_session_mic_mute(struct voice_session *session, bool state);
 
-void start_voice_session_bt_sco(struct voice_session *session);
+void start_voice_session_bt_sco(struct audio_device *adev);
+void stop_voice_session_bt_sco(struct audio_device *adev);
 
 bool voice_session_uses_twomic(struct voice_session *session);
 bool voice_session_uses_wideband(struct voice_session *session);