blob: 53cf4d2d1a1071caaf0334635479478be8d2f865 [file] [log] [blame]
Marie Janssena84a4ee2016-01-15 16:14:14 -08001/******************************************************************************
2 *
Jakub Pawlowski3b10fdd2017-09-18 09:00:20 -07003 * Copyright 2016 Google, Inc.
Marie Janssena84a4ee2016-01-15 16:14:14 -08004 *
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 ******************************************************************************/
Marie Janssena84a4ee2016-01-15 16:14:14 -080018#define LOG_TAG "bt_osi_metrics"
19
Jack He777228a2016-12-08 19:29:00 -080020#include <unistd.h>
21#include <algorithm>
22#include <cerrno>
23#include <chrono>
24#include <cstdint>
25#include <cstring>
26#include <memory>
27#include <mutex>
Marie Janssena84a4ee2016-01-15 16:14:14 -080028
Jack He777228a2016-12-08 19:29:00 -080029#include <base/base64.h>
30#include <base/logging.h>
Marie Janssena84a4ee2016-01-15 16:14:14 -080031
Jack He777228a2016-12-08 19:29:00 -080032#include "osi/include/leaky_bonded_queue.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080033#include "osi/include/log.h"
34#include "osi/include/osi.h"
Jack He777228a2016-12-08 19:29:00 -080035#include "osi/include/time.h"
36#include "stack/include/btm_api_types.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080037
Jack He65b2a572016-12-07 18:25:17 -080038#include "src/protos/bluetooth.pb.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080039
Jack He777228a2016-12-08 19:29:00 -080040#include "osi/include/metrics.h"
41
42namespace system_bt_osi {
Marie Janssena84a4ee2016-01-15 16:14:14 -080043
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -080044using clearcut::connectivity::A2DPSession;
Marie Janssena84a4ee2016-01-15 16:14:14 -080045using clearcut::connectivity::BluetoothLog;
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -080046using clearcut::connectivity::BluetoothSession;
Jack He777228a2016-12-08 19:29:00 -080047using clearcut::connectivity::BluetoothSession_ConnectionTechnologyType;
Jack He9bebcc02017-01-17 15:41:30 -080048using clearcut::connectivity::BluetoothSession_DisconnectReasonType;
Marie Janssena84a4ee2016-01-15 16:14:14 -080049using clearcut::connectivity::DeviceInfo;
50using clearcut::connectivity::DeviceInfo_DeviceType;
51using clearcut::connectivity::PairEvent;
52using clearcut::connectivity::ScanEvent;
53using clearcut::connectivity::ScanEvent_ScanTechnologyType;
54using clearcut::connectivity::ScanEvent_ScanEventType;
55using clearcut::connectivity::WakeEvent;
56using clearcut::connectivity::WakeEvent_WakeEventType;
57
Jack He777228a2016-12-08 19:29:00 -080058/*
59 * Get current OS boot time in millisecond
60 */
61static int64_t time_get_os_boottime_ms(void) {
62 return time_get_os_boottime_us() / 1000;
63}
64
65static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
66 int64_t ct_b) {
67 if (ct_a > 0 && ct_b > 0) {
68 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
69 } else if (ct_b > 0) {
70 return avg_b;
71 } else {
72 return avg_a;
Marie Janssena84a4ee2016-01-15 16:14:14 -080073 }
74}
75
Jack He777228a2016-12-08 19:29:00 -080076static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
77 int64_t ct_b) {
78 if (ct_a > 0 && ct_b > 0) {
79 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
80 } else if (ct_b > 0) {
81 return avg_b;
82 } else {
83 return avg_a;
84 }
85}
Marie Janssena84a4ee2016-01-15 16:14:14 -080086
Jack He777228a2016-12-08 19:29:00 -080087void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
Jack He723bef82017-01-20 11:17:44 -080088 if (metrics.audio_duration_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -080089 audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
90 audio_duration_ms += metrics.audio_duration_ms;
91 }
Jack He723bef82017-01-20 11:17:44 -080092 if (metrics.media_timer_min_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -080093 if (media_timer_min_ms < 0) {
94 media_timer_min_ms = metrics.media_timer_min_ms;
95 } else {
96 media_timer_min_ms =
97 std::min(media_timer_min_ms, metrics.media_timer_min_ms);
98 }
99 }
Jack He723bef82017-01-20 11:17:44 -0800100 if (metrics.media_timer_max_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800101 media_timer_max_ms =
102 std::max(media_timer_max_ms, metrics.media_timer_max_ms);
103 }
Jack He723bef82017-01-20 11:17:44 -0800104 if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800105 if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
106 media_timer_avg_ms = metrics.media_timer_avg_ms;
107 total_scheduling_count = metrics.total_scheduling_count;
108 } else {
109 media_timer_avg_ms = combine_averages(
110 media_timer_avg_ms, total_scheduling_count,
111 metrics.media_timer_avg_ms, metrics.total_scheduling_count);
112 total_scheduling_count += metrics.total_scheduling_count;
113 }
114 }
Jack He723bef82017-01-20 11:17:44 -0800115 if (metrics.buffer_overruns_max_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800116 buffer_overruns_max_count =
117 std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
118 }
Jack He723bef82017-01-20 11:17:44 -0800119 if (metrics.buffer_overruns_total >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800120 buffer_overruns_total =
121 std::max(static_cast<int32_t>(0), buffer_overruns_total);
122 buffer_overruns_total += metrics.buffer_overruns_total;
123 }
Jack He723bef82017-01-20 11:17:44 -0800124 if (metrics.buffer_underruns_average >= 0 &&
125 metrics.buffer_underruns_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800126 if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
127 buffer_underruns_average = metrics.buffer_underruns_average;
128 buffer_underruns_count = metrics.buffer_underruns_count;
129 } else {
130 buffer_underruns_average = combine_averages(
Jack He723bef82017-01-20 11:17:44 -0800131 buffer_underruns_average, buffer_underruns_count,
132 metrics.buffer_underruns_average, metrics.buffer_underruns_count);
Jack He777228a2016-12-08 19:29:00 -0800133 buffer_underruns_count += metrics.buffer_underruns_count;
134 }
135 }
136}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800137
Jack He777228a2016-12-08 19:29:00 -0800138bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
139 return audio_duration_ms == rhs.audio_duration_ms &&
140 media_timer_min_ms == rhs.media_timer_min_ms &&
141 media_timer_max_ms == rhs.media_timer_max_ms &&
142 media_timer_avg_ms == rhs.media_timer_avg_ms &&
143 total_scheduling_count == rhs.total_scheduling_count &&
144 buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
145 buffer_overruns_total == rhs.buffer_overruns_total &&
146 buffer_underruns_average == rhs.buffer_underruns_average &&
147 buffer_underruns_count == rhs.buffer_underruns_count;
148}
149
150static DeviceInfo_DeviceType get_device_type(device_type_t type) {
151 switch (type) {
152 case DEVICE_TYPE_BREDR:
153 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR;
154 case DEVICE_TYPE_LE:
155 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE;
156 case DEVICE_TYPE_DUMO:
157 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO;
158 case DEVICE_TYPE_UNKNOWN:
159 default:
160 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN;
161 }
162}
163
164static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(
165 connection_tech_t type) {
166 switch (type) {
167 case CONNECTION_TECHNOLOGY_TYPE_LE:
168 return BluetoothSession_ConnectionTechnologyType::
169 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE;
170 case CONNECTION_TECHNOLOGY_TYPE_BREDR:
171 return BluetoothSession_ConnectionTechnologyType::
172 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR;
173 case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN:
174 default:
175 return BluetoothSession_ConnectionTechnologyType::
176 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN;
177 }
178}
179
180static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) {
181 switch (type) {
182 case SCAN_TECH_TYPE_LE:
183 return ScanEvent_ScanTechnologyType::
184 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE;
185 case SCAN_TECH_TYPE_BREDR:
186 return ScanEvent_ScanTechnologyType::
187 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR;
188 case SCAN_TECH_TYPE_BOTH:
189 return ScanEvent_ScanTechnologyType::
190 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH;
191 case SCAN_TYPE_UNKNOWN:
192 default:
193 return ScanEvent_ScanTechnologyType::
194 ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN;
195 }
196}
197
198static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) {
199 switch (type) {
200 case WAKE_EVENT_ACQUIRED:
201 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED;
202 case WAKE_EVENT_RELEASED:
203 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED;
204 case WAKE_EVENT_UNKNOWN:
205 default:
206 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN;
207 }
208}
209
Jack He9bebcc02017-01-17 15:41:30 -0800210static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(
211 disconnect_reason_t type) {
212 switch (type) {
213 case DISCONNECT_REASON_METRICS_DUMP:
214 return BluetoothSession_DisconnectReasonType::
215 BluetoothSession_DisconnectReasonType_METRICS_DUMP;
216 case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS:
217 return BluetoothSession_DisconnectReasonType::
218 BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS;
219 case DISCONNECT_REASON_UNKNOWN:
220 default:
221 return BluetoothSession_DisconnectReasonType::
222 BluetoothSession_DisconnectReasonType_UNKNOWN;
223 }
224}
225
Jack He777228a2016-12-08 19:29:00 -0800226struct BluetoothMetricsLogger::impl {
227 impl(size_t max_bluetooth_session, size_t max_pair_event,
228 size_t max_wake_event, size_t max_scan_event)
229 : bt_session_queue_(
230 new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)),
231 pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)),
232 wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
233 scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
234 bluetooth_log_ = BluetoothLog::default_instance().New();
235 bluetooth_session_ = nullptr;
236 bluetooth_session_start_time_ms_ = 0;
237 a2dp_session_metrics_ = A2dpSessionMetrics();
238 }
239
240 /* Bluetooth log lock protected */
241 BluetoothLog* bluetooth_log_;
242 std::recursive_mutex bluetooth_log_lock_;
243 /* End Bluetooth log lock protected */
244 /* Bluetooth session lock protected */
245 BluetoothSession* bluetooth_session_;
246 uint64_t bluetooth_session_start_time_ms_;
247 A2dpSessionMetrics a2dp_session_metrics_;
248 std::recursive_mutex bluetooth_session_lock_;
249 /* End bluetooth session lock protected */
250 std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_;
251 std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_;
252 std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_;
253 std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_;
254};
255
256BluetoothMetricsLogger::BluetoothMetricsLogger()
Jack He9bebcc02017-01-17 15:41:30 -0800257 : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
258 kMaxNumWakeEvent, kMaxNumScanEvent)) {}
Jack He777228a2016-12-08 19:29:00 -0800259
260void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
261 uint64_t timestamp_ms,
262 uint32_t device_class,
263 device_type_t device_type) {
264 PairEvent* event = new PairEvent();
Myles Watson914a9dc2016-10-19 13:15:34 -0700265 DeviceInfo* info = event->mutable_device_paired_with();
Marie Janssena84a4ee2016-01-15 16:14:14 -0800266 info->set_device_class(device_class);
Jack He777228a2016-12-08 19:29:00 -0800267 info->set_device_type(get_device_type(device_type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800268 event->set_disconnect_reason(disconnect_reason);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800269 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800270 pimpl_->pair_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800271 {
272 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
273 pimpl_->bluetooth_log_->set_num_pair_event(
274 pimpl_->bluetooth_log_->num_pair_event() + 1);
275 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800276}
277
Jack He777228a2016-12-08 19:29:00 -0800278void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
279 const std::string& requestor,
280 const std::string& name,
281 uint64_t timestamp_ms) {
282 WakeEvent* event = new WakeEvent();
283 event->set_wake_event_type(get_wake_event_type(type));
284 event->set_requestor(requestor);
285 event->set_name(name);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800286 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800287 pimpl_->wake_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800288 {
289 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
290 pimpl_->bluetooth_log_->set_num_wake_event(
291 pimpl_->bluetooth_log_->num_wake_event() + 1);
292 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800293}
294
Jack He777228a2016-12-08 19:29:00 -0800295void BluetoothMetricsLogger::LogScanEvent(bool start,
296 const std::string& initator,
297 scan_tech_t type, uint32_t results,
298 uint64_t timestamp_ms) {
299 ScanEvent* event = new ScanEvent();
300 if (start) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800301 event->set_scan_event_type(ScanEvent::SCAN_EVENT_START);
Jack He777228a2016-12-08 19:29:00 -0800302 } else {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800303 event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP);
Jack He777228a2016-12-08 19:29:00 -0800304 }
305 event->set_initiator(initator);
306 event->set_scan_technology_type(get_scan_tech_type(type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800307 event->set_number_results(results);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800308 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800309 pimpl_->scan_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800310 {
311 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
312 pimpl_->bluetooth_log_->set_num_scan_event(
313 pimpl_->bluetooth_log_->num_scan_event() + 1);
314 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800315}
316
Jack He777228a2016-12-08 19:29:00 -0800317void BluetoothMetricsLogger::LogBluetoothSessionStart(
318 connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
319 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
320 if (pimpl_->bluetooth_session_ != nullptr) {
Jack He9bebcc02017-01-17 15:41:30 -0800321 LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
Jack He777228a2016-12-08 19:29:00 -0800322 0);
323 }
324 if (timestamp_ms == 0) {
325 timestamp_ms = time_get_os_boottime_ms();
326 }
327 pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
328 pimpl_->bluetooth_session_ = new BluetoothSession();
329 pimpl_->bluetooth_session_->set_connection_technology_type(
330 get_connection_tech_type(connection_tech_type));
331}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800332
Jack He777228a2016-12-08 19:29:00 -0800333void BluetoothMetricsLogger::LogBluetoothSessionEnd(
Jack He9bebcc02017-01-17 15:41:30 -0800334 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
Jack He777228a2016-12-08 19:29:00 -0800335 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
336 if (pimpl_->bluetooth_session_ == nullptr) {
337 return;
338 }
339 if (timestamp_ms == 0) {
340 timestamp_ms = time_get_os_boottime_ms();
341 }
342 int64_t session_duration_sec =
343 (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
344 pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec);
Jack He9bebcc02017-01-17 15:41:30 -0800345 pimpl_->bluetooth_session_->set_disconnect_reason_type(
346 get_disconnect_reason_type(disconnect_reason));
Jack He777228a2016-12-08 19:29:00 -0800347 pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
348 pimpl_->bluetooth_session_ = nullptr;
Jack He9bebcc02017-01-17 15:41:30 -0800349 {
350 std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
351 pimpl_->bluetooth_log_->set_num_bluetooth_session(
352 pimpl_->bluetooth_log_->num_bluetooth_session() + 1);
353 }
Jack He777228a2016-12-08 19:29:00 -0800354}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800355
Jack He777228a2016-12-08 19:29:00 -0800356void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
357 uint32_t device_class, device_type_t device_type) {
358 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
359 if (pimpl_->bluetooth_session_ == nullptr) {
360 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
361 }
362 DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to();
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800363 info->set_device_class(device_class);
364 info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800365}
366
Jack He777228a2016-12-08 19:29:00 -0800367void BluetoothMetricsLogger::LogA2dpSession(
368 const A2dpSessionMetrics& a2dp_session_metrics) {
369 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
370 if (pimpl_->bluetooth_session_ == nullptr) {
371 // When no bluetooth session exist, create one on system's behalf
372 // Set connection type: for A2DP it is always BR/EDR
373 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
374 LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR);
375 }
376 // Accumulate metrics
377 pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics);
378 // Get or allocate new A2DP session object
379 A2DPSession* a2dp_session =
380 pimpl_->bluetooth_session_->mutable_a2dp_session();
381 a2dp_session->set_audio_duration_millis(
382 pimpl_->a2dp_session_metrics_.audio_duration_ms);
383 a2dp_session->set_media_timer_min_millis(
384 pimpl_->a2dp_session_metrics_.media_timer_min_ms);
385 a2dp_session->set_media_timer_max_millis(
386 pimpl_->a2dp_session_metrics_.media_timer_max_ms);
387 a2dp_session->set_media_timer_avg_millis(
388 pimpl_->a2dp_session_metrics_.media_timer_avg_ms);
389 a2dp_session->set_buffer_overruns_max_count(
390 pimpl_->a2dp_session_metrics_.buffer_overruns_max_count);
391 a2dp_session->set_buffer_overruns_total(
392 pimpl_->a2dp_session_metrics_.buffer_overruns_total);
393 a2dp_session->set_buffer_underruns_average(
394 pimpl_->a2dp_session_metrics_.buffer_underruns_average);
395 a2dp_session->set_buffer_underruns_count(
396 pimpl_->a2dp_session_metrics_.buffer_underruns_count);
397}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800398
Jack He777228a2016-12-08 19:29:00 -0800399void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
400 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
401 LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
402 Build();
403 LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
404 if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800405 LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
406 return;
407 }
Ajay Panickerfe357dc2016-02-18 12:24:10 -0800408 if (clear) {
Jack He777228a2016-12-08 19:29:00 -0800409 pimpl_->bluetooth_log_->Clear();
Ajay Panickerfe357dc2016-02-18 12:24:10 -0800410 }
Jack He777228a2016-12-08 19:29:00 -0800411}
Ajay Panickerfe357dc2016-02-18 12:24:10 -0800412
Jack He777228a2016-12-08 19:29:00 -0800413void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
414 bool clear) {
415 this->WriteString(serialized, clear);
416 base::Base64Encode(*serialized, serialized);
417}
418
419void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
Ajay Panicker4336ba52016-02-17 18:18:00 -0800420 std::string protoBase64;
Jack He777228a2016-12-08 19:29:00 -0800421 this->WriteBase64String(&protoBase64, clear);
Pavlin Radoslavovc608acf2016-05-12 11:36:44 -0700422 ssize_t ret;
423 OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
424 if (ret == -1) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800425 LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
426 strerror(errno), errno);
427 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800428}
Jack He777228a2016-12-08 19:29:00 -0800429
430void BluetoothMetricsLogger::CutoffSession() {
431 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
432 if (pimpl_->bluetooth_session_ != nullptr) {
433 BluetoothSession* new_bt_session =
434 new BluetoothSession(*pimpl_->bluetooth_session_);
435 new_bt_session->clear_a2dp_session();
436 new_bt_session->clear_rfcomm_session();
Jack He9bebcc02017-01-17 15:41:30 -0800437 LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
Jack He777228a2016-12-08 19:29:00 -0800438 pimpl_->bluetooth_session_ = new_bt_session;
439 pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms();
440 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
441 }
442}
443
444void BluetoothMetricsLogger::Build() {
445 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
446 CutoffSession();
447 BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_;
448 while (!pimpl_->bt_session_queue_->Empty() &&
449 static_cast<size_t>(bluetooth_log->session_size()) <=
450 pimpl_->bt_session_queue_->Capacity()) {
451 bluetooth_log->mutable_session()->AddAllocated(
452 pimpl_->bt_session_queue_->Dequeue());
453 }
454 while (!pimpl_->pair_event_queue_->Empty() &&
455 static_cast<size_t>(bluetooth_log->pair_event_size()) <=
456 pimpl_->pair_event_queue_->Capacity()) {
457 bluetooth_log->mutable_pair_event()->AddAllocated(
458 pimpl_->pair_event_queue_->Dequeue());
459 }
460 while (!pimpl_->scan_event_queue_->Empty() &&
461 static_cast<size_t>(bluetooth_log->scan_event_size()) <=
462 pimpl_->scan_event_queue_->Capacity()) {
463 bluetooth_log->mutable_scan_event()->AddAllocated(
464 pimpl_->scan_event_queue_->Dequeue());
465 }
466 while (!pimpl_->wake_event_queue_->Empty() &&
467 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
468 pimpl_->wake_event_queue_->Capacity()) {
469 bluetooth_log->mutable_wake_event()->AddAllocated(
470 pimpl_->wake_event_queue_->Dequeue());
471 }
472 while (!pimpl_->bt_session_queue_->Empty() &&
473 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
474 pimpl_->wake_event_queue_->Capacity()) {
475 bluetooth_log->mutable_wake_event()->AddAllocated(
476 pimpl_->wake_event_queue_->Dequeue());
477 }
478}
479
480void BluetoothMetricsLogger::ResetSession() {
481 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
482 if (pimpl_->bluetooth_session_ != nullptr) {
483 delete pimpl_->bluetooth_session_;
484 pimpl_->bluetooth_session_ = nullptr;
485 }
486 pimpl_->bluetooth_session_start_time_ms_ = 0;
487 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
488}
489
490void BluetoothMetricsLogger::ResetLog() {
491 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
492 pimpl_->bluetooth_log_->Clear();
493}
494
495void BluetoothMetricsLogger::Reset() {
496 ResetSession();
497 ResetLog();
498 pimpl_->bt_session_queue_->Clear();
499 pimpl_->pair_event_queue_->Clear();
500 pimpl_->wake_event_queue_->Clear();
501 pimpl_->scan_event_queue_->Clear();
502}
503
504} // namespace system_bt_osi