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;
}
}