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