• 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 <stdint.h>
23 #include <memory>
24 #include <string>
25 
26 namespace system_bt_osi {
27 
28 // Typedefs to hide protobuf definition to the rest of stack
29 
30 typedef enum {
31   DEVICE_TYPE_UNKNOWN,
32   DEVICE_TYPE_BREDR,
33   DEVICE_TYPE_LE,
34   DEVICE_TYPE_DUMO,
35 } device_type_t;
36 
37 typedef enum {
38   WAKE_EVENT_UNKNOWN,
39   WAKE_EVENT_ACQUIRED,
40   WAKE_EVENT_RELEASED,
41 } wake_event_type_t;
42 
43 typedef enum {
44   SCAN_TYPE_UNKNOWN,
45   SCAN_TECH_TYPE_LE,
46   SCAN_TECH_TYPE_BREDR,
47   SCAN_TECH_TYPE_BOTH,
48 } scan_tech_t;
49 
50 typedef enum {
51   CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
52   CONNECTION_TECHNOLOGY_TYPE_LE,
53   CONNECTION_TECHNOLOGY_TYPE_BREDR,
54 } connection_tech_t;
55 
56 typedef enum {
57   DISCONNECT_REASON_UNKNOWN,
58   DISCONNECT_REASON_METRICS_DUMP,
59   DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
60 } disconnect_reason_t;
61 
62 /* Values of A2DP metrics that we care about
63  *
64  *    audio_duration_ms : sum of audio duration (in milliseconds).
65  *    device_class: device class of the paired device.
66  *    media_timer_min_ms : minimum scheduled time (in milliseconds)
67  *                         of the media timer.
68  *    media_timer_max_ms: maximum scheduled time (in milliseconds)
69  *                        of the media timer.
70  *    media_timer_avg_ms: average scheduled time (in milliseconds)
71  *                        of the media timer.
72  *    buffer_overruns_max_count: TODO - not clear what this is.
73  *    buffer_overruns_total : number of times the media buffer with
74  *                            audio data has overrun
75  *    buffer_underruns_average: TODO - not clear what this is.
76  *    buffer_underruns_count: number of times there was no enough
77  *                            audio data to add to the media buffer.
78  * NOTE: Negative values are invalid
79 */
80 class A2dpSessionMetrics {
81  public:
A2dpSessionMetrics()82   A2dpSessionMetrics() {}
83 
84   /*
85    * Update the metrics value in the current metrics object using the metrics
86    * objects supplied
87    */
88   void Update(const A2dpSessionMetrics& metrics);
89 
90   /*
91    * Compare whether two metrics objects are equal
92    */
93   bool operator==(const A2dpSessionMetrics& rhs) const;
94 
95   /*
96    * Initialize all values to -1 which is invalid in order to make a distinction
97    * between 0 and invalid values
98    */
99   int64_t audio_duration_ms = -1;
100   int32_t media_timer_min_ms = -1;
101   int32_t media_timer_max_ms = -1;
102   int32_t media_timer_avg_ms = -1;
103   int64_t total_scheduling_count = -1;
104   int32_t buffer_overruns_max_count = -1;
105   int32_t buffer_overruns_total = -1;
106   float buffer_underruns_average = -1;
107   int32_t buffer_underruns_count = -1;
108 };
109 
110 class BluetoothMetricsLogger {
111  public:
GetInstance()112   static BluetoothMetricsLogger* GetInstance() {
113     static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
114     return instance;
115   }
116 
117   /*
118    * Record a pairing event
119    *
120    * Parameters:
121    *    timestamp_ms: Unix epoch time in milliseconds
122    *    device_class: class of remote device
123    *    device_type: type of remote device
124    *    disconnect_reason: HCI reason for pairing disconnection.
125    *                       See: stack/include/hcidefs.h
126    */
127   void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
128                     uint32_t device_class, device_type_t device_type);
129 
130   /*
131    * Record a wake event
132    *
133    * Parameters:
134    *    timestamp_ms: Unix epoch time in milliseconds
135    *    type: whether it was acquired or released
136    *    requestor: if provided is the service requesting the wake lock
137    *    name: the name of the wake lock held
138    */
139   void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
140                     const std::string& name, uint64_t timestamp_ms);
141 
142   /*
143    * Record a scan event
144    *
145    * Parameters
146    *    timestamp_ms : Unix epoch time in milliseconds
147    *    start : true if this is the beginning of the scan
148    *    initiator: a unique ID identifying the app starting the scan
149    *    type: whether the scan reports BR/EDR, LE, or both.
150    *    results: number of results to be reported.
151    */
152   void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
153                     uint32_t results, uint64_t timestamp_ms);
154 
155   /*
156    * Start logging a Bluetooth session
157    *
158    * A Bluetooth session is defined a a connection between this device and
159    * another remote device which may include multiple profiles and protocols
160    *
161    * Only one Bluetooth session can exist at one time. Calling this method twice
162    * without LogBluetoothSessionEnd will result in logging a premature end of
163    * current Bluetooth session
164    *
165    * Parameters:
166    *    connection_tech_type : type of connection technology
167    *    timestamp_ms : the timestamp for session start, 0 means now
168    *
169    */
170   void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
171                                 uint64_t timestamp_ms);
172 
173   /*
174    * Stop logging a Bluetooth session and pushes it to the log queue
175    *
176    * If no Bluetooth session exist, this method exits immediately
177    *
178    * Parameters:
179    *    disconnect_reason : A string representation of disconnect reason
180    *    timestamp_ms : the timestamp of session end, 0 means now
181    *
182    */
183   void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
184                               uint64_t timestamp_ms);
185 
186   /*
187    * Log information about remote device in a current Bluetooth session
188    *
189    * If a Bluetooth session does not exist, create one with default parameter
190    * and timestamp now
191    *
192    * Parameters:
193    *    device_class : device_class defined in btm_api_types.h
194    *    device_type : type of remote device
195    */
196   void LogBluetoothSessionDeviceInfo(uint32_t device_class,
197                                      device_type_t device_type);
198 
199   /*
200    * Log A2DP Audio Session Information
201    *
202    * - Repeated calls to this method will override previous metrics if in the
203    *   same Bluetooth connection
204    * - If a Bluetooth session does not exist, create one with default parameter
205    *   and timestamp now
206    *
207    * Parameters:
208    *    a2dp_session_metrics - pointer to struct holding a2dp stats
209    *
210    */
211   void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
212 
213   /**
214    * Log Headset profile RFCOMM connection event
215    *
216    * @param service_id the BTA service ID for this headset connection
217    */
218   void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
219 
220   /*
221    * Writes the metrics, in base64 protobuf format, into the descriptor FD,
222    * metrics events are always cleared after dump
223    */
224   void WriteBase64(int fd);
225   void WriteBase64String(std::string* serialized);
226   void WriteString(std::string* serialized);
227 
228   /*
229    * Reset the metrics logger by cleaning up its staging queues and existing
230    * protobuf objects.
231    */
232   void Reset();
233 
234   /*
235    * Maximum number of log entries for each session or event
236    */
237   static const size_t kMaxNumBluetoothSession = 50;
238   static const size_t kMaxNumPairEvent = 50;
239   static const size_t kMaxNumWakeEvent = 1000;
240   static const size_t kMaxNumScanEvent = 50;
241 
242  private:
243   BluetoothMetricsLogger();
244 
245   /*
246    * When a Bluetooth session is on and the user initiates a metrics dump, we
247    * need to be able to upload whatever we have first. This method breaks the
248    * ongoing Bluetooth session into two sessions with the previous one labeled
249    * as "METRICS_DUMP" for the disconnect reason.
250    */
251   void CutoffSession();
252 
253   /*
254    * Build the internal metrics object using information gathered
255    */
256   void Build();
257 
258   /*
259    * Reset objects related to current Bluetooth session
260    */
261   void ResetSession();
262 
263   /*
264    * Reset the underlining BluetoothLog object
265    */
266   void ResetLog();
267 
268   /*
269    * PIMPL style implementation to hide internal dependencies
270    */
271   struct impl;
272   std::unique_ptr<impl> const pimpl_;
273 };
274 }
275