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