Corrected default value assignments in Bluetooth A2DP Metrics

* In certain cases btif_media_task_stop_aa_req() could be called before
  btif_media_task_start_aa_req() is called, resulting in session_start_us
  to be 0. In this case, audio_duration_ms = time_now_us() - 0 will be a
  very large number that is not the actual audio duration.This CL marks
  audio_duration_ms as -1 in the above situation so that we can
  differentiate between valid and invalid audio durations
* Set default timer and counter values to 0 when
  tx_queue_dequeue_stats.total_updates > 1
* Move update_scheduling_stats for tx_queue_enqueue_stats to
  btif_media_task_aa_handle_timer as we intend to capture the time
  intervals for enqueue scheduling instead of time intervals between
  frame enqueue (i.e. one scheduling event can enqueue multiple frames)
* Use tx_queue_enqueue_stats instead of *dequeue* since only enqueue is
  triggered by timer event

Bug: 33694310
Test: Code compilation, BtFunhausMetricsTest
Change-Id: I10984920afd4d77f07a5ac75736f8dcd69b13af8
diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c
index 7179ffb..cf464e1 100644
--- a/btif/src/btif_media_task.c
+++ b/btif/src/btif_media_task.c
@@ -1471,6 +1471,9 @@
     if (alarm_is_scheduled(btif_media_cb.media_alarm))
     {
         btif_media_send_aa_frame(timestamp_us);
+        update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats,
+                                timestamp_us,
+                                BTIF_SINK_MEDIA_TIME_TICK_MS * 1000);
     }
     else
     {
@@ -1768,7 +1771,12 @@
     fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
     memset(&btif_media_cb.stats, 0, sizeof(btif_media_stats_t));
+    // Assign session_start_us to 1 when time_now_us() is 0 to indicate
+    // btif_media_task_start_aa_req() has been called
     btif_media_cb.stats.session_start_us = time_now_us();
+    if (btif_media_cb.stats.session_start_us == 0) {
+        btif_media_cb.stats.session_start_us = 1;
+    }
     btif_media_cb.stats.session_end_us = 0;
     return TRUE;
 }
@@ -3154,9 +3162,6 @@
             }
 
             /* Enqueue the encoded SBC frame in AA Tx Queue */
-            update_scheduling_stats(&btif_media_cb.stats.tx_queue_enqueue_stats,
-                                    timestamp_us,
-                                    BTIF_SINK_MEDIA_TIME_TICK_MS * 1000);
             uint8_t done_nb_frame = remain_nb_frame - nb_frame;
             remain_nb_frame = nb_frame;
             btif_media_cb.stats.tx_queue_total_frames += done_nb_frame;
