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