1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <base/logging.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #ifdef OS_ANDROID
21 #include <statslog_bt.h>
22 #endif
23 #include <stdio.h>
24 #include <sys/stat.h>
25
26 #include "btif_bqr.h"
27 #include "btif_common.h"
28 #include "btm_api.h"
29 #include "btm_ble_api.h"
30 #include "common/leaky_bonded_queue.h"
31 #include "common/time_util.h"
32 #include "osi/include/properties.h"
33
34 namespace bluetooth {
35 namespace bqr {
36
37 using bluetooth::common::LeakyBondedQueue;
38 using std::chrono::system_clock;
39
40 // The instance of BQR event queue
41 static std::unique_ptr<LeakyBondedQueue<BqrVseSubEvt>> kpBqrEventQueue(
42 new LeakyBondedQueue<BqrVseSubEvt>(kBqrEventQueueSize));
43
44 static uint16_t vendor_cap_supported_version;
45
ParseBqrLinkQualityEvt(uint8_t length,const uint8_t * p_param_buf)46 void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length,
47 const uint8_t* p_param_buf) {
48 if (length < kLinkQualityParamTotalLen) {
49 LOG(FATAL) << __func__
50 << ": Parameter total length: " << std::to_string(length)
51 << " is abnormal. It shall be not shorter than: "
52 << std::to_string(kLinkQualityParamTotalLen);
53 return;
54 }
55
56 STREAM_TO_UINT8(bqr_link_quality_event_.quality_report_id, p_param_buf);
57 STREAM_TO_UINT8(bqr_link_quality_event_.packet_types, p_param_buf);
58 STREAM_TO_UINT16(bqr_link_quality_event_.connection_handle, p_param_buf);
59 STREAM_TO_UINT8(bqr_link_quality_event_.connection_role, p_param_buf);
60 STREAM_TO_INT8(bqr_link_quality_event_.tx_power_level, p_param_buf);
61 STREAM_TO_INT8(bqr_link_quality_event_.rssi, p_param_buf);
62 STREAM_TO_UINT8(bqr_link_quality_event_.snr, p_param_buf);
63 STREAM_TO_UINT8(bqr_link_quality_event_.unused_afh_channel_count,
64 p_param_buf);
65 STREAM_TO_UINT8(bqr_link_quality_event_.afh_select_unideal_channel_count,
66 p_param_buf);
67 STREAM_TO_UINT16(bqr_link_quality_event_.lsto, p_param_buf);
68 STREAM_TO_UINT32(bqr_link_quality_event_.connection_piconet_clock,
69 p_param_buf);
70 STREAM_TO_UINT32(bqr_link_quality_event_.retransmission_count, p_param_buf);
71 STREAM_TO_UINT32(bqr_link_quality_event_.no_rx_count, p_param_buf);
72 STREAM_TO_UINT32(bqr_link_quality_event_.nak_count, p_param_buf);
73 STREAM_TO_UINT32(bqr_link_quality_event_.last_tx_ack_timestamp, p_param_buf);
74 STREAM_TO_UINT32(bqr_link_quality_event_.flow_off_count, p_param_buf);
75 STREAM_TO_UINT32(bqr_link_quality_event_.last_flow_on_timestamp, p_param_buf);
76 STREAM_TO_UINT32(bqr_link_quality_event_.buffer_overflow_bytes, p_param_buf);
77 STREAM_TO_UINT32(bqr_link_quality_event_.buffer_underflow_bytes, p_param_buf);
78
79 if (vendor_cap_supported_version >= kBqrIsoVersion) {
80 if (length < kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen) {
81 LOG(WARNING) << __func__
82 << ": Parameter total length: " << std::to_string(length)
83 << " is abnormal. "
84 << "vendor_cap_supported_version: "
85 << vendor_cap_supported_version << " "
86 << " (>= "
87 << "kBqrIsoVersion=" << kBqrIsoVersion << "), "
88 << "It should not be shorter than: "
89 << std::to_string(kLinkQualityParamTotalLen +
90 kISOLinkQualityParamTotalLen);
91 } else {
92 STREAM_TO_UINT32(bqr_link_quality_event_.tx_total_packets, p_param_buf);
93 STREAM_TO_UINT32(bqr_link_quality_event_.tx_unacked_packets, p_param_buf);
94 STREAM_TO_UINT32(bqr_link_quality_event_.tx_flushed_packets, p_param_buf);
95 STREAM_TO_UINT32(bqr_link_quality_event_.tx_last_subevent_packets,
96 p_param_buf);
97 STREAM_TO_UINT32(bqr_link_quality_event_.crc_error_packets, p_param_buf);
98 STREAM_TO_UINT32(bqr_link_quality_event_.rx_duplicate_packets,
99 p_param_buf);
100 }
101 }
102
103 const auto now = system_clock::to_time_t(system_clock::now());
104 localtime_r(&now, &tm_timestamp_);
105 }
106
WriteLmpLlTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)107 void BqrVseSubEvt::WriteLmpLlTraceLogFile(int fd, uint8_t length,
108 const uint8_t* p_param_buf) {
109 const auto now = system_clock::to_time_t(system_clock::now());
110 localtime_r(&now, &tm_timestamp_);
111
112 STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
113 STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
114 length -= kLogDumpParamTotalLen;
115 bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
116
117 std::stringstream ss_log;
118 ss_log << "\n"
119 << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
120 << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
121 << " VSP: ";
122
123 TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
124 TEMP_FAILURE_RETRY(
125 write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
126 LmpLlMessageTraceCounter++;
127 }
128
WriteBtSchedulingTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)129 void BqrVseSubEvt::WriteBtSchedulingTraceLogFile(int fd, uint8_t length,
130 const uint8_t* p_param_buf) {
131 const auto now = system_clock::to_time_t(system_clock::now());
132 localtime_r(&now, &tm_timestamp_);
133
134 STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
135 STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
136 length -= kLogDumpParamTotalLen;
137 bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
138
139 std::stringstream ss_log;
140 ss_log << "\n"
141 << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
142 << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
143 << " VSP: ";
144
145 TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
146 TEMP_FAILURE_RETRY(
147 write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
148 BtSchedulingTraceCounter++;
149 }
150
ToString() const151 std::string BqrVseSubEvt::ToString() const {
152 std::stringstream ss;
153 ss << QualityReportIdToString(bqr_link_quality_event_.quality_report_id)
154 << ", Handle: " << loghex(bqr_link_quality_event_.connection_handle)
155 << ", " << PacketTypeToString(bqr_link_quality_event_.packet_types) << ", "
156 << ((bqr_link_quality_event_.connection_role == 0) ? "Central"
157 : "Peripheral ")
158 << ", PwLv: " << std::to_string(bqr_link_quality_event_.tx_power_level)
159 << ", RSSI: " << std::to_string(bqr_link_quality_event_.rssi)
160 << ", SNR: " << std::to_string(bqr_link_quality_event_.snr)
161 << ", UnusedCh: "
162 << std::to_string(bqr_link_quality_event_.unused_afh_channel_count)
163 << ", UnidealCh: "
164 << std::to_string(bqr_link_quality_event_.afh_select_unideal_channel_count)
165 << ", ReTx: "
166 << std::to_string(bqr_link_quality_event_.retransmission_count)
167 << ", NoRX: " << std::to_string(bqr_link_quality_event_.no_rx_count)
168 << ", NAK: " << std::to_string(bqr_link_quality_event_.nak_count)
169 << ", FlowOff: " << std::to_string(bqr_link_quality_event_.flow_off_count)
170 << ", OverFlow: "
171 << std::to_string(bqr_link_quality_event_.buffer_overflow_bytes)
172 << ", UndFlow: "
173 << std::to_string(bqr_link_quality_event_.buffer_underflow_bytes);
174
175 if (vendor_cap_supported_version >= kBqrIsoVersion) {
176 ss << ", TxTotal: "
177 << std::to_string(bqr_link_quality_event_.tx_total_packets)
178 << ", TxUnAcked: "
179 << std::to_string(bqr_link_quality_event_.tx_unacked_packets)
180 << ", TxFlushed: "
181 << std::to_string(bqr_link_quality_event_.tx_flushed_packets)
182 << ", TxLastSubEvent: "
183 << std::to_string(bqr_link_quality_event_.tx_last_subevent_packets)
184 << ", CRCError: "
185 << std::to_string(bqr_link_quality_event_.crc_error_packets)
186 << ", RxDuplicate: "
187 << std::to_string(bqr_link_quality_event_.rx_duplicate_packets);
188 }
189
190 return ss.str();
191 }
192
QualityReportIdToString(uint8_t quality_report_id)193 std::string QualityReportIdToString(uint8_t quality_report_id) {
194 switch (quality_report_id) {
195 case QUALITY_REPORT_ID_MONITOR_MODE:
196 return "Monitoring ";
197 case QUALITY_REPORT_ID_APPROACH_LSTO:
198 return "Appro LSTO ";
199 case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
200 return "A2DP Choppy";
201 case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
202 return "SCO Choppy ";
203 case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
204 return "LE Audio Choppy";
205 default:
206 return "Invalid ";
207 }
208 }
209
PacketTypeToString(uint8_t packet_type)210 std::string PacketTypeToString(uint8_t packet_type) {
211 switch (packet_type) {
212 case PACKET_TYPE_ID:
213 return "ID";
214 case PACKET_TYPE_NULL:
215 return "NULL";
216 case PACKET_TYPE_POLL:
217 return "POLL";
218 case PACKET_TYPE_FHS:
219 return "FHS";
220 case PACKET_TYPE_HV1:
221 return "HV1";
222 case PACKET_TYPE_HV2:
223 return "HV2";
224 case PACKET_TYPE_HV3:
225 return "HV3";
226 case PACKET_TYPE_DV:
227 return "DV";
228 case PACKET_TYPE_EV3:
229 return "EV3";
230 case PACKET_TYPE_EV4:
231 return "EV4";
232 case PACKET_TYPE_EV5:
233 return "EV5";
234 case PACKET_TYPE_2EV3:
235 return "2EV3";
236 case PACKET_TYPE_2EV5:
237 return "2EV5";
238 case PACKET_TYPE_3EV3:
239 return "3EV3";
240 case PACKET_TYPE_3EV5:
241 return "3EV5";
242 case PACKET_TYPE_DM1:
243 return "DM1";
244 case PACKET_TYPE_DH1:
245 return "DH1";
246 case PACKET_TYPE_DM3:
247 return "DM3";
248 case PACKET_TYPE_DH3:
249 return "DH3";
250 case PACKET_TYPE_DM5:
251 return "DM5";
252 case PACKET_TYPE_DH5:
253 return "DH5";
254 case PACKET_TYPE_AUX1:
255 return "AUX1";
256 case PACKET_TYPE_2DH1:
257 return "2DH1";
258 case PACKET_TYPE_2DH3:
259 return "2DH3";
260 case PACKET_TYPE_2DH5:
261 return "2DH5";
262 case PACKET_TYPE_3DH1:
263 return "3DH1";
264 case PACKET_TYPE_3DH3:
265 return "3DH3";
266 case PACKET_TYPE_3DH5:
267 return "3DH5";
268 case PACKET_TYPE_ISO:
269 return "ISO";
270 default:
271 return "UnKnown ";
272 }
273 }
274
EnableBtQualityReport(bool is_enable)275 void EnableBtQualityReport(bool is_enable) {
276 LOG(INFO) << __func__ << ": is_enable: " << logbool(is_enable);
277
278 char bqr_prop_evtmask[PROPERTY_VALUE_MAX] = {0};
279 char bqr_prop_interval_ms[PROPERTY_VALUE_MAX] = {0};
280 osi_property_get(kpPropertyEventMask, bqr_prop_evtmask, "");
281 osi_property_get(kpPropertyMinReportIntervalMs, bqr_prop_interval_ms, "");
282
283 if (strlen(bqr_prop_evtmask) == 0 || strlen(bqr_prop_interval_ms) == 0) {
284 LOG(WARNING) << __func__ << ": Bluetooth Quality Report is disabled."
285 << " bqr_prop_evtmask: " << bqr_prop_evtmask
286 << ", bqr_prop_interval_ms: " << bqr_prop_interval_ms;
287 return;
288 }
289
290 BqrConfiguration bqr_config = {};
291
292 if (is_enable) {
293 bqr_config.report_action = REPORT_ACTION_ADD;
294 bqr_config.quality_event_mask =
295 static_cast<uint32_t>(atoi(bqr_prop_evtmask));
296 bqr_config.minimum_report_interval_ms =
297 static_cast<uint16_t>(atoi(bqr_prop_interval_ms));
298 } else {
299 bqr_config.report_action = REPORT_ACTION_CLEAR;
300 bqr_config.quality_event_mask = kQualityEventMaskAllOff;
301 bqr_config.minimum_report_interval_ms = kMinReportIntervalNoLimit;
302 }
303
304 tBTM_BLE_VSC_CB cmn_vsc_cb;
305 BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
306 vendor_cap_supported_version = cmn_vsc_cb.version_supported;
307
308 LOG(INFO) << __func__
309 << ": Event Mask: " << loghex(bqr_config.quality_event_mask)
310 << ", Interval: " << bqr_config.minimum_report_interval_ms
311 << ", vendor_cap_supported_version: "
312 << vendor_cap_supported_version;
313 ConfigureBqr(bqr_config);
314 }
315
ConfigureBqr(const BqrConfiguration & bqr_config)316 void ConfigureBqr(const BqrConfiguration& bqr_config) {
317 if (bqr_config.report_action > REPORT_ACTION_CLEAR ||
318 bqr_config.quality_event_mask > kQualityEventMaskAll ||
319 bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) {
320 LOG(FATAL) << __func__ << ": Invalid Parameter"
321 << ", Action: " << bqr_config.report_action
322 << ", Mask: " << loghex(bqr_config.quality_event_mask)
323 << ", Interval: " << bqr_config.minimum_report_interval_ms;
324 return;
325 }
326
327 LOG(INFO) << __func__ << ": Action: "
328 << loghex(static_cast<uint8_t>(bqr_config.report_action))
329 << ", Mask: " << loghex(bqr_config.quality_event_mask)
330 << ", Interval: " << bqr_config.minimum_report_interval_ms;
331
332 uint8_t param[sizeof(BqrConfiguration)];
333 uint8_t* p_param = param;
334 UINT8_TO_STREAM(p_param, bqr_config.report_action);
335 UINT32_TO_STREAM(p_param, bqr_config.quality_event_mask);
336 UINT16_TO_STREAM(p_param, bqr_config.minimum_report_interval_ms);
337
338 BTM_VendorSpecificCommand(HCI_CONTROLLER_BQR, p_param - param, param,
339 BqrVscCompleteCallback);
340 }
341
BqrVscCompleteCallback(tBTM_VSC_CMPL * p_vsc_cmpl_params)342 void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) {
343 if (p_vsc_cmpl_params->param_len < 1) {
344 LOG(ERROR) << __func__ << ": The length of returned parameters is less than 1";
345 return;
346 }
347
348 uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
349 uint8_t status = 0xff;
350 // [Return Parameter] | [Size] | [Purpose]
351 // Status | 1 octet | Command complete status
352 // Current_Quality_Event_Mask | 4 octets | Indicates current bit mask setting
353 STREAM_TO_UINT8(status, p_event_param_buf);
354 if (status != HCI_SUCCESS) {
355 LOG(ERROR) << __func__ << ": Fail to configure BQR. status: " << loghex(status);
356 return;
357 }
358
359 if (p_vsc_cmpl_params->param_len != 5) {
360 LOG(FATAL) << __func__
361 << ": The length of returned parameters is not equal to 5: "
362 << std::to_string(p_vsc_cmpl_params->param_len);
363 return;
364 }
365
366 uint32_t current_quality_event_mask = kQualityEventMaskAllOff;
367 STREAM_TO_UINT32(current_quality_event_mask, p_event_param_buf);
368
369 LOG(INFO) << __func__
370 << ", current event mask: " << loghex(current_quality_event_mask);
371 ConfigureBqrCmpl(current_quality_event_mask);
372 }
373
ConfigureBqrCmpl(uint32_t current_evt_mask)374 void ConfigureBqrCmpl(uint32_t current_evt_mask) {
375 LOG(INFO) << __func__ << ": current_evt_mask: " << loghex(current_evt_mask);
376 // (Un)Register for VSE of Bluetooth Quality Report sub event
377 tBTM_STATUS btm_status = BTM_BT_Quality_Report_VSE_Register(
378 current_evt_mask > kQualityEventMaskAllOff, CategorizeBqrEvent);
379
380 if (btm_status != BTM_SUCCESS) {
381 LOG(ERROR) << __func__ << ": Fail to (un)register VSE of BQR sub event."
382 << " status: " << btm_status;
383 return;
384 }
385
386 if (LmpLlMessageTraceLogFd != INVALID_FD &&
387 (current_evt_mask & kQualityEventMaskLmpMessageTrace) == 0) {
388 LOG(INFO) << __func__ << ": Closing LMP/LL log file.";
389 close(LmpLlMessageTraceLogFd);
390 LmpLlMessageTraceLogFd = INVALID_FD;
391 }
392 if (BtSchedulingTraceLogFd != INVALID_FD &&
393 (current_evt_mask & kQualityEventMaskBtSchedulingTrace) == 0) {
394 LOG(INFO) << __func__ << ": Closing Scheduling log file.";
395 close(BtSchedulingTraceLogFd);
396 BtSchedulingTraceLogFd = INVALID_FD;
397 }
398 }
399
CategorizeBqrEvent(uint8_t length,const uint8_t * p_bqr_event)400 void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) {
401 if (length == 0) {
402 LOG(WARNING) << __func__ << ": Lengths of all of the parameters are zero.";
403 return;
404 }
405
406 uint8_t quality_report_id = p_bqr_event[0];
407 switch (quality_report_id) {
408 case QUALITY_REPORT_ID_MONITOR_MODE:
409 case QUALITY_REPORT_ID_APPROACH_LSTO:
410 case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
411 case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
412 case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
413 if (length < kLinkQualityParamTotalLen) {
414 LOG(FATAL) << __func__
415 << ": Parameter total length: " << std::to_string(length)
416 << " is abnormal. It shall be not shorter than: "
417 << std::to_string(kLinkQualityParamTotalLen);
418 return;
419 }
420
421 AddLinkQualityEventToQueue(length, p_bqr_event);
422 break;
423
424 // The Root Inflammation and Log Dump related event should be handled and
425 // intercepted already.
426 case QUALITY_REPORT_ID_ROOT_INFLAMMATION:
427 case QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE:
428 case QUALITY_REPORT_ID_BT_SCHEDULING_TRACE:
429 case QUALITY_REPORT_ID_CONTROLLER_DBG_INFO:
430 LOG(WARNING) << __func__
431 << ": Unexpected ID: " << loghex(quality_report_id);
432 break;
433
434 default:
435 LOG(WARNING) << __func__ << ": Unknown ID: " << loghex(quality_report_id);
436 break;
437 }
438 }
439
AddLinkQualityEventToQueue(uint8_t length,const uint8_t * p_link_quality_event)440 void AddLinkQualityEventToQueue(uint8_t length,
441 const uint8_t* p_link_quality_event) {
442 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
443 p_bqr_event->ParseBqrLinkQualityEvt(length, p_link_quality_event);
444
445 LOG(WARNING) << *p_bqr_event;
446 invoke_link_quality_report_cb(
447 bluetooth::common::time_get_os_boottime_ms(),
448 p_bqr_event->bqr_link_quality_event_.quality_report_id,
449 p_bqr_event->bqr_link_quality_event_.rssi,
450 p_bqr_event->bqr_link_quality_event_.snr,
451 p_bqr_event->bqr_link_quality_event_.retransmission_count,
452 p_bqr_event->bqr_link_quality_event_.no_rx_count,
453 p_bqr_event->bqr_link_quality_event_.nak_count);
454
455 #ifdef OS_ANDROID
456 int ret = stats_write(
457 BLUETOOTH_QUALITY_REPORT_REPORTED,
458 p_bqr_event->bqr_link_quality_event_.quality_report_id,
459 p_bqr_event->bqr_link_quality_event_.packet_types,
460 p_bqr_event->bqr_link_quality_event_.connection_handle,
461 p_bqr_event->bqr_link_quality_event_.connection_role,
462 p_bqr_event->bqr_link_quality_event_.tx_power_level,
463 p_bqr_event->bqr_link_quality_event_.rssi,
464 p_bqr_event->bqr_link_quality_event_.snr,
465 p_bqr_event->bqr_link_quality_event_.unused_afh_channel_count,
466 p_bqr_event->bqr_link_quality_event_.afh_select_unideal_channel_count,
467 p_bqr_event->bqr_link_quality_event_.lsto,
468 p_bqr_event->bqr_link_quality_event_.connection_piconet_clock,
469 p_bqr_event->bqr_link_quality_event_.retransmission_count,
470 p_bqr_event->bqr_link_quality_event_.no_rx_count,
471 p_bqr_event->bqr_link_quality_event_.nak_count,
472 p_bqr_event->bqr_link_quality_event_.last_tx_ack_timestamp,
473 p_bqr_event->bqr_link_quality_event_.flow_off_count,
474 p_bqr_event->bqr_link_quality_event_.last_flow_on_timestamp,
475 p_bqr_event->bqr_link_quality_event_.buffer_overflow_bytes,
476 p_bqr_event->bqr_link_quality_event_.buffer_underflow_bytes);
477 if (ret < 0) {
478 LOG(WARNING) << __func__ << ": failed to log BQR event to statsd, error "
479 << ret;
480 }
481 #else
482 // TODO(abps) Metrics for non-Android build
483 #endif
484 kpBqrEventQueue->Enqueue(p_bqr_event.release());
485 }
486
DumpLmpLlMessage(uint8_t length,const uint8_t * p_lmp_ll_message_event)487 void DumpLmpLlMessage(uint8_t length, const uint8_t* p_lmp_ll_message_event) {
488 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
489
490 if (LmpLlMessageTraceLogFd == INVALID_FD ||
491 LmpLlMessageTraceCounter >= kLogDumpEventPerFile) {
492 LmpLlMessageTraceLogFd = OpenLmpLlTraceLogFile();
493 }
494 if (LmpLlMessageTraceLogFd != INVALID_FD) {
495 p_bqr_event->WriteLmpLlTraceLogFile(LmpLlMessageTraceLogFd, length,
496 p_lmp_ll_message_event);
497 }
498 }
499
OpenLmpLlTraceLogFile()500 int OpenLmpLlTraceLogFile() {
501 if (rename(kpLmpLlMessageTraceLogPath, kpLmpLlMessageTraceLastLogPath) != 0 &&
502 errno != ENOENT) {
503 LOG(ERROR) << __func__ << ": Unable to rename '"
504 << kpLmpLlMessageTraceLogPath << "' to '"
505 << kpLmpLlMessageTraceLastLogPath << "' : " << strerror(errno);
506 }
507
508 mode_t prevmask = umask(0);
509 int logfile_fd =
510 open(kpLmpLlMessageTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
511 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
512 umask(prevmask);
513 if (logfile_fd == INVALID_FD) {
514 LOG(ERROR) << __func__ << ": Unable to open '" << kpLmpLlMessageTraceLogPath
515 << "' : " << strerror(errno);
516 } else {
517 LmpLlMessageTraceCounter = 0;
518 }
519 return logfile_fd;
520 }
521
DumpBtScheduling(uint8_t length,const uint8_t * p_bt_scheduling_event)522 void DumpBtScheduling(uint8_t length, const uint8_t* p_bt_scheduling_event) {
523 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
524
525 if (BtSchedulingTraceLogFd == INVALID_FD ||
526 BtSchedulingTraceCounter == kLogDumpEventPerFile) {
527 BtSchedulingTraceLogFd = OpenBtSchedulingTraceLogFile();
528 }
529 if (BtSchedulingTraceLogFd != INVALID_FD) {
530 p_bqr_event->WriteBtSchedulingTraceLogFile(BtSchedulingTraceLogFd, length,
531 p_bt_scheduling_event);
532 }
533 }
534
OpenBtSchedulingTraceLogFile()535 int OpenBtSchedulingTraceLogFile() {
536 if (rename(kpBtSchedulingTraceLogPath, kpBtSchedulingTraceLastLogPath) != 0 &&
537 errno != ENOENT) {
538 LOG(ERROR) << __func__ << ": Unable to rename '"
539 << kpBtSchedulingTraceLogPath << "' to '"
540 << kpBtSchedulingTraceLastLogPath << "' : " << strerror(errno);
541 }
542
543 mode_t prevmask = umask(0);
544 int logfile_fd =
545 open(kpBtSchedulingTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
546 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
547 umask(prevmask);
548 if (logfile_fd == INVALID_FD) {
549 LOG(ERROR) << __func__ << ": Unable to open '" << kpBtSchedulingTraceLogPath
550 << "' : " << strerror(errno);
551 } else {
552 BtSchedulingTraceCounter = 0;
553 }
554 return logfile_fd;
555 }
556
DebugDump(int fd)557 void DebugDump(int fd) {
558 dprintf(fd, "\nBT Quality Report Events: \n");
559
560 if (kpBqrEventQueue->Empty()) {
561 dprintf(fd, "Event queue is empty.\n");
562 return;
563 }
564
565 while (!kpBqrEventQueue->Empty()) {
566 std::unique_ptr<BqrVseSubEvt> p_event(kpBqrEventQueue->Dequeue());
567
568 bool warning = (p_event->bqr_link_quality_event_.rssi < kCriWarnRssi ||
569 p_event->bqr_link_quality_event_.unused_afh_channel_count >
570 kCriWarnUnusedCh);
571
572 std::stringstream ss_timestamp;
573 ss_timestamp << std::put_time(&p_event->tm_timestamp_, "%m-%d %H:%M:%S");
574
575 dprintf(fd, "%c %s %s\n", warning ? '*' : ' ', ss_timestamp.str().c_str(),
576 p_event->ToString().c_str());
577 }
578
579 dprintf(fd, "\n");
580 }
581
582 } // namespace bqr
583 } // namespace bluetooth
584