Merge "audio HAL: fix thread starvation" into mnc-dr-ryu-dev
diff --git a/audio/hal/audio_hw.c b/audio/hal/audio_hw.c
index ff785b2..83a623d 100644
--- a/audio/hal/audio_hw.c
+++ b/audio/hal/audio_hw.c
@@ -1245,6 +1245,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);
+}
+
 static int uc_release_pcm_devices(struct audio_usecase *usecase)
 {
     struct stream_out *out = (struct stream_out *)usecase->stream;
@@ -1629,7 +1643,7 @@
 
     ALOGV("%s: enter: usecase(%d: %s)", __func__,
           out->usecase, use_case_table[out->usecase]);
-    pthread_mutex_lock(&out->lock);
+    lock_output_stream(out);
     if (!out->standby) {
         pthread_mutex_lock(&adev->lock);
         do_out_standby_l(out);
@@ -1669,7 +1683,7 @@
     if (ret >= 0) {
         val = atoi(value);
         pthread_mutex_lock(&adev->lock_inputs);
-        pthread_mutex_lock(&out->lock);
+        lock_output_stream(out);
         pthread_mutex_lock(&adev->lock);
         if (val != 0) {
             out->devices = val;
@@ -1815,7 +1829,7 @@
     unsigned char *data = NULL;
     struct pcm_config config;
 
-    pthread_mutex_lock(&out->lock);
+    lock_output_stream(out);
     if (out->standby) {
         pthread_mutex_lock(&adev->lock);
         ret = start_output_stream(out);
@@ -1932,7 +1946,7 @@
     int ret = -1;
     unsigned long dsp_frames;
 
-    pthread_mutex_lock(&out->lock);
+    lock_output_stream(out);
 
     /* FIXME: which device to read from? */
     if (!list_empty(&out->pcm_dev_list)) {
@@ -2056,7 +2070,7 @@
 {
     struct audio_device *adev = in->dev;
     int status = 0;
-    pthread_mutex_lock(&in->lock);
+    lock_input_stream(in);
     if (!in->standby) {
         pthread_mutex_lock(&adev->lock);
         status = do_in_standby_l(in);
@@ -2107,7 +2121,7 @@
     ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
 
     pthread_mutex_lock(&adev->lock_inputs);
-    pthread_mutex_lock(&in->lock);
+    lock_input_stream(in);
     pthread_mutex_lock(&adev->lock);
     if (ret >= 0) {
         val = atoi(value);
@@ -2202,11 +2216,11 @@
     size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
 
     /* no need to acquire adev->lock_inputs because API contract prevents a close */
-    pthread_mutex_lock(&in->lock);
+    lock_input_stream(in);
     if (in->standby) {
         pthread_mutex_unlock(&in->lock);
         pthread_mutex_lock(&adev->lock_inputs);
-        pthread_mutex_lock(&in->lock);
+        lock_input_stream(in);
         if (!in->standby) {
             pthread_mutex_unlock(&adev->lock_inputs);
             goto false_alarm;
@@ -2358,6 +2372,7 @@
     /* out->written = 0; by calloc() */
 
     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);
 
     config->format = out->stream.common.get_format(&out->stream.common);
@@ -2662,6 +2677,9 @@
     }
     in->usecase_type = usecase_type;
 
+    pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
+    pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
+
     *stream_in = &in->stream;
     ALOGV("%s: exit", __func__);
     return 0;
diff --git a/audio/hal/audio_hw.h b/audio/hal/audio_hw.h
index 775df1b..92aff51 100644
--- a/audio/hal/audio_hw.h
+++ b/audio/hal/audio_hw.h
@@ -206,6 +206,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 listnode             pcm_dev_list;
@@ -234,6 +235,8 @@
 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
+                                                     capture thread */
     struct pcm_config                   config;
     struct listnode                     pcm_dev_list;
     int                                 standby;