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 #pragma once 20 21 #include <bta/include/bta_api.h> 22 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h> 23 #include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h> 24 #include <frameworks/proto_logging/stats/enums/bluetooth/le/enums.pb.h> 25 #include <stdint.h> 26 27 #include <memory> 28 #include <string> 29 #include <vector> 30 31 #include "hci/address.h" 32 #include "os/metrics.h" 33 #include "types/raw_address.h" 34 35 namespace bluetooth { 36 37 namespace common { 38 39 // Typedefs to hide protobuf definition to the rest of stack 40 41 typedef enum { 42 DEVICE_TYPE_UNKNOWN, 43 DEVICE_TYPE_BREDR, 44 DEVICE_TYPE_LE, 45 DEVICE_TYPE_DUMO, 46 } device_type_t; 47 48 typedef enum { 49 WAKE_EVENT_UNKNOWN, 50 WAKE_EVENT_ACQUIRED, 51 WAKE_EVENT_RELEASED, 52 } wake_event_type_t; 53 54 typedef enum { 55 SCAN_TYPE_UNKNOWN, 56 SCAN_TECH_TYPE_LE, 57 SCAN_TECH_TYPE_BREDR, 58 SCAN_TECH_TYPE_BOTH, 59 } scan_tech_t; 60 61 typedef enum { 62 CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 63 CONNECTION_TECHNOLOGY_TYPE_LE, 64 CONNECTION_TECHNOLOGY_TYPE_BREDR, 65 } connection_tech_t; 66 67 typedef enum { 68 DISCONNECT_REASON_UNKNOWN, 69 DISCONNECT_REASON_METRICS_DUMP, 70 DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, 71 } disconnect_reason_t; 72 73 /* Values of A2DP metrics that we care about 74 * 75 * audio_duration_ms : sum of audio duration (in milliseconds). 76 * device_class: device class of the paired device. 77 * media_timer_min_ms : minimum scheduled time (in milliseconds) 78 * of the media timer. 79 * media_timer_max_ms: maximum scheduled time (in milliseconds) 80 * of the media timer. 81 * media_timer_avg_ms: average scheduled time (in milliseconds) 82 * of the media timer. 83 * buffer_overruns_max_count: TODO - not clear what this is. 84 * buffer_overruns_total : number of times the media buffer with 85 * audio data has overrun 86 * buffer_underruns_average: TODO - not clear what this is. 87 * buffer_underruns_count: number of times there was no enough 88 * audio data to add to the media buffer. 89 * NOTE: Negative values are invalid 90 */ 91 class A2dpSessionMetrics { 92 public: A2dpSessionMetrics()93 A2dpSessionMetrics() {} 94 95 /* 96 * Update the metrics value in the current metrics object using the metrics 97 * objects supplied 98 */ 99 void Update(const A2dpSessionMetrics& metrics); 100 101 /* 102 * Compare whether two metrics objects are equal 103 */ 104 bool operator==(const A2dpSessionMetrics& rhs) const; 105 106 /* 107 * Initialize all values to -1 which is invalid in order to make a distinction 108 * between 0 and invalid values 109 */ 110 int64_t audio_duration_ms = -1; 111 int32_t media_timer_min_ms = -1; 112 int32_t media_timer_max_ms = -1; 113 int32_t media_timer_avg_ms = -1; 114 int64_t total_scheduling_count = -1; 115 int32_t buffer_overruns_max_count = -1; 116 int32_t buffer_overruns_total = -1; 117 float buffer_underruns_average = -1; 118 int32_t buffer_underruns_count = -1; 119 int64_t codec_index = -1; 120 bool is_a2dp_offload = false; 121 }; 122 123 class BluetoothMetricsLogger { 124 public: GetInstance()125 static BluetoothMetricsLogger* GetInstance() { 126 static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger(); 127 return instance; 128 } 129 130 /* 131 * Record a pairing event 132 * 133 * Parameters: 134 * timestamp_ms: Unix epoch time in milliseconds 135 * device_class: class of remote device 136 * device_type: type of remote device 137 * disconnect_reason: HCI reason for pairing disconnection. 138 * See: stack/include/hcidefs.h 139 */ 140 void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms, uint32_t device_class, 141 device_type_t device_type); 142 143 /* 144 * Record a wake event 145 * 146 * Parameters: 147 * timestamp_ms: Unix epoch time in milliseconds 148 * type: whether it was acquired or released 149 * requestor: if provided is the service requesting the wake lock 150 * name: the name of the wake lock held 151 */ 152 void LogWakeEvent(wake_event_type_t type, const std::string& requestor, const std::string& name, 153 uint64_t timestamp_ms); 154 155 /* 156 * Record a scan event 157 * 158 * Parameters 159 * timestamp_ms : Unix epoch time in milliseconds 160 * start : true if this is the beginning of the scan 161 * initiator: a unique ID identifying the app starting the scan 162 * type: whether the scan reports BR/EDR, LE, or both. 163 * results: number of results to be reported. 164 */ 165 void LogScanEvent(bool start, const std::string& initiator, scan_tech_t type, uint32_t results, 166 uint64_t timestamp_ms); 167 168 /* 169 * Start logging a Bluetooth session 170 * 171 * A Bluetooth session is defined a a connection between this device and 172 * another remote device which may include multiple profiles and protocols 173 * 174 * Only one Bluetooth session can exist at one time. Calling this method twice 175 * without LogBluetoothSessionEnd will result in logging a premature end of 176 * current Bluetooth session 177 * 178 * Parameters: 179 * connection_tech_type : type of connection technology 180 * timestamp_ms : the timestamp for session start, 0 means now 181 * 182 */ 183 void LogBluetoothSessionStart(connection_tech_t connection_tech_type, uint64_t timestamp_ms); 184 185 /* 186 * Stop logging a Bluetooth session and pushes it to the log queue 187 * 188 * If no Bluetooth session exist, this method exits immediately 189 * 190 * Parameters: 191 * disconnect_reason : A string representation of disconnect reason 192 * timestamp_ms : the timestamp of session end, 0 means now 193 * 194 */ 195 void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason, uint64_t timestamp_ms); 196 197 /* 198 * Log information about remote device in a current Bluetooth session 199 * 200 * If a Bluetooth session does not exist, create one with default parameter 201 * and timestamp now 202 * 203 * Parameters: 204 * device_class : device_class defined in btm_api_types.h 205 * device_type : type of remote device 206 */ 207 void LogBluetoothSessionDeviceInfo(uint32_t device_class, device_type_t device_type); 208 209 /* 210 * Log A2DP Audio Session Information 211 * 212 * - Repeated calls to this method will override previous metrics if in the 213 * same Bluetooth connection 214 * - If a Bluetooth session does not exist, create one with default parameter 215 * and timestamp now 216 * 217 * Parameters: 218 * a2dp_session_metrics - pointer to struct holding a2dp stats 219 * 220 */ 221 void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics); 222 223 /** 224 * Log Headset profile RFCOMM connection event 225 * 226 * @param service_id the BTA service ID for this headset connection 227 */ 228 void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id); 229 230 /* 231 * Writes the metrics, in base64 protobuf format, into the descriptor FD, 232 * metrics events are always cleared after dump 233 */ 234 void WriteBase64(int fd); 235 void WriteBase64String(std::string* serialized); 236 void WriteString(std::string* serialized); 237 238 /* 239 * Reset the metrics logger by cleaning up its staging queues and existing 240 * protobuf objects. 241 */ 242 void Reset(); 243 244 /* 245 * Maximum number of log entries for each session or event 246 */ 247 static const size_t kMaxNumBluetoothSession = 50; 248 static const size_t kMaxNumPairEvent = 50; 249 static const size_t kMaxNumWakeEvent = 1000; 250 static const size_t kMaxNumScanEvent = 50; 251 252 private: 253 BluetoothMetricsLogger(); 254 255 /* 256 * When a Bluetooth session is on and the user initiates a metrics dump, we 257 * need to be able to upload whatever we have first. This method breaks the 258 * ongoing Bluetooth session into two sessions with the previous one labeled 259 * as "METRICS_DUMP" for the disconnect reason. 260 */ 261 void CutoffSession(); 262 263 /* 264 * Build the internal metrics object using information gathered 265 */ 266 void Build(); 267 268 /* 269 * Reset objects related to current Bluetooth session 270 */ 271 void ResetSession(); 272 273 /* 274 * Reset the underlining BluetoothLog object 275 */ 276 void ResetLog(); 277 278 /* 279 * PIMPL style implementation to hide internal dependencies 280 */ 281 struct impl; 282 std::unique_ptr<impl> const pimpl_; 283 }; 284 285 /** 286 * Unknown connection handle for metrics purpose 287 */ 288 static const uint32_t kUnknownConnectionHandle = 0xFFFF; 289 290 /** 291 * Log link layer connection event 292 * 293 * @param address Stack wide consistent Bluetooth address of this event, 294 * nullptr if unknown 295 * @param connection_handle connection handle of this event, 296 * {@link kUnknownConnectionHandle} if unknown 297 * @param direction direction of this connection 298 * @param link_type type of the link 299 * @param hci_cmd HCI command opecode associated with this event, if any 300 * @param hci_event HCI event code associated with this event, if any 301 * @param hci_ble_event HCI BLE event code associated with this event, if any 302 * @param cmd_status Command status associated with this event, if any 303 * @param reason_code Reason code associated with this event, if any 304 */ 305 void LogLinkLayerConnectionEvent(const RawAddress* address, uint32_t connection_handle, 306 android::bluetooth::DirectionEnum direction, uint16_t link_type, 307 uint32_t hci_cmd, uint16_t hci_event, uint16_t hci_ble_event, 308 uint16_t cmd_status, uint16_t reason_code); 309 310 /** 311 * Logs when Bluetooth controller failed to reply with command status within 312 * a timeout period after receiving an HCI command from the host 313 * 314 * @param hci_cmd opcode of HCI command that caused this timeout 315 */ 316 void LogHciTimeoutEvent(uint32_t hci_cmd); 317 318 /** 319 * Logs when we receive Bluetooth Read Remote Version Information Complete 320 * Event from the remote device, as documented by the Bluetooth Core HCI 321 * specification 322 * 323 * Reference: 5.0 Core Specification, Vol 2, Part E, Page 1118 324 * 325 * @param handle handle of associated ACL connection 326 * @param status HCI command status of this event 327 * @param version version code from read remote version complete event 328 * @param manufacturer_name manufacturer code from read remote version complete 329 * event 330 * @param subversion subversion code from read remote version complete event 331 */ 332 void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version, 333 uint16_t manufacturer_name, uint16_t subversion); 334 335 /** 336 * Log A2DP audio buffer underrun event 337 * 338 * @param address A2DP device associated with this event 339 * @param encoding_interval_millis encoding interval in milliseconds 340 * @param num_missing_pcm_bytes number of PCM bytes that cannot be read from 341 * the source 342 */ 343 void LogA2dpAudioUnderrunEvent(const RawAddress& address, uint64_t encoding_interval_millis, 344 int num_missing_pcm_bytes); 345 346 /** 347 * Log A2DP audio buffer overrun event 348 * 349 * @param address A2DP device associated with this event 350 * @param encoding_interval_millis encoding interval in milliseconds 351 * @param num_dropped_buffers number of encoded buffers dropped from Tx queue 352 * @param num_dropped_encoded_frames number of encoded frames dropped from Tx 353 * queue 354 * @param num_dropped_encoded_bytes number of encoded bytes dropped from Tx 355 * queue 356 */ 357 void LogA2dpAudioOverrunEvent(const RawAddress& address, uint64_t encoding_interval_millis, 358 int num_dropped_buffers, int num_dropped_encoded_frames, 359 int num_dropped_encoded_bytes); 360 361 /** 362 * Log A2DP playback state changed event 363 * 364 * @param address A2DP device associated with this event 365 * @param playback_state audio playback state 366 * @param audio_coding_mode audio codec encoding mode 367 */ 368 void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state, int audio_coding_mode); 369 370 /** 371 * Log read RSSI result 372 * 373 * @param address device associated with this event 374 * @param handle connection handle of this event, 375 * {@link kUnknownConnectionHandle} if unknown 376 * @param cmd_status command status from read RSSI command 377 * @param rssi rssi value in dBm 378 */ 379 void LogReadRssiResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status, 380 int8_t rssi); 381 382 /** 383 * Log failed contact counter report 384 * 385 * @param address device associated with this event 386 * @param handle connection handle of this event, 387 * {@link kUnknownConnectionHandle} if unknown 388 * @param cmd_status command status from read failed contact counter command 389 * @param failed_contact_counter Number of consecutive failed contacts for a 390 * connection corresponding to the Handle 391 */ 392 void LogReadFailedContactCounterResult(const RawAddress& address, uint16_t handle, 393 uint32_t cmd_status, int32_t failed_contact_counter); 394 395 /** 396 * Log transmit power level for a particular device after read 397 * 398 * @param address device associated with this event 399 * @param handle connection handle of this event, 400 * {@link kUnknownConnectionHandle} if unknown 401 * @param cmd_status command status from read failed contact counter command 402 * @param transmit_power_level transmit power level for connection to this 403 * device 404 */ 405 void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status, 406 int32_t transmit_power_level); 407 408 /** 409 * Logs when there is an event related to Bluetooth Security Manager Protocol 410 * 411 * @param address address of associated device 412 * @param smp_cmd SMP command code associated with this event 413 * @param direction direction of this SMP command 414 * @param smp_fail_reason SMP pairing failure reason code from SMP spec 415 */ 416 void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd, 417 android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason); 418 419 /** 420 * Logs there is an event related Bluetooth classic pairing 421 * 422 * @param address address of associated device 423 * @param handle connection handle of this event, 424 * {@link kUnknownConnectionHandle} if unknown 425 * @param hci_cmd HCI command associated with this event 426 * @param hci_event HCI event associated with this event 427 * @param cmd_status Command status associated with this event 428 * @param reason_code Reason code associated with this event 429 * @param event_value A status value related to this specific event 430 */ 431 void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, 432 uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code, 433 int64_t event_value); 434 435 /** 436 * Logs when certain Bluetooth SDP attributes are discovered 437 * 438 * @param address address of associated device 439 * @param protocol_uuid 16 bit protocol UUID from Bluetooth Assigned Numbers 440 * @param attribute_id 16 bit attribute ID from Bluetooth Assigned Numbers 441 * @param attribute_size size of this attribute 442 * @param attribute_value pointer to the attribute data, must be larger than 443 * attribute_size 444 */ 445 void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id, 446 size_t attribute_size, const char* attribute_value); 447 448 /** 449 * Logs when there is a change in Bluetooth socket connection state 450 * 451 * @param address address of associated device, empty if this is a server port 452 * @param port port of this socket connection 453 * @param type type of socket 454 * @param connection_state socket connection state 455 * @param tx_bytes number of bytes transmitted 456 * @param rx_bytes number of bytes received 457 * @param server_port server port of this socket, if any. When both 458 * |server_port| and |port| fields are populated, |port| must be spawned 459 * by |server_port| 460 * @param socket_role role of this socket, server or connection 461 * @param uid socket owner's uid 462 */ 463 void LogSocketConnectionState(const RawAddress& address, int port, int type, 464 android::bluetooth::SocketConnectionstateEnum connection_state, 465 int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, 466 android::bluetooth::SocketRoleEnum socket_role); 467 468 /** 469 * Logs when a Bluetooth device's manufacturer information is learnt 470 * 471 * @param address address of associated device 472 * @param source_type where is this device info obtained from 473 * @param source_name name of the data source, internal or external 474 * @param manufacturer name of the manufacturer of this device 475 * @param model model of this device 476 * @param hardware_version hardware version of this device 477 * @param software_version software version of this device 478 */ 479 void LogManufacturerInfo(const RawAddress& address, 480 android::bluetooth::AddressTypeEnum address_type, 481 android::bluetooth::DeviceInfoSrcEnum source_type, 482 const std::string& source_name, const std::string& manufacturer, 483 const std::string& model, const std::string& hardware_version, 484 const std::string& software_version); 485 486 /** 487 * Logs when received Bluetooth HAL crash reason report. 488 * 489 * @param address current connected address. 490 * @param error_code the crash reason from bluetooth hal 491 * @param vendor_error_code the vendor crash reason from bluetooth Firmware 492 */ 493 void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code, 494 uint32_t vendor_error_code); 495 496 void LogLeAudioConnectionSessionReported( 497 int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos, 498 const std::vector<int64_t>& device_connecting_offset_nanos, 499 const std::vector<int64_t>& device_connected_offset_nanos, 500 const std::vector<int64_t>& device_connection_duration_nanos, 501 const std::vector<int32_t>& device_connection_status, 502 const std::vector<int32_t>& device_disconnection_status, 503 const std::vector<RawAddress>& device_address, 504 const std::vector<int64_t>& streaming_offset_nanos, 505 const std::vector<int64_t>& streaming_duration_nanos, 506 const std::vector<int32_t>& streaming_context_type); 507 508 void LogLeAudioBroadcastSessionReported(int64_t duration_nanos); 509 510 } // namespace common 511 512 } // namespace bluetooth 513