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