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