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#define LOG_TAG "bt_osi_metrics" 19 20#include <unistd.h> 21#include <algorithm> 22#include <cerrno> 23#include <chrono> 24#include <cstdint> 25#include <cstring> 26#include <memory> 27#include <mutex> 28 29#include <base/base64.h> 30#include <base/logging.h> 31 32#include "osi/include/leaky_bonded_queue.h" 33#include "osi/include/log.h" 34#include "osi/include/osi.h" 35#include "osi/include/time.h" 36 37#include "osi/include/metrics.h" 38 39namespace system_bt_osi { 40 41// Maximum number of log entries for each repeated field 42#define MAX_NUM_BLUETOOTH_SESSION 50 43#define MAX_NUM_PAIR_EVENT 50 44#define MAX_NUM_WAKE_EVENT 50 45#define MAX_NUM_SCAN_EVENT 50 46 47static float combine_averages(float avg_a, int64_t ct_a, float avg_b, 48 int64_t ct_b) { 49 if (ct_a > 0 && ct_b > 0) { 50 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); 51 } else if (ct_b > 0) { 52 return avg_b; 53 } else { 54 return avg_a; 55 } 56} 57 58static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b, 59 int64_t ct_b) { 60 if (ct_a > 0 && ct_b > 0) { 61 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); 62 } else if (ct_b > 0) { 63 return avg_b; 64 } else { 65 return avg_a; 66 } 67} 68 69void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) { 70 if (metrics.audio_duration_ms > 0) { 71 audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms); 72 audio_duration_ms += metrics.audio_duration_ms; 73 } 74 if (metrics.media_timer_min_ms > 0) { 75 if (media_timer_min_ms < 0) { 76 media_timer_min_ms = metrics.media_timer_min_ms; 77 } else { 78 media_timer_min_ms = 79 std::min(media_timer_min_ms, metrics.media_timer_min_ms); 80 } 81 } 82 if (metrics.media_timer_max_ms > 0) { 83 media_timer_max_ms = 84 std::max(media_timer_max_ms, metrics.media_timer_max_ms); 85 } 86 if (metrics.media_timer_avg_ms > 0 && metrics.total_scheduling_count > 0) { 87 if (media_timer_avg_ms < 0 || total_scheduling_count < 0) { 88 media_timer_avg_ms = metrics.media_timer_avg_ms; 89 total_scheduling_count = metrics.total_scheduling_count; 90 } else { 91 media_timer_avg_ms = combine_averages( 92 media_timer_avg_ms, total_scheduling_count, 93 metrics.media_timer_avg_ms, metrics.total_scheduling_count); 94 total_scheduling_count += metrics.total_scheduling_count; 95 } 96 } 97 if (metrics.buffer_overruns_max_count > 0) { 98 buffer_overruns_max_count = 99 std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count); 100 } 101 if (metrics.buffer_overruns_total > 0) { 102 buffer_overruns_total = 103 std::max(static_cast<int32_t>(0), buffer_overruns_total); 104 buffer_overruns_total += metrics.buffer_overruns_total; 105 } 106 if (metrics.buffer_underruns_average > 0 && 107 metrics.buffer_underruns_count > 0) { 108 if (buffer_underruns_average < 0 || buffer_underruns_count < 0) { 109 buffer_underruns_average = metrics.buffer_underruns_average; 110 buffer_underruns_count = metrics.buffer_underruns_count; 111 } else { 112 buffer_underruns_average = combine_averages( 113 metrics.buffer_underruns_average, metrics.buffer_underruns_count, 114 buffer_underruns_average, buffer_underruns_count); 115 buffer_underruns_count += metrics.buffer_underruns_count; 116 } 117 } 118} 119 120bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const { 121 return audio_duration_ms == rhs.audio_duration_ms && 122 media_timer_min_ms == rhs.media_timer_min_ms && 123 media_timer_max_ms == rhs.media_timer_max_ms && 124 media_timer_avg_ms == rhs.media_timer_avg_ms && 125 total_scheduling_count == rhs.total_scheduling_count && 126 buffer_overruns_max_count == rhs.buffer_overruns_max_count && 127 buffer_overruns_total == rhs.buffer_overruns_total && 128 buffer_underruns_average == rhs.buffer_underruns_average && 129 buffer_underruns_count == rhs.buffer_underruns_count; 130} 131 132struct BluetoothMetricsLogger::impl { 133 // TODO(siyuanh): Implement for linux 134}; 135 136BluetoothMetricsLogger::BluetoothMetricsLogger() : pimpl_(new impl) {} 137 138void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason, 139 uint64_t timestamp_ms, 140 uint32_t device_class, 141 device_type_t device_type) { 142 // TODO(siyuanh): Implement for linux 143} 144 145void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type, 146 const std::string& requestor, 147 const std::string& name, 148 uint64_t timestamp_ms) { 149 // TODO(siyuanh): Implement for linux 150} 151 152void BluetoothMetricsLogger::LogScanEvent(bool start, 153 const std::string& initator, 154 scan_tech_t type, uint32_t results, 155 uint64_t timestamp_ms) { 156 // TODO(siyuanh): Implement for linux 157} 158 159void BluetoothMetricsLogger::LogBluetoothSessionStart( 160 connection_tech_t connection_tech_type, uint64_t timestamp_ms) { 161 // TODO(siyuanh): Implement for linux 162} 163 164void BluetoothMetricsLogger::LogBluetoothSessionEnd( 165 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) { 166 // TODO(siyuanh): Implement for linux 167} 168 169void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo( 170 uint32_t device_class, device_type_t device_type) { 171 // TODO(siyuanh): Implement for linux 172} 173 174void BluetoothMetricsLogger::LogA2dpSession( 175 const A2dpSessionMetrics& a2dp_session_metrics) { 176 // TODO(siyuanh): Implement for linux 177} 178 179void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) { 180 // TODO(siyuanh): Implement for linux 181} 182 183void BluetoothMetricsLogger::WriteBase64String(std::string* serialized, 184 bool clear) { 185 // TODO(siyuanh): Implement for linux 186} 187 188void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) { 189 // TODO(siyuanh): Implement for linux 190} 191 192void BluetoothMetricsLogger::CutoffSession() { 193 // TODO(siyuanh): Implement for linux 194} 195 196void BluetoothMetricsLogger::Build() { 197 // TODO(siyuanh): Implement for linux 198} 199 200void BluetoothMetricsLogger::Reset() { 201 // TODO(siyuanh): Implement for linux 202} 203 204} // namespace system_bt_osi 205