• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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