st-hal: Rework audio concurrency handling
Dedicated path: One change that affects dedicated path
usecases is to handle audio capture concurrency changes on
device events instead of stream events.
Non-dedicated path: The above change is also applicable. Also,
AR will transition to NLPI in order to avoid LPI to NLPI
transitions during audio caputre concurrencies. The reason for
this is that there could be a mismatch between the AFE channel
count and channel mask if transitions are allowed. The issue
comes from not being allowed to disable the backend device
during capture concurrencies, so this is avoided with this
change.
Change-Id: I82248dc506a79227d3d9f92064e560af350c590e
diff --git a/sound_trigger_hw.c b/sound_trigger_hw.c
index e4772cb..fde2cb1 100644
--- a/sound_trigger_hw.c
+++ b/sound_trigger_hw.c
@@ -793,6 +793,21 @@
if (!num_sessions) {
stdev->session_allowed = conc_allowed;
+ /*
+ * This is needed for the following usecase:
+ *
+ * 1. LPI and NLPI have different number of MICs (different devices).
+ * 2. ST session is stopped from app and unloaded while Tx active.
+ * 3. Tx stops.
+ * 4. ST session started again from app on LPI.
+ *
+ * The device disablement is missed in step 3 because the st_session was
+ * deinitialized. Thus, it is handled here.
+ */
+ if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE &&
+ !platform_stdev_is_dedicated_sva_path(stdev->platform) &&
+ platform_stdev_backend_reset_allowed(stdev->platform))
+ platform_stdev_disable_stale_devices(stdev->platform);
pthread_mutex_unlock(&stdev->lock);
return;
}
@@ -849,12 +864,26 @@
}
} else {
if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE) {
+ /*
+ * The reset_backend flag allows the backend device to be disabled. This should
+ * only be disallowed when in non-dedicated path mode and there is an active
+ * audio input stream.
+ */
+ stdev->reset_backend = platform_stdev_backend_reset_allowed(stdev->platform);
+ st_hw_check_and_update_lpi(stdev, p_ses);
+ stdev->vad_enable = st_hw_check_vad_support(stdev, p_ses, stdev->lpi_enable);
+
list_for_each(p_ses_node, &stdev->sound_model_list) {
p_ses = node_to_item(p_ses_node, st_session_t, list_node);
ALOGD("%s:[%d] Capture device is disabled, pause SVA session",
__func__, p_ses->sm_handle);
st_session_pause(p_ses);
}
+ /*
+ * This is needed when the session goes to loaded state, then
+ * LPI/NLPI switch happens due to Rx event.
+ */
+ platform_stdev_disable_stale_devices(stdev->platform);
list_for_each(p_ses_node, &stdev->sound_model_list) {
p_ses = node_to_item(p_ses_node, st_session_t, list_node);
ALOGD("%s:[%d] Capture device is disabled, resume SVA session",
@@ -922,6 +951,15 @@
}
}
}
+ /*
+ * The device can be disabled within this thread upon reception of the device
+ * active event because audio hal does not enable the device until after returning
+ * from this callback. After this thread exits, device disablement will be
+ * disallowed until the device inactive event is received.
+ */
+ if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE &&
+ !platform_stdev_is_dedicated_sva_path(stdev->platform))
+ stdev->reset_backend = platform_stdev_backend_reset_allowed(stdev->platform);
pthread_mutex_unlock(&stdev->lock);
ALOGV("%s: Exit", __func__);
}
diff --git a/sound_trigger_platform.c b/sound_trigger_platform.c
index cefc47e..620b51c 100644
--- a/sound_trigger_platform.c
+++ b/sound_trigger_platform.c
@@ -3797,6 +3797,22 @@
return true;
}
+bool platform_stdev_backend_reset_allowed
+(
+ void *platform
+)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ sound_trigger_device_t *stdev = my_data->stdev;
+
+ if (stdev->conc_capture_supported &&
+ stdev->tx_concurrency_active > 0 &&
+ !platform_stdev_is_dedicated_sva_path(platform))
+ return false;
+ else
+ return true;
+}
+
static int platform_stdev_get_device_sample_rate
(
struct platform_data *my_data,
@@ -5005,8 +5021,8 @@
if (event_type == AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE ||
event_type == AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE) {
/* handle CAPTURE_DEVICE events */
- ALOGI("%s: Received DEVICE event, event type %d",
- __func__, event_type);
+ ALOGI("%s: Received DEVICE event, event type %d, usecase type %d",
+ __func__, event_type, config->u.usecase.type);
/*
* for device status events, if:
* 1. conc audio disabled - return with false to disable VA sessions
@@ -5016,10 +5032,30 @@
switch (event_type) {
case AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE:
stdev->tx_concurrency_active++;
+ switch (config->u.usecase.type) {
+ case USECASE_TYPE_VOICE_CALL:
+ stdev->conc_voice_active = true;
+ break;
+ case USECASE_TYPE_VOIP_CALL:
+ stdev->conc_voip_active = true;
+ break;
+ default:
+ break;
+ }
break;
case AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE:
if (stdev->tx_concurrency_active > 0)
stdev->tx_concurrency_active--;
+ switch (config->u.usecase.type) {
+ case USECASE_TYPE_VOICE_CALL:
+ stdev->conc_voice_active = false;
+ break;
+ case USECASE_TYPE_VOIP_CALL:
+ stdev->conc_voip_active = false;
+ break;
+ default:
+ break;
+ }
break;
default:
break;
@@ -5033,39 +5069,15 @@
ALOGI("%s: Received STREAM event, event type %d, usecase type %d",
__func__, event_type, config->u.usecase.type);
switch (event_type) {
- case AUDIO_EVENT_CAPTURE_STREAM_ACTIVE:
- switch (config->u.usecase.type) {
- case USECASE_TYPE_VOICE_CALL:
- stdev->conc_voice_active = true;
- break;
- case USECASE_TYPE_VOIP_CALL:
- stdev->conc_voip_active = true;
- break;
- default:
- break;
- }
- break;
- case AUDIO_EVENT_CAPTURE_STREAM_INACTIVE:
- switch (config->u.usecase.type) {
- case USECASE_TYPE_VOICE_CALL:
- stdev->conc_voice_active = false;
- break;
- case USECASE_TYPE_VOIP_CALL:
- stdev->conc_voip_active = false;
- break;
- default:
- break;
- }
- break;
- case AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE:
- stdev->rx_concurrency_active++;
- break;
- case AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE:
- if (stdev->rx_concurrency_active > 0)
- stdev->rx_concurrency_active--;
- break;
- default:
- break;
+ case AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE:
+ stdev->rx_concurrency_active++;
+ break;
+ case AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE:
+ if (stdev->rx_concurrency_active > 0)
+ stdev->rx_concurrency_active--;
+ break;
+ default:
+ break;
}
if (event_type == AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE ||
event_type == AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE) {
@@ -5085,15 +5097,20 @@
}
/*
- * Mark reset_backend as false to prevent disabling tx
- * device when pausing VA sessions.
+ * This disablement of VOIP/Voice flags is needed for the following usecase:
+ *
+ * 1. VOIP/Voice and AR active.
+ * 2. VOIP/Voice stops - AHAL sends stream inactive events for each stream,
+ * followed by the shared device inactive and device active events which
+ * both have VOIP/voice usecase, followed by one stream active event for AR.
+ * 3. AR stops - stream and device inactive events with pcm capture usecase.
+ *
+ * In this usecase the VOIP/voice flags get stuck set to true, so reset them here.
*/
- if (stdev->conc_capture_supported &&
- stdev->tx_concurrency_active > 0 &&
- (!platform_stdev_is_dedicated_sva_path(stdev->platform)))
- stdev->reset_backend = false;
- else
- stdev->reset_backend = true;
+ if (stdev->tx_concurrency_active == 0) {
+ stdev->conc_voice_active = false;
+ stdev->conc_voip_active = false;
+ }
ALOGD("%s: dedicated path %d, reset backend %d, tx %d, rx %d,"
" concurrency session%s allowed",
@@ -5893,6 +5910,45 @@
return app_type;
}
+void platform_stdev_disable_stale_devices
+(
+ void *platform
+)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ sound_trigger_device_t *stdev = my_data->stdev;
+ char st_device_name[DEVICE_NAME_MAX_SIZE] = {0};
+
+ /*
+ * There can be stale devices while exec_mode is NONE with the
+ * below usecase:
+ *
+ * 1. SVA is active in non-dedicated path mode.
+ * 2. Tx starts, transitioning SVA to NLPI.
+ * 3. SVA stops and unloads, but cannot disable the BE device.
+ * 4. Tx stops - this function will get called with exec_mode NONE.
+ */
+ if (stdev->exec_mode == ST_EXEC_MODE_ADSP ||
+ (stdev->exec_mode == ST_EXEC_MODE_NONE &&
+ !stdev->is_gcs)) {
+ pthread_mutex_lock(&stdev->ref_cnt_lock);
+ for (int i = ST_DEVICE_MIN; i < ST_DEVICE_MAX; i++) {
+ if (0 < stdev->dev_enable_cnt[i]) {
+ platform_stdev_get_device_name(stdev->platform,
+ ST_EXEC_MODE_ADSP, i, st_device_name);
+ ALOGD("%s: disable device (%x) = %s", __func__, i,
+ st_device_name);
+ ATRACE_BEGIN("sthal: audio_route_reset_and_update_path");
+ audio_route_reset_and_update_path(stdev->audio_route,
+ st_device_name);
+ ATRACE_END();
+ --(stdev->dev_enable_cnt[i]);
+ }
+ }
+ pthread_mutex_unlock(&stdev->ref_cnt_lock);
+ }
+}
+
static void check_and_append_ec_ref_device_name
(
void *platform,
diff --git a/sound_trigger_platform.h b/sound_trigger_platform.h
index 1ffda2a..bf33b12 100644
--- a/sound_trigger_platform.h
+++ b/sound_trigger_platform.h
@@ -652,6 +652,11 @@
char *use_case
);
+void platform_stdev_disable_stale_devices
+(
+ void *platform
+);
+
void platform_stdev_check_and_update_ec_ref_config
(
void *platform,
@@ -711,6 +716,11 @@
void *platform
);
+bool platform_stdev_backend_reset_allowed
+(
+ void *platform
+);
+
int platform_stdev_derive_mixer_ctl_from_backend
(
void *platform,
diff --git a/st_hw_common.c b/st_hw_common.c
index 1255c43..97624cb 100644
--- a/st_hw_common.c
+++ b/st_hw_common.c
@@ -205,7 +205,8 @@
}
if (stdev->rx_concurrency_active || stdev->conc_voice_active ||
- stdev->conc_voip_active) {
+ stdev->conc_voip_active ||
+ !platform_stdev_backend_reset_allowed(stdev->platform)) {
ALOGD("%s: lpi NOT supported due to concurrency", __func__);
return;
}