blob: 075a268ac376b9fbab03ef422c79fb402b47a96e [file] [log] [blame]
Marie Janssen77f579f2016-01-15 16:14:14 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2016 Google, Inc.
Marie Janssen77f579f2016-01-15 16:14:14 -08004 *
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
Jack Hed8be4d32019-01-20 21:31:12 -080021#include <android/bluetooth/hci/enums.pb.h>
Jack He8bc22a12018-04-02 13:04:58 -070022#include <bta/include/bta_api.h>
Jack He9d9df722018-12-20 15:46:17 -080023#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
Marie Janssen77f579f2016-01-15 16:14:14 -080024#include <stdint.h>
Jack Hef3175622016-12-08 19:29:00 -080025#include <memory>
26#include <string>
27
Jack He959bc332018-08-15 12:38:37 -070028namespace bluetooth {
29
30namespace common {
Jack Hef3175622016-12-08 19:29:00 -080031
32// Typedefs to hide protobuf definition to the rest of stack
Marie Janssen77f579f2016-01-15 16:14:14 -080033
34typedef enum {
35 DEVICE_TYPE_UNKNOWN,
36 DEVICE_TYPE_BREDR,
37 DEVICE_TYPE_LE,
38 DEVICE_TYPE_DUMO,
39} device_type_t;
40
Marie Janssen77f579f2016-01-15 16:14:14 -080041typedef enum {
42 WAKE_EVENT_UNKNOWN,
43 WAKE_EVENT_ACQUIRED,
44 WAKE_EVENT_RELEASED,
45} wake_event_type_t;
46
Marie Janssen77f579f2016-01-15 16:14:14 -080047typedef 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
Jack Hef3175622016-12-08 19:29:00 -080054typedef enum {
55 CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
56 CONNECTION_TECHNOLOGY_TYPE_LE,
57 CONNECTION_TECHNOLOGY_TYPE_BREDR,
58} connection_tech_t;
Marie Janssen77f579f2016-01-15 16:14:14 -080059
Jack Hea3f831c2017-01-17 15:41:30 -080060typedef enum {
61 DISCONNECT_REASON_UNKNOWN,
62 DISCONNECT_REASON_METRICS_DUMP,
63 DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
64} disconnect_reason_t;
65
Jack Hef3175622016-12-08 19:29:00 -080066/* 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
Jack He959bc332018-08-15 12:38:37 -070083 */
Jack Hef3175622016-12-08 19:29:00 -080084class A2dpSessionMetrics {
85 public:
86 A2dpSessionMetrics() {}
Pavlin Radoslavova1bccb92016-02-17 15:42:38 -080087
Jack Hef3175622016-12-08 19:29:00 -080088 /*
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;
Jack Hefeeaf5f2018-06-08 20:13:23 -0700112 int64_t codec_index = -1;
113 bool is_a2dp_offload = false;
Jack Hef3175622016-12-08 19:29:00 -0800114};
115
116class BluetoothMetricsLogger {
117 public:
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 */
Jack Hea3f831c2017-01-17 15:41:30 -0800189 void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
Jack Hef3175622016-12-08 19:29:00 -0800190 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
Jack He8bc22a12018-04-02 13:04:58 -0700219 /**
220 * Log Headset profile RFCOMM connection event
221 *
222 * @param service_id the BTA service ID for this headset connection
Jack Hef3175622016-12-08 19:29:00 -0800223 */
Jack He8bc22a12018-04-02 13:04:58 -0700224 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);
Jack Hef3175622016-12-08 19:29:00 -0800233
234 /*
235 * Reset the metrics logger by cleaning up its staging queues and existing
236 * protobuf objects.
237 */
238 void Reset();
239
Jack Hea3f831c2017-01-17 15:41:30 -0800240 /*
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
Jack Hef3175622016-12-08 19:29:00 -0800248 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};
Jack He959bc332018-08-15 12:38:37 -0700280
Jack He9d9df722018-12-20 15:46:17 -0800281/**
282 * Unknown connection handle for metrics purpose
283 */
284static 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 */
301void LogLinkLayerConnectionEvent(const RawAddress* address,
302 uint32_t connection_handle,
303 android::bluetooth::DirectionEnum direction,
304 uint32_t link_type, uint32_t hci_cmd,
305 uint32_t hci_event, uint32_t hci_ble_event,
306 uint32_t cmd_status, uint32_t reason_code);
307
Jack He7ff9ac62019-01-20 23:16:45 -0800308/**
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 */
314void LogHciTimeoutEvent(uint32_t hci_cmd);
315
Jack He468cdc32019-01-29 14:49:34 -0800316/**
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 */
330void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
331 uint16_t manufacturer_name, uint16_t subversion);
Jack Hed8be4d32019-01-20 21:31:12 -0800332
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 */
341void 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 */
356void 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 */
371void 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 */
384void 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 */
398void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
399 uint32_t cmd_status,
400 int32_t transmit_power_level);
401
Jack He959bc332018-08-15 12:38:37 -0700402} // namespace common
403
404} // namespace bluetooth