• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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