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,
.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) {

@ -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;

@ -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();

@ -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);

Loading…
Cancel
Save