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 
19 #include <unistd.h>
20 #include <algorithm>
21 #include <array>
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 #include <include/hardware/bt_av.h>
32 #include <statslog.h>
33 
34 #include "bluetooth/metrics/bluetooth.pb.h"
35 #include "osi/include/osi.h"
36 #include "stack/include/btm_api_types.h"
37 
38 #include "address_obfuscator.h"
39 #include "leaky_bonded_queue.h"
40 #include "metric_id_allocator.h"
41 #include "metrics.h"
42 #include "time_util.h"
43 
44 namespace bluetooth {
45 
46 namespace common {
47 
48 using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
49 using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
50 using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog;
51 using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession;
52 using bluetooth::metrics::BluetoothMetricsProto::
53     BluetoothSession_ConnectionTechnologyType;
54 using bluetooth::metrics::BluetoothMetricsProto::
55     BluetoothSession_DisconnectReasonType;
56 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
57 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
58 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
59 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
60 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
61 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
62 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
63 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
64 using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
65 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
66 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
67 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
68 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
69 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
70 
combine_averages(float avg_a,int64_t ct_a,float avg_b,int64_t ct_b)71 static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
72                               int64_t ct_b) {
73   if (ct_a > 0 && ct_b > 0) {
74     return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
75   } else if (ct_b > 0) {
76     return avg_b;
77   } else {
78     return avg_a;
79   }
80 }
81 
combine_averages(int32_t avg_a,int64_t ct_a,int32_t avg_b,int64_t ct_b)82 static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
83                                 int64_t ct_b) {
84   if (ct_a > 0 && ct_b > 0) {
85     return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
86   } else if (ct_b > 0) {
87     return avg_b;
88   } else {
89     return avg_a;
90   }
91 }
92 
Update(const A2dpSessionMetrics & metrics)93 void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
94   if (metrics.audio_duration_ms >= 0) {
95     audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
96     audio_duration_ms += metrics.audio_duration_ms;
97   }
98   if (metrics.media_timer_min_ms >= 0) {
99     if (media_timer_min_ms < 0) {
100       media_timer_min_ms = metrics.media_timer_min_ms;
101     } else {
102       media_timer_min_ms =
103           std::min(media_timer_min_ms, metrics.media_timer_min_ms);
104     }
105   }
106   if (metrics.media_timer_max_ms >= 0) {
107     media_timer_max_ms =
108         std::max(media_timer_max_ms, metrics.media_timer_max_ms);
109   }
110   if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
111     if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
112       media_timer_avg_ms = metrics.media_timer_avg_ms;
113       total_scheduling_count = metrics.total_scheduling_count;
114     } else {
115       media_timer_avg_ms = combine_averages(
116           media_timer_avg_ms, total_scheduling_count,
117           metrics.media_timer_avg_ms, metrics.total_scheduling_count);
118       total_scheduling_count += metrics.total_scheduling_count;
119     }
120   }
121   if (metrics.buffer_overruns_max_count >= 0) {
122     buffer_overruns_max_count =
123         std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
124   }
125   if (metrics.buffer_overruns_total >= 0) {
126     buffer_overruns_total =
127         std::max(static_cast<int32_t>(0), buffer_overruns_total);
128     buffer_overruns_total += metrics.buffer_overruns_total;
129   }
130   if (metrics.buffer_underruns_average >= 0 &&
131       metrics.buffer_underruns_count >= 0) {
132     if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
133       buffer_underruns_average = metrics.buffer_underruns_average;
134       buffer_underruns_count = metrics.buffer_underruns_count;
135     } else {
136       buffer_underruns_average = combine_averages(
137           buffer_underruns_average, buffer_underruns_count,
138           metrics.buffer_underruns_average, metrics.buffer_underruns_count);
139       buffer_underruns_count += metrics.buffer_underruns_count;
140     }
141   }
142   if (codec_index < 0) {
143     codec_index = metrics.codec_index;
144   }
145   if (!is_a2dp_offload) {
146     is_a2dp_offload = metrics.is_a2dp_offload;
147   }
148 }
149 
operator ==(const A2dpSessionMetrics & rhs) const150 bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
151   return audio_duration_ms == rhs.audio_duration_ms &&
152          media_timer_min_ms == rhs.media_timer_min_ms &&
153          media_timer_max_ms == rhs.media_timer_max_ms &&
154          media_timer_avg_ms == rhs.media_timer_avg_ms &&
155          total_scheduling_count == rhs.total_scheduling_count &&
156          buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
157          buffer_overruns_total == rhs.buffer_overruns_total &&
158          buffer_underruns_average == rhs.buffer_underruns_average &&
159          buffer_underruns_count == rhs.buffer_underruns_count &&
160          codec_index == rhs.codec_index &&
161          is_a2dp_offload == rhs.is_a2dp_offload;
162 }
163 
get_device_type(device_type_t type)164 static DeviceInfo_DeviceType get_device_type(device_type_t type) {
165   switch (type) {
166     case DEVICE_TYPE_BREDR:
167       return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR;
168     case DEVICE_TYPE_LE:
169       return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE;
170     case DEVICE_TYPE_DUMO:
171       return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO;
172     case DEVICE_TYPE_UNKNOWN:
173     default:
174       return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN;
175   }
176 }
177 
get_connection_tech_type(connection_tech_t type)178 static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(
179     connection_tech_t type) {
180   switch (type) {
181     case CONNECTION_TECHNOLOGY_TYPE_LE:
182       return BluetoothSession_ConnectionTechnologyType::
183           BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE;
184     case CONNECTION_TECHNOLOGY_TYPE_BREDR:
185       return BluetoothSession_ConnectionTechnologyType::
186           BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR;
187     case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN:
188     default:
189       return BluetoothSession_ConnectionTechnologyType::
190           BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN;
191   }
192 }
193 
get_scan_tech_type(scan_tech_t type)194 static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) {
195   switch (type) {
196     case SCAN_TECH_TYPE_LE:
197       return ScanEvent_ScanTechnologyType::
198           ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE;
199     case SCAN_TECH_TYPE_BREDR:
200       return ScanEvent_ScanTechnologyType::
201           ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR;
202     case SCAN_TECH_TYPE_BOTH:
203       return ScanEvent_ScanTechnologyType::
204           ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH;
205     case SCAN_TYPE_UNKNOWN:
206     default:
207       return ScanEvent_ScanTechnologyType::
208           ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN;
209   }
210 }
211 
get_wake_event_type(wake_event_type_t type)212 static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) {
213   switch (type) {
214     case WAKE_EVENT_ACQUIRED:
215       return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED;
216     case WAKE_EVENT_RELEASED:
217       return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED;
218     case WAKE_EVENT_UNKNOWN:
219     default:
220       return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN;
221   }
222 }
223 
get_disconnect_reason_type(disconnect_reason_t type)224 static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(
225     disconnect_reason_t type) {
226   switch (type) {
227     case DISCONNECT_REASON_METRICS_DUMP:
228       return BluetoothSession_DisconnectReasonType::
229           BluetoothSession_DisconnectReasonType_METRICS_DUMP;
230     case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS:
231       return BluetoothSession_DisconnectReasonType::
232           BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS;
233     case DISCONNECT_REASON_UNKNOWN:
234     default:
235       return BluetoothSession_DisconnectReasonType::
236           BluetoothSession_DisconnectReasonType_UNKNOWN;
237   }
238 }
239 
get_a2dp_source_codec(int64_t codec_index)240 static A2dpSourceCodec get_a2dp_source_codec(int64_t codec_index) {
241   switch (codec_index) {
242     case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
243       return A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC;
244     case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
245       return A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC;
246     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
247       return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX;
248     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
249       return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX_HD;
250     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
251       return A2dpSourceCodec::A2DP_SOURCE_CODEC_LDAC;
252     default:
253       return A2dpSourceCodec::A2DP_SOURCE_CODEC_UNKNOWN;
254   }
255 }
256 
257 struct BluetoothMetricsLogger::impl {
implbluetooth::common::BluetoothMetricsLogger::impl258   impl(size_t max_bluetooth_session, size_t max_pair_event,
259        size_t max_wake_event, size_t max_scan_event)
260       : bt_session_queue_(
261             new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)),
262         pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)),
263         wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
264         scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
265     bluetooth_log_ = BluetoothLog::default_instance().New();
266     headset_profile_connection_counts_.fill(0);
267     bluetooth_session_ = nullptr;
268     bluetooth_session_start_time_ms_ = 0;
269     a2dp_session_metrics_ = A2dpSessionMetrics();
270   }
271 
272   /* Bluetooth log lock protected */
273   BluetoothLog* bluetooth_log_;
274   std::array<int, HeadsetProfileType_ARRAYSIZE>
275       headset_profile_connection_counts_;
276   std::recursive_mutex bluetooth_log_lock_;
277   /* End Bluetooth log lock protected */
278   /* Bluetooth session lock protected */
279   BluetoothSession* bluetooth_session_;
280   uint64_t bluetooth_session_start_time_ms_;
281   A2dpSessionMetrics a2dp_session_metrics_;
282   std::recursive_mutex bluetooth_session_lock_;
283   /* End bluetooth session lock protected */
284   std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_;
285   std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_;
286   std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_;
287   std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_;
288 };
289 
BluetoothMetricsLogger()290 BluetoothMetricsLogger::BluetoothMetricsLogger()
291     : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
292                       kMaxNumWakeEvent, kMaxNumScanEvent)) {}
293 
LogPairEvent(uint32_t disconnect_reason,uint64_t timestamp_ms,uint32_t device_class,device_type_t device_type)294 void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
295                                           uint64_t timestamp_ms,
296                                           uint32_t device_class,
297                                           device_type_t device_type) {
298   PairEvent* event = new PairEvent();
299   DeviceInfo* info = event->mutable_device_paired_with();
300   info->set_device_class(device_class);
301   info->set_device_type(get_device_type(device_type));
302   event->set_disconnect_reason(disconnect_reason);
303   event->set_event_time_millis(timestamp_ms);
304   pimpl_->pair_event_queue_->Enqueue(event);
305   {
306     std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
307     pimpl_->bluetooth_log_->set_num_pair_event(
308         pimpl_->bluetooth_log_->num_pair_event() + 1);
309   }
310 }
311 
LogWakeEvent(wake_event_type_t type,const std::string & requestor,const std::string & name,uint64_t timestamp_ms)312 void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
313                                           const std::string& requestor,
314                                           const std::string& name,
315                                           uint64_t timestamp_ms) {
316   WakeEvent* event = new WakeEvent();
317   event->set_wake_event_type(get_wake_event_type(type));
318   event->set_requestor(requestor);
319   event->set_name(name);
320   event->set_event_time_millis(timestamp_ms);
321   pimpl_->wake_event_queue_->Enqueue(event);
322   {
323     std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
324     pimpl_->bluetooth_log_->set_num_wake_event(
325         pimpl_->bluetooth_log_->num_wake_event() + 1);
326   }
327 }
328 
LogScanEvent(bool start,const std::string & initator,scan_tech_t type,uint32_t results,uint64_t timestamp_ms)329 void BluetoothMetricsLogger::LogScanEvent(bool start,
330                                           const std::string& initator,
331                                           scan_tech_t type, uint32_t results,
332                                           uint64_t timestamp_ms) {
333   ScanEvent* event = new ScanEvent();
334   if (start) {
335     event->set_scan_event_type(ScanEvent::SCAN_EVENT_START);
336   } else {
337     event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP);
338   }
339   event->set_initiator(initator);
340   event->set_scan_technology_type(get_scan_tech_type(type));
341   event->set_number_results(results);
342   event->set_event_time_millis(timestamp_ms);
343   pimpl_->scan_event_queue_->Enqueue(event);
344   {
345     std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
346     pimpl_->bluetooth_log_->set_num_scan_event(
347         pimpl_->bluetooth_log_->num_scan_event() + 1);
348   }
349 }
350 
LogBluetoothSessionStart(connection_tech_t connection_tech_type,uint64_t timestamp_ms)351 void BluetoothMetricsLogger::LogBluetoothSessionStart(
352     connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
353   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
354   if (pimpl_->bluetooth_session_ != nullptr) {
355     LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
356                            0);
357   }
358   if (timestamp_ms == 0) {
359     timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
360   }
361   pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
362   pimpl_->bluetooth_session_ = new BluetoothSession();
363   pimpl_->bluetooth_session_->set_connection_technology_type(
364       get_connection_tech_type(connection_tech_type));
365 }
366 
LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,uint64_t timestamp_ms)367 void BluetoothMetricsLogger::LogBluetoothSessionEnd(
368     disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
369   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
370   if (pimpl_->bluetooth_session_ == nullptr) {
371     return;
372   }
373   if (timestamp_ms == 0) {
374     timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
375   }
376   int64_t session_duration_sec =
377       (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
378   pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec);
379   pimpl_->bluetooth_session_->set_disconnect_reason_type(
380       get_disconnect_reason_type(disconnect_reason));
381   pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
382   pimpl_->bluetooth_session_ = nullptr;
383   pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
384   {
385     std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
386     pimpl_->bluetooth_log_->set_num_bluetooth_session(
387         pimpl_->bluetooth_log_->num_bluetooth_session() + 1);
388   }
389 }
390 
LogBluetoothSessionDeviceInfo(uint32_t device_class,device_type_t device_type)391 void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
392     uint32_t device_class, device_type_t device_type) {
393   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
394   if (pimpl_->bluetooth_session_ == nullptr) {
395     LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
396   }
397   DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to();
398   info->set_device_class(device_class);
399   info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR);
400 }
401 
LogA2dpSession(const A2dpSessionMetrics & a2dp_session_metrics)402 void BluetoothMetricsLogger::LogA2dpSession(
403     const A2dpSessionMetrics& a2dp_session_metrics) {
404   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
405   if (pimpl_->bluetooth_session_ == nullptr) {
406     // When no bluetooth session exist, create one on system's behalf
407     // Set connection type: for A2DP it is always BR/EDR
408     LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
409     LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR);
410   }
411   // Accumulate metrics
412   pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics);
413   // Get or allocate new A2DP session object
414   A2DPSession* a2dp_session =
415       pimpl_->bluetooth_session_->mutable_a2dp_session();
416   a2dp_session->set_audio_duration_millis(
417       pimpl_->a2dp_session_metrics_.audio_duration_ms);
418   a2dp_session->set_media_timer_min_millis(
419       pimpl_->a2dp_session_metrics_.media_timer_min_ms);
420   a2dp_session->set_media_timer_max_millis(
421       pimpl_->a2dp_session_metrics_.media_timer_max_ms);
422   a2dp_session->set_media_timer_avg_millis(
423       pimpl_->a2dp_session_metrics_.media_timer_avg_ms);
424   a2dp_session->set_buffer_overruns_max_count(
425       pimpl_->a2dp_session_metrics_.buffer_overruns_max_count);
426   a2dp_session->set_buffer_overruns_total(
427       pimpl_->a2dp_session_metrics_.buffer_overruns_total);
428   a2dp_session->set_buffer_underruns_average(
429       pimpl_->a2dp_session_metrics_.buffer_underruns_average);
430   a2dp_session->set_buffer_underruns_count(
431       pimpl_->a2dp_session_metrics_.buffer_underruns_count);
432   a2dp_session->set_source_codec(
433       get_a2dp_source_codec(pimpl_->a2dp_session_metrics_.codec_index));
434   a2dp_session->set_is_a2dp_offload(
435       pimpl_->a2dp_session_metrics_.is_a2dp_offload);
436 }
437 
LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id)438 void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
439     tBTA_SERVICE_ID service_id) {
440   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
441   switch (service_id) {
442     case BTA_HSP_SERVICE_ID:
443       pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++;
444       break;
445     case BTA_HFP_SERVICE_ID:
446       pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++;
447       break;
448     default:
449       pimpl_->headset_profile_connection_counts_
450           [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++;
451       break;
452   }
453   return;
454 }
455 
WriteString(std::string * serialized)456 void BluetoothMetricsLogger::WriteString(std::string* serialized) {
457   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
458   LOG(INFO) << __func__ << ": building metrics";
459   Build();
460   LOG(INFO) << __func__ << ": serializing metrics";
461   if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
462     LOG(ERROR) << __func__ << ": error serializing metrics";
463   }
464   // Always clean up log objects
465   pimpl_->bluetooth_log_->Clear();
466 }
467 
WriteBase64String(std::string * serialized)468 void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {
469   this->WriteString(serialized);
470   base::Base64Encode(*serialized, serialized);
471 }
472 
WriteBase64(int fd)473 void BluetoothMetricsLogger::WriteBase64(int fd) {
474   std::string protoBase64;
475   this->WriteBase64String(&protoBase64);
476   ssize_t ret;
477   OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
478   if (ret == -1) {
479     LOG(ERROR) << __func__
480                << ": error writing to dumpsys fd: " << strerror(errno) << " ("
481                << std::to_string(errno) << ")";
482   }
483 }
484 
CutoffSession()485 void BluetoothMetricsLogger::CutoffSession() {
486   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
487   if (pimpl_->bluetooth_session_ != nullptr) {
488     BluetoothSession* new_bt_session =
489         new BluetoothSession(*pimpl_->bluetooth_session_);
490     new_bt_session->clear_a2dp_session();
491     new_bt_session->clear_rfcomm_session();
492     LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
493     pimpl_->bluetooth_session_ = new_bt_session;
494     pimpl_->bluetooth_session_start_time_ms_ =
495         bluetooth::common::time_get_os_boottime_ms();
496     pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
497   }
498 }
499 
Build()500 void BluetoothMetricsLogger::Build() {
501   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
502   CutoffSession();
503   BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_;
504   while (!pimpl_->bt_session_queue_->Empty() &&
505          static_cast<size_t>(bluetooth_log->session_size()) <=
506              pimpl_->bt_session_queue_->Capacity()) {
507     bluetooth_log->mutable_session()->AddAllocated(
508         pimpl_->bt_session_queue_->Dequeue());
509   }
510   while (!pimpl_->pair_event_queue_->Empty() &&
511          static_cast<size_t>(bluetooth_log->pair_event_size()) <=
512              pimpl_->pair_event_queue_->Capacity()) {
513     bluetooth_log->mutable_pair_event()->AddAllocated(
514         pimpl_->pair_event_queue_->Dequeue());
515   }
516   while (!pimpl_->scan_event_queue_->Empty() &&
517          static_cast<size_t>(bluetooth_log->scan_event_size()) <=
518              pimpl_->scan_event_queue_->Capacity()) {
519     bluetooth_log->mutable_scan_event()->AddAllocated(
520         pimpl_->scan_event_queue_->Dequeue());
521   }
522   while (!pimpl_->wake_event_queue_->Empty() &&
523          static_cast<size_t>(bluetooth_log->wake_event_size()) <=
524              pimpl_->wake_event_queue_->Capacity()) {
525     bluetooth_log->mutable_wake_event()->AddAllocated(
526         pimpl_->wake_event_queue_->Dequeue());
527   }
528   while (!pimpl_->bt_session_queue_->Empty() &&
529          static_cast<size_t>(bluetooth_log->wake_event_size()) <=
530              pimpl_->wake_event_queue_->Capacity()) {
531     bluetooth_log->mutable_wake_event()->AddAllocated(
532         pimpl_->wake_event_queue_->Dequeue());
533   }
534   for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) {
535     int num_times_connected = pimpl_->headset_profile_connection_counts_[i];
536     if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) {
537       HeadsetProfileConnectionStats* headset_profile_connection_stats =
538           bluetooth_log->add_headset_profile_connection_stats();
539       // Able to static_cast because HeadsetProfileType_IsValid(i) is true
540       headset_profile_connection_stats->set_headset_profile_type(
541           static_cast<HeadsetProfileType>(i));
542       headset_profile_connection_stats->set_num_times_connected(
543           num_times_connected);
544     }
545   }
546   pimpl_->headset_profile_connection_counts_.fill(0);
547 }
548 
ResetSession()549 void BluetoothMetricsLogger::ResetSession() {
550   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
551   if (pimpl_->bluetooth_session_ != nullptr) {
552     delete pimpl_->bluetooth_session_;
553     pimpl_->bluetooth_session_ = nullptr;
554   }
555   pimpl_->bluetooth_session_start_time_ms_ = 0;
556   pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
557 }
558 
ResetLog()559 void BluetoothMetricsLogger::ResetLog() {
560   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
561   pimpl_->bluetooth_log_->Clear();
562 }
563 
Reset()564 void BluetoothMetricsLogger::Reset() {
565   ResetSession();
566   ResetLog();
567   pimpl_->bt_session_queue_->Clear();
568   pimpl_->pair_event_queue_->Clear();
569   pimpl_->wake_event_queue_->Clear();
570   pimpl_->scan_event_queue_->Clear();
571 }
572 
LogLinkLayerConnectionEvent(const RawAddress * address,uint32_t connection_handle,android::bluetooth::DirectionEnum direction,uint16_t link_type,uint32_t hci_cmd,uint16_t hci_event,uint16_t hci_ble_event,uint16_t cmd_status,uint16_t reason_code)573 void LogLinkLayerConnectionEvent(const RawAddress* address,
574                                  uint32_t connection_handle,
575                                  android::bluetooth::DirectionEnum direction,
576                                  uint16_t link_type, uint32_t hci_cmd,
577                                  uint16_t hci_event, uint16_t hci_ble_event,
578                                  uint16_t cmd_status, uint16_t reason_code) {
579   std::string obfuscated_id;
580   int metric_id = 0;
581   if (address != nullptr) {
582     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(*address);
583     metric_id = MetricIdAllocator::GetInstance().AllocateId(*address);
584   }
585   // nullptr and size 0 represent missing value for obfuscated_id
586   android::util::BytesField bytes_field(
587       address != nullptr ? obfuscated_id.c_str() : nullptr,
588       address != nullptr ? obfuscated_id.size() : 0);
589   int ret = android::util::stats_write(
590       android::util::BLUETOOTH_LINK_LAYER_CONNECTION_EVENT, bytes_field,
591       connection_handle, direction, link_type, hci_cmd, hci_event,
592       hci_ble_event, cmd_status, reason_code, metric_id);
593   if (ret < 0) {
594     LOG(WARNING) << __func__ << ": failed to log status " << loghex(cmd_status)
595                  << ", reason " << loghex(reason_code) << " from cmd "
596                  << loghex(hci_cmd) << ", event " << loghex(hci_event)
597                  << ", ble_event " << loghex(hci_ble_event) << " for "
598                  << address << ", handle " << connection_handle << ", type "
599                  << loghex(link_type) << ", error " << ret;
600   }
601 }
602 
LogHciTimeoutEvent(uint32_t hci_cmd)603 void LogHciTimeoutEvent(uint32_t hci_cmd) {
604   int ret =
605       android::util::stats_write(android::util::BLUETOOTH_HCI_TIMEOUT_REPORTED,
606                                  static_cast<int64_t>(hci_cmd));
607   if (ret < 0) {
608     LOG(WARNING) << __func__ << ": failed for opcode " << loghex(hci_cmd)
609                  << ", error " << ret;
610   }
611 }
612 
LogRemoteVersionInfo(uint16_t handle,uint8_t status,uint8_t version,uint16_t manufacturer_name,uint16_t subversion)613 void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
614                           uint16_t manufacturer_name, uint16_t subversion) {
615   int ret = android::util::stats_write(
616       android::util::BLUETOOTH_REMOTE_VERSION_INFO_REPORTED, handle, status,
617       version, manufacturer_name, subversion);
618   if (ret < 0) {
619     LOG(WARNING) << __func__ << ": failed for handle " << handle << ", status "
620                  << loghex(status) << ", version " << loghex(version)
621                  << ", manufacturer_name " << loghex(manufacturer_name)
622                  << ", subversion " << loghex(subversion) << ", error " << ret;
623   }
624 }
625 
LogA2dpAudioUnderrunEvent(const RawAddress & address,uint64_t encoding_interval_millis,int num_missing_pcm_bytes)626 void LogA2dpAudioUnderrunEvent(const RawAddress& address,
627                                uint64_t encoding_interval_millis,
628                                int num_missing_pcm_bytes) {
629   std::string obfuscated_id;
630   int metric_id = 0;
631   if (!address.IsEmpty()) {
632     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
633     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
634   }
635   // nullptr and size 0 represent missing value for obfuscated_id
636   android::util::BytesField bytes_field(
637       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
638       address.IsEmpty() ? 0 : obfuscated_id.size());
639   int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
640   int ret = android::util::stats_write(
641       android::util::BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED, bytes_field,
642       encoding_interval_nanos, num_missing_pcm_bytes, metric_id);
643   if (ret < 0) {
644     LOG(WARNING) << __func__ << ": failed for " << address
645                  << ", encoding_interval_nanos " << encoding_interval_nanos
646                  << ", num_missing_pcm_bytes " << num_missing_pcm_bytes
647                  << ", error " << ret;
648   }
649 }
650 
LogA2dpAudioOverrunEvent(const RawAddress & address,uint64_t encoding_interval_millis,int num_dropped_buffers,int num_dropped_encoded_frames,int num_dropped_encoded_bytes)651 void LogA2dpAudioOverrunEvent(const RawAddress& address,
652                               uint64_t encoding_interval_millis,
653                               int num_dropped_buffers,
654                               int num_dropped_encoded_frames,
655                               int num_dropped_encoded_bytes) {
656   std::string obfuscated_id;
657   int metric_id = 0;
658   if (!address.IsEmpty()) {
659     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
660     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
661   }
662   // nullptr and size 0 represent missing value for obfuscated_id
663   android::util::BytesField bytes_field(
664       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
665       address.IsEmpty() ? 0 : obfuscated_id.size());
666   int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
667   int ret = android::util::stats_write(
668       android::util::BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED, bytes_field,
669       encoding_interval_nanos, num_dropped_buffers, num_dropped_encoded_frames,
670       num_dropped_encoded_bytes, metric_id);
671   if (ret < 0) {
672     LOG(WARNING) << __func__ << ": failed to log for " << address
673                  << ", encoding_interval_nanos " << encoding_interval_nanos
674                  << ", num_dropped_buffers " << num_dropped_buffers
675                  << ", num_dropped_encoded_frames "
676                  << num_dropped_encoded_frames << ", num_dropped_encoded_bytes "
677                  << num_dropped_encoded_bytes << ", error " << ret;
678   }
679 }
680 
LogA2dpPlaybackEvent(const RawAddress & address,int playback_state,int audio_coding_mode)681 void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state,
682                           int audio_coding_mode) {
683   std::string obfuscated_id;
684   int metric_id = 0;
685   if (!address.IsEmpty()) {
686     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
687     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
688   }
689   // nullptr and size 0 represent missing value for obfuscated_id
690   android::util::BytesField bytes_field(
691       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
692       address.IsEmpty() ? 0 : obfuscated_id.size());
693   int ret = android::util::stats_write(
694       android::util::BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED, bytes_field,
695       playback_state, audio_coding_mode, metric_id);
696   if (ret < 0) {
697     LOG(WARNING) << __func__ << ": failed to log for " << address
698                  << ", playback_state " << playback_state
699                  << ", audio_coding_mode " << audio_coding_mode << ", error "
700                  << ret;
701   }
702 }
703 
LogReadRssiResult(const RawAddress & address,uint16_t handle,uint32_t cmd_status,int8_t rssi)704 void LogReadRssiResult(const RawAddress& address, uint16_t handle,
705                        uint32_t cmd_status, int8_t rssi) {
706   std::string obfuscated_id;
707   int metric_id = 0;
708   if (!address.IsEmpty()) {
709     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
710     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
711   }
712   // nullptr and size 0 represent missing value for obfuscated_id
713   android::util::BytesField bytes_field(
714       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
715       address.IsEmpty() ? 0 : obfuscated_id.size());
716   int ret = android::util::stats_write(
717       android::util::BLUETOOTH_DEVICE_RSSI_REPORTED, bytes_field, handle,
718       cmd_status, rssi, metric_id);
719   if (ret < 0) {
720     LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
721                  << handle << ", status " << loghex(cmd_status) << ", rssi "
722                  << rssi << " dBm, error " << ret;
723   }
724 }
725 
LogReadFailedContactCounterResult(const RawAddress & address,uint16_t handle,uint32_t cmd_status,int32_t failed_contact_counter)726 void LogReadFailedContactCounterResult(const RawAddress& address,
727                                        uint16_t handle, uint32_t cmd_status,
728                                        int32_t failed_contact_counter) {
729   std::string obfuscated_id;
730   int metric_id = 0;
731   if (!address.IsEmpty()) {
732     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
733     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
734   }
735   // nullptr and size 0 represent missing value for obfuscated_id
736   android::util::BytesField bytes_field(
737       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
738       address.IsEmpty() ? 0 : obfuscated_id.size());
739   int ret = android::util::stats_write(
740       android::util::BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED,
741       bytes_field, handle, cmd_status, failed_contact_counter, metric_id);
742   if (ret < 0) {
743     LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
744                  << handle << ", status " << loghex(cmd_status)
745                  << ", failed_contact_counter " << failed_contact_counter
746                  << " packets, error " << ret;
747   }
748 }
749 
LogReadTxPowerLevelResult(const RawAddress & address,uint16_t handle,uint32_t cmd_status,int32_t transmit_power_level)750 void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
751                                uint32_t cmd_status,
752                                int32_t transmit_power_level) {
753   std::string obfuscated_id;
754   int metric_id = 0;
755   if (!address.IsEmpty()) {
756     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
757     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
758   }
759   // nullptr and size 0 represent missing value for obfuscated_id
760   android::util::BytesField bytes_field(
761       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
762       address.IsEmpty() ? 0 : obfuscated_id.size());
763   int ret = android::util::stats_write(
764       android::util::BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED, bytes_field,
765       handle, cmd_status, transmit_power_level, metric_id);
766   if (ret < 0) {
767     LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
768                  << handle << ", status " << loghex(cmd_status)
769                  << ", transmit_power_level " << transmit_power_level
770                  << " packets, error " << ret;
771   }
772 }
773 
LogSmpPairingEvent(const RawAddress & address,uint8_t smp_cmd,android::bluetooth::DirectionEnum direction,uint8_t smp_fail_reason)774 void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
775                         android::bluetooth::DirectionEnum direction,
776                         uint8_t smp_fail_reason) {
777   std::string obfuscated_id;
778   int metric_id = 0;
779   if (!address.IsEmpty()) {
780     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
781     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
782   }
783   // nullptr and size 0 represent missing value for obfuscated_id
784   android::util::BytesField obfuscated_id_field(
785       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
786       address.IsEmpty() ? 0 : obfuscated_id.size());
787   int ret = android::util::stats_write(
788       android::util::BLUETOOTH_SMP_PAIRING_EVENT_REPORTED, obfuscated_id_field,
789       smp_cmd, direction, smp_fail_reason, metric_id);
790   if (ret < 0) {
791     LOG(WARNING) << __func__ << ": failed for " << address << ", smp_cmd "
792                  << loghex(smp_cmd) << ", direction " << direction
793                  << ", smp_fail_reason " << loghex(smp_fail_reason)
794                  << ", error " << ret;
795   }
796 }
797 
LogClassicPairingEvent(const RawAddress & address,uint16_t handle,uint32_t hci_cmd,uint16_t hci_event,uint16_t cmd_status,uint16_t reason_code,int64_t event_value)798 void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event,
799                             uint16_t cmd_status, uint16_t reason_code, int64_t event_value) {
800   std::string obfuscated_id;
801   int metric_id = 0;
802   if (!address.IsEmpty()) {
803     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
804     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
805   }
806   // nullptr and size 0 represent missing value for obfuscated_id
807   android::util::BytesField obfuscated_id_field(
808       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
809       address.IsEmpty() ? 0 : obfuscated_id.size());
810   int ret = android::util::stats_write(
811       android::util::BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED,
812       obfuscated_id_field, handle, hci_cmd, hci_event, cmd_status, reason_code,
813       event_value, metric_id);
814   if (ret < 0) {
815     LOG(WARNING) << __func__ << ": failed for " << address << ", handle " << handle << ", hci_cmd " << loghex(hci_cmd)
816                  << ", hci_event " << loghex(hci_event) << ", cmd_status " << loghex(cmd_status) << ", reason "
817                  << loghex(reason_code) << ", event_value " << event_value << ", error " << ret;
818   }
819 }
820 
LogSdpAttribute(const RawAddress & address,uint16_t protocol_uuid,uint16_t attribute_id,size_t attribute_size,const char * attribute_value)821 void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid,
822                      uint16_t attribute_id, size_t attribute_size,
823                      const char* attribute_value) {
824   std::string obfuscated_id;
825   int metric_id = 0;
826   if (!address.IsEmpty()) {
827     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
828     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
829   }
830   // nullptr and size 0 represent missing value for obfuscated_id
831   android::util::BytesField obfuscated_id_field(
832       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
833       address.IsEmpty() ? 0 : obfuscated_id.size());
834   android::util::BytesField attribute_field(attribute_value, attribute_size);
835   int ret = android::util::stats_write(
836       android::util::BLUETOOTH_SDP_ATTRIBUTE_REPORTED, obfuscated_id_field,
837       protocol_uuid, attribute_id, attribute_field, metric_id);
838   if (ret < 0) {
839     LOG(WARNING) << __func__ << ": failed for " << address << ", protocol_uuid "
840                  << loghex(protocol_uuid) << ", attribute_id "
841                  << loghex(attribute_id) << ", error " << ret;
842   }
843 }
844 
LogSocketConnectionState(const RawAddress & address,int port,int type,android::bluetooth::SocketConnectionstateEnum connection_state,int64_t tx_bytes,int64_t rx_bytes,int uid,int server_port,android::bluetooth::SocketRoleEnum socket_role)845 void LogSocketConnectionState(
846     const RawAddress& address, int port, int type,
847     android::bluetooth::SocketConnectionstateEnum connection_state,
848     int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
849     android::bluetooth::SocketRoleEnum socket_role) {
850   std::string obfuscated_id;
851   int metric_id = 0;
852   if (!address.IsEmpty()) {
853     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
854     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
855   }
856   // nullptr and size 0 represent missing value for obfuscated_id
857   android::util::BytesField obfuscated_id_field(
858       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
859       address.IsEmpty() ? 0 : obfuscated_id.size());
860   int ret = android::util::stats_write(
861       android::util::BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED,
862       obfuscated_id_field, port, type, connection_state, tx_bytes, rx_bytes,
863       uid, server_port, socket_role, metric_id);
864   if (ret < 0) {
865     LOG(WARNING) << __func__ << ": failed for " << address << ", port " << port
866                  << ", type " << type << ", state " << connection_state
867                  << ", tx_bytes " << tx_bytes << ", rx_bytes " << rx_bytes
868                  << ", uid " << uid << ", server_port " << server_port
869                  << ", socket_role " << socket_role << ", error " << ret;
870   }
871 }
872 
LogManufacturerInfo(const RawAddress & address,android::bluetooth::DeviceInfoSrcEnum source_type,const std::string & source_name,const std::string & manufacturer,const std::string & model,const std::string & hardware_version,const std::string & software_version)873 void LogManufacturerInfo(const RawAddress& address,
874                          android::bluetooth::DeviceInfoSrcEnum source_type,
875                          const std::string& source_name,
876                          const std::string& manufacturer,
877                          const std::string& model,
878                          const std::string& hardware_version,
879                          const std::string& software_version) {
880   std::string obfuscated_id;
881   int metric_id = 0;
882   if (!address.IsEmpty()) {
883     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
884     metric_id = MetricIdAllocator::GetInstance().AllocateId(address);
885   }
886   // nullptr and size 0 represent missing value for obfuscated_id
887   android::util::BytesField obfuscated_id_field(
888       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
889       address.IsEmpty() ? 0 : obfuscated_id.size());
890   int ret = android::util::stats_write(
891       android::util::BLUETOOTH_DEVICE_INFO_REPORTED, obfuscated_id_field,
892       source_type, source_name.c_str(), manufacturer.c_str(), model.c_str(),
893       hardware_version.c_str(), software_version.c_str(), metric_id);
894   if (ret < 0) {
895     LOG(WARNING) << __func__ << ": failed for " << address << ", source_type "
896                  << source_type << ", source_name " << source_name
897                  << ", manufacturer " << manufacturer << ", model " << model
898                  << ", hardware_version " << hardware_version
899                  << ", software_version " << software_version << ", error "
900                  << ret;
901   }
902 }
903 
LogBluetoothHalCrashReason(const RawAddress & address,uint32_t error_code,uint32_t vendor_error_code)904 void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code,
905                                 uint32_t vendor_error_code) {
906   std::string obfuscated_id;
907   if (!address.IsEmpty()) {
908     obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
909   }
910   // nullptr and size 0 represent missing value for obfuscated_id
911   android::util::BytesField obfuscated_id_field(
912       address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
913       address.IsEmpty() ? 0 : obfuscated_id.size());
914   int ret = android::util::stats_write(
915       android::util::BLUETOOTH_HAL_CRASH_REASON_REPORTED, 0,
916       obfuscated_id_field, error_code, vendor_error_code);
917   if (ret < 0) {
918     LOG(WARNING) << __func__ << ": failed for " << address << ", error_code "
919                  << loghex(error_code) << ", vendor_error_code "
920                  << loghex(vendor_error_code) << ", error " << ret;
921   }
922 }
923 
924 }  // namespace common
925 
926 }  // namespace bluetooth
927