diff options
author | Zhou Song <zhous@codeaurora.org> | 2020-11-20 13:57:39 +0800 |
---|---|---|
committer | Zhou Song <zhous@codeaurora.org> | 2020-12-21 16:30:57 +0800 |
commit | 1f93fa53f8f3cf20f0b48c39244561b8b48c8821 (patch) | |
tree | 9776a8eacd0fc06e2175b7691a599fc5b8aedf86 | |
parent | 9ebf6791339176b119385c749f17a5b19700c930 (diff) |
hal: mute stream and switch to speaker during a2dp suspend
During A2DP to SCO transition, in order to avoid audible
PCM data pumping to BT SoC during suspend, mute stream
from DSP and switch to speaker to tear down slimbus to
avoid glitches heard after SCO connection is established.
Change-Id: Iabe2216e574b462cfc179369e75007998a576480
-rw-r--r-- | hal/audio_hw.c | 135 | ||||
-rw-r--r-- | hal/audio_hw.h | 2 |
2 files changed, 71 insertions, 66 deletions
diff --git a/hal/audio_hw.c b/hal/audio_hw.c index 93214773..d732fa52 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -102,6 +102,7 @@ #define INVALID_OUT_VOLUME -1 #define AUDIO_IO_PORTS_MAX 32 +#define PLAYBACK_GAIN_MAX 1.0f #define RECORD_GAIN_MIN 0.0f #define RECORD_GAIN_MAX 1.0f #define RECORD_VOLUME_CTL_MAX 0x2000 @@ -1227,15 +1228,10 @@ int enable_audio_route(struct audio_device *adev, if (audio_extn_is_maxx_audio_enabled()) audio_extn_ma_set_device(usecase); audio_extn_utils_send_audio_calibration(adev, usecase); - if ((usecase->type == PCM_PLAYBACK) && - ((out = usecase->stream.out) != NULL)) { - if (!is_offload_usecase(out->usecase)) { - pthread_mutex_lock(&out->latch_lock); - out->muted = false; - pthread_mutex_unlock(&out->latch_lock); - } else if (out->compr) { + if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) { + out = usecase->stream.out; + if (out && out->compr) audio_extn_utils_compress_set_clk_rec_mode(usecase); - } } if (usecase->type == PCM_CAPTURE) { @@ -3641,6 +3637,8 @@ static int stop_output_stream(struct stream_out *out) return -EINVAL; } + out->a2dp_muted = false; + if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info)) ALOGE("%s: failed to stop ext hw plugin", __func__); @@ -3689,9 +3687,6 @@ static int stop_output_stream(struct stream_out *out) list_remove(&uc_info->list); out->started = 0; - pthread_mutex_lock(&out->latch_lock); - out->muted = false; - pthread_mutex_unlock(&out->latch_lock); if (is_offload_usecase(out->usecase) && (audio_extn_passthru_is_passthrough_stream(out))) { ALOGV("Disable passthrough , reset mixer to pcm"); @@ -4979,17 +4974,19 @@ int route_output_stream(struct stream_out *out, platform_set_swap_channels(adev, true); audio_extn_perf_lock_release(&adev->perf_lock_handle); } - if (is_offload_usecase(out->usecase) && - (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) { - pthread_mutex_lock(&out->latch_lock); - if (out->a2dp_compress_mute) { - out->a2dp_compress_mute = false; - out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); + pthread_mutex_lock(&out->latch_lock); + if (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready()) { + if (out->a2dp_muted) { + out->a2dp_muted = false; + if (is_offload_usecase(out->usecase)) + out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); + else if (out->usecase != USECASE_AUDIO_PLAYBACK_VOIP) + out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r); } - pthread_mutex_unlock(&out->latch_lock); - } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { - out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); } + if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP && !out->a2dp_muted) + out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); + pthread_mutex_unlock(&out->latch_lock); } } @@ -5541,9 +5538,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left, ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right); if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) { /* only take left channel into account: the API is for stereo anyway */ - pthread_mutex_lock(&out->latch_lock); out->muted = (left == 0.0f); - pthread_mutex_unlock(&out->latch_lock); return 0; } else if (is_offload_usecase(out->usecase)) { if (audio_extn_passthru_is_passthrough_stream(out)) { @@ -5581,15 +5576,15 @@ static int out_set_volume(struct audio_stream_out *stream, float left, } } pthread_mutex_lock(&out->latch_lock); - if (!out->a2dp_compress_mute) { + if (!out->a2dp_muted) { ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); } pthread_mutex_unlock(&out->latch_lock); return ret; } else { pthread_mutex_lock(&out->latch_lock); - ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute); - if (!out->a2dp_compress_mute) + ALOGV("%s: compress mute %d", __func__, out->a2dp_muted); + if (!out->a2dp_muted) ret = out_set_compr_volume(stream, left, right); out->volume_l = left; out->volume_r = right; @@ -5599,14 +5594,17 @@ static int out_set_volume(struct audio_stream_out *stream, float left, } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX); out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX); + pthread_mutex_lock(&out->latch_lock); if (!out->standby) { audio_extn_utils_send_app_type_gain(out->dev, out->app_type_cfg.app_type, &out->app_type_cfg.gain[0]); - ret = out_set_voip_volume(stream, left, right); + if (!out->a2dp_muted) + ret = out_set_voip_volume(stream, left, right); } out->volume_l = left; out->volume_r = right; + pthread_mutex_unlock(&out->latch_lock); return ret; } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) { ALOGV("%s: MMAP set volume called", __func__); @@ -5618,21 +5616,25 @@ static int out_set_volume(struct audio_stream_out *stream, float left, } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER || out->usecase == USECASE_AUDIO_PLAYBACK_ULL) { + pthread_mutex_lock(&out->latch_lock); /* Volume control for pcm playback */ - if (!out->standby) + if (!out->standby && !out->a2dp_muted) ret = out_set_pcm_volume(stream, left, right); else out->apply_volume = true; out->volume_l = left; out->volume_r = right; + pthread_mutex_unlock(&out->latch_lock); return ret; } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) { ALOGV("%s: bus device set volume called", __func__); - if (!out->standby) + pthread_mutex_lock(&out->latch_lock); + if (!out->standby && !out->a2dp_muted) ret = out_set_pcm_volume(stream, left, right); out->volume_l = left; out->volume_r = right; + pthread_mutex_unlock(&out->latch_lock); return ret; } @@ -6018,10 +6020,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } else { if (out->pcm) { size_t bytes_to_write = bytes; - pthread_mutex_lock(&out->latch_lock); if (out->muted) memset((void *)buffer, 0, bytes); - pthread_mutex_unlock(&out->latch_lock); ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu", __func__, frames, frame_size, bytes_to_write); @@ -7773,7 +7773,7 @@ int adev_open_output_stream(struct audio_hw_device *dev, out->non_blocking = 0; out->convert_buffer = NULL; out->started = 0; - out->a2dp_compress_mute = false; + out->a2dp_muted = false; out->hal_output_suspend_supported = 0; out->dynamic_pm_qos_config_supported = 0; out->set_dual_mono = false; @@ -8504,6 +8504,8 @@ int adev_open_output_stream(struct audio_hw_device *dev, out->kernel_buffer_size = out->config.period_size * out->config.period_count; out->standby = 1; + out->volume_l = PLAYBACK_GAIN_MAX; + out->volume_r = PLAYBACK_GAIN_MAX; /* out->muted = false; by calloc() */ /* out->written = 0; by calloc() */ @@ -8644,7 +8646,7 @@ void adev_close_output_stream(struct audio_hw_device *dev __unused, free(out->compr_config.codec); } - out->a2dp_compress_mute = false; + out->a2dp_muted = false; if (is_interactive_usecase(out->usecase)) free_interactive_usecase(adev, out->usecase); @@ -8897,17 +8899,12 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) //force device switch to re configure encoder select_devices(adev, usecase->id); ALOGD("Unmuting the stream after select_devices"); - pthread_mutex_lock(&usecase->stream.out->latch_lock); - usecase->stream.out->a2dp_compress_mute = false; - out_set_compr_volume(&usecase->stream.out->stream, - usecase->stream.out->volume_l, - usecase->stream.out->volume_r); - pthread_mutex_unlock(&usecase->stream.out->latch_lock); + check_a2dp_restore_l(adev, usecase->stream.out, true); audio_extn_a2dp_set_handoff_mode(false); break; } else if (is_offload_usecase(usecase->stream.out->usecase)) { pthread_mutex_lock(&usecase->stream.out->latch_lock); - if (usecase->stream.out->a2dp_compress_mute) { + if (usecase->stream.out->a2dp_muted) { pthread_mutex_unlock(&usecase->stream.out->latch_lock); reassign_device_list(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, ""); @@ -10357,8 +10354,8 @@ int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool } list_init(&devices); - ALOGD("%s: enter: usecase(%d: %s)", __func__, - out->usecase, use_case_table[out->usecase]); + ALOGD("%s: enter: usecase(%d: %s), a2dp muted %d", __func__, + out->usecase, use_case_table[out->usecase], out->a2dp_muted); if (restore) { pthread_mutex_lock(&out->latch_lock); @@ -10367,42 +10364,50 @@ int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool ALOGD("%s: restoring A2dp and unmuting stream", __func__); if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP) select_devices(adev, uc_info->id); - if (is_offload_usecase(out->usecase) && - (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) { - if (out->a2dp_compress_mute) { - out->a2dp_compress_mute = false; + + if (is_offload_usecase(out->usecase)) { + if (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP) out_set_compr_volume(&out->stream, out->volume_l, out->volume_r); - } + } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { + out_set_voip_volume(&out->stream, out->volume_l, out->volume_r); + } else { + out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r); } + out->a2dp_muted = false; } - out->muted = false; pthread_mutex_unlock(&out->latch_lock); } else { pthread_mutex_lock(&out->latch_lock); - if (is_offload_usecase(out->usecase)) { - // mute compress stream if suspended - if (!out->a2dp_compress_mute && !out->standby) { - ALOGD("%s: selecting speaker and muting stream", __func__); - assign_devices(&devices, &out->device_list); - reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, ""); - left_p = out->volume_l; - right_p = out->volume_r; + // mute stream and switch to speaker if suspended + if (!out->a2dp_muted && !out->standby) { + ALOGD("%s: selecting speaker and muting stream", __func__); + assign_devices(&devices, &out->device_list); + reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, ""); + left_p = out->volume_l; + right_p = out->volume_r; + out->a2dp_muted = true; + if (is_offload_usecase(out->usecase)) { if (out->offload_state == OFFLOAD_STATE_PLAYING) compress_pause(out->compr); out_set_compr_volume(&out->stream, (float)0, (float)0); - out->a2dp_compress_mute = true; - select_devices(adev, out->usecase); + } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) { + out_set_voip_volume(&out->stream, (float)0, (float)0); + } else { + out_set_pcm_volume(&out->stream, (float)0, (float)0); + /* wait for stale pcm drained before switching to speaker */ + uint32_t latency = + (out->config.period_count * out->config.period_size * 1000) / + (out->config.rate); + usleep(latency * 1000); + } + select_devices(adev, out->usecase); + if (is_offload_usecase(out->usecase)) { if (out->offload_state == OFFLOAD_STATE_PLAYING) compress_resume(out->compr); - assign_devices(&out->device_list, &devices); - out->volume_l = left_p; - out->volume_r = right_p; - } - } else { - // mute for non offloaded streams - if (audio_extn_a2dp_source_is_suspended()) { - out->muted = true; } + assign_devices(&out->device_list, &devices); + out->volume_l = left_p; + out->volume_r = right_p; } pthread_mutex_unlock(&out->latch_lock); } diff --git a/hal/audio_hw.h b/hal/audio_hw.h index f1e86721..32271bb1 100644 --- a/hal/audio_hw.h +++ b/hal/audio_hw.h @@ -442,7 +442,7 @@ struct stream_out { qahwi_stream_out_t qahwi_out; bool is_iec61937_info_available; - bool a2dp_compress_mute; + bool a2dp_muted; float volume_l; float volume_r; bool apply_volume; |