audio: Add support for bluetooth voice calls

Change-Id: Ic63b7c09ed7401ab72824a406db333e3fbce780b
tirimbino
Andreas Schneider 8 years ago committed by Christopher N. Hesse
parent 1983165ec8
commit 05bc1882e2
  1. 40
      audio/audio_hw.c
  2. 1
      audio/audio_hw.h
  3. 81
      audio/voice.c
  4. 5
      audio/voice.h

@ -634,8 +634,6 @@ 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_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
} else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
snd_device = SND_DEVICE_IN_BT_SCO_MIC;
}
if (voice_session_uses_twomic(adev->voice.session)) {
@ -661,6 +659,17 @@ static snd_device_t get_input_snd_device(struct audio_device *adev, audio_device
}
}
}
/* BT SCO */
if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
snd_device = SND_DEVICE_IN_VOICE_MIC;
if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
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;
}
}
} else if (source == AUDIO_SOURCE_CAMCORDER) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
in_device & AUDIO_DEVICE_IN_BACK_MIC) {
@ -2726,6 +2735,11 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
}
#endif
if (val != 0) {
bool bt_sco_active = false;
if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
bt_sco_active = true;
}
out->devices = val;
if (!out->standby) {
@ -2758,6 +2772,10 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
} 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) {
start_voice_session_bt_sco(adev->voice.session);
}
select_devices(adev, USECASE_VOICE_CALL);
}
}
@ -3933,6 +3951,9 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
parms = str_parms_create_str(kvpairs);
/******************************************************
*** BT SCO
******************************************************/
ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
if (ret >= 0) {
/* When set to false, HAL should disable EC and NS
@ -3944,6 +3965,21 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
adev->voice.bluetooth_nrec = false;
}
ret = str_parms_get_str(parms,
AUDIO_PARAMETER_KEY_BT_SCO_WB,
value,
sizeof(value));
if (ret >= 0) {
/* TODO: Add support in voice calls */
if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
adev->voice.bluetooth_wb = true;
ALOGI("%s: Implement support for BT SCO wideband calls!!!",
__func__);
} else {
adev->voice.bluetooth_wb = false;
}
}
ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
if (ret >= 0) {
if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)

@ -381,6 +381,7 @@ struct voice_data {
bool in_call;
float volume;
bool bluetooth_nrec;
bool bluetooth_wb;
void *session;
};

@ -50,6 +50,14 @@ static struct pcm_config pcm_config_voicecall_wideband = {
.format = PCM_FORMAT_S16_LE,
};
struct pcm_config pcm_config_voice_sco = {
.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);
@ -113,6 +121,70 @@ 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) {
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 (session->pcm_sco_tx != NULL) {
pcm_stop(session->pcm_sco_tx);
pcm_close(session->pcm_sco_tx);
session->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)
{
if (session->pcm_sco_rx != NULL || session->pcm_sco_tx != NULL) {
ALOGW("%s: SCO PCMs already open!\n", __func__);
return;
}
ALOGV("%s: Opening SCO PCMs", __func__);
/* TODO: Add wideband support */
session->pcm_sco_rx = pcm_open(SOUND_CARD,
SOUND_PLAYBACK_SCO_DEVICE,
PCM_OUT|PCM_MONOTONIC,
&pcm_config_voice_sco);
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));
goto err_sco_rx;
}
session->pcm_sco_tx = pcm_open(SOUND_CARD,
SOUND_CAPTURE_SCO_DEVICE,
PCM_IN|PCM_MONOTONIC,
&pcm_config_voice_sco);
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));
goto err_sco_tx;
}
pcm_start(session->pcm_sco_rx);
pcm_start(session->pcm_sco_tx);
return;
err_sco_tx:
pcm_close(session->pcm_sco_tx);
session->pcm_sco_tx = NULL;
err_sco_rx:
pcm_close(session->pcm_sco_rx);
session->pcm_sco_rx = NULL;
}
/*
* This function must be called with hw device mutex locked, OK to hold other
* mutexes
@ -170,7 +242,9 @@ int start_voice_session(struct voice_session *session)
pcm_start(session->pcm_voice_rx);
pcm_start(session->pcm_voice_tx);
/* TODO: handle SCO */
if (session->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
start_voice_session_bt_sco(session);
}
if (session->two_mic_control) {
ALOGV("%s: enabling two mic control", __func__);
@ -209,7 +283,10 @@ void stop_voice_session(struct voice_session *session)
status++;
}
/* TODO: handle SCO */
if (session->out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
stop_voice_session_bt_sco(session);
}
session->out_device = AUDIO_DEVICE_NONE;

@ -25,6 +25,9 @@ struct voice_session {
struct pcm *pcm_voice_rx;
struct pcm *pcm_voice_tx;
struct pcm *pcm_sco_rx;
struct pcm *pcm_sco_tx;
bool wb_amr;
bool two_mic_control;
bool two_mic_disabled;
@ -41,6 +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);
bool voice_session_uses_twomic(struct voice_session *session);
bool voice_session_uses_wideband(struct voice_session *session);

Loading…
Cancel
Save