hal: fix position query issue for track offload

Currently the real time when position queried is returned as
framesAt for track offload, while the actual framesAt should
be earlier when query happens within the write cycle, this can
lead drift in calculated played duration. Thus A/V sync is
mismatched.
Fix this by returning with the rendered time instead of the
current real time when position is queried.

Change-Id: I0837c7db8ec996dde50fd91c50052090b46bdbf1
CRs-Fixed: 2167391
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 4506115..a23561f 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3267,7 +3267,7 @@
     return (size/(channel_count * bytes_per_sample));
 }
 
-static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
+static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
 {
     uint64_t actual_frames_rendered = 0;
     size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
@@ -3278,6 +3278,7 @@
     int64_t platform_latency =  platform_render_latency(out->usecase) *
                                 out->sample_rate / 1000000LL;
 
+    pthread_mutex_lock(&out->position_query_lock);
     /* not querying actual state of buffering in kernel as it would involve an ioctl call
      * which then needs protection, this causes delay in TS query for pcm_offload usecase
      * hence only estimate.
@@ -3286,8 +3287,14 @@
 
     signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
 
-    if (signed_frames > 0)
+    if (signed_frames > 0) {
         actual_frames_rendered = signed_frames;
+        if (timestamp != NULL )
+            *timestamp = out->writeAt;
+    } else if (timestamp != NULL) {
+        clock_gettime(CLOCK_MONOTONIC, timestamp);
+    }
+    pthread_mutex_unlock(&out->position_query_lock);
 
     ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
             "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
@@ -4154,8 +4161,13 @@
     else if (!is_offload_usecase(out->usecase))
         bpf = audio_bytes_per_sample(out->format) *
              audio_channel_count_from_out_mask(out->channel_mask);
-    if (bpf != 0)
+
+    pthread_mutex_lock(&out->position_query_lock);
+    if (bpf != 0) {
         out->written += bytes / bpf;
+        clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
+    }
+    pthread_mutex_unlock(&out->position_query_lock);
 }
 
 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
@@ -4480,7 +4492,7 @@
          * this operation and adev_close_output_stream(where out gets reset).
          */
         if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
-            *dsp_frames = get_actual_pcm_frames_rendered(out);
+            *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
              ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
              adjust_frames_for_device_delay(out, dsp_frames);
              return 0;
@@ -4553,9 +4565,7 @@
      */
     if (is_offload_usecase(out->usecase) && !out->non_blocking &&
         !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
-        *frames = get_actual_pcm_frames_rendered(out);
-        /* this is the best we can do */
-        clock_gettime(CLOCK_MONOTONIC, timestamp);
+        *frames = get_actual_pcm_frames_rendered(out, timestamp);
         ALOGVV("frames %lld playedat %lld",(long long int)*frames,
              timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
         return 0;
@@ -5515,6 +5525,7 @@
     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->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
+    pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
     pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
 
     if (devices == AUDIO_DEVICE_NONE)
@@ -5822,6 +5833,8 @@
         out->is_compr_metadata_avail = false;
         out->offload_state = OFFLOAD_STATE_IDLE;
         out->playback_started = 0;
+        out->writeAt.tv_sec = 0;
+        out->writeAt.tv_nsec = 0;
 
         audio_extn_dts_create_state_notifier_node(out->usecase);
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index c5ee848..730972f 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -271,6 +271,7 @@
     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_mutex_t compr_mute_lock; /* acquire before setting compress volume */
+    pthread_mutex_t position_query_lock; /* acquire before updating/getting position of track offload*/
     pthread_cond_t  cond;
     struct pcm_config config;
     struct compr_config compr_config;
@@ -301,6 +302,7 @@
     pthread_t offload_thread;
     struct listnode offload_cmd_list;
     bool offload_thread_blocked;
+    struct timespec writeAt;
 
     void *adsp_hdlr_stream_handle;
     void *ip_hdlr_handle;