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