1 /******************************************************************************
2  *
3  *  Copyright 2021 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 #define LOG_TAG "BluetoothMetrics"
20 
21 #include <statslog.h>
22 
23 #include "common/metric_id_manager.h"
24 #include "common/strings.h"
25 #include "os/log.h"
26 #include "os/metrics.h"
27 
28 namespace bluetooth {
29 
30 namespace os {
31 
32 using bluetooth::common::MetricIdManager;
33 using bluetooth::hci::Address;
34 
35 /**
36  * nullptr and size 0 represent missing value for obfuscated_id
37  */
38 static const android::util::BytesField byteField(nullptr, 0);
39 
LogMetricLinkLayerConnectionEvent(const Address * 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)40 void LogMetricLinkLayerConnectionEvent(
41     const Address* address,
42     uint32_t connection_handle,
43     android::bluetooth::DirectionEnum direction,
44     uint16_t link_type,
45     uint32_t hci_cmd,
46     uint16_t hci_event,
47     uint16_t hci_ble_event,
48     uint16_t cmd_status,
49     uint16_t reason_code) {
50   int metric_id = 0;
51   if (address != nullptr) {
52     metric_id = MetricIdManager::GetInstance().AllocateId(*address);
53   }
54   int ret = android::util::stats_write(
55       android::util::BLUETOOTH_LINK_LAYER_CONNECTION_EVENT,
56       byteField,
57       connection_handle,
58       direction,
59       link_type,
60       hci_cmd,
61       hci_event,
62       hci_ble_event,
63       cmd_status,
64       reason_code,
65       metric_id);
66   if (ret < 0) {
67     LOG_WARN(
68         "Failed to log status %s , reason %s, from cmd %s, event %s,  ble_event %s, for %s, handle %d, type %s, "
69         "error %d",
70         common::ToHexString(cmd_status).c_str(),
71         common::ToHexString(reason_code).c_str(),
72         common::ToHexString(hci_cmd).c_str(),
73         common::ToHexString(hci_event).c_str(),
74         common::ToHexString(hci_ble_event).c_str(),
75         address ? address->ToString().c_str() : "(NULL)",
76         connection_handle,
77         common::ToHexString(link_type).c_str(),
78         ret);
79   }
80 }
81 
LogMetricHciTimeoutEvent(uint32_t hci_cmd)82 void LogMetricHciTimeoutEvent(uint32_t hci_cmd) {
83   int ret = android::util::stats_write(android::util::BLUETOOTH_HCI_TIMEOUT_REPORTED, static_cast<int64_t>(hci_cmd));
84   if (ret < 0) {
85     LOG_WARN("Failed for opcode %s, error %d", common::ToHexString(hci_cmd).c_str(), ret);
86   }
87 }
88 
LogMetricRemoteVersionInfo(uint16_t handle,uint8_t status,uint8_t version,uint16_t manufacturer_name,uint16_t subversion)89 void LogMetricRemoteVersionInfo(
90     uint16_t handle, uint8_t status, uint8_t version, uint16_t manufacturer_name, uint16_t subversion) {
91   int ret = android::util::stats_write(
92       android::util::BLUETOOTH_REMOTE_VERSION_INFO_REPORTED, handle, status, version, manufacturer_name, subversion);
93   if (ret < 0) {
94     LOG_WARN(
95         "Failed for handle %d, status %s, version %s, manufacturer_name %s, subversion %s, error %d",
96         handle,
97         common::ToHexString(status).c_str(),
98         common::ToHexString(version).c_str(),
99         common::ToHexString(manufacturer_name).c_str(),
100         common::ToHexString(subversion).c_str(),
101         ret);
102   }
103 }
104 
LogMetricA2dpAudioUnderrunEvent(const Address & address,uint64_t encoding_interval_millis,int num_missing_pcm_bytes)105 void LogMetricA2dpAudioUnderrunEvent(
106     const Address& address, uint64_t encoding_interval_millis, int num_missing_pcm_bytes) {
107   int metric_id = 0;
108   if (!address.IsEmpty()) {
109     metric_id = MetricIdManager::GetInstance().AllocateId(address);
110   }
111   int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
112   int ret = android::util::stats_write(
113       android::util::BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED,
114       byteField,
115       encoding_interval_nanos,
116       num_missing_pcm_bytes,
117       metric_id);
118   if (ret < 0) {
119     LOG_WARN(
120         "Failed for %s, encoding_interval_nanos %s, num_missing_pcm_bytes %d, error %d",
121         address.ToString().c_str(),
122         std::to_string(encoding_interval_nanos).c_str(),
123         num_missing_pcm_bytes,
124         ret);
125   }
126 }
127 
LogMetricA2dpAudioOverrunEvent(const Address & address,uint64_t encoding_interval_millis,int num_dropped_buffers,int num_dropped_encoded_frames,int num_dropped_encoded_bytes)128 void LogMetricA2dpAudioOverrunEvent(
129     const Address& address,
130     uint64_t encoding_interval_millis,
131     int num_dropped_buffers,
132     int num_dropped_encoded_frames,
133     int num_dropped_encoded_bytes) {
134   int metric_id = 0;
135   if (!address.IsEmpty()) {
136     metric_id = MetricIdManager::GetInstance().AllocateId(address);
137   }
138 
139   int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
140   int ret = android::util::stats_write(
141       android::util::BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED,
142       byteField,
143       encoding_interval_nanos,
144       num_dropped_buffers,
145       num_dropped_encoded_frames,
146       num_dropped_encoded_bytes,
147       metric_id);
148   if (ret < 0) {
149     LOG_WARN(
150         "Failed to log for %s, encoding_interval_nanos %s, num_dropped_buffers %d, "
151         "num_dropped_encoded_frames %d, num_dropped_encoded_bytes %d, error %d",
152         address.ToString().c_str(),
153         std::to_string(encoding_interval_nanos).c_str(),
154         num_dropped_buffers,
155         num_dropped_encoded_frames,
156         num_dropped_encoded_bytes,
157         ret);
158   }
159 }
160 
LogMetricA2dpPlaybackEvent(const Address & address,int playback_state,int audio_coding_mode)161 void LogMetricA2dpPlaybackEvent(const Address& address, int playback_state, int audio_coding_mode) {
162   int metric_id = 0;
163   if (!address.IsEmpty()) {
164     metric_id = MetricIdManager::GetInstance().AllocateId(address);
165   }
166 
167   int ret = android::util::stats_write(
168       android::util::BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED, byteField, playback_state, audio_coding_mode, metric_id);
169   if (ret < 0) {
170     LOG_WARN(
171         "Failed to log for %s, playback_state %d, audio_coding_mode %d,error %d",
172         address.ToString().c_str(),
173         playback_state,
174         audio_coding_mode,
175         ret);
176   }
177 }
178 
LogMetricReadRssiResult(const Address & address,uint16_t handle,uint32_t cmd_status,int8_t rssi)179 void LogMetricReadRssiResult(const Address& address, uint16_t handle, uint32_t cmd_status, int8_t rssi) {
180   int metric_id = 0;
181   if (!address.IsEmpty()) {
182     metric_id = MetricIdManager::GetInstance().AllocateId(address);
183   }
184   int ret = android::util::stats_write(
185       android::util::BLUETOOTH_DEVICE_RSSI_REPORTED, byteField, handle, cmd_status, rssi, metric_id);
186   if (ret < 0) {
187     LOG_WARN(
188         "Failed for %s, handle %d, status %s, rssi %d dBm, error %d",
189         address.ToString().c_str(),
190         handle,
191         common::ToHexString(cmd_status).c_str(),
192         rssi,
193         ret);
194   }
195 }
196 
LogMetricReadFailedContactCounterResult(const Address & address,uint16_t handle,uint32_t cmd_status,int32_t failed_contact_counter)197 void LogMetricReadFailedContactCounterResult(
198     const Address& address, uint16_t handle, uint32_t cmd_status, int32_t failed_contact_counter) {
199   int metric_id = 0;
200   if (!address.IsEmpty()) {
201     metric_id = MetricIdManager::GetInstance().AllocateId(address);
202   }
203   int ret = android::util::stats_write(
204       android::util::BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED,
205       byteField,
206       handle,
207       cmd_status,
208       failed_contact_counter,
209       metric_id);
210   if (ret < 0) {
211     LOG_WARN(
212         "Failed for %s, handle %d, status %s, failed_contact_counter %d packets, error %d",
213         address.ToString().c_str(),
214         handle,
215         common::ToHexString(cmd_status).c_str(),
216         failed_contact_counter,
217         ret);
218   }
219 }
220 
LogMetricReadTxPowerLevelResult(const Address & address,uint16_t handle,uint32_t cmd_status,int32_t transmit_power_level)221 void LogMetricReadTxPowerLevelResult(
222     const Address& address, uint16_t handle, uint32_t cmd_status, int32_t transmit_power_level) {
223   int metric_id = 0;
224   if (!address.IsEmpty()) {
225     metric_id = MetricIdManager::GetInstance().AllocateId(address);
226   }
227   int ret = android::util::stats_write(
228       android::util::BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED,
229       byteField,
230       handle,
231       cmd_status,
232       transmit_power_level,
233       metric_id);
234   if (ret < 0) {
235     LOG_WARN(
236         "Failed for %s, handle %d, status %s, transmit_power_level %d packets, error %d",
237         address.ToString().c_str(),
238         handle,
239         common::ToHexString(cmd_status).c_str(),
240         transmit_power_level,
241         ret);
242   }
243 }
244 
LogMetricSmpPairingEvent(const Address & address,uint8_t smp_cmd,android::bluetooth::DirectionEnum direction,uint8_t smp_fail_reason)245 void LogMetricSmpPairingEvent(
246     const Address& address, uint8_t smp_cmd, android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {
247   int metric_id = 0;
248   if (!address.IsEmpty()) {
249     metric_id = MetricIdManager::GetInstance().AllocateId(address);
250   }
251   int ret = android::util::stats_write(
252       android::util::BLUETOOTH_SMP_PAIRING_EVENT_REPORTED, byteField, smp_cmd, direction, smp_fail_reason, metric_id);
253   if (ret < 0) {
254     LOG_WARN(
255         "Failed for %s, smp_cmd %s, direction %d, smp_fail_reason %s, error %d",
256         address.ToString().c_str(),
257         common::ToHexString(smp_cmd).c_str(),
258         direction,
259         common::ToHexString(smp_fail_reason).c_str(),
260         ret);
261   }
262 }
263 
LogMetricClassicPairingEvent(const Address & address,uint16_t handle,uint32_t hci_cmd,uint16_t hci_event,uint16_t cmd_status,uint16_t reason_code,int64_t event_value)264 void LogMetricClassicPairingEvent(
265     const Address& address,
266     uint16_t handle,
267     uint32_t hci_cmd,
268     uint16_t hci_event,
269     uint16_t cmd_status,
270     uint16_t reason_code,
271     int64_t event_value) {
272   int metric_id = 0;
273   if (!address.IsEmpty()) {
274     metric_id = MetricIdManager::GetInstance().AllocateId(address);
275   }
276   int ret = android::util::stats_write(
277       android::util::BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED,
278       byteField,
279       handle,
280       hci_cmd,
281       hci_event,
282       cmd_status,
283       reason_code,
284       event_value,
285       metric_id);
286   if (ret < 0) {
287     LOG_WARN(
288         "Failed for %s, handle %d, hci_cmd %s, hci_event %s, cmd_status %s, "
289         "reason %s, event_value %s, error %d",
290         address.ToString().c_str(),
291         handle,
292         common::ToHexString(hci_cmd).c_str(),
293         common::ToHexString(hci_event).c_str(),
294         common::ToHexString(cmd_status).c_str(),
295         common::ToHexString(reason_code).c_str(),
296         std::to_string(event_value).c_str(),
297         ret);
298   }
299 }
300 
LogMetricSdpAttribute(const Address & address,uint16_t protocol_uuid,uint16_t attribute_id,size_t attribute_size,const char * attribute_value)301 void LogMetricSdpAttribute(
302     const Address& address,
303     uint16_t protocol_uuid,
304     uint16_t attribute_id,
305     size_t attribute_size,
306     const char* attribute_value) {
307   int metric_id = 0;
308   if (!address.IsEmpty()) {
309     metric_id = MetricIdManager::GetInstance().AllocateId(address);
310   }
311   android::util::BytesField attribute_field(attribute_value, attribute_size);
312   int ret = android::util::stats_write(
313       android::util::BLUETOOTH_SDP_ATTRIBUTE_REPORTED,
314       byteField,
315       protocol_uuid,
316       attribute_id,
317       attribute_field,
318       metric_id);
319   if (ret < 0) {
320     LOG_WARN(
321         "Failed for %s, protocol_uuid %s, attribute_id %s, error %d",
322         address.ToString().c_str(),
323         common::ToHexString(protocol_uuid).c_str(),
324         common::ToHexString(attribute_id).c_str(),
325         ret);
326   }
327 }
328 
LogMetricSocketConnectionState(const Address & 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)329 void LogMetricSocketConnectionState(
330     const Address& address,
331     int port,
332     int type,
333     android::bluetooth::SocketConnectionstateEnum connection_state,
334     int64_t tx_bytes,
335     int64_t rx_bytes,
336     int uid,
337     int server_port,
338     android::bluetooth::SocketRoleEnum socket_role) {
339   int metric_id = 0;
340   if (!address.IsEmpty()) {
341     metric_id = MetricIdManager::GetInstance().AllocateId(address);
342   }
343   int ret = android::util::stats_write(
344       android::util::BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED,
345       byteField,
346       port,
347       type,
348       connection_state,
349       tx_bytes,
350       rx_bytes,
351       uid,
352       server_port,
353       socket_role,
354       metric_id);
355   if (ret < 0) {
356     LOG_WARN(
357         "Failed for %s, port %d, type %d, state %d, tx_bytes %s, rx_bytes %s, uid %d, server_port %d, "
358         "socket_role %d, error %d",
359         address.ToString().c_str(),
360         port,
361         type,
362         connection_state,
363         std::to_string(tx_bytes).c_str(),
364         std::to_string(rx_bytes).c_str(),
365         uid,
366         server_port,
367         socket_role,
368         ret);
369   }
370 }
371 
LogMetricManufacturerInfo(const Address & 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)372 void LogMetricManufacturerInfo(
373     const Address& address,
374     android::bluetooth::DeviceInfoSrcEnum source_type,
375     const std::string& source_name,
376     const std::string& manufacturer,
377     const std::string& model,
378     const std::string& hardware_version,
379     const std::string& software_version) {
380   int metric_id = 0;
381   if (!address.IsEmpty()) {
382     metric_id = MetricIdManager::GetInstance().AllocateId(address);
383   }
384   int ret = android::util::stats_write(
385       android::util::BLUETOOTH_DEVICE_INFO_REPORTED,
386       byteField,
387       source_type,
388       source_name.c_str(),
389       manufacturer.c_str(),
390       model.c_str(),
391       hardware_version.c_str(),
392       software_version.c_str(),
393       metric_id);
394   if (ret < 0) {
395     LOG_WARN(
396         "Failed for %s, source_type %d, source_name %s, manufacturer %s, model %s, hardware_version %s, "
397         "software_version %s, error %d",
398         address.ToString().c_str(),
399         source_type,
400         source_name.c_str(),
401         manufacturer.c_str(),
402         model.c_str(),
403         hardware_version.c_str(),
404         software_version.c_str(),
405         ret);
406   }
407 }
408 
LogMetricBluetoothHalCrashReason(const Address & address,uint32_t error_code,uint32_t vendor_error_code)409 void LogMetricBluetoothHalCrashReason(
410     const Address& address,
411     uint32_t error_code,
412     uint32_t vendor_error_code) {
413   int ret = android::util::stats_write(
414       android::util::BLUETOOTH_HAL_CRASH_REASON_REPORTED,
415       0 /* metric_id */,
416       byteField,
417       error_code,
418       vendor_error_code);
419   if (ret < 0) {
420     LOG_WARN(
421         "Failed for %s, error_code %s, vendor_error_code %s, error %d",
422         address.ToString().c_str(),
423         common::ToHexString(error_code).c_str(),
424         common::ToHexString(vendor_error_code).c_str(),
425         ret);
426   }
427 }
428 
429 }  // namespace os
430 }  // namespace bluetooth
431