hal: make latch lock recursive

Make latch lock recursive.

Change-Id: I9bc7d5ea6488b2af492d67efeb0fd494c85a7c83
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 83c35c7..baa55e0 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3426,6 +3426,7 @@
     pthread_mutex_lock(&out->latch_lock);
     out->offload_state = OFFLOAD_STATE_IDLE;
     pthread_mutex_unlock(&out->latch_lock);
+
     out->playback_started = 0;
     out->send_new_metadata = 1;
     if (out->compr != NULL) {
@@ -7749,6 +7750,7 @@
 #ifdef AUDIO_GKI_ENABLED
     __s32 *generic_dec;
 #endif
+    pthread_mutexattr_t latch_attr;
 
     if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
         is_usb_dev = false;
@@ -7778,7 +7780,10 @@
 
     pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
     pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
-    pthread_mutex_init(&out->latch_lock, (const pthread_mutexattr_t *) NULL);
+    pthread_mutexattr_init(&latch_attr);
+    pthread_mutexattr_settype(&latch_attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&out->latch_lock, &latch_attr);
+    pthread_mutexattr_destroy(&latch_attr);
     pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
     pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
 
@@ -10455,10 +10460,12 @@
                     if (out->offload_state == OFFLOAD_STATE_PLAYING)
                         compress_pause(out->compr);
                     out_set_compr_volume(&out->stream, (float)0, (float)0);
-                } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
-                    out_set_voip_volume(&out->stream, (float)0, (float)0);
                 } else {
-                    out_set_pcm_volume(&out->stream, (float)0, (float)0);
+                    if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
+                        out_set_voip_volume(&out->stream, (float)0, (float)0);
+                    else
+                        out_set_pcm_volume(&out->stream, (float)0, (float)0);
+
                     /* wait for stale pcm drained before switching to speaker */
                     uint32_t latency =
                         (out->config.period_count * out->config.period_size * 1000) /
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 8caefe8..b357401 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -392,11 +392,12 @@
     pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
     pthread_cond_t  cond;
     /* stream_out->lock is of large granularity, and can only be held before device lock
-     * latch is a supplemetary lock to protect certain fields of out stream and
-     * it can be held after device lock
+     * latch is a supplemetary lock to protect certain fields of out stream (such as
+     * offload_state, a2dp_muted, to add any stream member that needs to be accessed
+     * with device lock held) and it can be held after device lock
      */
     pthread_mutex_t latch_lock;
-    pthread_mutex_t position_query_lock; /* sychronize frame written */
+    pthread_mutex_t position_query_lock;
     struct pcm_config config;
     struct compr_config compr_config;
     struct pcm *pcm;
@@ -424,7 +425,7 @@
 
     int non_blocking;
     int playback_started;
-    int offload_state;
+    int offload_state; /* guarded by latch_lock */
     pthread_cond_t offload_cond;
     pthread_t offload_thread;
     struct listnode offload_cmd_list;
@@ -466,7 +467,7 @@
     qahwi_stream_out_t qahwi_out;
 
     bool is_iec61937_info_available;
-    bool a2dp_muted;
+    bool a2dp_muted; /* guarded by latch_lock */
     float volume_l;
     float volume_r;
     bool apply_volume;
@@ -802,6 +803,7 @@
 audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
                                                  usecase_type_t type);
 
+/* adev lock held */
 int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
 
 int adev_open_output_stream(struct audio_hw_device *dev,
@@ -859,7 +861,8 @@
 
 /*
  * NOTE: when multiple mutexes have to be acquired, always take the
- * stream_in or stream_out mutex first, followed by the audio_device mutex.
+ * stream_in or stream_out mutex first, followed by the audio_device mutex
+ * and latch at last.
  */
 
 #endif // QCOM_AUDIO_HW_H