Loading hal/audio_extn/audio_extn.c +7 −1 Original line number Diff line number Diff line Loading @@ -1294,6 +1294,12 @@ static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev, set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; break; case 4: set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; set_values[2] = PCM_CHANNEL_LS; set_values[3] = PCM_CHANNEL_LFE; break; case 6: set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; Loading Loading @@ -1390,7 +1396,7 @@ int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev, } mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); if (channel_count == 6 || channel_count == 8 || channel_count == 2) { if (channel_count == 6 || channel_count == 8 || channel_count == 2 || channel_count == 4) { ret = afe_proxy_set_channel_mapping(adev, channel_count, snd_device); } else { ALOGE("%s: set unsupported channel count(%d)", __func__, channel_count); Loading hal/audio_hw.c +118 −90 Original line number Diff line number Diff line /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project Loading Loading @@ -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 Loading Loading @@ -1227,16 +1228,11 @@ 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) { in = usecase->stream.in; Loading Loading @@ -2987,6 +2983,30 @@ int select_devices(struct audio_device *adev, audio_usecase_t uc_id) } enable_audio_route(adev, usecase); if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) { struct stream_in *voip_in = get_voice_communication_input(adev); struct audio_usecase *voip_in_usecase = NULL; voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP); if (voip_in != NULL && voip_in_usecase != NULL && !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER || out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) && (voip_in_usecase->in_snd_device == platform_get_input_snd_device(adev->platform, voip_in, &usecase->stream.out->device_list,usecase->type))) { /* * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path * for enabling echo-reference-voip with correct port */ ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__); disable_audio_route(adev, voip_in_usecase); disable_snd_device(adev, voip_in_usecase->in_snd_device); enable_snd_device(adev, voip_in_usecase->in_snd_device); enable_audio_route(adev, voip_in_usecase); } } audio_extn_qdsp_set_device(usecase); /* If input stream is already running then effect needs to be Loading Loading @@ -3351,10 +3371,12 @@ static int send_offload_cmd_l(struct stream_out* out, int command) return 0; } /* must be called with out->lock and latch lock */ /* must be called with out->lock */ static void stop_compressed_output_l(struct stream_out *out) { pthread_mutex_lock(&out->latch_lock); out->offload_state = OFFLOAD_STATE_IDLE; pthread_mutex_unlock(&out->latch_lock); out->playback_started = 0; out->send_new_metadata = 1; if (out->compr != NULL) { Loading Loading @@ -3612,11 +3634,9 @@ static int create_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) { lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_join(out->offload_thread, (void **) NULL); pthread_cond_destroy(&out->offload_cond); Loading @@ -3641,6 +3661,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__); Loading Loading @@ -3689,9 +3711,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"); Loading Loading @@ -3827,7 +3846,7 @@ int start_output_stream(struct stream_out *out) if (is_speaker_active || is_speaker_safe_active) { a2dp_combo = true; } else { if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { if (!is_offload_usecase(out->usecase)) { ALOGE("%s: A2DP profile is not ready, return error", __func__); ret = -EAGAIN; goto error_config; Loading Loading @@ -4512,9 +4531,7 @@ static int out_standby(struct audio_stream *stream) adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_lock(&adev->lock); Loading Loading @@ -4589,9 +4606,7 @@ static int out_on_error(struct audio_stream *stream) // is needed e.g. when SSR happens within compress_open // since the stream is active, offload_callback_thread is also active. if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_unlock(&out->lock); Loading Loading @@ -4630,9 +4645,7 @@ int out_standby_l(struct audio_stream *stream) adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } out->standby = true; Loading Loading @@ -4979,17 +4992,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 ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (!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; 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); } } Loading Loading @@ -5541,9 +5556,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)) { Loading Loading @@ -5581,15 +5594,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; Loading @@ -5599,14 +5612,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]); 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__); Loading @@ -5618,21 +5634,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; } Loading Loading @@ -5852,7 +5872,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, (audio_extn_a2dp_source_is_suspended())) { if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) || compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) { if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { if (!is_offload_usecase(out->usecase)) { ret = -EIO; goto exit; } Loading Loading @@ -6018,10 +6038,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); Loading Loading @@ -6470,12 +6488,13 @@ static int out_flush(struct audio_stream_out* stream) lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->offload_state == OFFLOAD_STATE_PAUSED) { pthread_mutex_unlock(&out->latch_lock); stop_compressed_output_l(out); } else { ALOGW("%s called in invalid state %d", __func__, out->offload_state); pthread_mutex_unlock(&out->latch_lock); } out->written = 0; pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); ALOGD("copl(%p):out of compress flush", out); return 0; Loading Loading @@ -7773,7 +7792,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; Loading Loading @@ -8504,6 +8523,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() */ Loading Loading @@ -8644,7 +8665,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); Loading Loading @@ -8703,6 +8724,8 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) /* notify adev and input/output streams on the snd card status */ adev_snd_mon_cb((void *)adev, parms); ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value)); if (ret >= 0) { list_for_each(node, &adev->active_outputs_list) { streams_output_ctxt_t *out_ctxt = node_to_item(node, streams_output_ctxt_t, Loading @@ -8716,6 +8739,7 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) list); in_snd_mon_cb((void *)in_ctxt->input, parms); } } pthread_mutex_lock(&adev->lock); ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value)); Loading Loading @@ -8897,17 +8921,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 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { } 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, ""); Loading Loading @@ -9523,6 +9542,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->config.rate = config->sample_rate; in->af_period_multiplier = 1; } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION && (!voice_extn_is_compress_voip_supported()) && in->flags & AUDIO_INPUT_FLAG_VOIP_TX && (config->sample_rate == 8000 || config->sample_rate == 16000 || Loading Loading @@ -10357,8 +10377,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); Loading @@ -10367,43 +10387,51 @@ 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 ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (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 (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { // mute compress stream if suspended if (!out->a2dp_compress_mute && !out->standby) { // 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; } 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; } } pthread_mutex_unlock(&out->latch_lock); } ALOGV("%s: exit", __func__); Loading hal/audio_hw.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
hal/audio_extn/audio_extn.c +7 −1 Original line number Diff line number Diff line Loading @@ -1294,6 +1294,12 @@ static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev, set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; break; case 4: set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; set_values[2] = PCM_CHANNEL_LS; set_values[3] = PCM_CHANNEL_LFE; break; case 6: set_values[0] = PCM_CHANNEL_FL; set_values[1] = PCM_CHANNEL_FR; Loading Loading @@ -1390,7 +1396,7 @@ int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev, } mixer_ctl_set_enum_by_string(ctl, channel_cnt_str); if (channel_count == 6 || channel_count == 8 || channel_count == 2) { if (channel_count == 6 || channel_count == 8 || channel_count == 2 || channel_count == 4) { ret = afe_proxy_set_channel_mapping(adev, channel_count, snd_device); } else { ALOGE("%s: set unsupported channel count(%d)", __func__, channel_count); Loading
hal/audio_hw.c +118 −90 Original line number Diff line number Diff line /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2013 The Android Open Source Project Loading Loading @@ -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 Loading Loading @@ -1227,16 +1228,11 @@ 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) { in = usecase->stream.in; Loading Loading @@ -2987,6 +2983,30 @@ int select_devices(struct audio_device *adev, audio_usecase_t uc_id) } enable_audio_route(adev, usecase); if (uc_id == USECASE_AUDIO_PLAYBACK_VOIP) { struct stream_in *voip_in = get_voice_communication_input(adev); struct audio_usecase *voip_in_usecase = NULL; voip_in_usecase = get_usecase_from_list(adev, USECASE_AUDIO_RECORD_VOIP); if (voip_in != NULL && voip_in_usecase != NULL && !(out_snd_device == AUDIO_DEVICE_OUT_SPEAKER || out_snd_device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) && (voip_in_usecase->in_snd_device == platform_get_input_snd_device(adev->platform, voip_in, &usecase->stream.out->device_list,usecase->type))) { /* * if VOIP TX is enabled before VOIP RX, needs to re-route the TX path * for enabling echo-reference-voip with correct port */ ALOGD("%s: VOIP TX is enabled before VOIP RX,needs to re-route the TX path",__func__); disable_audio_route(adev, voip_in_usecase); disable_snd_device(adev, voip_in_usecase->in_snd_device); enable_snd_device(adev, voip_in_usecase->in_snd_device); enable_audio_route(adev, voip_in_usecase); } } audio_extn_qdsp_set_device(usecase); /* If input stream is already running then effect needs to be Loading Loading @@ -3351,10 +3371,12 @@ static int send_offload_cmd_l(struct stream_out* out, int command) return 0; } /* must be called with out->lock and latch lock */ /* must be called with out->lock */ static void stop_compressed_output_l(struct stream_out *out) { pthread_mutex_lock(&out->latch_lock); out->offload_state = OFFLOAD_STATE_IDLE; pthread_mutex_unlock(&out->latch_lock); out->playback_started = 0; out->send_new_metadata = 1; if (out->compr != NULL) { Loading Loading @@ -3612,11 +3634,9 @@ static int create_offload_callback_thread(struct stream_out *out) static int destroy_offload_callback_thread(struct stream_out *out) { lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); send_offload_cmd_l(out, OFFLOAD_CMD_EXIT); pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); pthread_join(out->offload_thread, (void **) NULL); pthread_cond_destroy(&out->offload_cond); Loading @@ -3641,6 +3661,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__); Loading Loading @@ -3689,9 +3711,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"); Loading Loading @@ -3827,7 +3846,7 @@ int start_output_stream(struct stream_out *out) if (is_speaker_active || is_speaker_safe_active) { a2dp_combo = true; } else { if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { if (!is_offload_usecase(out->usecase)) { ALOGE("%s: A2DP profile is not ready, return error", __func__); ret = -EAGAIN; goto error_config; Loading Loading @@ -4512,9 +4531,7 @@ static int out_standby(struct audio_stream *stream) adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_lock(&adev->lock); Loading Loading @@ -4589,9 +4606,7 @@ static int out_on_error(struct audio_stream *stream) // is needed e.g. when SSR happens within compress_open // since the stream is active, offload_callback_thread is also active. if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } pthread_mutex_unlock(&out->lock); Loading Loading @@ -4630,9 +4645,7 @@ int out_standby_l(struct audio_stream *stream) adev->adm_deregister_stream(adev->adm_data, out->handle); if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->latch_lock); stop_compressed_output_l(out); pthread_mutex_unlock(&out->latch_lock); } out->standby = true; Loading Loading @@ -4979,17 +4992,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 ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (!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; 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); } } Loading Loading @@ -5541,9 +5556,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)) { Loading Loading @@ -5581,15 +5594,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; Loading @@ -5599,14 +5612,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]); 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__); Loading @@ -5618,21 +5634,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; } Loading Loading @@ -5852,7 +5872,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, (audio_extn_a2dp_source_is_suspended())) { if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) || compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) { if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { if (!is_offload_usecase(out->usecase)) { ret = -EIO; goto exit; } Loading Loading @@ -6018,10 +6038,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); Loading Loading @@ -6470,12 +6488,13 @@ static int out_flush(struct audio_stream_out* stream) lock_output_stream(out); pthread_mutex_lock(&out->latch_lock); if (out->offload_state == OFFLOAD_STATE_PAUSED) { pthread_mutex_unlock(&out->latch_lock); stop_compressed_output_l(out); } else { ALOGW("%s called in invalid state %d", __func__, out->offload_state); pthread_mutex_unlock(&out->latch_lock); } out->written = 0; pthread_mutex_unlock(&out->latch_lock); pthread_mutex_unlock(&out->lock); ALOGD("copl(%p):out of compress flush", out); return 0; Loading Loading @@ -7773,7 +7792,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; Loading Loading @@ -8504,6 +8523,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() */ Loading Loading @@ -8644,7 +8665,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); Loading Loading @@ -8703,6 +8724,8 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) /* notify adev and input/output streams on the snd card status */ adev_snd_mon_cb((void *)adev, parms); ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value)); if (ret >= 0) { list_for_each(node, &adev->active_outputs_list) { streams_output_ctxt_t *out_ctxt = node_to_item(node, streams_output_ctxt_t, Loading @@ -8716,6 +8739,7 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) list); in_snd_mon_cb((void *)in_ctxt->input, parms); } } pthread_mutex_lock(&adev->lock); ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value)); Loading Loading @@ -8897,17 +8921,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 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { } 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, ""); Loading Loading @@ -9523,6 +9542,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->config.rate = config->sample_rate; in->af_period_multiplier = 1; } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION && (!voice_extn_is_compress_voip_supported()) && in->flags & AUDIO_INPUT_FLAG_VOIP_TX && (config->sample_rate == 8000 || config->sample_rate == 16000 || Loading Loading @@ -10357,8 +10377,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); Loading @@ -10367,43 +10387,51 @@ 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 ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && (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 (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { // mute compress stream if suspended if (!out->a2dp_compress_mute && !out->standby) { // 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; } 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; } } pthread_mutex_unlock(&out->latch_lock); } ALOGV("%s: exit", __func__); Loading
hal/audio_hw.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading