blob: 73450b94449b7302c454dbdfb0f2042bd17594f2 [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>
Jack He7ebb85a2018-04-02 13:04:58 -070022#include <array>
Jack He777228a2016-12-08 19:29:00 -080023#include <cerrno>
24#include <chrono>
25#include <cstdint>
26#include <cstring>
27#include <memory>
28#include <mutex>
Marie Janssena84a4ee2016-01-15 16:14:14 -080029
Jack He777228a2016-12-08 19:29:00 -080030#include <base/base64.h>
31#include <base/logging.h>
Jack Heeeb9f352018-06-08 20:13:23 -070032#include <include/hardware/bt_av.h>
Marie Janssena84a4ee2016-01-15 16:14:14 -080033
Jack He9a30a9f2018-03-03 00:03:25 -080034#include "bluetooth/metrics/bluetooth.pb.h"
Jack He777228a2016-12-08 19:29:00 -080035#include "osi/include/leaky_bonded_queue.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080036#include "osi/include/log.h"
37#include "osi/include/osi.h"
Jack He777228a2016-12-08 19:29:00 -080038#include "osi/include/time.h"
39#include "stack/include/btm_api_types.h"
Marie Janssena84a4ee2016-01-15 16:14:14 -080040
Jack He777228a2016-12-08 19:29:00 -080041#include "osi/include/metrics.h"
42
43namespace system_bt_osi {
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;
55using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
56using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
57using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
58using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
59using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
60using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
Jack He7ebb85a2018-04-02 13:04:58 -070061using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
62using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
63using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
64using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
65using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
66using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
Jack He777228a2016-12-08 19:29:00 -080067/*
68 * Get current OS boot time in millisecond
69 */
70static int64_t time_get_os_boottime_ms(void) {
71 return time_get_os_boottime_us() / 1000;
72}
73
74static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
75 int64_t ct_b) {
76 if (ct_a > 0 && ct_b > 0) {
77 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
78 } else if (ct_b > 0) {
79 return avg_b;
80 } else {
81 return avg_a;
Marie Janssena84a4ee2016-01-15 16:14:14 -080082 }
83}
84
Jack He777228a2016-12-08 19:29:00 -080085static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
86 int64_t ct_b) {
87 if (ct_a > 0 && ct_b > 0) {
88 return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
89 } else if (ct_b > 0) {
90 return avg_b;
91 } else {
92 return avg_a;
93 }
94}
Marie Janssena84a4ee2016-01-15 16:14:14 -080095
Jack He777228a2016-12-08 19:29:00 -080096void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
Jack He723bef82017-01-20 11:17:44 -080097 if (metrics.audio_duration_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -080098 audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
99 audio_duration_ms += metrics.audio_duration_ms;
100 }
Jack He723bef82017-01-20 11:17:44 -0800101 if (metrics.media_timer_min_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800102 if (media_timer_min_ms < 0) {
103 media_timer_min_ms = metrics.media_timer_min_ms;
104 } else {
105 media_timer_min_ms =
106 std::min(media_timer_min_ms, metrics.media_timer_min_ms);
107 }
108 }
Jack He723bef82017-01-20 11:17:44 -0800109 if (metrics.media_timer_max_ms >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800110 media_timer_max_ms =
111 std::max(media_timer_max_ms, metrics.media_timer_max_ms);
112 }
Jack He723bef82017-01-20 11:17:44 -0800113 if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800114 if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
115 media_timer_avg_ms = metrics.media_timer_avg_ms;
116 total_scheduling_count = metrics.total_scheduling_count;
117 } else {
118 media_timer_avg_ms = combine_averages(
119 media_timer_avg_ms, total_scheduling_count,
120 metrics.media_timer_avg_ms, metrics.total_scheduling_count);
121 total_scheduling_count += metrics.total_scheduling_count;
122 }
123 }
Jack He723bef82017-01-20 11:17:44 -0800124 if (metrics.buffer_overruns_max_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800125 buffer_overruns_max_count =
126 std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
127 }
Jack He723bef82017-01-20 11:17:44 -0800128 if (metrics.buffer_overruns_total >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800129 buffer_overruns_total =
130 std::max(static_cast<int32_t>(0), buffer_overruns_total);
131 buffer_overruns_total += metrics.buffer_overruns_total;
132 }
Jack He723bef82017-01-20 11:17:44 -0800133 if (metrics.buffer_underruns_average >= 0 &&
134 metrics.buffer_underruns_count >= 0) {
Jack He777228a2016-12-08 19:29:00 -0800135 if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
136 buffer_underruns_average = metrics.buffer_underruns_average;
137 buffer_underruns_count = metrics.buffer_underruns_count;
138 } else {
139 buffer_underruns_average = combine_averages(
Jack He723bef82017-01-20 11:17:44 -0800140 buffer_underruns_average, buffer_underruns_count,
141 metrics.buffer_underruns_average, metrics.buffer_underruns_count);
Jack He777228a2016-12-08 19:29:00 -0800142 buffer_underruns_count += metrics.buffer_underruns_count;
143 }
144 }
Jack Heeeb9f352018-06-08 20:13:23 -0700145 if (codec_index < 0) {
146 codec_index = metrics.codec_index;
147 }
148 if (!is_a2dp_offload) {
149 is_a2dp_offload = metrics.is_a2dp_offload;
150 }
Jack He777228a2016-12-08 19:29:00 -0800151}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800152
Jack He777228a2016-12-08 19:29:00 -0800153bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
154 return audio_duration_ms == rhs.audio_duration_ms &&
155 media_timer_min_ms == rhs.media_timer_min_ms &&
156 media_timer_max_ms == rhs.media_timer_max_ms &&
157 media_timer_avg_ms == rhs.media_timer_avg_ms &&
158 total_scheduling_count == rhs.total_scheduling_count &&
159 buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
160 buffer_overruns_total == rhs.buffer_overruns_total &&
161 buffer_underruns_average == rhs.buffer_underruns_average &&
Jack Heeeb9f352018-06-08 20:13:23 -0700162 buffer_underruns_count == rhs.buffer_underruns_count &&
163 codec_index == rhs.codec_index &&
164 is_a2dp_offload == rhs.is_a2dp_offload;
Jack He777228a2016-12-08 19:29:00 -0800165}
166
167static DeviceInfo_DeviceType get_device_type(device_type_t type) {
168 switch (type) {
169 case DEVICE_TYPE_BREDR:
170 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR;
171 case DEVICE_TYPE_LE:
172 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE;
173 case DEVICE_TYPE_DUMO:
174 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO;
175 case DEVICE_TYPE_UNKNOWN:
176 default:
177 return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN;
178 }
179}
180
181static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(
182 connection_tech_t type) {
183 switch (type) {
184 case CONNECTION_TECHNOLOGY_TYPE_LE:
185 return BluetoothSession_ConnectionTechnologyType::
186 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE;
187 case CONNECTION_TECHNOLOGY_TYPE_BREDR:
188 return BluetoothSession_ConnectionTechnologyType::
189 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR;
190 case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN:
191 default:
192 return BluetoothSession_ConnectionTechnologyType::
193 BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN;
194 }
195}
196
197static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) {
198 switch (type) {
199 case SCAN_TECH_TYPE_LE:
200 return ScanEvent_ScanTechnologyType::
201 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE;
202 case SCAN_TECH_TYPE_BREDR:
203 return ScanEvent_ScanTechnologyType::
204 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR;
205 case SCAN_TECH_TYPE_BOTH:
206 return ScanEvent_ScanTechnologyType::
207 ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH;
208 case SCAN_TYPE_UNKNOWN:
209 default:
210 return ScanEvent_ScanTechnologyType::
211 ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN;
212 }
213}
214
215static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) {
216 switch (type) {
217 case WAKE_EVENT_ACQUIRED:
218 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED;
219 case WAKE_EVENT_RELEASED:
220 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED;
221 case WAKE_EVENT_UNKNOWN:
222 default:
223 return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN;
224 }
225}
226
Jack He9bebcc02017-01-17 15:41:30 -0800227static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(
228 disconnect_reason_t type) {
229 switch (type) {
230 case DISCONNECT_REASON_METRICS_DUMP:
231 return BluetoothSession_DisconnectReasonType::
232 BluetoothSession_DisconnectReasonType_METRICS_DUMP;
233 case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS:
234 return BluetoothSession_DisconnectReasonType::
235 BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS;
236 case DISCONNECT_REASON_UNKNOWN:
237 default:
238 return BluetoothSession_DisconnectReasonType::
239 BluetoothSession_DisconnectReasonType_UNKNOWN;
240 }
241}
242
Jack Heeeb9f352018-06-08 20:13:23 -0700243static A2dpSourceCodec get_a2dp_source_codec(int64_t codec_index) {
244 switch (codec_index) {
245 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
246 return A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC;
247 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
248 return A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC;
249 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
250 return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX;
251 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
252 return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX_HD;
253 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
254 return A2dpSourceCodec::A2DP_SOURCE_CODEC_LDAC;
255 default:
256 return A2dpSourceCodec::A2DP_SOURCE_CODEC_UNKNOWN;
257 }
258}
259
Jack He777228a2016-12-08 19:29:00 -0800260struct BluetoothMetricsLogger::impl {
261 impl(size_t max_bluetooth_session, size_t max_pair_event,
262 size_t max_wake_event, size_t max_scan_event)
263 : bt_session_queue_(
264 new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)),
265 pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)),
266 wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
267 scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
268 bluetooth_log_ = BluetoothLog::default_instance().New();
Jack He7ebb85a2018-04-02 13:04:58 -0700269 headset_profile_connection_counts_.fill(0);
Jack He777228a2016-12-08 19:29:00 -0800270 bluetooth_session_ = nullptr;
271 bluetooth_session_start_time_ms_ = 0;
272 a2dp_session_metrics_ = A2dpSessionMetrics();
273 }
274
275 /* Bluetooth log lock protected */
276 BluetoothLog* bluetooth_log_;
Jack He7ebb85a2018-04-02 13:04:58 -0700277 std::array<int, HeadsetProfileType_ARRAYSIZE>
278 headset_profile_connection_counts_;
Jack He777228a2016-12-08 19:29:00 -0800279 std::recursive_mutex bluetooth_log_lock_;
280 /* End Bluetooth log lock protected */
281 /* Bluetooth session lock protected */
282 BluetoothSession* bluetooth_session_;
283 uint64_t bluetooth_session_start_time_ms_;
284 A2dpSessionMetrics a2dp_session_metrics_;
285 std::recursive_mutex bluetooth_session_lock_;
286 /* End bluetooth session lock protected */
287 std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_;
288 std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_;
289 std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_;
290 std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_;
291};
292
293BluetoothMetricsLogger::BluetoothMetricsLogger()
Jack He9bebcc02017-01-17 15:41:30 -0800294 : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
295 kMaxNumWakeEvent, kMaxNumScanEvent)) {}
Jack He777228a2016-12-08 19:29:00 -0800296
297void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
298 uint64_t timestamp_ms,
299 uint32_t device_class,
300 device_type_t device_type) {
301 PairEvent* event = new PairEvent();
Myles Watson914a9dc2016-10-19 13:15:34 -0700302 DeviceInfo* info = event->mutable_device_paired_with();
Marie Janssena84a4ee2016-01-15 16:14:14 -0800303 info->set_device_class(device_class);
Jack He777228a2016-12-08 19:29:00 -0800304 info->set_device_type(get_device_type(device_type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800305 event->set_disconnect_reason(disconnect_reason);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800306 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800307 pimpl_->pair_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800308 {
309 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
310 pimpl_->bluetooth_log_->set_num_pair_event(
311 pimpl_->bluetooth_log_->num_pair_event() + 1);
312 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800313}
314
Jack He777228a2016-12-08 19:29:00 -0800315void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
316 const std::string& requestor,
317 const std::string& name,
318 uint64_t timestamp_ms) {
319 WakeEvent* event = new WakeEvent();
320 event->set_wake_event_type(get_wake_event_type(type));
321 event->set_requestor(requestor);
322 event->set_name(name);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800323 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800324 pimpl_->wake_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800325 {
326 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
327 pimpl_->bluetooth_log_->set_num_wake_event(
328 pimpl_->bluetooth_log_->num_wake_event() + 1);
329 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800330}
331
Jack He777228a2016-12-08 19:29:00 -0800332void BluetoothMetricsLogger::LogScanEvent(bool start,
333 const std::string& initator,
334 scan_tech_t type, uint32_t results,
335 uint64_t timestamp_ms) {
336 ScanEvent* event = new ScanEvent();
337 if (start) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800338 event->set_scan_event_type(ScanEvent::SCAN_EVENT_START);
Jack He777228a2016-12-08 19:29:00 -0800339 } else {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800340 event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP);
Jack He777228a2016-12-08 19:29:00 -0800341 }
342 event->set_initiator(initator);
343 event->set_scan_technology_type(get_scan_tech_type(type));
Marie Janssena84a4ee2016-01-15 16:14:14 -0800344 event->set_number_results(results);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800345 event->set_event_time_millis(timestamp_ms);
Jack He777228a2016-12-08 19:29:00 -0800346 pimpl_->scan_event_queue_->Enqueue(event);
Jack He9bebcc02017-01-17 15:41:30 -0800347 {
348 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
349 pimpl_->bluetooth_log_->set_num_scan_event(
350 pimpl_->bluetooth_log_->num_scan_event() + 1);
351 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800352}
353
Jack He777228a2016-12-08 19:29:00 -0800354void BluetoothMetricsLogger::LogBluetoothSessionStart(
355 connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
356 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
357 if (pimpl_->bluetooth_session_ != nullptr) {
Jack He9bebcc02017-01-17 15:41:30 -0800358 LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
Jack He777228a2016-12-08 19:29:00 -0800359 0);
360 }
361 if (timestamp_ms == 0) {
362 timestamp_ms = time_get_os_boottime_ms();
363 }
364 pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
365 pimpl_->bluetooth_session_ = new BluetoothSession();
366 pimpl_->bluetooth_session_->set_connection_technology_type(
367 get_connection_tech_type(connection_tech_type));
368}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800369
Jack He777228a2016-12-08 19:29:00 -0800370void BluetoothMetricsLogger::LogBluetoothSessionEnd(
Jack He9bebcc02017-01-17 15:41:30 -0800371 disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
Jack He777228a2016-12-08 19:29:00 -0800372 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
373 if (pimpl_->bluetooth_session_ == nullptr) {
374 return;
375 }
376 if (timestamp_ms == 0) {
377 timestamp_ms = time_get_os_boottime_ms();
378 }
379 int64_t session_duration_sec =
380 (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
381 pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec);
Jack He9bebcc02017-01-17 15:41:30 -0800382 pimpl_->bluetooth_session_->set_disconnect_reason_type(
383 get_disconnect_reason_type(disconnect_reason));
Jack He777228a2016-12-08 19:29:00 -0800384 pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_);
385 pimpl_->bluetooth_session_ = nullptr;
Jack Heeeb9f352018-06-08 20:13:23 -0700386 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
Jack He9bebcc02017-01-17 15:41:30 -0800387 {
388 std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_);
389 pimpl_->bluetooth_log_->set_num_bluetooth_session(
390 pimpl_->bluetooth_log_->num_bluetooth_session() + 1);
391 }
Jack He777228a2016-12-08 19:29:00 -0800392}
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800393
Jack He777228a2016-12-08 19:29:00 -0800394void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
395 uint32_t device_class, device_type_t device_type) {
396 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
397 if (pimpl_->bluetooth_session_ == nullptr) {
398 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
399 }
400 DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to();
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800401 info->set_device_class(device_class);
402 info->set_device_type(DeviceInfo::DEVICE_TYPE_BREDR);
Pavlin Radoslavov9aa6f122016-02-17 15:42:38 -0800403}
404
Jack He777228a2016-12-08 19:29:00 -0800405void BluetoothMetricsLogger::LogA2dpSession(
406 const A2dpSessionMetrics& a2dp_session_metrics) {
407 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
408 if (pimpl_->bluetooth_session_ == nullptr) {
409 // When no bluetooth session exist, create one on system's behalf
410 // Set connection type: for A2DP it is always BR/EDR
411 LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
412 LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR);
413 }
414 // Accumulate metrics
415 pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics);
416 // Get or allocate new A2DP session object
417 A2DPSession* a2dp_session =
418 pimpl_->bluetooth_session_->mutable_a2dp_session();
419 a2dp_session->set_audio_duration_millis(
420 pimpl_->a2dp_session_metrics_.audio_duration_ms);
421 a2dp_session->set_media_timer_min_millis(
422 pimpl_->a2dp_session_metrics_.media_timer_min_ms);
423 a2dp_session->set_media_timer_max_millis(
424 pimpl_->a2dp_session_metrics_.media_timer_max_ms);
425 a2dp_session->set_media_timer_avg_millis(
426 pimpl_->a2dp_session_metrics_.media_timer_avg_ms);
427 a2dp_session->set_buffer_overruns_max_count(
428 pimpl_->a2dp_session_metrics_.buffer_overruns_max_count);
429 a2dp_session->set_buffer_overruns_total(
430 pimpl_->a2dp_session_metrics_.buffer_overruns_total);
431 a2dp_session->set_buffer_underruns_average(
432 pimpl_->a2dp_session_metrics_.buffer_underruns_average);
433 a2dp_session->set_buffer_underruns_count(
434 pimpl_->a2dp_session_metrics_.buffer_underruns_count);
Jack Heeeb9f352018-06-08 20:13:23 -0700435 a2dp_session->set_source_codec(
436 get_a2dp_source_codec(pimpl_->a2dp_session_metrics_.codec_index));
437 a2dp_session->set_is_a2dp_offload(
438 pimpl_->a2dp_session_metrics_.is_a2dp_offload);
Jack He777228a2016-12-08 19:29:00 -0800439}
Marie Janssena84a4ee2016-01-15 16:14:14 -0800440
Jack He7ebb85a2018-04-02 13:04:58 -0700441void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
442 tBTA_SERVICE_ID service_id) {
443 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
444 switch (service_id) {
445 case BTA_HSP_SERVICE_ID:
446 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++;
447 break;
448 case BTA_HFP_SERVICE_ID:
449 pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++;
450 break;
451 default:
452 pimpl_->headset_profile_connection_counts_
453 [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++;
454 break;
455 }
456 return;
457}
458
459void BluetoothMetricsLogger::WriteString(std::string* serialized) {
Jack He777228a2016-12-08 19:29:00 -0800460 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
461 LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
462 Build();
463 LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
464 if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800465 LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
Marie Janssena84a4ee2016-01-15 16:14:14 -0800466 }
Jack He7ebb85a2018-04-02 13:04:58 -0700467 // Always clean up log objects
468 pimpl_->bluetooth_log_->Clear();
Jack He777228a2016-12-08 19:29:00 -0800469}
Ajay Panickerfe357dc2016-02-18 12:24:10 -0800470
Jack He7ebb85a2018-04-02 13:04:58 -0700471void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {
472 this->WriteString(serialized);
Jack He777228a2016-12-08 19:29:00 -0800473 base::Base64Encode(*serialized, serialized);
474}
475
Jack He7ebb85a2018-04-02 13:04:58 -0700476void BluetoothMetricsLogger::WriteBase64(int fd) {
Ajay Panicker4336ba52016-02-17 18:18:00 -0800477 std::string protoBase64;
Jack He7ebb85a2018-04-02 13:04:58 -0700478 this->WriteBase64String(&protoBase64);
Pavlin Radoslavovc608acf2016-05-12 11:36:44 -0700479 ssize_t ret;
480 OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
481 if (ret == -1) {
Marie Janssena84a4ee2016-01-15 16:14:14 -0800482 LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
483 strerror(errno), errno);
484 }
Marie Janssena84a4ee2016-01-15 16:14:14 -0800485}
Jack He777228a2016-12-08 19:29:00 -0800486
487void BluetoothMetricsLogger::CutoffSession() {
488 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
489 if (pimpl_->bluetooth_session_ != nullptr) {
490 BluetoothSession* new_bt_session =
491 new BluetoothSession(*pimpl_->bluetooth_session_);
492 new_bt_session->clear_a2dp_session();
493 new_bt_session->clear_rfcomm_session();
Jack He9bebcc02017-01-17 15:41:30 -0800494 LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
Jack He777228a2016-12-08 19:29:00 -0800495 pimpl_->bluetooth_session_ = new_bt_session;
496 pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms();
497 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
498 }
499}
500
501void BluetoothMetricsLogger::Build() {
502 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
503 CutoffSession();
504 BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_;
505 while (!pimpl_->bt_session_queue_->Empty() &&
506 static_cast<size_t>(bluetooth_log->session_size()) <=
507 pimpl_->bt_session_queue_->Capacity()) {
508 bluetooth_log->mutable_session()->AddAllocated(
509 pimpl_->bt_session_queue_->Dequeue());
510 }
511 while (!pimpl_->pair_event_queue_->Empty() &&
512 static_cast<size_t>(bluetooth_log->pair_event_size()) <=
513 pimpl_->pair_event_queue_->Capacity()) {
514 bluetooth_log->mutable_pair_event()->AddAllocated(
515 pimpl_->pair_event_queue_->Dequeue());
516 }
517 while (!pimpl_->scan_event_queue_->Empty() &&
518 static_cast<size_t>(bluetooth_log->scan_event_size()) <=
519 pimpl_->scan_event_queue_->Capacity()) {
520 bluetooth_log->mutable_scan_event()->AddAllocated(
521 pimpl_->scan_event_queue_->Dequeue());
522 }
523 while (!pimpl_->wake_event_queue_->Empty() &&
524 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
525 pimpl_->wake_event_queue_->Capacity()) {
526 bluetooth_log->mutable_wake_event()->AddAllocated(
527 pimpl_->wake_event_queue_->Dequeue());
528 }
529 while (!pimpl_->bt_session_queue_->Empty() &&
530 static_cast<size_t>(bluetooth_log->wake_event_size()) <=
531 pimpl_->wake_event_queue_->Capacity()) {
532 bluetooth_log->mutable_wake_event()->AddAllocated(
533 pimpl_->wake_event_queue_->Dequeue());
534 }
Jack He7ebb85a2018-04-02 13:04:58 -0700535 for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) {
536 int num_times_connected = pimpl_->headset_profile_connection_counts_[i];
537 if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) {
538 HeadsetProfileConnectionStats* headset_profile_connection_stats =
539 bluetooth_log->add_headset_profile_connection_stats();
540 // Able to static_cast because HeadsetProfileType_IsValid(i) is true
541 headset_profile_connection_stats->set_headset_profile_type(
542 static_cast<HeadsetProfileType>(i));
543 headset_profile_connection_stats->set_num_times_connected(
544 num_times_connected);
545 }
546 }
547 pimpl_->headset_profile_connection_counts_.fill(0);
Jack He777228a2016-12-08 19:29:00 -0800548}
549
550void BluetoothMetricsLogger::ResetSession() {
551 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_);
552 if (pimpl_->bluetooth_session_ != nullptr) {
553 delete pimpl_->bluetooth_session_;
554 pimpl_->bluetooth_session_ = nullptr;
555 }
556 pimpl_->bluetooth_session_start_time_ms_ = 0;
557 pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
558}
559
560void BluetoothMetricsLogger::ResetLog() {
561 std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
562 pimpl_->bluetooth_log_->Clear();
563}
564
565void BluetoothMetricsLogger::Reset() {
566 ResetSession();
567 ResetLog();
568 pimpl_->bt_session_queue_->Clear();
569 pimpl_->pair_event_queue_->Clear();
570 pimpl_->wake_event_queue_->Clear();
571 pimpl_->scan_event_queue_->Clear();
572}
573
574} // namespace system_bt_osi