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