blob: ace021be30b9a1f6d6863a1ec04aa0305dd45ea1 [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
Jack He777228a2016-12-08 19:29:00 -080019#include <unistd.h>
20#include <algorithm>
Jack He7ebb85a2018-04-02 13:04:58 -070021#include <array>
Jack He777228a2016-12-08 19:29:00 -080022#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>
Jack Heeeb9f352018-06-08 20:13:23 -070031#include <include/hardware/bt_av.h>
Marie Janssena84a4ee2016-01-15 16:14:14 -080032
Jack He9a30a9f2018-03-03 00:03:25 -080033#include "bluetooth/metrics/bluetooth.pb.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080034#include "osi/include/osi.h"
Jack He777228a2016-12-08 19:29:00 -080035#include "stack/include/btm_api_types.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080036
Jack He42823982018-08-15 12:38:37 -070037#include "leaky_bonded_queue.h"
38#include "metrics.h"
39#include "time_util.h"
Jack He777228a2016-12-08 19:29:00 -080040
Jack He42823982018-08-15 12:38:37 -070041namespace bluetooth {
42
43namespace common {
Marie Janssena84a4ee2016-01-15 16:14:14 -080044
Jack He9a30a9f2018-03-03 00:03:25 -080045using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
Jack Heeeb9f352018-06-08 20:13:23 -070046using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
Jack He9a30a9f2018-03-03 00:03:25 -080047using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog;
48using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession;
49using bluetooth::metrics::BluetoothMetricsProto::
50 BluetoothSession_ConnectionTechnologyType;
51using bluetooth::metrics::BluetoothMetricsProto::
52 BluetoothSession_DisconnectReasonType;
53using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
54using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
Jack He42823982018-08-15 12:38:37 -070055using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
Jack He7ebb85a2018-04-02 13:04:58 -070056using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
Jack He7ebb85a2018-04-02 13:04:58 -070057using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
58using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
Jack He42823982018-08-15 12:38:37 -070059using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
60using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
61using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
62using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
63using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
64using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
65using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
66using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
Jack He777228a2016-12-08 19:29:00 -080067
68static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
69 int64_t ct_b) {
70 if (ct_a > 0 && ct_b > 0) {
71 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
72 } else if (ct_b > 0) {
73 return avg_b;
74 } else {
75 return avg_a;
Marie Janssena84a4ee2016-01-15 16:14:14 -080076 }
77}
78
Jack He777228a2016-12-08 19:29:00 -080079static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
80 int64_t ct_b) {
81 if (ct_a > 0 && ct_b > 0) {
82 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
83 } else if (ct_b > 0) {
84 return avg_b;
85 } else {
86 return avg_a;
87 }
88}
Marie Janssena84a4ee2016-01-15 16:14:14 -080089
Jack He777228a2016-12-08 19:29:00 -080090void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
Jack He723bef82017-01-20 11:17:44 -080091 if (metrics.audio_duration_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -080092 audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
93 audio_duration_ms += metrics.audio_duration_ms;
94 }
Jack He723bef82017-01-20 11:17:44 -080095 if (metrics.media_timer_min_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -080096 if (media_timer_min_ms < 0) {
97 media_timer_min_ms = metrics.media_timer_min_ms;
98 } else {
99 media_timer_min_ms =
100 std::min(media_timer_min_ms, metrics.media_timer_min_ms);
101 }
102 }
Jack He723bef82017-01-20 11:17:44 -0800103 if (metrics.media_timer_max_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800104 media_timer_max_ms =
105 std::max(media_timer_max_ms, metrics.media_timer_max_ms);
106 }
Jack He723bef82017-01-20 11:17:44 -0800107 if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800108 if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
109 media_timer_avg_ms = metrics.media_timer_avg_ms;
110 total_scheduling_count = metrics.total_scheduling_count;
111 } else {
112 media_timer_avg_ms = combine_averages(
113 media_timer_avg_ms, total_scheduling_count,
114 metrics.media_timer_avg_ms, metrics.total_scheduling_count);
115 total_scheduling_count += metrics.total_scheduling_count;
116 }
117 }
Jack He723bef82017-01-20 11:17:44 -0800118 if (metrics.buffer_overruns_max_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800119 buffer_overruns_max_count =
120 std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
121 }
Jack He723bef82017-01-20 11:17:44 -0800122 if (metrics.buffer_overruns_total >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800123 buffer_overruns_total =
124 std::max(static_cast<int32_t>(0), buffer_overruns_total);
125 buffer_overruns_total += metrics.buffer_overruns_total;
126 }
Jack He723bef82017-01-20 11:17:44 -0800127 if (metrics.buffer_underruns_average >= 0 &&
128 metrics.buffer_underruns_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800129 if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
130 buffer_underruns_average = metrics.buffer_underruns_average;
131 buffer_underruns_count = metrics.buffer_underruns_count;
132 } else {
133 buffer_underruns_average = combine_averages(
Jack He723bef82017-01-20 11:17:44 -0800134 buffer_underruns_average, buffer_underruns_count,
135 metrics.buffer_underruns_average, metrics.buffer_underruns_count);
Jack He777228a2016-12-08 19:29:00 -0800136 buffer_underruns_count += metrics.buffer_underruns_count;
137 }
138 }
Jack Heeeb9f352018-06-08 20:13:23 -0700139 if (codec_index < 0) {
140 codec_index = metrics.codec_index;
141 }
142 if (!is_a2dp_offload) {
143 is_a2dp_offload = metrics.is_a2dp_offload;
144 }
Jack He777228a2016-12-08 19:29:00 -0800145}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800146
Jack He777228a2016-12-08 19:29:00 -0800147bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
148 return audio_duration_ms == rhs.audio_duration_ms &&
149 media_timer_min_ms == rhs.media_timer_min_ms &&
150 media_timer_max_ms == rhs.media_timer_max_ms &&
151 media_timer_avg_ms == rhs.media_timer_avg_ms &&
152 total_scheduling_count == rhs.total_scheduling_count &&
153 buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
154 buffer_overruns_total == rhs.buffer_overruns_total &&
155 buffer_underruns_average == rhs.buffer_underruns_average &&
Jack Heeeb9f352018-06-08 20:13:23 -0700156 buffer_underruns_count == rhs.buffer_underruns_count &&
157 codec_index == rhs.codec_index &&
158 is_a2dp_offload == rhs.is_a2dp_offload;
Jack He777228a2016-12-08 19:29:00 -0800159}
160
161static DeviceInfo_DeviceType get_device_type(device_type_t type) {
162 switch (type) {
163 case DEVICE_TYPE_BREDR:
164 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR;
165 case DEVICE_TYPE_LE:
166 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE;
167 case DEVICE_TYPE_DUMO:
168 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO;
169 case DEVICE_TYPE_UNKNOWN:
170 default:
171 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN;
172 }
173}
174
175static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(
176 connection_tech_t type) {
177 switch (type) {
178 case CONNECTION_TECHNOLOGY_TYPE_LE:
179 return BluetoothSession_ConnectionTechnologyType::
180 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE;
181 case CONNECTION_TECHNOLOGY_TYPE_BREDR:
182 return BluetoothSession_ConnectionTechnologyType::
183 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR;
184 case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN:
185 default:
186 return BluetoothSession_ConnectionTechnologyType::
187 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN;
188 }
189}
190
191static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) {
192 switch (type) {
193 case SCAN_TECH_TYPE_LE:
194 return ScanEvent_ScanTechnologyType::
195 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE;
196 case SCAN_TECH_TYPE_BREDR:
197 return ScanEvent_ScanTechnologyType::
198 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR;
199 case SCAN_TECH_TYPE_BOTH:
200 return ScanEvent_ScanTechnologyType::
201 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH;
202 case SCAN_TYPE_UNKNOWN:
203 default:
204 return ScanEvent_ScanTechnologyType::
205 ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN;
206 }
207}
208
209static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) {
210 switch (type) {
211 case WAKE_EVENT_ACQUIRED:
212 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED;
213 case WAKE_EVENT_RELEASED:
214 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED;
215 case WAKE_EVENT_UNKNOWN:
216 default:
217 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN;
218 }
219}
220
Jack He9bebcc02017-01-17 15:41:30 -0800221static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(
222 disconnect_reason_t type) {
223 switch (type) {
224 case DISCONNECT_REASON_METRICS_DUMP:
225 return BluetoothSession_DisconnectReasonType::
226 BluetoothSession_DisconnectReasonType_METRICS_DUMP;
227 case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS:
228 return BluetoothSession_DisconnectReasonType::
229 BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS;
230 case DISCONNECT_REASON_UNKNOWN:
231 default:
232 return BluetoothSession_DisconnectReasonType::
233 BluetoothSession_DisconnectReasonType_UNKNOWN;
234 }
235}
236
Jack Heeeb9f352018-06-08 20:13:23 -0700237static A2dpSourceCodec get_a2dp_source_codec(int64_t codec_index) {
238 switch (codec_index) {
239 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
240 return A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC;
241 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
242 return A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC;
243 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
244 return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX;
245 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
246 return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX_HD;
247 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
248 return A2dpSourceCodec::A2DP_SOURCE_CODEC_LDAC;
249 default:
250 return A2dpSourceCodec::A2DP_SOURCE_CODEC_UNKNOWN;
251 }
252}
253
Jack He777228a2016-12-08 19:29:00 -0800254struct BluetoothMetricsLogger::impl {
255 impl(size_t max_bluetooth_session, size_t max_pair_event,
256 size_t max_wake_event, size_t max_scan_event)
257 : bt_session_queue_(
258 new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)),
259 pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)),
260 wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
261 scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
262 bluetooth_log_ = BluetoothLog::default_instance().New();
Jack He7ebb85a2018-04-02 13:04:58 -0700263 headset_profile_connection_counts_.fill(0);
Jack He777228a2016-12-08 19:29:00 -0800264 bluetooth_session_ = nullptr;
265 bluetooth_session_start_time_ms_ = 0;
266 a2dp_session_metrics_ = A2dpSessionMetrics();
267 }
268
269 /* Bluetooth log lock protected */
270 BluetoothLog* bluetooth_log_;
Jack He7ebb85a2018-04-02 13:04:58 -0700271 std::array<int, HeadsetProfileType_ARRAYSIZE>
272 headset_profile_connection_counts_;
Jack He777228a2016-12-08 19:29:00 -0800273 std::recursive_mutex bluetooth_log_lock_;
274 /* End Bluetooth log lock protected */
275 /* Bluetooth session lock protected */
276 BluetoothSession* bluetooth_session_;
277 uint64_t bluetooth_session_start_time_ms_;
278 A2dpSessionMetrics a2dp_session_metrics_;
279 std::recursive_mutex bluetooth_session_lock_;
280 /* End bluetooth session lock protected */
281 std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_;
282 std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_;
283 std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_;
284 std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_;
285};
286
287BluetoothMetricsLogger::BluetoothMetricsLogger()
Jack He9bebcc02017-01-17 15:41:30 -0800288 : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
289 kMaxNumWakeEvent, kMaxNumScanEvent)) {}
Jack He777228a2016-12-08 19:29:00 -0800290
291void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
292 uint64_t timestamp_ms,
293 uint32_t device_class,
294 device_type_t device_type) {
295 PairEvent* event = new PairEvent();
Myles Watson914a9dc2016-10-19 13:15:34 -0700296 DeviceInfo* info = event->mutable_device_paired_with();
Marie Janssena84a4ee2016-01-15 16:14:14 -0800297 info->set_device_class(device_class);
Jack He777228a2016-12-08 19:29:00 -0800298 info->set_device_type(get_device_type(device_type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800299 event->set_disconnect_reason(disconnect_reason);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800300 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800301 pimpl_->pair_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800302 {
303 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
304 pimpl_->bluetooth_log_->set_num_pair_event(
305 pimpl_->bluetooth_log_->num_pair_event() + 1);
306 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800307}
308
Jack He777228a2016-12-08 19:29:00 -0800309void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
310 const std::string& requestor,
311 const std::string& name,
312 uint64_t timestamp_ms) {
313 WakeEvent* event = new WakeEvent();
314 event->set_wake_event_type(get_wake_event_type(type));
315 event->set_requestor(requestor);
316 event->set_name(name);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800317 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800318 pimpl_->wake_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800319 {
320 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
321 pimpl_->bluetooth_log_->set_num_wake_event(
322 pimpl_->bluetooth_log_->num_wake_event() + 1);
323 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800324}
325
Jack He777228a2016-12-08 19:29:00 -0800326void BluetoothMetricsLogger::LogScanEvent(bool start,
327 const std::string& initator,
328 scan_tech_t type, uint32_t results,
329 uint64_t timestamp_ms) {
330 ScanEvent* event = new ScanEvent();
331 if (start) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800332 event->set_scan_event_type(ScanEvent::SCAN_EVENT_START);
Jack He777228a2016-12-08 19:29:00 -0800333 } else {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800334 event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP);
Jack He777228a2016-12-08 19:29:00 -0800335 }
336 event->set_initiator(initator);
337 event->set_scan_technology_type(get_scan_tech_type(type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800338 event->set_number_results(results);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800339 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800340 pimpl_->scan_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800341 {
342 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
343 pimpl_->bluetooth_log_->set_num_scan_event(
344 pimpl_->bluetooth_log_->num_scan_event() + 1);
345 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800346}
347
Jack He777228a2016-12-08 19:29:00 -0800348void BluetoothMetricsLogger::LogBluetoothSessionStart(
349 connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
350 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
351 if (pimpl_->bluetooth_session_ != nullptr) {
Jack He9bebcc02017-01-17 15:41:30 -0800352 LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
Jack He777228a2016-12-08 19:29:00 -0800353 0);
354 }
355 if (timestamp_ms == 0) {
Jack He42823982018-08-15 12:38:37 -0700356 timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
Jack He777228a2016-12-08 19:29:00 -0800357 }
358 pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
359 pimpl_->bluetooth_session_ = new BluetoothSession();
360 pimpl_->bluetooth_session_->set_connection_technology_type(
361 get_connection_tech_type(connection_tech_type));
362}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800363
Jack He777228a2016-12-08 19:29:00 -0800364void BluetoothMetricsLogger::LogBluetoothSessionEnd(
Jack He9bebcc02017-01-17 15:41:30 -0800365 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
Jack He777228a2016-12-08 19:29:00 -0800366 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
367 if (pimpl_->bluetooth_session_ == nullptr) {
368 return;
369 }
370 if (timestamp_ms == 0) {
Jack He42823982018-08-15 12:38:37 -0700371 timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
Jack He777228a2016-12-08 19:29:00 -0800372 }
373 int64_t session_duration_sec =
374 (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
375 pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec);
Jack He9bebcc02017-01-17 15:41:30 -0800376 pimpl_->bluetooth_session_->set_disconnect_reason_type(
377 get_disconnect_reason_type(disconnect_reason));
Jack He777228a2016-12-08 19:29:00 -0800378 pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
379 pimpl_->bluetooth_session_ = nullptr;
Jack Heeeb9f352018-06-08 20:13:23 -0700380 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
Jack He9bebcc02017-01-17 15:41:30 -0800381 {
382 std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
383 pimpl_->bluetooth_log_->set_num_bluetooth_session(
384 pimpl_->bluetooth_log_->num_bluetooth_session() + 1);
385 }
Jack He777228a2016-12-08 19:29:00 -0800386}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800387
Jack He777228a2016-12-08 19:29:00 -0800388void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
389 uint32_t device_class, device_type_t device_type) {
390 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
391 if (pimpl_->bluetooth_session_ == nullptr) {
392 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
393 }
394 DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to();
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800395 info->set_device_class(device_class);
396 info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800397}
398
Jack He777228a2016-12-08 19:29:00 -0800399void BluetoothMetricsLogger::LogA2dpSession(
400 const A2dpSessionMetrics& a2dp_session_metrics) {
401 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
402 if (pimpl_->bluetooth_session_ == nullptr) {
403 // When no bluetooth session exist, create one on system's behalf
404 // Set connection type: for A2DP it is always BR/EDR
405 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
406 LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR);
407 }
408 // Accumulate metrics
409 pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics);
410 // Get or allocate new A2DP session object
411 A2DPSession* a2dp_session =
412 pimpl_->bluetooth_session_->mutable_a2dp_session();
413 a2dp_session->set_audio_duration_millis(
414 pimpl_->a2dp_session_metrics_.audio_duration_ms);
415 a2dp_session->set_media_timer_min_millis(
416 pimpl_->a2dp_session_metrics_.media_timer_min_ms);
417 a2dp_session->set_media_timer_max_millis(
418 pimpl_->a2dp_session_metrics_.media_timer_max_ms);
419 a2dp_session->set_media_timer_avg_millis(
420 pimpl_->a2dp_session_metrics_.media_timer_avg_ms);
421 a2dp_session->set_buffer_overruns_max_count(
422 pimpl_->a2dp_session_metrics_.buffer_overruns_max_count);
423 a2dp_session->set_buffer_overruns_total(
424 pimpl_->a2dp_session_metrics_.buffer_overruns_total);
425 a2dp_session->set_buffer_underruns_average(
426 pimpl_->a2dp_session_metrics_.buffer_underruns_average);
427 a2dp_session->set_buffer_underruns_count(
428 pimpl_->a2dp_session_metrics_.buffer_underruns_count);
Jack Heeeb9f352018-06-08 20:13:23 -0700429 a2dp_session->set_source_codec(
430 get_a2dp_source_codec(pimpl_->a2dp_session_metrics_.codec_index));
431 a2dp_session->set_is_a2dp_offload(
432 pimpl_->a2dp_session_metrics_.is_a2dp_offload);
Jack He777228a2016-12-08 19:29:00 -0800433}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800434
Jack He7ebb85a2018-04-02 13:04:58 -0700435void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
436 tBTA_SERVICE_ID service_id) {
437 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
438 switch (service_id) {
439 case BTA_HSP_SERVICE_ID:
440 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++;
441 break;
442 case BTA_HFP_SERVICE_ID:
443 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++;
444 break;
445 default:
446 pimpl_->headset_profile_connection_counts_
447 [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++;
448 break;
449 }
450 return;
451}
452
453void BluetoothMetricsLogger::WriteString(std::string* serialized) {
Jack He777228a2016-12-08 19:29:00 -0800454 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
Jack He42823982018-08-15 12:38:37 -0700455 LOG(INFO) << __func__ << ": building metrics";
Jack He777228a2016-12-08 19:29:00 -0800456 Build();
Jack He42823982018-08-15 12:38:37 -0700457 LOG(INFO) << __func__ << ": serializing metrics";
Jack He777228a2016-12-08 19:29:00 -0800458 if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
Jack He42823982018-08-15 12:38:37 -0700459 LOG(ERROR) << __func__ << ": error serializing metrics";
Marie Janssena84a4ee2016-01-15 16:14:14 -0800460 }
Jack He7ebb85a2018-04-02 13:04:58 -0700461 // Always clean up log objects
462 pimpl_->bluetooth_log_->Clear();
Jack He777228a2016-12-08 19:29:00 -0800463}
Ajay Panickerfe357dc2016-02-18 12:24:10 -0800464
Jack He7ebb85a2018-04-02 13:04:58 -0700465void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {
466 this->WriteString(serialized);
Jack He777228a2016-12-08 19:29:00 -0800467 base::Base64Encode(*serialized, serialized);
468}
469
Jack He7ebb85a2018-04-02 13:04:58 -0700470void BluetoothMetricsLogger::WriteBase64(int fd) {
Ajay Panicker4336ba52016-02-17 18:18:00 -0800471 std::string protoBase64;
Jack He7ebb85a2018-04-02 13:04:58 -0700472 this->WriteBase64String(&protoBase64);
Pavlin Radoslavovc608acf2016-05-12 11:36:44 -0700473 ssize_t ret;
474 OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
475 if (ret == -1) {
Jack He42823982018-08-15 12:38:37 -0700476 LOG(ERROR) << __func__
477 << ": error writing to dumpsys fd: " << strerror(errno) << " ("
478 << std::to_string(errno) << ")";
Marie Janssena84a4ee2016-01-15 16:14:14 -0800479 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800480}
Jack He777228a2016-12-08 19:29:00 -0800481
482void BluetoothMetricsLogger::CutoffSession() {
483 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
484 if (pimpl_->bluetooth_session_ != nullptr) {
485 BluetoothSession* new_bt_session =
486 new BluetoothSession(*pimpl_->bluetooth_session_);
487 new_bt_session->clear_a2dp_session();
488 new_bt_session->clear_rfcomm_session();
Jack He9bebcc02017-01-17 15:41:30 -0800489 LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
Jack He777228a2016-12-08 19:29:00 -0800490 pimpl_->bluetooth_session_ = new_bt_session;
Jack He42823982018-08-15 12:38:37 -0700491 pimpl_->bluetooth_session_start_time_ms_ =
492 bluetooth::common::time_get_os_boottime_ms();
Jack He777228a2016-12-08 19:29:00 -0800493 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
494 }
495}
496
497void BluetoothMetricsLogger::Build() {
498 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
499 CutoffSession();
500 BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_;
501 while (!pimpl_->bt_session_queue_->Empty() &&
502 static_cast<size_t>(bluetooth_log->session_size()) <=
503 pimpl_->bt_session_queue_->Capacity()) {
504 bluetooth_log->mutable_session()->AddAllocated(
505 pimpl_->bt_session_queue_->Dequeue());
506 }
507 while (!pimpl_->pair_event_queue_->Empty() &&
508 static_cast<size_t>(bluetooth_log->pair_event_size()) <=
509 pimpl_->pair_event_queue_->Capacity()) {
510 bluetooth_log->mutable_pair_event()->AddAllocated(
511 pimpl_->pair_event_queue_->Dequeue());
512 }
513 while (!pimpl_->scan_event_queue_->Empty() &&
514 static_cast<size_t>(bluetooth_log->scan_event_size()) <=
515 pimpl_->scan_event_queue_->Capacity()) {
516 bluetooth_log->mutable_scan_event()->AddAllocated(
517 pimpl_->scan_event_queue_->Dequeue());
518 }
519 while (!pimpl_->wake_event_queue_->Empty() &&
520 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
521 pimpl_->wake_event_queue_->Capacity()) {
522 bluetooth_log->mutable_wake_event()->AddAllocated(
523 pimpl_->wake_event_queue_->Dequeue());
524 }
525 while (!pimpl_->bt_session_queue_->Empty() &&
526 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
527 pimpl_->wake_event_queue_->Capacity()) {
528 bluetooth_log->mutable_wake_event()->AddAllocated(
529 pimpl_->wake_event_queue_->Dequeue());
530 }
Jack He7ebb85a2018-04-02 13:04:58 -0700531 for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) {
532 int num_times_connected = pimpl_->headset_profile_connection_counts_[i];
533 if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) {
534 HeadsetProfileConnectionStats* headset_profile_connection_stats =
535 bluetooth_log->add_headset_profile_connection_stats();
536 // Able to static_cast because HeadsetProfileType_IsValid(i) is true
537 headset_profile_connection_stats->set_headset_profile_type(
538 static_cast<HeadsetProfileType>(i));
539 headset_profile_connection_stats->set_num_times_connected(
540 num_times_connected);
541 }
542 }
543 pimpl_->headset_profile_connection_counts_.fill(0);
Jack He777228a2016-12-08 19:29:00 -0800544}
545
546void BluetoothMetricsLogger::ResetSession() {
547 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
548 if (pimpl_->bluetooth_session_ != nullptr) {
549 delete pimpl_->bluetooth_session_;
550 pimpl_->bluetooth_session_ = nullptr;
551 }
552 pimpl_->bluetooth_session_start_time_ms_ = 0;
553 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
554}
555
556void BluetoothMetricsLogger::ResetLog() {
557 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
558 pimpl_->bluetooth_log_->Clear();
559}
560
561void BluetoothMetricsLogger::Reset() {
562 ResetSession();
563 ResetLog();
564 pimpl_->bt_session_queue_->Clear();
565 pimpl_->pair_event_queue_->Clear();
566 pimpl_->wake_event_queue_->Clear();
567 pimpl_->scan_event_queue_->Clear();
568}
569
Jack He42823982018-08-15 12:38:37 -0700570} // namespace common
571
572} // namespace bluetooth