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 <stenkinevgeniy@gmail.com>
tirimbino
stenkinevgeniy 7 years ago committed by Jan Altensen
parent 282d59245e
commit 53929f79f9
No known key found for this signature in database
GPG Key ID: 3E45BB95F7AD33DA
  1. 55
      audio/audio_hw.c
  2. 4
      audio/audio_hw.h
  3. 56
      audio/voice.c
  4. 6
      audio/voice.h

@ -72,9 +72,7 @@ static struct pcm_device_profile pcm_device_playback = {
.id = SOUND_PLAYBACK_DEVICE, .id = SOUND_PLAYBACK_DEVICE,
.type = PCM_PLAYBACK, .type = PCM_PLAYBACK,
.devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE| .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE| AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
}; };
static struct pcm_device_profile pcm_device_deep_buffer = { 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, .id = SOUND_DEEP_BUFFER_DEVICE,
.type = PCM_PLAYBACK, .type = PCM_PLAYBACK,
.devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE| .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE| AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
}; };
static struct pcm_device_profile pcm_device_capture = { static struct pcm_device_profile pcm_device_capture = {
@ -112,7 +108,7 @@ static struct pcm_device_profile pcm_device_capture = {
.card = SOUND_CARD, .card = SOUND_CARD,
.id = SOUND_CAPTURE_DEVICE, .id = SOUND_CAPTURE_DEVICE,
.type = PCM_CAPTURE, .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 = { 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, .card = SOUND_CARD,
.id = SOUND_CAPTURE_DEVICE, .id = SOUND_CAPTURE_DEVICE,
.type = PCM_CAPTURE_LOW_LATENCY, .type = PCM_CAPTURE_LOW_LATENCY,
.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_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,
}; };
static struct pcm_device_profile * const pcm_devices[] = { static struct pcm_device_profile * const pcm_devices[] = {
&pcm_device_playback, &pcm_device_playback,
&pcm_device_capture, &pcm_device_capture,
&pcm_device_capture_low_latency, &pcm_device_capture_low_latency,
&pcm_device_capture_sco,
NULL, NULL,
}; };
@ -2675,11 +2652,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
} }
#endif #endif
if (val != SND_DEVICE_NONE) { 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; out->devices = val;
if (!out->standby) { 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 && if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
(out == adev->primary_output)) { (out == adev->primary_output)) {
start_voice_call(adev); start_voice_call(adev);
} else if ((adev->mode == AUDIO_MODE_IN_CALL) && } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
adev->voice.in_call && adev->voice.in_call &&
(out == adev->primary_output)) { (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 * When we select different devices we need to restart the
* voice call. The modem closes the stream on its end and * 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); stop_voice_call(adev);
start_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.in_call = false;
adev->voice.bluetooth_wb = false; adev->voice.bluetooth_wb = false;
adev->bt_sco_active = false;
/* adev->cur_hdmi_channels = 0; by calloc() */ /* adev->cur_hdmi_channels = 0; by calloc() */
adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int)); adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
if (adev->snd_dev_ref_cnt == NULL) { if (adev->snd_dev_ref_cnt == NULL) {

@ -381,6 +381,10 @@ struct audio_device {
bool mic_mute; bool mic_mute;
bool screen_off; bool screen_off;
bool bt_sco_active;
struct pcm *pcm_sco_rx;
struct pcm *pcm_sco_tx;
struct voice_data voice; struct voice_data voice;
int* snd_dev_ref_cnt; int* snd_dev_ref_cnt;

@ -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 * This must be called with the hw device mutex locked, OK to hold other
* mutexes. * 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__); ALOGV("%s: Closing SCO PCMs", __func__);
if (session->pcm_sco_rx != NULL) { if (adev->pcm_sco_rx != NULL) {
pcm_stop(session->pcm_sco_rx); pcm_stop(adev->pcm_sco_rx);
pcm_close(session->pcm_sco_rx); pcm_close(adev->pcm_sco_rx);
session->pcm_sco_rx = NULL; adev->pcm_sco_rx = NULL;
} }
if (session->pcm_sco_tx != NULL) { if (adev->pcm_sco_tx != NULL) {
pcm_stop(session->pcm_sco_tx); pcm_stop(adev->pcm_sco_tx);
pcm_close(session->pcm_sco_tx); pcm_close(adev->pcm_sco_tx);
session->pcm_sco_tx = NULL; adev->pcm_sco_tx = NULL;
} }
} }
/* must be called with the hw device mutex locked, OK to hold other mutexes */ /* 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; 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__); ALOGW("%s: SCO PCMs already open!\n", __func__);
return; return;
} }
ALOGV("%s: Opening SCO PCMs", __func__); ALOGV("%s: Opening SCO PCMs", __func__);
if (session->vdata->bluetooth_wb) { if (adev->voice.bluetooth_wb) {
ALOGV("%s: pcm_config wideband", __func__); ALOGV("%s: pcm_config wideband", __func__);
voice_sco_config = &pcm_config_voice_sco_wb; voice_sco_config = &pcm_config_voice_sco_wb;
} else { } else {
@ -175,37 +175,37 @@ void start_voice_session_bt_sco(struct voice_session *session)
voice_sco_config = &pcm_config_voice_sco; 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, SOUND_PLAYBACK_SCO_DEVICE,
PCM_OUT|PCM_MONOTONIC, PCM_OUT|PCM_MONOTONIC,
voice_sco_config); 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", 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; goto err_sco_rx;
} }
session->pcm_sco_tx = pcm_open(SOUND_CARD, adev->pcm_sco_tx = pcm_open(SOUND_CARD,
SOUND_CAPTURE_SCO_DEVICE, SOUND_CAPTURE_SCO_DEVICE,
PCM_IN|PCM_MONOTONIC, PCM_IN|PCM_MONOTONIC,
voice_sco_config); 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", 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; goto err_sco_tx;
} }
pcm_start(session->pcm_sco_rx); pcm_start(adev->pcm_sco_rx);
pcm_start(session->pcm_sco_tx); pcm_start(adev->pcm_sco_tx);
return; return;
err_sco_tx: err_sco_tx:
pcm_close(session->pcm_sco_tx); pcm_close(adev->pcm_sco_tx);
session->pcm_sco_tx = NULL; adev->pcm_sco_tx = NULL;
err_sco_rx: err_sco_rx:
pcm_close(session->pcm_sco_rx); pcm_close(adev->pcm_sco_rx);
session->pcm_sco_rx = NULL; adev->pcm_sco_rx = NULL;
} }
/* /*
* This function must be called with hw device mutex locked, OK to hold other * 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_rx);
pcm_start(session->pcm_voice_tx); 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 #ifdef AUDIENCE_EARSMART_IC
ALOGV("%s: Enabling Audience IC", __func__); ALOGV("%s: Enabling Audience IC", __func__);
es_start_voice_session(session); es_start_voice_session(session);
@ -311,10 +307,6 @@ void stop_voice_session(struct voice_session *session)
status++; status++;
} }
if (session->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
stop_voice_session_bt_sco(session);
}
#ifdef AUDIENCE_EARSMART_IC #ifdef AUDIENCE_EARSMART_IC
ALOGV("%s: Disabling Audience IC", __func__); ALOGV("%s: Disabling Audience IC", __func__);
es_stop_voice_session(); es_stop_voice_session();

@ -25,9 +25,6 @@ struct voice_session {
struct pcm *pcm_voice_rx; struct pcm *pcm_voice_rx;
struct pcm *pcm_voice_tx; struct pcm *pcm_voice_tx;
struct pcm *pcm_sco_rx;
struct pcm *pcm_sco_tx;
int wb_amr_type; int wb_amr_type;
bool two_mic_control; bool two_mic_control;
bool two_mic_disabled; 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_audio_path(struct voice_session *session);
void set_voice_session_mic_mute(struct voice_session *session, bool state); 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_twomic(struct voice_session *session);
bool voice_session_uses_wideband(struct voice_session *session); bool voice_session_uses_wideband(struct voice_session *session);

Loading…
Cancel
Save