hal: defer compress input usecase availability check to start
Compressed input usecase availability check in open input stream
is hitting error frequently due to race condition in calling close
on existing stream with respect to opening new input stream.
Defer usecase availability check to make compress usecase inline
with normal record usecase which can withstand race condition for
open vs close without hitting error.
Change-Id: I3f27fca31042e0d351550f2465efded9361d639a
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index f457462..5c402d8 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -95,8 +95,9 @@
struct str_parms *parms);
bool cin_applicable_stream(struct stream_in *in);
-bool cin_attached_usecase(audio_usecase_t uc_id);
+bool cin_attached_usecase(struct stream_in *in);
bool cin_format_supported(audio_format_t format);
+int cin_acquire_usecase(struct stream_in *in);
size_t cin_get_buffer_size(struct stream_in *in);
int cin_open_input_stream(struct stream_in *in);
void cin_stop_input_stream(struct stream_in *in);
@@ -5161,14 +5162,18 @@
{
return (audio_extn_compress_in_enabled? cin_applicable_stream(in): false);
}
-bool audio_extn_cin_attached_usecase(audio_usecase_t uc_id)
+bool audio_extn_cin_attached_usecase(struct stream_in *in)
{
- return (audio_extn_compress_in_enabled? cin_attached_usecase(uc_id): false);
+ return (audio_extn_compress_in_enabled? cin_attached_usecase(in): false);
}
bool audio_extn_cin_format_supported(audio_format_t format)
{
return (audio_extn_compress_in_enabled? cin_format_supported(format): false);
}
+int audio_extn_cin_acquire_usecase(struct stream_in *in)
+{
+ return (audio_extn_compress_in_enabled? cin_acquire_usecase(in): 0);
+}
size_t audio_extn_cin_get_buffer_size(struct stream_in *in)
{
return (audio_extn_compress_in_enabled? cin_get_buffer_size(in): 0);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 82a4b25..9fc3c5a 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1093,8 +1093,9 @@
// START: COMPRESS_INPUT_ENABLED ===============================
bool audio_extn_cin_applicable_stream(struct stream_in *in);
-bool audio_extn_cin_attached_usecase(audio_usecase_t uc_id);
+bool audio_extn_cin_attached_usecase(struct stream_in *in);
bool audio_extn_cin_format_supported(audio_format_t format);
+int audio_extn_cin_acquire_usecase(struct stream_in *in);
size_t audio_extn_cin_get_buffer_size(struct stream_in *in);
int audio_extn_cin_open_input_stream(struct stream_in *in);
void audio_extn_cin_stop_input_stream(struct stream_in *in);
diff --git a/hal/audio_extn/compress_in.c b/hal/audio_extn/compress_in.c
index 558b581..8795d52 100644
--- a/hal/audio_extn/compress_in.c
+++ b/hal/audio_extn/compress_in.c
@@ -78,6 +78,7 @@
struct cin_private_data {
struct compr_config compr_config;
struct compress *compr;
+ bool usecase_acquired;
};
typedef struct cin_private_data cin_private_data_t;
@@ -109,14 +110,14 @@
* 2. cin_configure_input_stream(in, in_config)
*/
-bool cin_attached_usecase(audio_usecase_t uc_id)
+bool cin_attached_usecase(struct stream_in *in)
{
- unsigned int i;
+ unsigned int i = 0;
+ audio_usecase_t uc_id = in->usecase;
for (i = 0; i < sizeof(cin_usecases)/
sizeof(cin_usecases[0]); i++) {
- if (uc_id == cin_usecases[i] &&
- (cin_usecases_state & (0x1 << i)))
+ if (uc_id == cin_usecases[i] && in->cin_extn != NULL)
return true;
}
return false;
@@ -170,6 +171,27 @@
return false;
}
+int cin_acquire_usecase(struct stream_in *in)
+{
+ audio_usecase_t usecase = USECASE_INVALID;
+ cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
+
+ if (cin_data->usecase_acquired) {
+ ALOGW("%s: in %p, usecase already acquired!", __func__, in);
+ return 0;
+ }
+
+ usecase = get_cin_usecase();
+ if (usecase == USECASE_INVALID) {
+ ALOGE("%s: in %p, failed to acquire usecase, max count reached!", __func__, in);
+ return -EBUSY;
+ }
+
+ in->usecase = usecase;
+ cin_data->usecase_acquired = true;
+ return 0;
+}
+
size_t cin_get_buffer_size(struct stream_in *in)
{
size_t sz = 0;
@@ -192,6 +214,12 @@
cin_private_data_t *cin_data = (cin_private_data_t *) in->cin_extn;
ALOGV("%s: in %p, cin_data %p", __func__, in, cin_data);
+
+ if (!cin_data->usecase_acquired) {
+ ALOGE("%s: in %p, invalid state: usecase not acquired yet!", __func__, in);
+ return ret;
+ }
+
cin_data->compr = compress_open(adev->snd_card, in->pcm_device_id,
COMPRESS_OUT, &cin_data->compr_config);
if (cin_data->compr == NULL || !is_compress_ready(cin_data->compr)) {
@@ -228,6 +256,11 @@
compress_close(cin_data->compr);
cin_data->compr = NULL;
}
+
+ if (cin_data->usecase_acquired) {
+ free_cin_usecase(in->usecase);
+ cin_data->usecase_acquired = false;
+ }
}
void cin_free_input_stream_resources(struct stream_in *in)
@@ -239,7 +272,6 @@
free(cin_data->compr_config.codec);
free(cin_data);
}
- free_cin_usecase(in->usecase);
}
int cin_read(struct stream_in *in, void *buffer,
@@ -310,13 +342,6 @@
goto err_config;
}
- in->usecase = get_cin_usecase();
- if (in->usecase == USECASE_INVALID) {
- ALOGE("%s, Max allowed compress record usecase reached!", __func__);
- ret = -EEXIST;
- goto err_config;
- }
-
config.sample_rate = in->sample_rate;
config.channel_mask = in->channel_mask;
config.format = in->format;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 8f18c8f..45b0a5d 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3054,6 +3054,9 @@
else
ALOGV("%s: usecase(%d)", __func__, in->usecase);
+ if (audio_extn_cin_attached_usecase(in))
+ audio_extn_cin_acquire_usecase(in);
+
if (get_usecase_from_list(adev, in->usecase) != NULL) {
ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
__func__, &in->stream, in->usecase, use_case_table[in->usecase]);
@@ -3095,7 +3098,7 @@
android_atomic_acquire_cas(true, false, &(in->capture_stopped));
- if (audio_extn_cin_attached_usecase(in->usecase)) {
+ if (audio_extn_cin_attached_usecase(in)) {
ret = audio_extn_cin_open_input_stream(in);
if (ret)
goto error_open;
@@ -6481,7 +6484,7 @@
return voice_extn_compress_voip_in_get_buffer_size(in);
else if(audio_extn_compr_cap_usecase_supported(in->usecase))
return audio_extn_compr_cap_get_buffer_size(in->config.format);
- else if(audio_extn_cin_attached_usecase(in->usecase))
+ else if(audio_extn_cin_attached_usecase(in))
return audio_extn_cin_get_buffer_size(in);
return in->config.period_size * in->af_period_multiplier *
@@ -6546,7 +6549,7 @@
in->mmap_shared_memory_fd = -1;
}
} else {
- if (audio_extn_cin_attached_usecase(in->usecase))
+ if (audio_extn_cin_attached_usecase(in))
audio_extn_cin_close_input_stream(in);
}
@@ -6882,7 +6885,7 @@
goto exit;
bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
- if (audio_extn_cin_attached_usecase(in->usecase)) {
+ if (audio_extn_cin_attached_usecase(in)) {
ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
} else if (in->pcm) {
if (audio_extn_ssr_get_stream() == in) {
@@ -6943,7 +6946,7 @@
pthread_mutex_unlock(&adev->lock);
in->standby = true;
}
- if (!audio_extn_cin_attached_usecase(in->usecase)) {
+ if (!audio_extn_cin_attached_usecase(in)) {
bytes_read = bytes;
memset(buffer, 0, bytes);
}
@@ -9470,7 +9473,7 @@
audio_extn_compr_cap_format_supported(in->config.format))
audio_extn_compr_cap_deinit();
- if (audio_extn_cin_attached_usecase(in->usecase))
+ if (audio_extn_cin_attached_usecase(in))
audio_extn_cin_free_input_stream_resources(in);
if (in->is_st_session) {
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
index 22c8685..4fece7e 100644
--- a/hal/audio_hw_extn_api.c
+++ b/hal/audio_hw_extn_api.c
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016-2017, 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -202,7 +202,7 @@
if (!in->standby) {
if (in->pcm != NULL ) {
pcm_stop(in->pcm);
- } else if (audio_extn_cin_attached_usecase(in->usecase)) {
+ } else if (audio_extn_cin_attached_usecase(in)) {
audio_extn_cin_stop_input_stream(in);
}