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 "gd/os/metrics.h" 32 #include "types/raw_address.h" 33 #include "hci/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, 141 uint32_t device_class, 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, 153 const std::string& name, 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& initator, scan_tech_t type, 166 uint32_t results, 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, 184 uint64_t timestamp_ms); 185 186 /* 187 * Stop logging a Bluetooth session and pushes it to the log queue 188 * 189 * If no Bluetooth session exist, this method exits immediately 190 * 191 * Parameters: 192 * disconnect_reason : A string representation of disconnect reason 193 * timestamp_ms : the timestamp of session end, 0 means now 194 * 195 */ 196 void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason, 197 uint64_t timestamp_ms); 198 199 /* 200 * Log information about remote device in a current Bluetooth session 201 * 202 * If a Bluetooth session does not exist, create one with default parameter 203 * and timestamp now 204 * 205 * Parameters: 206 * device_class : device_class defined in btm_api_types.h 207 * device_type : type of remote device 208 */ 209 void LogBluetoothSessionDeviceInfo(uint32_t device_class, 210 device_type_t device_type); 211 212 /* 213 * Log A2DP Audio Session Information 214 * 215 * - Repeated calls to this method will override previous metrics if in the 216 * same Bluetooth connection 217 * - If a Bluetooth session does not exist, create one with default parameter 218 * and timestamp now 219 * 220 * Parameters: 221 * a2dp_session_metrics - pointer to struct holding a2dp stats 222 * 223 */ 224 void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics); 225 226 /** 227 * Log Headset profile RFCOMM connection event 228 * 229 * @param service_id the BTA service ID for this headset connection 230 */ 231 void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id); 232 233 /* 234 * Writes the metrics, in base64 protobuf format, into the descriptor FD, 235 * metrics events are always cleared after dump 236 */ 237 void WriteBase64(int fd); 238 void WriteBase64String(std::string* serialized); 239 void WriteString(std::string* serialized); 240 241 /* 242 * Reset the metrics logger by cleaning up its staging queues and existing 243 * protobuf objects. 244 */ 245 void Reset(); 246 247 /* 248 * Maximum number of log entries for each session or event 249 */ 250 static const size_t kMaxNumBluetoothSession = 50; 251 static const size_t kMaxNumPairEvent = 50; 252 static const size_t kMaxNumWakeEvent = 1000; 253 static const size_t kMaxNumScanEvent = 50; 254 255 private: 256 BluetoothMetricsLogger(); 257 258 /* 259 * When a Bluetooth session is on and the user initiates a metrics dump, we 260 * need to be able to upload whatever we have first. This method breaks the 261 * ongoing Bluetooth session into two sessions with the previous one labeled 262 * as "METRICS_DUMP" for the disconnect reason. 263 */ 264 void CutoffSession(); 265 266 /* 267 * Build the internal metrics object using information gathered 268 */ 269 void Build(); 270 271 /* 272 * Reset objects related to current Bluetooth session 273 */ 274 void ResetSession(); 275 276 /* 277 * Reset the underlining BluetoothLog object 278 */ 279 void ResetLog(); 280 281 /* 282 * PIMPL style implementation to hide internal dependencies 283 */ 284 struct impl; 285 std::unique_ptr<impl> const pimpl_; 286 }; 287 288 /** 289 * Unknown connection handle for metrics purpose 290 */ 291 static const uint32_t kUnknownConnectionHandle = 0xFFFF; 292 293 /** 294 * Log link layer connection event 295 * 296 * @param address Stack wide consistent Bluetooth address of this event, 297 * nullptr if unknown 298 * @param connection_handle connection handle of this event, 299 * {@link kUnknownConnectionHandle} if unknown 300 * @param direction direction of this connection 301 * @param link_type type of the link 302 * @param hci_cmd HCI command opecode associated with this event, if any 303 * @param hci_event HCI event code associated with this event, if any 304 * @param hci_ble_event HCI BLE event code associated with this event, if any 305 * @param cmd_status Command status associated with this event, if any 306 * @param reason_code Reason code associated with this event, if any 307 */ 308 void LogLinkLayerConnectionEvent(const RawAddress* address, 309 uint32_t connection_handle, 310 android::bluetooth::DirectionEnum direction, 311 uint16_t link_type, uint32_t hci_cmd, 312 uint16_t hci_event, uint16_t hci_ble_event, 313 uint16_t cmd_status, uint16_t reason_code); 314 315 /** 316 * Logs when Bluetooth controller failed to reply with command status within 317 * a timeout period after receiving an HCI command from the host 318 * 319 * @param hci_cmd opcode of HCI command that caused this timeout 320 */ 321 void LogHciTimeoutEvent(uint32_t hci_cmd); 322 323 /** 324 * Logs when we receive Bluetooth Read Remote Version Information Complete 325 * Event from the remote device, as documented by the Bluetooth Core HCI 326 * specification 327 * 328 * Reference: 5.0 Core Specification, Vol 2, Part E, Page 1118 329 * 330 * @param handle handle of associated ACL connection 331 * @param status HCI command status of this event 332 * @param version version code from read remote version complete event 333 * @param manufacturer_name manufacturer code from read remote version complete 334 * event 335 * @param subversion subversion code from read remote version complete event 336 */ 337 void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version, 338 uint16_t manufacturer_name, uint16_t subversion); 339 340 /** 341 * Log A2DP audio buffer underrun event 342 * 343 * @param address A2DP device associated with this event 344 * @param encoding_interval_millis encoding interval in milliseconds 345 * @param num_missing_pcm_bytes number of PCM bytes that cannot be read from 346 * the source 347 */ 348 void LogA2dpAudioUnderrunEvent(const RawAddress& address, 349 uint64_t encoding_interval_millis, 350 int num_missing_pcm_bytes); 351 352 /** 353 * Log A2DP audio buffer overrun event 354 * 355 * @param address A2DP device associated with this event 356 * @param encoding_interval_millis encoding interval in milliseconds 357 * @param num_dropped_buffers number of encoded buffers dropped from Tx queue 358 * @param num_dropped_encoded_frames number of encoded frames dropped from Tx 359 * queue 360 * @param num_dropped_encoded_bytes number of encoded bytes dropped from Tx 361 * queue 362 */ 363 void LogA2dpAudioOverrunEvent(const RawAddress& address, 364 uint64_t encoding_interval_millis, 365 int num_dropped_buffers, 366 int num_dropped_encoded_frames, 367 int num_dropped_encoded_bytes); 368 369 /** 370 * Log A2DP playback state changed event 371 * 372 * @param address A2DP device associated with this event 373 * @param playback_state audio playback state 374 * @param audio_coding_mode audio codec encoding mode 375 */ 376 void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state, 377 int audio_coding_mode); 378 379 /** 380 * Log read RSSI result 381 * 382 * @param address device associated with this event 383 * @param handle connection handle of this event, 384 * {@link kUnknownConnectionHandle} if unknown 385 * @param cmd_status command status from read RSSI command 386 * @param rssi rssi value in dBm 387 */ 388 void LogReadRssiResult(const RawAddress& address, uint16_t handle, 389 uint32_t cmd_status, int8_t rssi); 390 391 /** 392 * Log failed contact counter report 393 * 394 * @param address device associated with this event 395 * @param handle connection handle of this event, 396 * {@link kUnknownConnectionHandle} if unknown 397 * @param cmd_status command status from read failed contact counter command 398 * @param failed_contact_counter Number of consecutive failed contacts for a 399 * connection corresponding to the Handle 400 */ 401 void LogReadFailedContactCounterResult(const RawAddress& address, 402 uint16_t handle, uint32_t cmd_status, 403 int32_t failed_contact_counter); 404 405 /** 406 * Log transmit power level for a particular device after read 407 * 408 * @param address device associated with this event 409 * @param handle connection handle of this event, 410 * {@link kUnknownConnectionHandle} if unknown 411 * @param cmd_status command status from read failed contact counter command 412 * @param transmit_power_level transmit power level for connection to this 413 * device 414 */ 415 void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle, 416 uint32_t cmd_status, 417 int32_t transmit_power_level); 418 419 /** 420 * Logs when there is an event related to Bluetooth Security Manager Protocol 421 * 422 * @param address address of associated device 423 * @param smp_cmd SMP command code associated with this event 424 * @param direction direction of this SMP command 425 * @param smp_fail_reason SMP pairing failure reason code from SMP spec 426 */ 427 void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd, 428 android::bluetooth::DirectionEnum direction, 429 uint8_t smp_fail_reason); 430 431 /** 432 * Logs there is an event related Bluetooth classic pairing 433 * 434 * @param address address of associated device 435 * @param handle connection handle of this event, 436 * {@link kUnknownConnectionHandle} if unknown 437 * @param hci_cmd HCI command associated with this event 438 * @param hci_event HCI event associated with this event 439 * @param cmd_status Command status associated with this event 440 * @param reason_code Reason code associated with this event 441 * @param event_value A status value related to this specific event 442 */ 443 void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event, 444 uint16_t cmd_status, uint16_t reason_code, int64_t event_value); 445 446 /** 447 * Logs when certain Bluetooth SDP attributes are discovered 448 * 449 * @param address address of associated device 450 * @param protocol_uuid 16 bit protocol UUID from Bluetooth Assigned Numbers 451 * @param attribute_id 16 bit attribute ID from Bluetooth Assigned Numbers 452 * @param attribute_size size of this attribute 453 * @param attribute_value pointer to the attribute data, must be larger than 454 * attribute_size 455 */ 456 void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, 457 uint16_t attribute_id, size_t attribute_size, 458 const char* attribute_value); 459 460 /** 461 * Logs when there is a change in Bluetooth socket connection state 462 * 463 * @param address address of associated device, empty if this is a server port 464 * @param port port of this socket connection 465 * @param type type of socket 466 * @param connection_state socket connection state 467 * @param tx_bytes number of bytes transmitted 468 * @param rx_bytes number of bytes received 469 * @param server_port server port of this socket, if any. When both 470 * |server_port| and |port| fields are populated, |port| must be spawned 471 * by |server_port| 472 * @param socket_role role of this socket, server or connection 473 * @param uid socket owner's uid 474 */ 475 void LogSocketConnectionState( 476 const RawAddress& address, int port, int type, 477 android::bluetooth::SocketConnectionstateEnum connection_state, 478 int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, 479 android::bluetooth::SocketRoleEnum socket_role); 480 481 /** 482 * Logs when a Bluetooth device's manufacturer information is learnt 483 * 484 * @param address address of associated device 485 * @param source_type where is this device info obtained from 486 * @param source_name name of the data source, internal or external 487 * @param manufacturer name of the manufacturer of this device 488 * @param model model of this device 489 * @param hardware_version hardware version of this device 490 * @param software_version software version of this device 491 */ 492 void LogManufacturerInfo(const RawAddress& address, 493 android::bluetooth::AddressTypeEnum address_type, 494 android::bluetooth::DeviceInfoSrcEnum source_type, 495 const std::string& source_name, 496 const std::string& manufacturer, 497 const std::string& model, 498 const std::string& hardware_version, 499 const std::string& software_version); 500 501 /** 502 * Logs when received Bluetooth HAL crash reason report. 503 * 504 * @param address current connected address. 505 * @param error_code the crash reason from bluetooth hal 506 * @param vendor_error_code the vendor crash reason from bluetooth Firmware 507 */ 508 void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code, 509 uint32_t vendor_error_code); 510 511 void LogLeAudioConnectionSessionReported( 512 int32_t group_size, int32_t group_metric_id, 513 int64_t connection_duration_nanos, 514 std::vector<int64_t>& device_connecting_offset_nanos, 515 std::vector<int64_t>& device_connected_offset_nanos, 516 std::vector<int64_t>& device_connection_duration_nanos, 517 std::vector<int32_t>& device_connection_status, 518 std::vector<int32_t>& device_disconnection_status, 519 std::vector<RawAddress>& device_address, 520 std::vector<int64_t>& streaming_offset_nanos, 521 std::vector<int64_t>& streaming_duration_nanos, 522 std::vector<int32_t>& streaming_context_type); 523 524 void LogLeAudioBroadcastSessionReported(int64_t duration_nanos); 525 526 void LogLeBluetoothConnectionMetricEventReported( 527 const RawAddress& raw_address, 528 android::bluetooth::le::LeConnectionOriginType origin_type, 529 android::bluetooth::le::LeConnectionType connection_type, 530 android::bluetooth::le::LeConnectionState transaction_state, 531 std::vector<std::pair<os::ArgumentType, int>> 532 argument_list); 533 534 } // namespace common 535 536 } // namespace bluetooth 537