From b81e05fb3668d75da64b4e98139cbeafcc9f155f Mon Sep 17 00:00:00 2001 From: stenkinevgeniy Date: Tue, 8 May 2018 12:02:35 +0000 Subject: [PATCH] Audio: check and route usecases Add check_and_route_usecases - this function is to make sure that all the usecases that are active on the hardware codec backend are always routed to any one device that is handled by the hardware codec. Example: When voice call starting - we need earpice - hal enable earpice, but befor - we put call button - and hal enable speaker and play sound - "click" And now we have speaker and earpice enabled. Later when audioflinger send standby (default after 3 sec) to stream which use speaker - hal disable speaker while voice call active - and we have no sound in earpice. check_and_route_usecases will not allow such situations. Change-Id: Ibc534bb14c25e4a4ffb4f3487d1424e9e1ed6a67 --- audio/audio_hw.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/audio/audio_hw.c b/audio/audio_hw.c index 9be5f339..6843fd25 100644 --- a/audio/audio_hw.c +++ b/audio/audio_hw.c @@ -985,6 +985,67 @@ int disable_snd_device(struct audio_device *adev, return 0; } +static void check_and_route_usecases(struct audio_device *adev, + struct audio_usecase *uc_info, + usecase_type_t type, + snd_device_t snd_device) +{ + struct listnode *node; + struct audio_usecase *usecase; + bool switch_device[AUDIO_USECASE_MAX], need_switch = false; + snd_device_t usecase_snd_device = SND_DEVICE_NONE; + int i; + + /* + * This function is to make sure that all the usecases that are active on + * the hardware codec backend are always routed to any one device that is + * handled by the hardware codec. + * For example, if low-latency and deep-buffer usecases are currently active + * on speaker and out_set_parameters(headset) is received on low-latency + * output, then we have to make sure deep-buffer is also switched to headset or + * if audio-record and voice-call usecases are currently + * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece) + * is received for voice call then we have to make sure that audio-record + * usecase is also switched to earpiece i.e. + * because of the limitation that both the devices cannot be enabled + * at the same time as they share the same backend. + */ + /* Disable all the usecases on the shared backend other than the + specified usecase */ + for (i = 0; i < AUDIO_USECASE_MAX; i++) + switch_device[i] = false; + + list_for_each(node, &adev->usecase_list) { + usecase = node_to_item(node, struct audio_usecase, adev_list_node); + if (usecase->type != type || usecase == uc_info) + continue; + usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device : + usecase->in_snd_device; + if (usecase_snd_device != snd_device) { + ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", + __func__, use_case_table[usecase->id], + get_snd_device_name(usecase_snd_device)); + switch_device[usecase->id] = true; + need_switch = true; + } + } + if (need_switch) { + list_for_each(node, &adev->usecase_list) { + usecase = node_to_item(node, struct audio_usecase, adev_list_node); + usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device : + usecase->in_snd_device; + if (switch_device[usecase->id]) { + disable_snd_device(adev, usecase, usecase_snd_device); + enable_snd_device(adev, usecase, snd_device); + if (type == PCM_PLAYBACK) + usecase->out_snd_device = snd_device; + else + usecase->in_snd_device = snd_device; + } + } + } +} + static int select_devices(struct audio_device *adev, audio_usecase_t uc_id) { @@ -1084,10 +1145,12 @@ static int select_devices(struct audio_device *adev, set_voice_session_audio_path(adev->voice.session); } + check_and_route_usecases(adev, usecase, PCM_PLAYBACK, out_snd_device); enable_snd_device(adev, usecase, out_snd_device); } if (in_snd_device != SND_DEVICE_NONE) { + check_and_route_usecases(adev, usecase, PCM_CAPTURE, in_snd_device); enable_snd_device(adev, usecase, in_snd_device); }