1 /****************************************************************************** 2 * 3 * Copyright 2016 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 #define LOG_TAG "bt_osi_metrics" 19 20 #include <unistd.h> 21 #include <algorithm> 22 #include <array> 23 #include <cerrno> 24 #include <chrono> 25 #include <cstdint> 26 #include <cstring> 27 #include <memory> 28 #include <mutex> 29 30 #include <base/base64.h> 31 #include <base/logging.h> 32 33 #include "bluetooth/metrics/bluetooth.pb.h" 34 #include "osi/include/leaky_bonded_queue.h" 35 #include "osi/include/log.h" 36 #include "osi/include/osi.h" 37 #include "osi/include/time.h" 38 #include "stack/include/btm_api_types.h" 39 40 #include "osi/include/metrics.h" 41 42 namespace system_bt_osi { 43 44 using bluetooth::metrics::BluetoothMetricsProto::A2DPSession; 45 using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog; 46 using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession; 47 using bluetooth::metrics::BluetoothMetricsProto:: 48 BluetoothSession_ConnectionTechnologyType; 49 using bluetooth::metrics::BluetoothMetricsProto:: 50 BluetoothSession_DisconnectReasonType; 51 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo; 52 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType; 53 using bluetooth::metrics::BluetoothMetricsProto::PairEvent; 54 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent; 55 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType; 56 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType; 57 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent; 58 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType; 59 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType; 60 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN; 61 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX; 62 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE; 63 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid; 64 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats; 65 /* 66 * Get current OS boot time in millisecond 67 */ 68 static int64_t time_get_os_boottime_ms(void) { 69 return time_get_os_boottime_us() / 1000; 70 } 71 72 static float combine_averages(float avg_a, int64_t ct_a, float avg_b, 73 int64_t ct_b) { 74 if (ct_a > 0 && ct_b > 0) { 75 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); 76 } else if (ct_b > 0) { 77 return avg_b; 78 } else { 79 return avg_a; 80 } 81 } 82 83 static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b, 84 int64_t ct_b) { 85 if (ct_a > 0 && ct_b > 0) { 86 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); 87 } else if (ct_b > 0) { 88 return avg_b; 89 } else { 90 return avg_a; 91 } 92 } 93 94 void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) { 95 if (metrics.audio_duration_ms >= 0) { 96 audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms); 97 audio_duration_ms += metrics.audio_duration_ms; 98 } 99 if (metrics.media_timer_min_ms >= 0) { 100 if (media_timer_min_ms < 0) { 101 media_timer_min_ms = metrics.media_timer_min_ms; 102 } else { 103 media_timer_min_ms = 104 std::min(media_timer_min_ms, metrics.media_timer_min_ms); 105 } 106 } 107 if (metrics.media_timer_max_ms >= 0) { 108 media_timer_max_ms = 109 std::max(media_timer_max_ms, metrics.media_timer_max_ms); 110 } 111 if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) { 112 if (media_timer_avg_ms < 0 || total_scheduling_count < 0) { 113 media_timer_avg_ms = metrics.media_timer_avg_ms; 114 total_scheduling_count = metrics.total_scheduling_count; 115 } else { 116 media_timer_avg_ms = combine_averages( 117 media_timer_avg_ms, total_scheduling_count, 118 metrics.media_timer_avg_ms, metrics.total_scheduling_count); 119 total_scheduling_count += metrics.total_scheduling_count; 120 } 121 } 122 if (metrics.buffer_overruns_max_count >= 0) { 123 buffer_overruns_max_count = 124 std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count); 125 } 126 if (metrics.buffer_overruns_total >= 0) { 127 buffer_overruns_total = 128 std::max(static_cast<int32_t>(0), buffer_overruns_total); 129 buffer_overruns_total += metrics.buffer_overruns_total; 130 } 131 if (metrics.buffer_underruns_average >= 0 && 132 metrics.buffer_underruns_count >= 0) { 133 if (buffer_underruns_average < 0 || buffer_underruns_count < 0) { 134 buffer_underruns_average = metrics.buffer_underruns_average; 135 buffer_underruns_count = metrics.buffer_underruns_count; 136 } else { 137 buffer_underruns_average = combine_averages( 138 buffer_underruns_average, buffer_underruns_count, 139 metrics.buffer_underruns_average, metrics.buffer_underruns_count); 140 buffer_underruns_count += metrics.buffer_underruns_count; 141 } 142 } 143 } 144 145 bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const { 146 return audio_duration_ms == rhs.audio_duration_ms && 147 media_timer_min_ms == rhs.media_timer_min_ms && 148 media_timer_max_ms == rhs.media_timer_max_ms && 149 media_timer_avg_ms == rhs.media_timer_avg_ms && 150 total_scheduling_count == rhs.total_scheduling_count && 151 buffer_overruns_max_count == rhs.buffer_overruns_max_count && 152 buffer_overruns_total == rhs.buffer_overruns_total && 153 buffer_underruns_average == rhs.buffer_underruns_average && 154 buffer_underruns_count == rhs.buffer_underruns_count; 155 } 156 157 static DeviceInfo_DeviceType get_device_type(device_type_t type) { 158 switch (type) { 159 case DEVICE_TYPE_BREDR: 160 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR; 161 case DEVICE_TYPE_LE: 162 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE; 163 case DEVICE_TYPE_DUMO: 164 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO; 165 case DEVICE_TYPE_UNKNOWN: 166 default: 167 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN; 168 } 169 } 170 171 static BluetoothSession_ConnectionTechnologyType get_connection_tech_type( 172 connection_tech_t type) { 173 switch (type) { 174 case CONNECTION_TECHNOLOGY_TYPE_LE: 175 return BluetoothSession_ConnectionTechnologyType:: 176 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE; 177 case CONNECTION_TECHNOLOGY_TYPE_BREDR: 178 return BluetoothSession_ConnectionTechnologyType:: 179 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR; 180 case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN: 181 default: 182 return BluetoothSession_ConnectionTechnologyType:: 183 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN; 184 } 185 } 186 187 static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) { 188 switch (type) { 189 case SCAN_TECH_TYPE_LE: 190 return ScanEvent_ScanTechnologyType:: 191 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE; 192 case SCAN_TECH_TYPE_BREDR: 193 return ScanEvent_ScanTechnologyType:: 194 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR; 195 case SCAN_TECH_TYPE_BOTH: 196 return ScanEvent_ScanTechnologyType:: 197 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH; 198 case SCAN_TYPE_UNKNOWN: 199 default: 200 return ScanEvent_ScanTechnologyType:: 201 ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN; 202 } 203 } 204 205 static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) { 206 switch (type) { 207 case WAKE_EVENT_ACQUIRED: 208 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED; 209 case WAKE_EVENT_RELEASED: 210 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED; 211 case WAKE_EVENT_UNKNOWN: 212 default: 213 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN; 214 } 215 } 216 217 static BluetoothSession_DisconnectReasonType get_disconnect_reason_type( 218 disconnect_reason_t type) { 219 switch (type) { 220 case DISCONNECT_REASON_METRICS_DUMP: 221 return BluetoothSession_DisconnectReasonType:: 222 BluetoothSession_DisconnectReasonType_METRICS_DUMP; 223 case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS: 224 return BluetoothSession_DisconnectReasonType:: 225 BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS; 226 case DISCONNECT_REASON_UNKNOWN: 227 default: 228 return BluetoothSession_DisconnectReasonType:: 229 BluetoothSession_DisconnectReasonType_UNKNOWN; 230 } 231 } 232 233 struct BluetoothMetricsLogger::impl { 234 impl(size_t max_bluetooth_session, size_t max_pair_event, 235 size_t max_wake_event, size_t max_scan_event) 236 : bt_session_queue_( 237 new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)), 238 pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)), 239 wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)), 240 scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) { 241 bluetooth_log_ = BluetoothLog::default_instance().New(); 242 headset_profile_connection_counts_.fill(0); 243 bluetooth_session_ = nullptr; 244 bluetooth_session_start_time_ms_ = 0; 245 a2dp_session_metrics_ = A2dpSessionMetrics(); 246 } 247 248 /* Bluetooth log lock protected */ 249 BluetoothLog* bluetooth_log_; 250 std::array<int, HeadsetProfileType_ARRAYSIZE> 251 headset_profile_connection_counts_; 252 std::recursive_mutex bluetooth_log_lock_; 253 /* End Bluetooth log lock protected */ 254 /* Bluetooth session lock protected */ 255 BluetoothSession* bluetooth_session_; 256 uint64_t bluetooth_session_start_time_ms_; 257 A2dpSessionMetrics a2dp_session_metrics_; 258 std::recursive_mutex bluetooth_session_lock_; 259 /* End bluetooth session lock protected */ 260 std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_; 261 std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_; 262 std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_; 263 std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_; 264 }; 265 266 BluetoothMetricsLogger::BluetoothMetricsLogger() 267 : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent, 268 kMaxNumWakeEvent, kMaxNumScanEvent)) {} 269 270 void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason, 271 uint64_t timestamp_ms, 272 uint32_t device_class, 273 device_type_t device_type) { 274 PairEvent* event = new PairEvent(); 275 DeviceInfo* info = event->mutable_device_paired_with(); 276 info->set_device_class(device_class); 277 info->set_device_type(get_device_type(device_type)); 278 event->set_disconnect_reason(disconnect_reason); 279 event->set_event_time_millis(timestamp_ms); 280 pimpl_->pair_event_queue_->Enqueue(event); 281 { 282 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 283 pimpl_->bluetooth_log_->set_num_pair_event( 284 pimpl_->bluetooth_log_->num_pair_event() + 1); 285 } 286 } 287 288 void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type, 289 const std::string& requestor, 290 const std::string& name, 291 uint64_t timestamp_ms) { 292 WakeEvent* event = new WakeEvent(); 293 event->set_wake_event_type(get_wake_event_type(type)); 294 event->set_requestor(requestor); 295 event->set_name(name); 296 event->set_event_time_millis(timestamp_ms); 297 pimpl_->wake_event_queue_->Enqueue(event); 298 { 299 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 300 pimpl_->bluetooth_log_->set_num_wake_event( 301 pimpl_->bluetooth_log_->num_wake_event() + 1); 302 } 303 } 304 305 void BluetoothMetricsLogger::LogScanEvent(bool start, 306 const std::string& initator, 307 scan_tech_t type, uint32_t results, 308 uint64_t timestamp_ms) { 309 ScanEvent* event = new ScanEvent(); 310 if (start) { 311 event->set_scan_event_type(ScanEvent::SCAN_EVENT_START); 312 } else { 313 event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP); 314 } 315 event->set_initiator(initator); 316 event->set_scan_technology_type(get_scan_tech_type(type)); 317 event->set_number_results(results); 318 event->set_event_time_millis(timestamp_ms); 319 pimpl_->scan_event_queue_->Enqueue(event); 320 { 321 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 322 pimpl_->bluetooth_log_->set_num_scan_event( 323 pimpl_->bluetooth_log_->num_scan_event() + 1); 324 } 325 } 326 327 void BluetoothMetricsLogger::LogBluetoothSessionStart( 328 connection_tech_t connection_tech_type, uint64_t timestamp_ms) { 329 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 330 if (pimpl_->bluetooth_session_ != nullptr) { 331 LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, 332 0); 333 } 334 if (timestamp_ms == 0) { 335 timestamp_ms = time_get_os_boottime_ms(); 336 } 337 pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms; 338 pimpl_->bluetooth_session_ = new BluetoothSession(); 339 pimpl_->bluetooth_session_->set_connection_technology_type( 340 get_connection_tech_type(connection_tech_type)); 341 } 342 343 void BluetoothMetricsLogger::LogBluetoothSessionEnd( 344 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) { 345 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 346 if (pimpl_->bluetooth_session_ == nullptr) { 347 return; 348 } 349 if (timestamp_ms == 0) { 350 timestamp_ms = time_get_os_boottime_ms(); 351 } 352 int64_t session_duration_sec = 353 (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000; 354 pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec); 355 pimpl_->bluetooth_session_->set_disconnect_reason_type( 356 get_disconnect_reason_type(disconnect_reason)); 357 pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_); 358 pimpl_->bluetooth_session_ = nullptr; 359 { 360 std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_); 361 pimpl_->bluetooth_log_->set_num_bluetooth_session( 362 pimpl_->bluetooth_log_->num_bluetooth_session() + 1); 363 } 364 } 365 366 void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo( 367 uint32_t device_class, device_type_t device_type) { 368 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 369 if (pimpl_->bluetooth_session_ == nullptr) { 370 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0); 371 } 372 DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to(); 373 info->set_device_class(device_class); 374 info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR); 375 } 376 377 void BluetoothMetricsLogger::LogA2dpSession( 378 const A2dpSessionMetrics& a2dp_session_metrics) { 379 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 380 if (pimpl_->bluetooth_session_ == nullptr) { 381 // When no bluetooth session exist, create one on system's behalf 382 // Set connection type: for A2DP it is always BR/EDR 383 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); 384 LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR); 385 } 386 // Accumulate metrics 387 pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics); 388 // Get or allocate new A2DP session object 389 A2DPSession* a2dp_session = 390 pimpl_->bluetooth_session_->mutable_a2dp_session(); 391 a2dp_session->set_audio_duration_millis( 392 pimpl_->a2dp_session_metrics_.audio_duration_ms); 393 a2dp_session->set_media_timer_min_millis( 394 pimpl_->a2dp_session_metrics_.media_timer_min_ms); 395 a2dp_session->set_media_timer_max_millis( 396 pimpl_->a2dp_session_metrics_.media_timer_max_ms); 397 a2dp_session->set_media_timer_avg_millis( 398 pimpl_->a2dp_session_metrics_.media_timer_avg_ms); 399 a2dp_session->set_buffer_overruns_max_count( 400 pimpl_->a2dp_session_metrics_.buffer_overruns_max_count); 401 a2dp_session->set_buffer_overruns_total( 402 pimpl_->a2dp_session_metrics_.buffer_overruns_total); 403 a2dp_session->set_buffer_underruns_average( 404 pimpl_->a2dp_session_metrics_.buffer_underruns_average); 405 a2dp_session->set_buffer_underruns_count( 406 pimpl_->a2dp_session_metrics_.buffer_underruns_count); 407 } 408 409 void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection( 410 tBTA_SERVICE_ID service_id) { 411 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 412 switch (service_id) { 413 case BTA_HSP_SERVICE_ID: 414 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++; 415 break; 416 case BTA_HFP_SERVICE_ID: 417 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++; 418 break; 419 default: 420 pimpl_->headset_profile_connection_counts_ 421 [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++; 422 break; 423 } 424 return; 425 } 426 427 void BluetoothMetricsLogger::WriteString(std::string* serialized) { 428 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 429 LOG_DEBUG(LOG_TAG, "%s building metrics", __func__); 430 Build(); 431 LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__); 432 if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) { 433 LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__); 434 } 435 // Always clean up log objects 436 pimpl_->bluetooth_log_->Clear(); 437 } 438 439 void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) { 440 this->WriteString(serialized); 441 base::Base64Encode(*serialized, serialized); 442 } 443 444 void BluetoothMetricsLogger::WriteBase64(int fd) { 445 std::string protoBase64; 446 this->WriteBase64String(&protoBase64); 447 ssize_t ret; 448 OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size())); 449 if (ret == -1) { 450 LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__, 451 strerror(errno), errno); 452 } 453 } 454 455 void BluetoothMetricsLogger::CutoffSession() { 456 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 457 if (pimpl_->bluetooth_session_ != nullptr) { 458 BluetoothSession* new_bt_session = 459 new BluetoothSession(*pimpl_->bluetooth_session_); 460 new_bt_session->clear_a2dp_session(); 461 new_bt_session->clear_rfcomm_session(); 462 LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0); 463 pimpl_->bluetooth_session_ = new_bt_session; 464 pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms(); 465 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); 466 } 467 } 468 469 void BluetoothMetricsLogger::Build() { 470 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 471 CutoffSession(); 472 BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_; 473 while (!pimpl_->bt_session_queue_->Empty() && 474 static_cast<size_t>(bluetooth_log->session_size()) <= 475 pimpl_->bt_session_queue_->Capacity()) { 476 bluetooth_log->mutable_session()->AddAllocated( 477 pimpl_->bt_session_queue_->Dequeue()); 478 } 479 while (!pimpl_->pair_event_queue_->Empty() && 480 static_cast<size_t>(bluetooth_log->pair_event_size()) <= 481 pimpl_->pair_event_queue_->Capacity()) { 482 bluetooth_log->mutable_pair_event()->AddAllocated( 483 pimpl_->pair_event_queue_->Dequeue()); 484 } 485 while (!pimpl_->scan_event_queue_->Empty() && 486 static_cast<size_t>(bluetooth_log->scan_event_size()) <= 487 pimpl_->scan_event_queue_->Capacity()) { 488 bluetooth_log->mutable_scan_event()->AddAllocated( 489 pimpl_->scan_event_queue_->Dequeue()); 490 } 491 while (!pimpl_->wake_event_queue_->Empty() && 492 static_cast<size_t>(bluetooth_log->wake_event_size()) <= 493 pimpl_->wake_event_queue_->Capacity()) { 494 bluetooth_log->mutable_wake_event()->AddAllocated( 495 pimpl_->wake_event_queue_->Dequeue()); 496 } 497 while (!pimpl_->bt_session_queue_->Empty() && 498 static_cast<size_t>(bluetooth_log->wake_event_size()) <= 499 pimpl_->wake_event_queue_->Capacity()) { 500 bluetooth_log->mutable_wake_event()->AddAllocated( 501 pimpl_->wake_event_queue_->Dequeue()); 502 } 503 for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) { 504 int num_times_connected = pimpl_->headset_profile_connection_counts_[i]; 505 if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) { 506 HeadsetProfileConnectionStats* headset_profile_connection_stats = 507 bluetooth_log->add_headset_profile_connection_stats(); 508 // Able to static_cast because HeadsetProfileType_IsValid(i) is true 509 headset_profile_connection_stats->set_headset_profile_type( 510 static_cast<HeadsetProfileType>(i)); 511 headset_profile_connection_stats->set_num_times_connected( 512 num_times_connected); 513 } 514 } 515 pimpl_->headset_profile_connection_counts_.fill(0); 516 } 517 518 void BluetoothMetricsLogger::ResetSession() { 519 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); 520 if (pimpl_->bluetooth_session_ != nullptr) { 521 delete pimpl_->bluetooth_session_; 522 pimpl_->bluetooth_session_ = nullptr; 523 } 524 pimpl_->bluetooth_session_start_time_ms_ = 0; 525 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); 526 } 527 528 void BluetoothMetricsLogger::ResetLog() { 529 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); 530 pimpl_->bluetooth_log_->Clear(); 531 } 532 533 void BluetoothMetricsLogger::Reset() { 534 ResetSession(); 535 ResetLog(); 536 pimpl_->bt_session_queue_->Clear(); 537 pimpl_->pair_event_queue_->Clear(); 538 pimpl_->wake_event_queue_->Clear(); 539 pimpl_->scan_event_queue_->Clear(); 540 } 541 542 } // namespace system_bt_osi 543