Merge "policy_hal: Reject offload path for AV streaming usecase"
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 7d9836f..f969de2 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1162,6 +1162,20 @@
return ret;
}
+void lock_input_stream(struct stream_in *in)
+{
+ pthread_mutex_lock(&in->pre_lock);
+ pthread_mutex_lock(&in->lock);
+ pthread_mutex_unlock(&in->pre_lock);
+}
+
+void lock_output_stream(struct stream_out *out)
+{
+ pthread_mutex_lock(&out->pre_lock);
+ pthread_mutex_lock(&out->lock);
+ pthread_mutex_unlock(&out->pre_lock);
+}
+
/* must be called with out->lock locked */
static int send_offload_cmd_l(struct stream_out* out, int command)
{
@@ -1250,7 +1264,7 @@
prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
for (;;) {
struct offload_cmd *cmd = NULL;
stream_callback_event_t event;
@@ -1329,7 +1343,7 @@
ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
break;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
if (send_callback && out->offload_callback) {
@@ -1361,7 +1375,7 @@
static int destroy_offload_callback_thread(struct stream_out *out)
{
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
@@ -1814,7 +1828,7 @@
return 0;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (!out->standby) {
if (adev->adm_deregister_stream)
adev->adm_deregister_stream(adev->adm_data, out->handle);
@@ -1903,7 +1917,7 @@
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
if (err >= 0) {
val = atoi(value);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
pthread_mutex_lock(&adev->lock);
/*
@@ -1967,7 +1981,7 @@
pthread_mutex_unlock(&adev->lock);
}
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
parse_compress_metadata(out, parms);
audio_extn_dts_create_state_notifier_node(out->usecase);
@@ -2123,7 +2137,7 @@
int snd_scard_state = get_snd_card_state(adev);
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
// increase written size during SSR to avoid mismatch
@@ -2268,7 +2282,7 @@
*dsp_frames = 0;
if (is_offload_usecase(out->usecase)) {
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL) {
ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
&out->sample_rate);
@@ -2327,7 +2341,7 @@
int ret = -1;
unsigned long dsp_frames;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (is_offload_usecase(out->usecase)) {
if (out->compr != NULL) {
@@ -2379,7 +2393,7 @@
struct stream_out *out = (struct stream_out *)stream;
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_callback = callback;
out->offload_cookie = cookie;
pthread_mutex_unlock(&out->lock);
@@ -2393,7 +2407,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):pause compress driver", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2421,7 +2435,7 @@
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):resume compress driver", out);
status = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2446,7 +2460,7 @@
int status = -ENOSYS;
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (type == AUDIO_DRAIN_EARLY_NOTIFY)
status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
else
@@ -2462,7 +2476,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):calling compress flush", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
pthread_mutex_unlock(&out->lock);
ALOGD("copl(%p):out of compress flush", out);
@@ -2534,7 +2548,7 @@
return status;
}
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (!in->standby && in->is_st_session) {
ALOGD("%s: sound trigger pcm stop lab", __func__);
audio_extn_sound_trigger_stop_lab(in);
@@ -2579,7 +2593,7 @@
if (!parms)
goto error;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&adev->lock);
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
@@ -2663,7 +2677,7 @@
int i, ret = -1;
int snd_scard_state = get_snd_card_state(adev);
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (in->is_st_session) {
ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
@@ -2763,7 +2777,7 @@
if (status != 0)
return status;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&in->dev->lock);
if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
in->enable_aec != enable &&
@@ -2831,6 +2845,7 @@
}
pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
if (devices == AUDIO_DEVICE_NONE)
@@ -3485,6 +3500,7 @@
devices, &in->stream, handle, source);
pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 542a3f1..59d6a89 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -181,6 +181,7 @@
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
pthread_cond_t cond;
struct pcm_config config;
struct compr_config compr_config;
@@ -225,6 +226,7 @@
struct stream_in {
struct audio_stream_in stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
struct pcm_config config;
struct pcm *pcm;
int standby;
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 2775d42..ac7d2de 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -1921,8 +1921,8 @@
void AudioPolicyManagerCustom::closeAllInputs() {
bool patchRemoved = false;
- for(size_t input_index = 0; input_index < mInputs.size(); input_index++) {
- sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
+ for(size_t input_index = mInputs.size(); input_index > 0; input_index--) {
+ sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index-1);
ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
if (patch_index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
@@ -1933,8 +1933,8 @@
if ((inputDesc->mIsSoundTrigger) && (mInputs.size() == 1)) {
ALOGD("Do not close sound trigger input handle");
} else {
- mpClientInterface->closeInput(mInputs.keyAt(input_index));
- mInputs.removeItem(mInputs.keyAt(input_index));
+ mpClientInterface->closeInput(mInputs.keyAt(input_index-1));
+ mInputs.removeItem(mInputs.keyAt(input_index-1));
}
}
nextAudioPortGeneration();