From 53929f79f9f1efe9ccd32a853ee99ce56003912f Mon Sep 17 00:00:00 2001 From: stenkinevgeniy Date: Mon, 9 Jul 2018 11:20:36 +0000 Subject: [PATCH] Audio: fix voip calls over bluetooth headset. 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 --- audio/audio_hw.c | 55 +++++++++++++++-------------------------------- audio/audio_hw.h | 4 ++++ audio/voice.c | 56 +++++++++++++++++++++--------------------------- audio/voice.h | 6 ++---- 4 files changed, 47 insertions(+), 74 deletions(-) diff --git a/audio/audio_hw.c b/audio/audio_hw.c index 3c7ea6b0..fd9c0b00 100644 --- a/audio/audio_hw.c +++ b/audio/audio_hw.c @@ -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, }; @@ -2675,11 +2652,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) { @@ -2706,17 +2678,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 @@ -2724,7 +2702,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) */ stop_voice_call(adev); start_voice_call(adev); - } } } @@ -4268,6 +4245,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) { diff --git a/audio/audio_hw.h b/audio/audio_hw.h index 871c04fb..7143d555 100644 --- a/audio/audio_hw.h +++ b/audio/audio_hw.h @@ -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; diff --git a/audio/voice.c b/audio/voice.c index a4cc03a2..2219d9a4 100644 --- a/audio/voice.c +++ b/audio/voice.c @@ -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(); diff --git a/audio/voice.h b/audio/voice.h index 01c6aac5..c5cc2f54 100644 --- a/audio/voice.h +++ b/audio/voice.h @@ -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);