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
39 namespace 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
combine_averages(float avg_a,int64_t ct_a,float avg_b,int64_t ct_b)47 static 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
combine_averages(int32_t avg_a,int64_t ct_a,int32_t avg_b,int64_t ct_b)58 static 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
Update(const A2dpSessionMetrics & metrics)69 void 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
operator ==(const A2dpSessionMetrics & rhs) const120 bool 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
132 struct BluetoothMetricsLogger::impl {
133 // TODO(siyuanh): Implement for linux
134 };
135
BluetoothMetricsLogger()136 BluetoothMetricsLogger::BluetoothMetricsLogger() : pimpl_(new impl) {}
137
LogPairEvent(uint32_t disconnect_reason,uint64_t timestamp_ms,uint32_t device_class,device_type_t device_type)138 void 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
LogWakeEvent(wake_event_type_t type,const std::string & requestor,const std::string & name,uint64_t timestamp_ms)145 void 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
LogScanEvent(bool start,const std::string & initator,scan_tech_t type,uint32_t results,uint64_t timestamp_ms)152 void 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
LogBluetoothSessionStart(connection_tech_t connection_tech_type,uint64_t timestamp_ms)159 void BluetoothMetricsLogger::LogBluetoothSessionStart(
160 connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
161 // TODO(siyuanh): Implement for linux
162 }
163
LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,uint64_t timestamp_ms)164 void BluetoothMetricsLogger::LogBluetoothSessionEnd(
165 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
166 // TODO(siyuanh): Implement for linux
167 }
168
LogBluetoothSessionDeviceInfo(uint32_t device_class,device_type_t device_type)169 void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
170 uint32_t device_class, device_type_t device_type) {
171 // TODO(siyuanh): Implement for linux
172 }
173
LogA2dpSession(const A2dpSessionMetrics & a2dp_session_metrics)174 void BluetoothMetricsLogger::LogA2dpSession(
175 const A2dpSessionMetrics& a2dp_session_metrics) {
176 // TODO(siyuanh): Implement for linux
177 }
178
WriteString(std::string * serialized,bool clear)179 void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
180 // TODO(siyuanh): Implement for linux
181 }
182
WriteBase64String(std::string * serialized,bool clear)183 void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
184 bool clear) {
185 // TODO(siyuanh): Implement for linux
186 }
187
WriteBase64(int fd,bool clear)188 void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
189 // TODO(siyuanh): Implement for linux
190 }
191
CutoffSession()192 void BluetoothMetricsLogger::CutoffSession() {
193 // TODO(siyuanh): Implement for linux
194 }
195
Build()196 void BluetoothMetricsLogger::Build() {
197 // TODO(siyuanh): Implement for linux
198 }
199
Reset()200 void BluetoothMetricsLogger::Reset() {
201 // TODO(siyuanh): Implement for linux
202 }
203
204 } // namespace system_bt_osi
205