@@ -3472,7 +3477,7 @@
 void btif_update_a2dp_metrics(void)
 {
     btif_media_stats_t* stats = &btif_media_cb.stats;
-    scheduling_stats_t* dequeue_stats = &stats->tx_queue_dequeue_stats;
+    scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats;
     A2dpSessionMetrics_t metrics;
     metrics.media_timer_min_ms = -1;
     metrics.media_timer_max_ms = -1;
@@ -3482,21 +3487,26 @@
     metrics.buffer_overruns_total = -1;
     metrics.buffer_underruns_average = -1.0;
     metrics.buffer_underruns_count = -1;
-    int64_t session_end_us = stats->session_end_us == 0
+    metrics.audio_duration_ms = -1;
+    // session_start_us is 0 when btif_media_task_start_aa_req() is not called
+    // mark the metric duration as invalid (-1) in this case
+    if (stats->session_start_us != 0) {
+        int64_t session_end_us = stats->session_end_us == 0
                                ? time_now_us()
                                : stats->session_end_us;
-    metrics.audio_duration_ms = (session_end_us - stats->session_start_us) / 1000;
-    if (dequeue_stats->total_updates > 1) {
+        metrics.audio_duration_ms = (session_end_us - stats->session_start_us) / 1000;
+    }
+    if (enqueue_stats->total_updates > 1) {
         metrics.media_timer_min_ms = BTIF_SINK_MEDIA_TIME_TICK_MS -
-            (dequeue_stats->max_premature_scheduling_delta_us / 1000);
+            (enqueue_stats->max_premature_scheduling_delta_us / 1000);
         metrics.media_timer_max_ms = BTIF_SINK_MEDIA_TIME_TICK_MS +
-            (dequeue_stats->max_overdue_scheduling_delta_us / 1000);
+            (enqueue_stats->max_overdue_scheduling_delta_us / 1000);
         metrics.total_scheduling_count
-            = dequeue_stats->overdue_scheduling_count +
-                dequeue_stats->premature_scheduling_count +
-                    dequeue_stats->exact_scheduling_count;
+            = enqueue_stats->overdue_scheduling_count +
+                enqueue_stats->premature_scheduling_count +
+                    enqueue_stats->exact_scheduling_count;
         if (metrics.total_scheduling_count > 0) {
-            metrics.media_timer_avg_ms = dequeue_stats->total_scheduling_time_us /
+            metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us /
                 (1000 * metrics.total_scheduling_count);
         }
         metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages;
@@ -3504,6 +3514,7 @@
         metrics.buffer_underruns_count =
             stats->media_read_total_underflow_count +
                 stats->media_read_total_underrun_count;
+        metrics.buffer_underruns_average = 0;
         if (metrics.buffer_underruns_count > 0) {
             metrics.buffer_underruns_average =
                 (stats->media_read_total_underflow_bytes +
diff --git a/osi/src/metrics.cpp b/osi/src/metrics.cpp
index dd67c4c..9a91983 100644
--- a/osi/src/metrics.cpp
+++ b/osi/src/metrics.cpp
@@ -93,11 +93,11 @@
 }
 
 void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
-  if (metrics.audio_duration_ms > 0) {
+  if (metrics.audio_duration_ms >= 0) {
     audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
     audio_duration_ms += metrics.audio_duration_ms;
   }
-  if (metrics.media_timer_min_ms > 0) {
+  if (metrics.media_timer_min_ms >= 0) {
     if (media_timer_min_ms < 0) {
       media_timer_min_ms = metrics.media_timer_min_ms;
     } else {
@@ -105,11 +105,11 @@
           std::min(media_timer_min_ms, metrics.media_timer_min_ms);
     }
   }
-  if (metrics.media_timer_max_ms > 0) {
+  if (metrics.media_timer_max_ms >= 0) {
     media_timer_max_ms =
         std::max(media_timer_max_ms, metrics.media_timer_max_ms);
   }
-  if (metrics.media_timer_avg_ms > 0 && metrics.total_scheduling_count > 0) {
+  if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
     if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
       media_timer_avg_ms = metrics.media_timer_avg_ms;
       total_scheduling_count = metrics.total_scheduling_count;
@@ -120,24 +120,24 @@
       total_scheduling_count += metrics.total_scheduling_count;
     }
   }
-  if (metrics.buffer_overruns_max_count > 0) {
+  if (metrics.buffer_overruns_max_count >= 0) {
     buffer_overruns_max_count =
         std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
   }
-  if (metrics.buffer_overruns_total > 0) {
+  if (metrics.buffer_overruns_total >= 0) {
     buffer_overruns_total =
         std::max(static_cast<int32_t>(0), buffer_overruns_total);
     buffer_overruns_total += metrics.buffer_overruns_total;
   }
-  if (metrics.buffer_underruns_average > 0 &&
-      metrics.buffer_underruns_count > 0) {
+  if (metrics.buffer_underruns_average >= 0 &&
+      metrics.buffer_underruns_count >= 0) {
     if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
       buffer_underruns_average = metrics.buffer_underruns_average;
       buffer_underruns_count = metrics.buffer_underruns_count;
     } else {
       buffer_underruns_average = combine_averages(
-          metrics.buffer_underruns_average, metrics.buffer_underruns_count,
-          buffer_underruns_average, buffer_underruns_count);
+          buffer_underruns_average, buffer_underruns_count,
+          metrics.buffer_underruns_average, metrics.buffer_underruns_count);
       buffer_underruns_count += metrics.buffer_underruns_count;
     }
   }