1 /****************************************************************************** 2 * 3 * Copyright (C) 2016 The Android Open Source Project 4 * Copyright (C) 2009-2012 Broadcom Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 ******************************************************************************/ 19 20 #define LOG_TAG "bt_btif_a2dp_source" 21 #define ATRACE_TAG ATRACE_TAG_AUDIO 22 23 #include <base/logging.h> 24 #ifndef OS_GENERIC 25 #include <cutils/trace.h> 26 #endif 27 #include <limits.h> 28 #include <string.h> 29 #include <algorithm> 30 31 #include "audio_a2dp_hw/include/audio_a2dp_hw.h" 32 #include "bt_common.h" 33 #include "bta_av_ci.h" 34 #include "btif_a2dp.h" 35 #include "btif_a2dp_control.h" 36 #include "btif_a2dp_source.h" 37 #include "btif_av.h" 38 #include "btif_av_co.h" 39 #include "btif_util.h" 40 #include "osi/include/fixed_queue.h" 41 #include "osi/include/log.h" 42 #include "osi/include/metrics.h" 43 #include "osi/include/mutex.h" 44 #include "osi/include/osi.h" 45 #include "osi/include/thread.h" 46 #include "osi/include/time.h" 47 #include "uipc.h" 48 49 using system_bt_osi::BluetoothMetricsLogger; 50 using system_bt_osi::A2dpSessionMetrics; 51 52 /** 53 * The typical runlevel of the tx queue size is ~1 buffer 54 * but due to link flow control or thread preemption in lower 55 * layers we might need to temporarily buffer up data. 56 */ 57 #define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (MAX_PCM_FRAME_NUM_PER_TICK * 2) 58 59 enum { 60 BTIF_A2DP_SOURCE_STATE_OFF, 61 BTIF_A2DP_SOURCE_STATE_STARTING_UP, 62 BTIF_A2DP_SOURCE_STATE_RUNNING, 63 BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN 64 }; 65 66 /* BTIF Media Source event definition */ 67 enum { 68 BTIF_MEDIA_AUDIO_TX_START = 1, 69 BTIF_MEDIA_AUDIO_TX_STOP, 70 BTIF_MEDIA_AUDIO_TX_FLUSH, 71 BTIF_MEDIA_SOURCE_ENCODER_INIT, 72 BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE, 73 BTIF_MEDIA_AUDIO_FEEDING_UPDATE 74 }; 75 76 /* tBTIF_A2DP_SOURCE_ENCODER_INIT msg structure */ 77 typedef struct { 78 BT_HDR hdr; 79 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 80 } tBTIF_A2DP_SOURCE_ENCODER_INIT; 81 82 /* tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE msg structure */ 83 typedef struct { 84 BT_HDR hdr; 85 btav_a2dp_codec_config_t user_config; 86 } tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE; 87 88 /* tBTIF_A2DP_AUDIO_FEEDING_UPDATE msg structure */ 89 typedef struct { 90 BT_HDR hdr; 91 btav_a2dp_codec_config_t feeding_params; 92 } tBTIF_A2DP_AUDIO_FEEDING_UPDATE; 93 94 typedef struct { 95 // Counter for total updates 96 size_t total_updates; 97 98 // Last update timestamp (in us) 99 uint64_t last_update_us; 100 101 // Counter for overdue scheduling 102 size_t overdue_scheduling_count; 103 104 // Accumulated overdue scheduling deviations (in us) 105 uint64_t total_overdue_scheduling_delta_us; 106 107 // Max. overdue scheduling delta time (in us) 108 uint64_t max_overdue_scheduling_delta_us; 109 110 // Counter for premature scheduling 111 size_t premature_scheduling_count; 112 113 // Accumulated premature scheduling deviations (in us) 114 uint64_t total_premature_scheduling_delta_us; 115 116 // Max. premature scheduling delta time (in us) 117 uint64_t max_premature_scheduling_delta_us; 118 119 // Counter for exact scheduling 120 size_t exact_scheduling_count; 121 122 // Accumulated and counted scheduling time (in us) 123 uint64_t total_scheduling_time_us; 124 } scheduling_stats_t; 125 126 typedef struct { 127 uint64_t session_start_us; 128 uint64_t session_end_us; 129 130 scheduling_stats_t tx_queue_enqueue_stats; 131 scheduling_stats_t tx_queue_dequeue_stats; 132 133 size_t tx_queue_total_frames; 134 size_t tx_queue_max_frames_per_packet; 135 136 uint64_t tx_queue_total_queueing_time_us; 137 uint64_t tx_queue_max_queueing_time_us; 138 139 size_t tx_queue_total_readbuf_calls; 140 uint64_t tx_queue_last_readbuf_us; 141 142 size_t tx_queue_total_flushed_messages; 143 uint64_t tx_queue_last_flushed_us; 144 145 size_t tx_queue_total_dropped_messages; 146 size_t tx_queue_max_dropped_messages; 147 size_t tx_queue_dropouts; 148 uint64_t tx_queue_last_dropouts_us; 149 150 size_t media_read_total_underflow_bytes; 151 size_t media_read_total_underflow_count; 152 uint64_t media_read_last_underflow_us; 153 } btif_media_stats_t; 154 155 typedef struct { 156 thread_t* worker_thread; 157 fixed_queue_t* cmd_msg_queue; 158 fixed_queue_t* tx_audio_queue; 159 bool tx_flush; /* Discards any outgoing data when true */ 160 alarm_t* media_alarm; 161 const tA2DP_ENCODER_INTERFACE* encoder_interface; 162 period_ms_t encoder_interval_ms; /* Local copy of the encoder interval */ 163 btif_media_stats_t stats; 164 btif_media_stats_t accumulated_stats; 165 } tBTIF_A2DP_SOURCE_CB; 166 167 static tBTIF_A2DP_SOURCE_CB btif_a2dp_source_cb; 168 static int btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF; 169 170 static void btif_a2dp_source_command_ready(fixed_queue_t* queue, void* context); 171 static void btif_a2dp_source_startup_delayed(void* context); 172 static void btif_a2dp_source_shutdown_delayed(void* context); 173 static void btif_a2dp_source_audio_tx_start_event(void); 174 static void btif_a2dp_source_audio_tx_stop_event(void); 175 static void btif_a2dp_source_audio_tx_flush_event(BT_HDR* p_msg); 176 static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg); 177 static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg); 178 static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg); 179 static void btif_a2dp_source_encoder_init(void); 180 static void btif_a2dp_source_encoder_init_req( 181 tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg); 182 static bool btif_a2dp_source_audio_tx_flush_req(void); 183 static void btif_a2dp_source_alarm_cb(void* context); 184 static void btif_a2dp_source_audio_handle_timer(void* context); 185 static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len); 186 static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n); 187 static void log_tstamps_us(const char* comment, uint64_t timestamp_us); 188 static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us, 189 uint64_t expected_delta); 190 static void btm_read_rssi_cb(void* data); 191 static void btm_read_failed_contact_counter_cb(void* data); 192 static void btm_read_automatic_flush_timeout_cb(void* data); 193 static void btm_read_tx_power_cb(void* data); 194 195 UNUSED_ATTR static const char* dump_media_event(uint16_t event) { 196 switch (event) { 197 CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_START) 198 CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_STOP) 199 CASE_RETURN_STR(BTIF_MEDIA_AUDIO_TX_FLUSH) 200 CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_INIT) 201 CASE_RETURN_STR(BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE) 202 CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_UPDATE) 203 default: 204 break; 205 } 206 return "UNKNOWN A2DP SOURCE EVENT"; 207 } 208 209 void btif_a2dp_source_accumulate_scheduling_stats(scheduling_stats_t* src, 210 scheduling_stats_t* dst) { 211 dst->total_updates += src->total_updates; 212 dst->last_update_us = src->last_update_us; 213 dst->overdue_scheduling_count += src->overdue_scheduling_count; 214 dst->total_overdue_scheduling_delta_us += 215 src->total_overdue_scheduling_delta_us; 216 dst->max_overdue_scheduling_delta_us = 217 std::max(dst->max_overdue_scheduling_delta_us, 218 src->max_overdue_scheduling_delta_us); 219 dst->premature_scheduling_count += src->premature_scheduling_count; 220 dst->total_premature_scheduling_delta_us += 221 src->total_premature_scheduling_delta_us; 222 dst->max_premature_scheduling_delta_us = 223 std::max(dst->max_premature_scheduling_delta_us, 224 src->max_premature_scheduling_delta_us); 225 dst->exact_scheduling_count += src->exact_scheduling_count; 226 dst->total_scheduling_time_us += src->total_scheduling_time_us; 227 } 228 229 void btif_a2dp_source_accumulate_stats(btif_media_stats_t* src, 230 btif_media_stats_t* dst) { 231 dst->tx_queue_total_frames += src->tx_queue_total_frames; 232 dst->tx_queue_max_frames_per_packet = std::max( 233 dst->tx_queue_max_frames_per_packet, src->tx_queue_max_frames_per_packet); 234 dst->tx_queue_total_queueing_time_us += src->tx_queue_total_queueing_time_us; 235 dst->tx_queue_max_queueing_time_us = std::max( 236 dst->tx_queue_max_queueing_time_us, src->tx_queue_max_queueing_time_us); 237 dst->tx_queue_total_readbuf_calls += src->tx_queue_total_readbuf_calls; 238 dst->tx_queue_last_readbuf_us = src->tx_queue_last_readbuf_us; 239 dst->tx_queue_total_flushed_messages += src->tx_queue_total_flushed_messages; 240 dst->tx_queue_last_flushed_us = src->tx_queue_last_flushed_us; 241 dst->tx_queue_total_dropped_messages += src->tx_queue_total_dropped_messages; 242 dst->tx_queue_max_dropped_messages = std::max( 243 dst->tx_queue_max_dropped_messages, src->tx_queue_max_dropped_messages); 244 dst->tx_queue_dropouts += src->tx_queue_dropouts; 245 dst->tx_queue_last_dropouts_us = src->tx_queue_last_dropouts_us; 246 dst->media_read_total_underflow_bytes += 247 src->media_read_total_underflow_bytes; 248 dst->media_read_total_underflow_count += 249 src->media_read_total_underflow_count; 250 dst->media_read_last_underflow_us = src->media_read_last_underflow_us; 251 btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_enqueue_stats, 252 &dst->tx_queue_enqueue_stats); 253 btif_a2dp_source_accumulate_scheduling_stats(&src->tx_queue_dequeue_stats, 254 &dst->tx_queue_dequeue_stats); 255 memset(src, 0, sizeof(btif_media_stats_t)); 256 } 257 258 bool btif_a2dp_source_startup(void) { 259 if (btif_a2dp_source_state != BTIF_A2DP_SOURCE_STATE_OFF) { 260 APPL_TRACE_ERROR("%s: A2DP Source media task already running", __func__); 261 return false; 262 } 263 264 memset(&btif_a2dp_source_cb, 0, sizeof(btif_a2dp_source_cb)); 265 btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_STARTING_UP; 266 267 APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##"); 268 269 /* Start A2DP Source media task */ 270 btif_a2dp_source_cb.worker_thread = 271 thread_new("btif_a2dp_source_worker_thread"); 272 if (btif_a2dp_source_cb.worker_thread == NULL) { 273 APPL_TRACE_ERROR("%s: unable to start up media thread", __func__); 274 btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF; 275 return false; 276 } 277 278 btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX); 279 280 btif_a2dp_source_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX); 281 fixed_queue_register_dequeue( 282 btif_a2dp_source_cb.cmd_msg_queue, 283 thread_get_reactor(btif_a2dp_source_cb.worker_thread), 284 btif_a2dp_source_command_ready, NULL); 285 286 APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##"); 287 288 /* Schedule the rest of the startup operations */ 289 thread_post(btif_a2dp_source_cb.worker_thread, 290 btif_a2dp_source_startup_delayed, NULL); 291 292 return true; 293 } 294 295 static void btif_a2dp_source_startup_delayed(UNUSED_ATTR void* context) { 296 raise_priority_a2dp(TASK_HIGH_MEDIA); 297 btif_a2dp_control_init(); 298 btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_RUNNING; 299 BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( 300 system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); 301 } 302 303 void btif_a2dp_source_shutdown(void) { 304 if ((btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) || 305 (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN)) { 306 return; 307 } 308 309 /* Make sure no channels are restarted while shutting down */ 310 btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN; 311 312 APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##"); 313 314 // Stop the timer 315 alarm_free(btif_a2dp_source_cb.media_alarm); 316 btif_a2dp_source_cb.media_alarm = NULL; 317 318 // Exit the thread 319 fixed_queue_free(btif_a2dp_source_cb.cmd_msg_queue, NULL); 320 btif_a2dp_source_cb.cmd_msg_queue = NULL; 321 thread_post(btif_a2dp_source_cb.worker_thread, 322 btif_a2dp_source_shutdown_delayed, NULL); 323 thread_free(btif_a2dp_source_cb.worker_thread); 324 btif_a2dp_source_cb.worker_thread = NULL; 325 } 326 327 static void btif_a2dp_source_shutdown_delayed(UNUSED_ATTR void* context) { 328 btif_a2dp_control_cleanup(); 329 fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, NULL); 330 btif_a2dp_source_cb.tx_audio_queue = NULL; 331 332 btif_a2dp_source_state = BTIF_A2DP_SOURCE_STATE_OFF; 333 BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( 334 system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0); 335 } 336 337 bool btif_a2dp_source_media_task_is_running(void) { 338 return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_RUNNING); 339 } 340 341 bool btif_a2dp_source_media_task_is_shutting_down(void) { 342 return (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_SHUTTING_DOWN); 343 } 344 345 bool btif_a2dp_source_is_streaming(void) { 346 return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm); 347 } 348 349 static void btif_a2dp_source_command_ready(fixed_queue_t* queue, 350 UNUSED_ATTR void* context) { 351 BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue); 352 353 LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event, 354 dump_media_event(p_msg->event)); 355 356 switch (p_msg->event) { 357 case BTIF_MEDIA_AUDIO_TX_START: 358 btif_a2dp_source_audio_tx_start_event(); 359 break; 360 case BTIF_MEDIA_AUDIO_TX_STOP: 361 btif_a2dp_source_audio_tx_stop_event(); 362 break; 363 case BTIF_MEDIA_AUDIO_TX_FLUSH: 364 btif_a2dp_source_audio_tx_flush_event(p_msg); 365 break; 366 case BTIF_MEDIA_SOURCE_ENCODER_INIT: 367 btif_a2dp_source_encoder_init_event(p_msg); 368 break; 369 case BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE: 370 btif_a2dp_source_encoder_user_config_update_event(p_msg); 371 break; 372 case BTIF_MEDIA_AUDIO_FEEDING_UPDATE: 373 btif_a2dp_source_audio_feeding_update_event(p_msg); 374 break; 375 default: 376 APPL_TRACE_ERROR("ERROR in %s unknown event %d", __func__, p_msg->event); 377 break; 378 } 379 380 osi_free(p_msg); 381 LOG_VERBOSE(LOG_TAG, "%s: %s DONE", __func__, dump_media_event(p_msg->event)); 382 } 383 384 void btif_a2dp_source_setup_codec(void) { 385 APPL_TRACE_EVENT("## A2DP SOURCE SETUP CODEC ##"); 386 387 mutex_global_lock(); 388 389 /* Init the encoding task */ 390 btif_a2dp_source_encoder_init(); 391 392 mutex_global_unlock(); 393 } 394 395 void btif_a2dp_source_start_audio_req(void) { 396 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR)); 397 398 p_buf->event = BTIF_MEDIA_AUDIO_TX_START; 399 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 400 memset(&btif_a2dp_source_cb.stats, 0, sizeof(btif_media_stats_t)); 401 // Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to 402 // indicate btif_a2dp_source_start_audio_req() has been called 403 btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us(); 404 if (btif_a2dp_source_cb.stats.session_start_us == 0) { 405 btif_a2dp_source_cb.stats.session_start_us = 1; 406 } 407 btif_a2dp_source_cb.stats.session_end_us = 0; 408 } 409 410 void btif_a2dp_source_stop_audio_req(void) { 411 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR)); 412 413 p_buf->event = BTIF_MEDIA_AUDIO_TX_STOP; 414 415 /* 416 * Explicitly check whether btif_a2dp_source_cb.cmd_msg_queue is not NULL 417 * to avoid a race condition during shutdown of the Bluetooth stack. 418 * This race condition is triggered when A2DP audio is streaming on 419 * shutdown: 420 * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_stop_audio_req()" 421 * is called to stop the particular audio stream, and this happens right 422 * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()" 423 * processing during the shutdown of the Bluetooth stack. 424 */ 425 if (btif_a2dp_source_cb.cmd_msg_queue != NULL) { 426 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 427 } 428 btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us(); 429 btif_a2dp_source_update_metrics(); 430 btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats, 431 &btif_a2dp_source_cb.accumulated_stats); 432 } 433 434 static void btif_a2dp_source_encoder_init(void) { 435 tBTIF_A2DP_SOURCE_ENCODER_INIT msg; 436 437 // Check to make sure the platform has 8 bits/byte since 438 // we're using that in frame size calculations now. 439 CHECK(CHAR_BIT == 8); 440 441 APPL_TRACE_DEBUG("%s", __func__); 442 443 bta_av_co_get_peer_params(&msg.peer_params); 444 btif_a2dp_source_encoder_init_req(&msg); 445 } 446 447 static void btif_a2dp_source_encoder_init_req( 448 tBTIF_A2DP_SOURCE_ENCODER_INIT* p_msg) { 449 tBTIF_A2DP_SOURCE_ENCODER_INIT* p_buf = 450 (tBTIF_A2DP_SOURCE_ENCODER_INIT*)osi_malloc( 451 sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT)); 452 453 memcpy(p_buf, p_msg, sizeof(tBTIF_A2DP_SOURCE_ENCODER_INIT)); 454 p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_INIT; 455 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 456 } 457 458 static void btif_a2dp_source_encoder_init_event(BT_HDR* p_msg) { 459 tBTIF_A2DP_SOURCE_ENCODER_INIT* p_encoder_init = 460 (tBTIF_A2DP_SOURCE_ENCODER_INIT*)p_msg; 461 462 APPL_TRACE_DEBUG("%s", __func__); 463 464 btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface(); 465 if (btif_a2dp_source_cb.encoder_interface == NULL) { 466 APPL_TRACE_ERROR("%s: Cannot stream audio: no source encoder interface", 467 __func__); 468 return; 469 } 470 471 A2dpCodecConfig* a2dp_codec_config = bta_av_get_a2dp_current_codec(); 472 if (a2dp_codec_config == nullptr) { 473 APPL_TRACE_ERROR("%s: Cannot stream audio: current codec is not set", 474 __func__); 475 return; 476 } 477 478 btif_a2dp_source_cb.encoder_interface->encoder_init( 479 &p_encoder_init->peer_params, a2dp_codec_config, 480 btif_a2dp_source_read_callback, btif_a2dp_source_enqueue_callback); 481 482 // Save a local copy of the encoder_interval_ms 483 btif_a2dp_source_cb.encoder_interval_ms = 484 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(); 485 } 486 487 void btif_a2dp_source_encoder_user_config_update_req( 488 const btav_a2dp_codec_config_t& codec_user_config) { 489 tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_buf = 490 (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)osi_malloc( 491 sizeof(tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE)); 492 493 p_buf->user_config = codec_user_config; 494 p_buf->hdr.event = BTIF_MEDIA_SOURCE_ENCODER_USER_CONFIG_UPDATE; 495 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 496 } 497 498 static void btif_a2dp_source_encoder_user_config_update_event(BT_HDR* p_msg) { 499 tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE* p_user_config = 500 (tBTIF_A2DP_SOURCE_ENCODER_USER_CONFIG_UPDATE*)p_msg; 501 502 APPL_TRACE_DEBUG("%s", __func__); 503 if (!bta_av_co_set_codec_user_config(p_user_config->user_config)) { 504 APPL_TRACE_ERROR("%s: cannot update codec user configuration", __func__); 505 } 506 } 507 508 void btif_a2dp_source_feeding_update_req( 509 const btav_a2dp_codec_config_t& codec_audio_config) { 510 tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_buf = 511 (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)osi_malloc( 512 sizeof(tBTIF_A2DP_AUDIO_FEEDING_UPDATE)); 513 514 p_buf->feeding_params = codec_audio_config; 515 p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_UPDATE; 516 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 517 } 518 519 static void btif_a2dp_source_audio_feeding_update_event(BT_HDR* p_msg) { 520 tBTIF_A2DP_AUDIO_FEEDING_UPDATE* p_feeding = 521 (tBTIF_A2DP_AUDIO_FEEDING_UPDATE*)p_msg; 522 523 APPL_TRACE_DEBUG("%s", __func__); 524 if (!bta_av_co_set_codec_audio_config(p_feeding->feeding_params)) { 525 APPL_TRACE_ERROR("%s: cannot update codec audio feeding parameters", 526 __func__); 527 } 528 } 529 530 void btif_a2dp_source_on_idle(void) { 531 if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return; 532 533 /* Make sure media task is stopped */ 534 btif_a2dp_source_stop_audio_req(); 535 } 536 537 void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { 538 APPL_TRACE_EVENT("## ON A2DP SOURCE STOPPED ##"); 539 540 if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return; 541 542 /* allow using this api for other than suspend */ 543 if (p_av_suspend != NULL) { 544 if (p_av_suspend->status != BTA_AV_SUCCESS) { 545 APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av_suspend->status); 546 if (p_av_suspend->initiator) { 547 APPL_TRACE_WARNING("%s: A2DP stop request failed: status = %d", 548 __func__, p_av_suspend->status); 549 btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); 550 } 551 return; 552 } 553 } 554 555 /* ensure tx frames are immediately suspended */ 556 btif_a2dp_source_cb.tx_flush = true; 557 558 /* request to stop media task */ 559 btif_a2dp_source_audio_tx_flush_req(); 560 btif_a2dp_source_stop_audio_req(); 561 562 /* once stream is fully stopped we will ack back */ 563 } 564 565 void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { 566 APPL_TRACE_EVENT("## ON A2DP SOURCE SUSPENDED ##"); 567 568 if (btif_a2dp_source_state == BTIF_A2DP_SOURCE_STATE_OFF) return; 569 570 /* check for status failures */ 571 if (p_av_suspend->status != BTA_AV_SUCCESS) { 572 if (p_av_suspend->initiator) { 573 APPL_TRACE_WARNING("%s: A2DP suspend request failed: status = %d", 574 __func__, p_av_suspend->status); 575 btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); 576 } 577 } 578 579 /* once stream is fully stopped we will ack back */ 580 581 /* ensure tx frames are immediately flushed */ 582 btif_a2dp_source_cb.tx_flush = true; 583 584 /* stop timer tick */ 585 btif_a2dp_source_stop_audio_req(); 586 } 587 588 /* when true media task discards any tx frames */ 589 void btif_a2dp_source_set_tx_flush(bool enable) { 590 APPL_TRACE_EVENT("## DROP TX %d ##", enable); 591 btif_a2dp_source_cb.tx_flush = enable; 592 } 593 594 static void btif_a2dp_source_audio_tx_start_event(void) { 595 APPL_TRACE_DEBUG( 596 "%s media_alarm is %srunning, streaming %s", __func__, 597 alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ", 598 btif_a2dp_source_is_streaming() ? "true" : "false"); 599 600 /* Reset the media feeding state */ 601 CHECK(btif_a2dp_source_cb.encoder_interface != NULL); 602 btif_a2dp_source_cb.encoder_interface->feeding_reset(); 603 604 APPL_TRACE_EVENT( 605 "starting timer %dms", 606 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms()); 607 608 alarm_free(btif_a2dp_source_cb.media_alarm); 609 btif_a2dp_source_cb.media_alarm = 610 alarm_new_periodic("btif.a2dp_source_media_alarm"); 611 if (btif_a2dp_source_cb.media_alarm == NULL) { 612 LOG_ERROR(LOG_TAG, "%s unable to allocate media alarm", __func__); 613 return; 614 } 615 616 alarm_set(btif_a2dp_source_cb.media_alarm, 617 btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(), 618 btif_a2dp_source_alarm_cb, NULL); 619 } 620 621 static void btif_a2dp_source_audio_tx_stop_event(void) { 622 APPL_TRACE_DEBUG( 623 "%s media_alarm is %srunning, streaming %s", __func__, 624 alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ", 625 btif_a2dp_source_is_streaming() ? "true" : "false"); 626 627 const bool send_ack = btif_a2dp_source_is_streaming(); 628 629 /* Stop the timer first */ 630 alarm_free(btif_a2dp_source_cb.media_alarm); 631 btif_a2dp_source_cb.media_alarm = NULL; 632 633 UIPC_Close(UIPC_CH_ID_AV_AUDIO); 634 635 /* 636 * Try to send acknowldegment once the media stream is 637 * stopped. This will make sure that the A2DP HAL layer is 638 * un-blocked on wait for acknowledgment for the sent command. 639 * This resolves a corner cases AVDTP SUSPEND collision 640 * when the DUT and the remote device issue SUSPEND simultaneously 641 * and due to the processing of the SUSPEND request from the remote, 642 * the media path is torn down. If the A2DP HAL happens to wait 643 * for ACK for the initiated SUSPEND, it would never receive it casuing 644 * a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed 645 * to get the ACK for any pending command in such cases. 646 */ 647 648 if (send_ack) btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS); 649 650 /* audio engine stopped, reset tx suspended flag */ 651 btif_a2dp_source_cb.tx_flush = false; 652 653 /* Reset the media feeding state */ 654 if (btif_a2dp_source_cb.encoder_interface != NULL) 655 btif_a2dp_source_cb.encoder_interface->feeding_reset(); 656 } 657 658 static void btif_a2dp_source_alarm_cb(UNUSED_ATTR void* context) { 659 thread_post(btif_a2dp_source_cb.worker_thread, 660 btif_a2dp_source_audio_handle_timer, NULL); 661 } 662 663 static void btif_a2dp_source_audio_handle_timer(UNUSED_ATTR void* context) { 664 uint64_t timestamp_us = time_get_os_boottime_us(); 665 log_tstamps_us("A2DP Source tx timer", timestamp_us); 666 667 if (alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) { 668 CHECK(btif_a2dp_source_cb.encoder_interface != NULL); 669 size_t transmit_queue_length = 670 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue); 671 #ifndef OS_GENERIC 672 ATRACE_INT("btif TX queue", transmit_queue_length); 673 #endif 674 if (btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length != 675 NULL) { 676 btif_a2dp_source_cb.encoder_interface->set_transmit_queue_length( 677 transmit_queue_length); 678 } 679 btif_a2dp_source_cb.encoder_interface->send_frames(timestamp_us); 680 bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); 681 update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_enqueue_stats, 682 timestamp_us, 683 btif_a2dp_source_cb.encoder_interval_ms * 1000); 684 } else { 685 APPL_TRACE_ERROR("ERROR Media task Scheduled after Suspend"); 686 } 687 } 688 689 static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) { 690 uint16_t event; 691 uint32_t bytes_read = UIPC_Read(UIPC_CH_ID_AV_AUDIO, &event, p_buf, len); 692 693 if (bytes_read < len) { 694 LOG_WARN(LOG_TAG, "%s: UNDERFLOW: ONLY READ %d BYTES OUT OF %d", __func__, 695 bytes_read, len); 696 btif_a2dp_source_cb.stats.media_read_total_underflow_bytes += 697 (len - bytes_read); 698 btif_a2dp_source_cb.stats.media_read_total_underflow_count++; 699 btif_a2dp_source_cb.stats.media_read_last_underflow_us = 700 time_get_os_boottime_us(); 701 } 702 703 return bytes_read; 704 } 705 706 static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n) { 707 uint64_t now_us = time_get_os_boottime_us(); 708 709 /* Check if timer was stopped (media task stopped) */ 710 if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) { 711 osi_free(p_buf); 712 return false; 713 } 714 715 /* Check if the transmission queue has been flushed */ 716 if (btif_a2dp_source_cb.tx_flush) { 717 LOG_VERBOSE(LOG_TAG, "%s: tx suspended, discarded frame", __func__); 718 719 btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages += 720 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue); 721 btif_a2dp_source_cb.stats.tx_queue_last_flushed_us = now_us; 722 fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free); 723 724 osi_free(p_buf); 725 return false; 726 } 727 728 // Check for TX queue overflow 729 // TODO: Using frames_n here is probably wrong: should be "+ 1" instead. 730 if (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue) + frames_n > 731 MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) { 732 LOG_WARN(LOG_TAG, "%s: TX queue buffer size now=%u adding=%u max=%d", 733 __func__, 734 (uint32_t)fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue), 735 (uint32_t)frames_n, MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ); 736 // Keep track of drop-outs 737 btif_a2dp_source_cb.stats.tx_queue_dropouts++; 738 btif_a2dp_source_cb.stats.tx_queue_last_dropouts_us = now_us; 739 740 // Flush all queued buffers 741 size_t drop_n = fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue); 742 btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages = std::max( 743 drop_n, btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages); 744 while (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue)) { 745 btif_a2dp_source_cb.stats.tx_queue_total_dropped_messages++; 746 osi_free(fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue)); 747 } 748 749 // Request additional debug info if we had to flush buffers 750 RawAddress peer_bda = btif_av_get_addr(); 751 tBTM_STATUS status = BTM_ReadRSSI(peer_bda, btm_read_rssi_cb); 752 if (status != BTM_CMD_STARTED) { 753 LOG_WARN(LOG_TAG, "%s: Cannot read RSSI: status %d", __func__, status); 754 } 755 status = BTM_ReadFailedContactCounter(peer_bda, 756 btm_read_failed_contact_counter_cb); 757 if (status != BTM_CMD_STARTED) { 758 LOG_WARN(LOG_TAG, "%s: Cannot read Failed Contact Counter: status %d", 759 __func__, status); 760 } 761 status = BTM_ReadAutomaticFlushTimeout(peer_bda, 762 btm_read_automatic_flush_timeout_cb); 763 if (status != BTM_CMD_STARTED) { 764 LOG_WARN(LOG_TAG, "%s: Cannot read Automatic Flush Timeout: status %d", 765 __func__, status); 766 } 767 status = 768 BTM_ReadTxPower(peer_bda, BT_TRANSPORT_BR_EDR, btm_read_tx_power_cb); 769 if (status != BTM_CMD_STARTED) { 770 LOG_WARN(LOG_TAG, "%s: Cannot read Tx Power: status %d", __func__, 771 status); 772 } 773 } 774 775 /* Update the statistics */ 776 btif_a2dp_source_cb.stats.tx_queue_total_frames += frames_n; 777 btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet = std::max( 778 frames_n, btif_a2dp_source_cb.stats.tx_queue_max_frames_per_packet); 779 CHECK(btif_a2dp_source_cb.encoder_interface != NULL); 780 781 fixed_queue_enqueue(btif_a2dp_source_cb.tx_audio_queue, p_buf); 782 783 return true; 784 } 785 786 static void btif_a2dp_source_audio_tx_flush_event(UNUSED_ATTR BT_HDR* p_msg) { 787 /* Flush all enqueued audio buffers (encoded) */ 788 APPL_TRACE_DEBUG("%s", __func__); 789 790 if (btif_a2dp_source_cb.encoder_interface != NULL) 791 btif_a2dp_source_cb.encoder_interface->feeding_flush(); 792 793 btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages += 794 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue); 795 btif_a2dp_source_cb.stats.tx_queue_last_flushed_us = 796 time_get_os_boottime_us(); 797 fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free); 798 799 UIPC_Ioctl(UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, NULL); 800 } 801 802 static bool btif_a2dp_source_audio_tx_flush_req(void) { 803 BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR)); 804 805 p_buf->event = BTIF_MEDIA_AUDIO_TX_FLUSH; 806 807 /* 808 * Explicitly check whether the btif_a2dp_source_cb.cmd_msg_queue is not 809 * NULL to avoid a race condition during shutdown of the Bluetooth stack. 810 * This race condition is triggered when A2DP audio is streaming on 811 * shutdown: 812 * "btif_a2dp_source_on_stopped() -> btif_a2dp_source_audio_tx_flush_req()" 813 * is called to stop the particular audio stream, and this happens right 814 * after the "BTIF_AV_CLEANUP_REQ_EVT -> btif_a2dp_source_shutdown()" 815 * processing during the shutdown of the Bluetooth stack. 816 */ 817 if (btif_a2dp_source_cb.cmd_msg_queue != NULL) 818 fixed_queue_enqueue(btif_a2dp_source_cb.cmd_msg_queue, p_buf); 819 820 return true; 821 } 822 823 BT_HDR* btif_a2dp_source_audio_readbuf(void) { 824 uint64_t now_us = time_get_os_boottime_us(); 825 BT_HDR* p_buf = 826 (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue); 827 828 btif_a2dp_source_cb.stats.tx_queue_total_readbuf_calls++; 829 btif_a2dp_source_cb.stats.tx_queue_last_readbuf_us = now_us; 830 if (p_buf != NULL) { 831 // Update the statistics 832 update_scheduling_stats(&btif_a2dp_source_cb.stats.tx_queue_dequeue_stats, 833 now_us, 834 btif_a2dp_source_cb.encoder_interval_ms * 1000); 835 } 836 837 return p_buf; 838 } 839 840 static void log_tstamps_us(const char* comment, uint64_t timestamp_us) { 841 static uint64_t prev_us = 0; 842 APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, 843 timestamp_us, timestamp_us - prev_us, 844 fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue)); 845 prev_us = timestamp_us; 846 } 847 848 static void update_scheduling_stats(scheduling_stats_t* stats, uint64_t now_us, 849 uint64_t expected_delta) { 850 uint64_t last_us = stats->last_update_us; 851 852 stats->total_updates++; 853 stats->last_update_us = now_us; 854 855 if (last_us == 0) return; // First update: expected delta doesn't apply 856 857 uint64_t deadline_us = last_us + expected_delta; 858 if (deadline_us < now_us) { 859 // Overdue scheduling 860 uint64_t delta_us = now_us - deadline_us; 861 // Ignore extreme outliers 862 if (delta_us < 10 * expected_delta) { 863 stats->max_overdue_scheduling_delta_us = 864 std::max(delta_us, stats->max_overdue_scheduling_delta_us); 865 stats->total_overdue_scheduling_delta_us += delta_us; 866 stats->overdue_scheduling_count++; 867 stats->total_scheduling_time_us += now_us - last_us; 868 } 869 } else if (deadline_us > now_us) { 870 // Premature scheduling 871 uint64_t delta_us = deadline_us - now_us; 872 // Ignore extreme outliers 873 if (delta_us < 10 * expected_delta) { 874 stats->max_premature_scheduling_delta_us = 875 std::max(delta_us, stats->max_premature_scheduling_delta_us); 876 stats->total_premature_scheduling_delta_us += delta_us; 877 stats->premature_scheduling_count++; 878 stats->total_scheduling_time_us += now_us - last_us; 879 } 880 } else { 881 // On-time scheduling 882 stats->exact_scheduling_count++; 883 stats->total_scheduling_time_us += now_us - last_us; 884 } 885 } 886 887 void btif_a2dp_source_debug_dump(int fd) { 888 btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats, 889 &btif_a2dp_source_cb.accumulated_stats); 890 uint64_t now_us = time_get_os_boottime_us(); 891 btif_media_stats_t* accumulated_stats = 892 &btif_a2dp_source_cb.accumulated_stats; 893 scheduling_stats_t* enqueue_stats = 894 &accumulated_stats->tx_queue_enqueue_stats; 895 scheduling_stats_t* dequeue_stats = 896 &accumulated_stats->tx_queue_dequeue_stats; 897 size_t ave_size; 898 uint64_t ave_time_us; 899 900 dprintf(fd, "\nA2DP State:\n"); 901 dprintf(fd, " TxQueue:\n"); 902 903 dprintf(fd, 904 " Counts (enqueue/dequeue/readbuf) : %zu / " 905 "%zu / %zu\n", 906 enqueue_stats->total_updates, dequeue_stats->total_updates, 907 accumulated_stats->tx_queue_total_readbuf_calls); 908 909 dprintf( 910 fd, 911 " Last update time ago in ms (enqueue/dequeue/readbuf) : %llu / %llu " 912 "/ %llu\n", 913 (enqueue_stats->last_update_us > 0) 914 ? (unsigned long long)(now_us - enqueue_stats->last_update_us) / 1000 915 : 0, 916 (dequeue_stats->last_update_us > 0) 917 ? (unsigned long long)(now_us - dequeue_stats->last_update_us) / 1000 918 : 0, 919 (accumulated_stats->tx_queue_last_readbuf_us > 0) 920 ? (unsigned long long)(now_us - 921 accumulated_stats->tx_queue_last_readbuf_us) / 922 1000 923 : 0); 924 925 ave_size = 0; 926 if (enqueue_stats->total_updates != 0) 927 ave_size = 928 accumulated_stats->tx_queue_total_frames / enqueue_stats->total_updates; 929 dprintf(fd, 930 " Frames per packet (total/max/ave) : %zu / " 931 "%zu / %zu\n", 932 accumulated_stats->tx_queue_total_frames, 933 accumulated_stats->tx_queue_max_frames_per_packet, ave_size); 934 935 dprintf(fd, 936 " Counts (flushed/dropped/dropouts) : %zu / " 937 "%zu / %zu\n", 938 accumulated_stats->tx_queue_total_flushed_messages, 939 accumulated_stats->tx_queue_total_dropped_messages, 940 accumulated_stats->tx_queue_dropouts); 941 942 dprintf(fd, 943 " Counts (max dropped) : %zu\n", 944 accumulated_stats->tx_queue_max_dropped_messages); 945 946 dprintf( 947 fd, 948 " Last update time ago in ms (flushed/dropped) : %llu / " 949 "%llu\n", 950 (accumulated_stats->tx_queue_last_flushed_us > 0) 951 ? (unsigned long long)(now_us - 952 accumulated_stats->tx_queue_last_flushed_us) / 953 1000 954 : 0, 955 (accumulated_stats->tx_queue_last_dropouts_us > 0) 956 ? (unsigned long long)(now_us - 957 accumulated_stats->tx_queue_last_dropouts_us) / 958 1000 959 : 0); 960 961 dprintf(fd, 962 " Counts (underflow) : %zu\n", 963 accumulated_stats->media_read_total_underflow_count); 964 965 dprintf(fd, 966 " Bytes (underflow) : %zu\n", 967 accumulated_stats->media_read_total_underflow_bytes); 968 969 dprintf(fd, 970 " Last update time ago in ms (underflow) : %llu\n", 971 (accumulated_stats->media_read_last_underflow_us > 0) 972 ? (unsigned long long)(now_us - 973 accumulated_stats 974 ->media_read_last_underflow_us) / 975 1000 976 : 0); 977 978 // 979 // TxQueue enqueue stats 980 // 981 dprintf( 982 fd, 983 " Enqueue deviation counts (overdue/premature) : %zu / %zu\n", 984 enqueue_stats->overdue_scheduling_count, 985 enqueue_stats->premature_scheduling_count); 986 987 ave_time_us = 0; 988 if (enqueue_stats->overdue_scheduling_count != 0) { 989 ave_time_us = enqueue_stats->total_overdue_scheduling_delta_us / 990 enqueue_stats->overdue_scheduling_count; 991 } 992 dprintf( 993 fd, 994 " Enqueue overdue scheduling time in ms (total/max/ave) : %llu / %llu " 995 "/ %llu\n", 996 (unsigned long long)enqueue_stats->total_overdue_scheduling_delta_us / 997 1000, 998 (unsigned long long)enqueue_stats->max_overdue_scheduling_delta_us / 1000, 999 (unsigned long long)ave_time_us / 1000); 1000 1001 ave_time_us = 0; 1002 if (enqueue_stats->premature_scheduling_count != 0) { 1003 ave_time_us = enqueue_stats->total_premature_scheduling_delta_us / 1004 enqueue_stats->premature_scheduling_count; 1005 } 1006 dprintf( 1007 fd, 1008 " Enqueue premature scheduling time in ms (total/max/ave) : %llu / %llu " 1009 "/ %llu\n", 1010 (unsigned long long)enqueue_stats->total_premature_scheduling_delta_us / 1011 1000, 1012 (unsigned long long)enqueue_stats->max_premature_scheduling_delta_us / 1013 1000, 1014 (unsigned long long)ave_time_us / 1000); 1015 1016 // 1017 // TxQueue dequeue stats 1018 // 1019 dprintf( 1020 fd, 1021 " Dequeue deviation counts (overdue/premature) : %zu / %zu\n", 1022 dequeue_stats->overdue_scheduling_count, 1023 dequeue_stats->premature_scheduling_count); 1024 1025 ave_time_us = 0; 1026 if (dequeue_stats->overdue_scheduling_count != 0) { 1027 ave_time_us = dequeue_stats->total_overdue_scheduling_delta_us / 1028 dequeue_stats->overdue_scheduling_count; 1029 } 1030 dprintf( 1031 fd, 1032 " Dequeue overdue scheduling time in ms (total/max/ave) : %llu / %llu " 1033 "/ %llu\n", 1034 (unsigned long long)dequeue_stats->total_overdue_scheduling_delta_us / 1035 1000, 1036 (unsigned long long)dequeue_stats->max_overdue_scheduling_delta_us / 1000, 1037 (unsigned long long)ave_time_us / 1000); 1038 1039 ave_time_us = 0; 1040 if (dequeue_stats->premature_scheduling_count != 0) { 1041 ave_time_us = dequeue_stats->total_premature_scheduling_delta_us / 1042 dequeue_stats->premature_scheduling_count; 1043 } 1044 dprintf( 1045 fd, 1046 " Dequeue premature scheduling time in ms (total/max/ave) : %llu / %llu " 1047 "/ %llu\n", 1048 (unsigned long long)dequeue_stats->total_premature_scheduling_delta_us / 1049 1000, 1050 (unsigned long long)dequeue_stats->max_premature_scheduling_delta_us / 1051 1000, 1052 (unsigned long long)ave_time_us / 1000); 1053 1054 // 1055 // Codec-specific stats 1056 // 1057 A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs(); 1058 if (a2dp_codecs != nullptr) { 1059 a2dp_codecs->debug_codec_dump(fd); 1060 } 1061 } 1062 1063 void btif_a2dp_source_update_metrics(void) { 1064 btif_media_stats_t* stats = &btif_a2dp_source_cb.stats; 1065 scheduling_stats_t* enqueue_stats = &stats->tx_queue_enqueue_stats; 1066 A2dpSessionMetrics metrics; 1067 // session_start_us is 0 when btif_a2dp_source_start_audio_req() is not called 1068 // mark the metric duration as invalid (-1) in this case 1069 if (stats->session_start_us != 0) { 1070 int64_t session_end_us = stats->session_end_us == 0 1071 ? time_get_os_boottime_us() 1072 : stats->session_end_us; 1073 metrics.audio_duration_ms = 1074 (session_end_us - stats->session_start_us) / 1000; 1075 } 1076 1077 if (enqueue_stats->total_updates > 1) { 1078 metrics.media_timer_min_ms = 1079 btif_a2dp_source_cb.encoder_interval_ms - 1080 (enqueue_stats->max_premature_scheduling_delta_us / 1000); 1081 metrics.media_timer_max_ms = 1082 btif_a2dp_source_cb.encoder_interval_ms + 1083 (enqueue_stats->max_overdue_scheduling_delta_us / 1000); 1084 1085 metrics.total_scheduling_count = enqueue_stats->overdue_scheduling_count + 1086 enqueue_stats->premature_scheduling_count + 1087 enqueue_stats->exact_scheduling_count; 1088 if (metrics.total_scheduling_count > 0) { 1089 metrics.media_timer_avg_ms = enqueue_stats->total_scheduling_time_us / 1090 (1000 * metrics.total_scheduling_count); 1091 } 1092 1093 metrics.buffer_overruns_max_count = stats->tx_queue_max_dropped_messages; 1094 metrics.buffer_overruns_total = stats->tx_queue_total_dropped_messages; 1095 metrics.buffer_underruns_count = stats->media_read_total_underflow_count; 1096 metrics.buffer_underruns_average = 0; 1097 if (metrics.buffer_underruns_count > 0) { 1098 metrics.buffer_underruns_average = 1099 stats->media_read_total_underflow_bytes / 1100 metrics.buffer_underruns_count; 1101 } 1102 } 1103 BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics); 1104 } 1105 1106 static void btm_read_rssi_cb(void* data) { 1107 if (data == nullptr) { 1108 LOG_ERROR(LOG_TAG, "%s Read RSSI request timed out", __func__); 1109 return; 1110 } 1111 1112 tBTM_RSSI_RESULT* result = (tBTM_RSSI_RESULT*)data; 1113 if (result->status != BTM_SUCCESS) { 1114 LOG_ERROR(LOG_TAG, "%s unable to read remote RSSI (status %d)", __func__, 1115 result->status); 1116 return; 1117 } 1118 1119 LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__, 1120 result->rem_bda.ToString().c_str(), result->rssi); 1121 } 1122 1123 static void btm_read_failed_contact_counter_cb(void* data) { 1124 if (data == nullptr) { 1125 LOG_ERROR(LOG_TAG, "%s Read Failed Contact Counter request timed out", 1126 __func__); 1127 return; 1128 } 1129 1130 tBTM_FAILED_CONTACT_COUNTER_RESULT* result = 1131 (tBTM_FAILED_CONTACT_COUNTER_RESULT*)data; 1132 if (result->status != BTM_SUCCESS) { 1133 LOG_ERROR(LOG_TAG, "%s unable to read Failed Contact Counter (status %d)", 1134 __func__, result->status); 1135 return; 1136 } 1137 1138 LOG_WARN(LOG_TAG, "%s device: %s, Failed Contact Counter: %u", __func__, 1139 result->rem_bda.ToString().c_str(), result->failed_contact_counter); 1140 } 1141 1142 static void btm_read_automatic_flush_timeout_cb(void* data) { 1143 if (data == nullptr) { 1144 LOG_ERROR(LOG_TAG, "%s Read Automatic Flush Timeout request timed out", 1145 __func__); 1146 return; 1147 } 1148 1149 tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT* result = 1150 (tBTM_AUTOMATIC_FLUSH_TIMEOUT_RESULT*)data; 1151 if (result->status != BTM_SUCCESS) { 1152 LOG_ERROR(LOG_TAG, "%s unable to read Automatic Flush Timeout (status %d)", 1153 __func__, result->status); 1154 return; 1155 } 1156 1157 LOG_WARN(LOG_TAG, "%s device: %s, Automatic Flush Timeout: %u", __func__, 1158 result->rem_bda.ToString().c_str(), result->automatic_flush_timeout); 1159 } 1160 1161 static void btm_read_tx_power_cb(void* data) { 1162 if (data == nullptr) { 1163 LOG_ERROR(LOG_TAG, "%s Read Tx Power request timed out", __func__); 1164 return; 1165 } 1166 1167 tBTM_TX_POWER_RESULT* result = (tBTM_TX_POWER_RESULT*)data; 1168 if (result->status != BTM_SUCCESS) { 1169 LOG_ERROR(LOG_TAG, "%s unable to read Tx Power (status %d)", __func__, 1170 result->status); 1171 return; 1172 } 1173 1174 LOG_WARN(LOG_TAG, "%s device: %s, Tx Power: %d", __func__, 1175 result->rem_bda.ToString().c_str(), result->tx_power); 1176 } 1177