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 <bluetooth/log.h>
18 #include <fcntl.h>
19 #ifdef __ANDROID__
20 #include <statslog_bt.h>
21 #endif
22 #include <sys/stat.h>
23 
24 #include <cerrno>
25 #include <cstdint>
26 
27 #include "btif/include/stack_manager_t.h"
28 #include "btif_bqr.h"
29 #include "btif_common.h"
30 #include "btif_storage.h"
31 #include "common/leaky_bonded_queue.h"
32 #include "common/postable_context.h"
33 #include "common/time_util.h"
34 #include "core_callbacks.h"
35 #include "hci/hci_interface.h"
36 #include "hci/hci_packets.h"
37 #include "internal_include/bt_trace.h"
38 #include "main/shim/entry.h"
39 #include "osi/include/properties.h"
40 #include "packet/raw_builder.h"
41 #include "raw_address.h"
42 #include "stack/btm/btm_dev.h"
43 #include "stack/include/bt_types.h"
44 #include "stack/include/btm_api.h"
45 #include "stack/include/btm_ble_api.h"
46 
47 namespace bluetooth {
48 namespace bqr {
49 
50 using bluetooth::common::LeakyBondedQueue;
51 using std::chrono::system_clock;
52 
53 // The instance of BQR event queue
54 static LeakyBondedQueue<BqrVseSubEvt> kpBqrEventQueue{kBqrEventQueueSize};
55 
56 static uint16_t vendor_cap_supported_version;
57 
58 class BluetoothQualityReportInterfaceImpl;
59 std::unique_ptr<BluetoothQualityReportInterface> bluetoothQualityReportInstance;
60 
61 namespace {
62 common::PostableContext* to_bind_ = nullptr;
63 }
64 
ParseBqrLinkQualityEvt(uint8_t length,const uint8_t * p_param_buf)65 void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length,
66                                           const uint8_t* p_param_buf) {
67   if (length < kLinkQualityParamTotalLen) {
68     log::fatal(
69         "Parameter total length: {} is abnormal. It shall be not shorter than: "
70         "{}",
71         length, kLinkQualityParamTotalLen);
72     return;
73   }
74 
75   STREAM_TO_UINT8(bqr_link_quality_event_.quality_report_id, p_param_buf);
76   STREAM_TO_UINT8(bqr_link_quality_event_.packet_types, p_param_buf);
77   STREAM_TO_UINT16(bqr_link_quality_event_.connection_handle, p_param_buf);
78   STREAM_TO_UINT8(bqr_link_quality_event_.connection_role, p_param_buf);
79   STREAM_TO_INT8(bqr_link_quality_event_.tx_power_level, p_param_buf);
80   STREAM_TO_INT8(bqr_link_quality_event_.rssi, p_param_buf);
81   STREAM_TO_UINT8(bqr_link_quality_event_.snr, p_param_buf);
82   STREAM_TO_UINT8(bqr_link_quality_event_.unused_afh_channel_count,
83                   p_param_buf);
84   STREAM_TO_UINT8(bqr_link_quality_event_.afh_select_unideal_channel_count,
85                   p_param_buf);
86   STREAM_TO_UINT16(bqr_link_quality_event_.lsto, p_param_buf);
87   STREAM_TO_UINT32(bqr_link_quality_event_.connection_piconet_clock,
88                    p_param_buf);
89   STREAM_TO_UINT32(bqr_link_quality_event_.retransmission_count, p_param_buf);
90   STREAM_TO_UINT32(bqr_link_quality_event_.no_rx_count, p_param_buf);
91   STREAM_TO_UINT32(bqr_link_quality_event_.nak_count, p_param_buf);
92   STREAM_TO_UINT32(bqr_link_quality_event_.last_tx_ack_timestamp, p_param_buf);
93   STREAM_TO_UINT32(bqr_link_quality_event_.flow_off_count, p_param_buf);
94   STREAM_TO_UINT32(bqr_link_quality_event_.last_flow_on_timestamp, p_param_buf);
95   STREAM_TO_UINT32(bqr_link_quality_event_.buffer_overflow_bytes, p_param_buf);
96   STREAM_TO_UINT32(bqr_link_quality_event_.buffer_underflow_bytes, p_param_buf);
97 
98   if (vendor_cap_supported_version >= kBqrVersion5_0) {
99     if (length < kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen +
100                      kVersion5_0ParamsTotalLen) {
101       log::warn(
102           "Parameter total length: {} is abnormal. "
103           "vendor_cap_supported_version: {}  (>= kBqrVersion5_0={}), It should "
104           "not be shorter than: {}",
105           length, vendor_cap_supported_version, kBqrVersion5_0,
106           kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen +
107               kVersion5_0ParamsTotalLen);
108     } else {
109       STREAM_TO_BDADDR(bqr_link_quality_event_.bdaddr, p_param_buf);
110       STREAM_TO_UINT8(bqr_link_quality_event_.cal_failed_item_count,
111                       p_param_buf);
112     }
113   }
114 
115   if (vendor_cap_supported_version >= kBqrIsoVersion) {
116     if (length < kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen) {
117       log::warn(
118           "Parameter total length: {} is abnormal. "
119           "vendor_cap_supported_version: {}  (>= kBqrIsoVersion={}), It should "
120           "not be shorter than: {}",
121           length, vendor_cap_supported_version, kBqrIsoVersion,
122           kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen);
123     } else {
124       STREAM_TO_UINT32(bqr_link_quality_event_.tx_total_packets, p_param_buf);
125       STREAM_TO_UINT32(bqr_link_quality_event_.tx_unacked_packets, p_param_buf);
126       STREAM_TO_UINT32(bqr_link_quality_event_.tx_flushed_packets, p_param_buf);
127       STREAM_TO_UINT32(bqr_link_quality_event_.tx_last_subevent_packets,
128                        p_param_buf);
129       STREAM_TO_UINT32(bqr_link_quality_event_.crc_error_packets, p_param_buf);
130       STREAM_TO_UINT32(bqr_link_quality_event_.rx_duplicate_packets,
131                        p_param_buf);
132     }
133   }
134 
135   if (vendor_cap_supported_version >= kBqrVersion6_0) {
136     if (length < kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen +
137                      kVersion5_0ParamsTotalLen + kVersion6_0ParamsTotalLen) {
138       log::warn(
139           "Parameter total length: {} is abnormal. "
140           "vendor_cap_supported_version: {}  (>= kBqrVersion6_0={}), It should "
141           "not be shorter than: {}",
142           length, vendor_cap_supported_version, kBqrVersion6_0,
143           kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen +
144               kVersion5_0ParamsTotalLen + kVersion6_0ParamsTotalLen);
145     } else {
146       STREAM_TO_UINT32(bqr_link_quality_event_.rx_unreceived_packets,
147                        p_param_buf);
148       STREAM_TO_UINT16(bqr_link_quality_event_.coex_info_mask, p_param_buf);
149     }
150   }
151 
152   const auto now = system_clock::to_time_t(system_clock::now());
153   localtime_r(&now, &tm_timestamp_);
154 }
155 
WriteLmpLlTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)156 void BqrVseSubEvt::WriteLmpLlTraceLogFile(int fd, uint8_t length,
157                                           const uint8_t* p_param_buf) {
158   const auto now = system_clock::to_time_t(system_clock::now());
159   localtime_r(&now, &tm_timestamp_);
160 
161   STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
162   STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
163   length -= kLogDumpParamTotalLen;
164   bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
165 
166   std::stringstream ss_log;
167   ss_log << "\n"
168          << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
169          << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
170          << " VSP: ";
171 
172   TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
173   TEMP_FAILURE_RETRY(
174       write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
175   LmpLlMessageTraceCounter++;
176 }
177 
WriteBtSchedulingTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)178 void BqrVseSubEvt::WriteBtSchedulingTraceLogFile(int fd, uint8_t length,
179                                                  const uint8_t* p_param_buf) {
180   const auto now = system_clock::to_time_t(system_clock::now());
181   localtime_r(&now, &tm_timestamp_);
182 
183   STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
184   STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
185   length -= kLogDumpParamTotalLen;
186   bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
187 
188   std::stringstream ss_log;
189   ss_log << "\n"
190          << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
191          << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
192          << " VSP: ";
193 
194   TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
195   TEMP_FAILURE_RETRY(
196       write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
197   BtSchedulingTraceCounter++;
198 }
199 
200 static std::string QualityReportIdToString(uint8_t quality_report_id);
201 static std::string PacketTypeToString(uint8_t packet_type);
202 
ToString() const203 std::string BqrVseSubEvt::ToString() const {
204   std::stringstream ss;
205   ss << QualityReportIdToString(bqr_link_quality_event_.quality_report_id)
206      << ", Handle: " << loghex(bqr_link_quality_event_.connection_handle)
207      << ", " << PacketTypeToString(bqr_link_quality_event_.packet_types) << ", "
208      << ((bqr_link_quality_event_.connection_role == 0) ? "Central"
209                                                         : "Peripheral ")
210      << ", PwLv: " << std::to_string(bqr_link_quality_event_.tx_power_level)
211      << ", RSSI: " << std::to_string(bqr_link_quality_event_.rssi)
212      << ", SNR: " << std::to_string(bqr_link_quality_event_.snr)
213      << ", UnusedCh: "
214      << std::to_string(bqr_link_quality_event_.unused_afh_channel_count)
215      << ", UnidealCh: "
216      << std::to_string(bqr_link_quality_event_.afh_select_unideal_channel_count)
217      << ", ReTx: "
218      << std::to_string(bqr_link_quality_event_.retransmission_count)
219      << ", NoRX: " << std::to_string(bqr_link_quality_event_.no_rx_count)
220      << ", NAK: " << std::to_string(bqr_link_quality_event_.nak_count)
221      << ", FlowOff: " << std::to_string(bqr_link_quality_event_.flow_off_count)
222      << ", OverFlow: "
223      << std::to_string(bqr_link_quality_event_.buffer_overflow_bytes)
224      << ", UndFlow: "
225      << std::to_string(bqr_link_quality_event_.buffer_underflow_bytes);
226   if (vendor_cap_supported_version >= kBqrVersion5_0) {
227     ss << ", RemoteDevAddr: "
228        << bqr_link_quality_event_.bdaddr.ToColonSepHexString()
229        << ", CalFailedItems: "
230        << std::to_string(bqr_link_quality_event_.cal_failed_item_count);
231   }
232   if (vendor_cap_supported_version >= kBqrIsoVersion) {
233     ss << ", TxTotal: "
234        << std::to_string(bqr_link_quality_event_.tx_total_packets)
235        << ", TxUnAcked: "
236        << std::to_string(bqr_link_quality_event_.tx_unacked_packets)
237        << ", TxFlushed: "
238        << std::to_string(bqr_link_quality_event_.tx_flushed_packets)
239        << ", TxLastSubEvent: "
240        << std::to_string(bqr_link_quality_event_.tx_last_subevent_packets)
241        << ", CRCError: "
242        << std::to_string(bqr_link_quality_event_.crc_error_packets)
243        << ", RxDuplicate: "
244        << std::to_string(bqr_link_quality_event_.rx_duplicate_packets);
245   }
246 
247   return ss.str();
248 }
249 
250 // Get a string representation of the Quality Report ID.
251 //
252 // @param quality_report_id The quality report ID to convert.
253 // @return a string representation of the Quality Report ID.
QualityReportIdToString(uint8_t quality_report_id)254 static std::string QualityReportIdToString(uint8_t quality_report_id) {
255   switch (quality_report_id) {
256     case QUALITY_REPORT_ID_MONITOR_MODE:
257       return "Monitoring";
258     case QUALITY_REPORT_ID_APPROACH_LSTO:
259       return "Approach LSTO";
260     case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
261       return "A2DP Choppy";
262     case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
263       return "SCO Choppy";
264     case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
265       return "LE Audio Choppy";
266     case QUALITY_REPORT_ID_CONNECT_FAIL:
267       return "Connect Fail";
268     default:
269       return "Invalid";
270   }
271 }
272 
273 // Get a string representation of the Packet Type.
274 //
275 // @param packet_type The packet type to convert.
276 // @return a string representation of the Packet Type.
PacketTypeToString(uint8_t packet_type)277 static std::string PacketTypeToString(uint8_t packet_type) {
278   switch (packet_type) {
279     case PACKET_TYPE_ID:
280       return "ID";
281     case PACKET_TYPE_NULL:
282       return "NULL";
283     case PACKET_TYPE_POLL:
284       return "POLL";
285     case PACKET_TYPE_FHS:
286       return "FHS";
287     case PACKET_TYPE_HV1:
288       return "HV1";
289     case PACKET_TYPE_HV2:
290       return "HV2";
291     case PACKET_TYPE_HV3:
292       return "HV3";
293     case PACKET_TYPE_DV:
294       return "DV";
295     case PACKET_TYPE_EV3:
296       return "EV3";
297     case PACKET_TYPE_EV4:
298       return "EV4";
299     case PACKET_TYPE_EV5:
300       return "EV5";
301     case PACKET_TYPE_2EV3:
302       return "2EV3";
303     case PACKET_TYPE_2EV5:
304       return "2EV5";
305     case PACKET_TYPE_3EV3:
306       return "3EV3";
307     case PACKET_TYPE_3EV5:
308       return "3EV5";
309     case PACKET_TYPE_DM1:
310       return "DM1";
311     case PACKET_TYPE_DH1:
312       return "DH1";
313     case PACKET_TYPE_DM3:
314       return "DM3";
315     case PACKET_TYPE_DH3:
316       return "DH3";
317     case PACKET_TYPE_DM5:
318       return "DM5";
319     case PACKET_TYPE_DH5:
320       return "DH5";
321     case PACKET_TYPE_AUX1:
322       return "AUX1";
323     case PACKET_TYPE_2DH1:
324       return "2DH1";
325     case PACKET_TYPE_2DH3:
326       return "2DH3";
327     case PACKET_TYPE_2DH5:
328       return "2DH5";
329     case PACKET_TYPE_3DH1:
330       return "3DH1";
331     case PACKET_TYPE_3DH3:
332       return "3DH3";
333     case PACKET_TYPE_3DH5:
334       return "3DH5";
335     case PACKET_TYPE_ISO:
336       return "ISO";
337     default:
338       return "UnKnown ";
339   }
340 }
341 
342 void register_vse();
343 void unregister_vse();
344 
345 static void ConfigureBqr(const BqrConfiguration& bqr_config);
346 
EnableBtQualityReport(common::PostableContext * to_bind)347 void EnableBtQualityReport(common::PostableContext* to_bind) {
348   log::info("is_enable: {}", to_bind != nullptr);
349   if (to_bind != nullptr) {
350     to_bind_ = to_bind;
351   }
352 
353   char bqr_prop_evtmask[PROPERTY_VALUE_MAX] = {0};
354   char bqr_prop_interval_ms[PROPERTY_VALUE_MAX] = {0};
355   char bqr_prop_vnd_quality_mask[PROPERTY_VALUE_MAX] = {0};
356   char bqr_prop_vnd_trace_mask[PROPERTY_VALUE_MAX] = {0};
357   char bqr_prop_interval_multiple[PROPERTY_VALUE_MAX] = {0};
358   osi_property_get(kpPropertyEventMask, bqr_prop_evtmask, "");
359   osi_property_get(kpPropertyMinReportIntervalMs, bqr_prop_interval_ms, "");
360   osi_property_get(kpPropertyVndQualityMask, bqr_prop_vnd_quality_mask, "");
361   osi_property_get(kpPropertyVndTraceMask, bqr_prop_vnd_trace_mask, "");
362   osi_property_get(kpPropertyIntervalMultiple, bqr_prop_interval_multiple, "");
363 
364   if (strlen(bqr_prop_evtmask) == 0 || strlen(bqr_prop_interval_ms) == 0) {
365     log::warn(
366         "Bluetooth Quality Report is disabled. bqr_prop_evtmask: {}, "
367         "bqr_prop_interval_ms: {}",
368         bqr_prop_evtmask, bqr_prop_interval_ms);
369     return;
370   }
371 
372   BqrConfiguration bqr_config = {};
373 
374   if (to_bind) {
375     bqr_config.report_action = REPORT_ACTION_ADD;
376     bqr_config.quality_event_mask =
377         static_cast<uint32_t>(atoi(bqr_prop_evtmask));
378     bqr_config.minimum_report_interval_ms =
379         static_cast<uint16_t>(atoi(bqr_prop_interval_ms));
380     bqr_config.vnd_quality_mask =
381         static_cast<uint32_t>(atoi(bqr_prop_vnd_quality_mask));
382     bqr_config.vnd_trace_mask =
383         static_cast<uint32_t>(atoi(bqr_prop_vnd_trace_mask));
384     bqr_config.report_interval_multiple =
385         static_cast<uint32_t>(atoi(bqr_prop_interval_multiple));
386     register_vse();
387     kpBqrEventQueue.Clear();
388   } else {
389     bqr_config.report_action = REPORT_ACTION_CLEAR;
390     bqr_config.quality_event_mask = kQualityEventMaskAllOff;
391     bqr_config.minimum_report_interval_ms = kMinReportIntervalNoLimit;
392     bqr_config.vnd_quality_mask = 0;
393     bqr_config.vnd_trace_mask = 0;
394     bqr_config.report_interval_multiple = 0;
395     unregister_vse();
396   }
397 
398   tBTM_BLE_VSC_CB cmn_vsc_cb;
399   BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
400   vendor_cap_supported_version = cmn_vsc_cb.version_supported;
401 
402   log::info(
403       "Event Mask: 0x{:x}, Interval: {}, Multiple: {}, "
404       "vendor_cap_supported_version: {}",
405       bqr_config.quality_event_mask, bqr_config.minimum_report_interval_ms,
406       bqr_config.report_interval_multiple, vendor_cap_supported_version);
407   ConfigureBqr(bqr_config);
408 }
409 
410 static void BqrVscCompleteCallback(hci::CommandCompleteView complete);
411 
412 // Configure Bluetooth Quality Report setting to the Bluetooth controller.
413 //
414 // @param bqr_config The struct of configuration parameters.
ConfigureBqr(const BqrConfiguration & bqr_config)415 void ConfigureBqr(const BqrConfiguration& bqr_config) {
416   if (vendor_cap_supported_version >= kBqrVersion6_0) {
417     if (bqr_config.report_action > REPORT_ACTION_QUERY ||
418         bqr_config.quality_event_mask > kQualityEventMaskAll ||
419         bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) {
420       log::fatal(
421           "Invalid Parameter, Action: {}, Mask: 0x{:x}, Interval: {} Multiple: "
422           "{}",
423           bqr_config.report_action, bqr_config.quality_event_mask,
424           bqr_config.minimum_report_interval_ms,
425           bqr_config.report_interval_multiple);
426       return;
427     } else {
428       if (bqr_config.report_action > REPORT_ACTION_CLEAR ||
429           bqr_config.quality_event_mask > kQualityEventMaskAll ||
430           bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) {
431         log::fatal("Invalid Parameter, Action: {}, Mask: 0x{:x}, Interval: {}",
432                    bqr_config.report_action, bqr_config.quality_event_mask,
433                    bqr_config.minimum_report_interval_ms);
434         return;
435       }
436     }
437   }
438 
439   log::info("Action: 0x{:x}, Mask: 0x{:x}, Interval: {} Multiple: {}",
440             static_cast<uint8_t>(bqr_config.report_action),
441             bqr_config.quality_event_mask,
442             bqr_config.minimum_report_interval_ms,
443             bqr_config.report_interval_multiple);
444 
445   auto payload = std::make_unique<packet::RawBuilder>();
446   payload->AddOctets1(bqr_config.report_action);
447   payload->AddOctets4(bqr_config.quality_event_mask);
448   payload->AddOctets2(bqr_config.minimum_report_interval_ms);
449   if (vendor_cap_supported_version >= kBqrVndLogVersion) {
450     payload->AddOctets4(bqr_config.vnd_quality_mask);
451     payload->AddOctets4(bqr_config.vnd_trace_mask);
452   }
453   if (vendor_cap_supported_version >= kBqrVersion6_0) {
454     payload->AddOctets4(bqr_config.report_interval_multiple);
455   }
456 
457   shim::GetHciLayer()->EnqueueCommand(
458       hci::CommandBuilder::Create(hci::OpCode::CONTROLLER_BQR,
459                                   std::move(payload)),
460       to_bind_->BindOnce(BqrVscCompleteCallback));
461 }
462 
463 static void ConfigureBqrCmpl(uint32_t current_evt_mask);
464 
465 // Callback invoked on completion of vendor specific Bluetooth Quality Report
466 // command.
467 //
468 // @param p_vsc_cmpl_params A pointer to the parameters contained in the vendor
469 //   specific command complete event.
BqrVscCompleteCallback(hci::CommandCompleteView complete)470 static void BqrVscCompleteCallback(hci::CommandCompleteView complete) {
471   std::vector<uint8_t> payload_vector{complete.GetPayload().begin(),
472                                       complete.GetPayload().end()};
473   tBTM_VSC_CMPL vsc_cmpl_params = {
474       .opcode = static_cast<uint16_t>(complete.GetCommandOpCode()),
475       .param_len = static_cast<uint16_t>(payload_vector.size()),
476       .p_param_buf = payload_vector.data()};
477   tBTM_VSC_CMPL* p_vsc_cmpl_params = &vsc_cmpl_params;
478 
479   if (p_vsc_cmpl_params->param_len < 1) {
480     log::error("The length of returned parameters is less than 1");
481     return;
482   }
483 
484   uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
485   uint8_t status = 0xff;
486   uint8_t command_complete_param_len = 5;
487   uint32_t current_vnd_quality_mask = 0;
488   uint32_t current_vnd_trace_mask = 0;
489   uint32_t bqr_report_interval = 0;
490   // [Return Parameter]         | [Size]   | [Purpose]
491   // Status                     | 1 octet  | Command complete status
492   // Current_Quality_Event_Mask | 4 octets | Indicates current bit mask setting
493   // Vendor_Specific_Quality_Mask | 4 octets | vendor quality bit mask setting
494   // Vendor_Specific_Trace_Mask | 4 octets | vendor trace bit mask setting
495   // bqr_report_interval | 4 octets | report interval from controller setting
496 
497   STREAM_TO_UINT8(status, p_event_param_buf);
498   if (status != HCI_SUCCESS) {
499     log::error("Fail to configure BQR. status: 0x{:x}", status);
500     return;
501   }
502 
503   if (vendor_cap_supported_version >= kBqrVndLogVersion) {
504     command_complete_param_len = 13;
505   }
506 
507   if (vendor_cap_supported_version >= kBqrVersion6_0) {
508     command_complete_param_len = 17;
509   }
510 
511   if (p_vsc_cmpl_params->param_len != command_complete_param_len) {
512     log::fatal("The length of returned parameters is incorrect: {}",
513                p_vsc_cmpl_params->param_len);
514     return;
515   }
516 
517   uint32_t current_quality_event_mask = kQualityEventMaskAllOff;
518   STREAM_TO_UINT32(current_quality_event_mask, p_event_param_buf);
519 
520   if (vendor_cap_supported_version >= kBqrVndLogVersion) {
521     STREAM_TO_UINT32(current_vnd_quality_mask, p_event_param_buf);
522     STREAM_TO_UINT32(current_vnd_trace_mask, p_event_param_buf);
523   }
524 
525   if (vendor_cap_supported_version >= kBqrVersion6_0) {
526     STREAM_TO_UINT32(bqr_report_interval, p_event_param_buf);
527   }
528 
529   log::info(
530       "current event mask: 0x{:x}, vendor quality: 0x{:x}, vendor trace: "
531       "0x{:x}, report interval: 0x{:x}",
532       current_quality_event_mask, current_vnd_quality_mask,
533       current_vnd_trace_mask, bqr_report_interval);
534 
535   ConfigureBqrCmpl(current_quality_event_mask);
536 }
537 
ConfigBqrA2dpScoThreshold()538 void ConfigBqrA2dpScoThreshold() {
539   uint8_t sub_opcode = 0x16;
540   uint16_t a2dp_choppy_threshold = 0;
541   uint16_t sco_choppy_threshold = 0;
542 
543   char bqr_prop_threshold[PROPERTY_VALUE_MAX] = {0};
544   osi_property_get(kpPropertyChoppyThreshold, bqr_prop_threshold, "");
545 
546   sscanf(bqr_prop_threshold, "%hu,%hu", &a2dp_choppy_threshold,
547          &sco_choppy_threshold);
548 
549   log::info("a2dp_choppy_threshold: {}, sco_choppy_threshold: {}",
550             a2dp_choppy_threshold, sco_choppy_threshold);
551 
552   auto payload = std::make_unique<packet::RawBuilder>();
553   payload->AddOctets1(sub_opcode);
554 
555   // A2dp glitch ID
556   payload->AddOctets1(QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY);
557   // A2dp glitch config data length
558   payload->AddOctets1(2);
559   // A2dp glitch threshold
560   payload->AddOctets2(a2dp_choppy_threshold == 0 ? 1 : a2dp_choppy_threshold);
561 
562   // Sco glitch ID
563   payload->AddOctets1(QUALITY_REPORT_ID_SCO_VOICE_CHOPPY);
564   // Sco glitch config data length
565   payload->AddOctets1(2);
566   // Sco glitch threshold
567   payload->AddOctets2(sco_choppy_threshold == 0 ? 1 : sco_choppy_threshold);
568 
569   shim::GetHciLayer()->EnqueueCommand(
570       hci::CommandBuilder::Create(
571           static_cast<hci::OpCode>(HCI_VS_HOST_LOG_OPCODE), std::move(payload)),
572       to_bind_->BindOnce([](hci::CommandCompleteView) {}));
573 }
574 
575 // Invoked on completion of Bluetooth Quality Report configuration. Then it will
576 // Register/Unregister for receiving VSE - Bluetooth Quality Report sub-event.
577 //
578 // @param current_evt_mask Indicates current quality event bit mask setting in
579 //   the Bluetooth controller.
ConfigureBqrCmpl(uint32_t current_evt_mask)580 static void ConfigureBqrCmpl(uint32_t current_evt_mask) {
581   log::info("current_evt_mask: 0x{:x}", current_evt_mask);
582 
583   if (current_evt_mask > kQualityEventMaskAllOff) {
584     ConfigBqrA2dpScoThreshold();
585   }
586 
587   if (LmpLlMessageTraceLogFd != INVALID_FD &&
588       (current_evt_mask & kQualityEventMaskLmpMessageTrace) == 0) {
589     log::info("Closing LMP/LL log file.");
590     close(LmpLlMessageTraceLogFd);
591     LmpLlMessageTraceLogFd = INVALID_FD;
592   }
593   if (BtSchedulingTraceLogFd != INVALID_FD &&
594       (current_evt_mask & kQualityEventMaskBtSchedulingTrace) == 0) {
595     log::info("Closing Scheduling log file.");
596     close(BtSchedulingTraceLogFd);
597     BtSchedulingTraceLogFd = INVALID_FD;
598   }
599 }
600 
601 static void AddLinkQualityEventToQueue(uint8_t length,
602                                        const uint8_t* p_link_quality_event);
603 // Categorize the incoming Bluetooth Quality Report.
604 //
605 // @param length Lengths of the quality report sent from the Bluetooth
606 //   controller.
607 // @param p_bqr_event A pointer to the BQR VSE sub-event which is sent from the
608 //   Bluetooth controller.
CategorizeBqrEvent(uint8_t length,const uint8_t * p_bqr_event)609 static void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) {
610   if (length == 0) {
611     log::warn("Lengths of all of the parameters are zero.");
612     return;
613   }
614 
615   uint8_t quality_report_id = p_bqr_event[0];
616   switch (quality_report_id) {
617     case QUALITY_REPORT_ID_MONITOR_MODE:
618     case QUALITY_REPORT_ID_APPROACH_LSTO:
619     case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
620     case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
621     case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
622     case QUALITY_REPORT_ID_CONNECT_FAIL:
623       if (length < kLinkQualityParamTotalLen) {
624         log::fatal(
625             "Parameter total length: {} is abnormal. It shall be not shorter "
626             "than: {}",
627             length, kLinkQualityParamTotalLen);
628         return;
629       }
630 
631       AddLinkQualityEventToQueue(length, p_bqr_event);
632       break;
633 
634     // The Root Inflammation and Log Dump related event should be handled and
635     // intercepted already.
636     case QUALITY_REPORT_ID_VENDOR_SPECIFIC_QUALITY:
637     case QUALITY_REPORT_ID_ROOT_INFLAMMATION:
638     case QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE:
639     case QUALITY_REPORT_ID_BT_SCHEDULING_TRACE:
640     case QUALITY_REPORT_ID_CONTROLLER_DBG_INFO:
641     case QUALITY_REPORT_ID_VENDOR_SPECIFIC_TRACE:
642       log::warn("Unexpected ID: 0x{:x}", quality_report_id);
643       break;
644 
645     default:
646       log::warn("Unknown ID: 0x{:x}", quality_report_id);
647       break;
648   }
649 }
650 
651 // Record a new incoming Link Quality related BQR event in quality event queue.
652 //
653 // @param length Lengths of the Link Quality related BQR event.
654 // @param p_link_quality_event A pointer to the Link Quality related BQR event.
AddLinkQualityEventToQueue(uint8_t length,const uint8_t * p_link_quality_event)655 static void AddLinkQualityEventToQueue(uint8_t length,
656                                        const uint8_t* p_link_quality_event) {
657   std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
658   RawAddress bd_addr;
659 
660   p_bqr_event->ParseBqrLinkQualityEvt(length, p_link_quality_event);
661 
662   GetInterfaceToProfiles()->events->invoke_link_quality_report_cb(
663       bluetooth::common::time_get_os_boottime_ms(),
664       p_bqr_event->bqr_link_quality_event_.quality_report_id,
665       p_bqr_event->bqr_link_quality_event_.rssi,
666       p_bqr_event->bqr_link_quality_event_.snr,
667       p_bqr_event->bqr_link_quality_event_.retransmission_count,
668       p_bqr_event->bqr_link_quality_event_.no_rx_count,
669       p_bqr_event->bqr_link_quality_event_.nak_count);
670 
671 #ifdef __ANDROID__
672   int ret = stats_write(
673       BLUETOOTH_QUALITY_REPORT_REPORTED,
674       p_bqr_event->bqr_link_quality_event_.quality_report_id,
675       p_bqr_event->bqr_link_quality_event_.packet_types,
676       p_bqr_event->bqr_link_quality_event_.connection_handle,
677       p_bqr_event->bqr_link_quality_event_.connection_role,
678       p_bqr_event->bqr_link_quality_event_.tx_power_level,
679       p_bqr_event->bqr_link_quality_event_.rssi,
680       p_bqr_event->bqr_link_quality_event_.snr,
681       p_bqr_event->bqr_link_quality_event_.unused_afh_channel_count,
682       p_bqr_event->bqr_link_quality_event_.afh_select_unideal_channel_count,
683       p_bqr_event->bqr_link_quality_event_.lsto,
684       p_bqr_event->bqr_link_quality_event_.connection_piconet_clock,
685       p_bqr_event->bqr_link_quality_event_.retransmission_count,
686       p_bqr_event->bqr_link_quality_event_.no_rx_count,
687       p_bqr_event->bqr_link_quality_event_.nak_count,
688       p_bqr_event->bqr_link_quality_event_.last_tx_ack_timestamp,
689       p_bqr_event->bqr_link_quality_event_.flow_off_count,
690       p_bqr_event->bqr_link_quality_event_.last_flow_on_timestamp,
691       p_bqr_event->bqr_link_quality_event_.buffer_overflow_bytes,
692       p_bqr_event->bqr_link_quality_event_.buffer_underflow_bytes);
693   if (ret < 0) {
694     log::warn("failed to log BQR event to statsd, error {}", ret);
695   }
696 #else
697   // TODO(abps) Metrics for non-Android build
698 #endif
699   BluetoothQualityReportInterface* bqrItf =
700       getBluetoothQualityReportInterface();
701 
702   if (bqrItf != NULL) {
703     bd_addr = p_bqr_event->bqr_link_quality_event_.bdaddr;
704     if (bd_addr.IsEmpty()) {
705       tBTM_SEC_DEV_REC* dev = btm_find_dev_by_handle(
706           p_bqr_event->bqr_link_quality_event_.connection_handle);
707       if (dev != NULL) {
708         bd_addr = dev->RemoteAddress();
709       }
710     }
711 
712     if (!bd_addr.IsEmpty()) {
713       bqrItf->bqr_delivery_event(bd_addr, (uint8_t*)p_link_quality_event,
714                                  length);
715     } else {
716       log::warn("failed to deliver BQR, bdaddr is empty");
717     }
718   } else {
719     log::warn("failed to deliver BQR, bqrItf is NULL");
720   }
721 
722   kpBqrEventQueue.Enqueue(p_bqr_event.release());
723 }
724 
725 static int OpenLmpLlTraceLogFile();
726 
727 // Dump the LMP/LL message handshaking with the remote device to a log file.
728 //
729 // @param length Lengths of the LMP/LL message trace event.
730 // @param p_lmp_ll_message_event A pointer to the LMP/LL message trace event.
DumpLmpLlMessage(uint8_t length,const uint8_t * p_lmp_ll_message_event)731 static void DumpLmpLlMessage(uint8_t length,
732                              const uint8_t* p_lmp_ll_message_event) {
733   std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
734 
735   if (LmpLlMessageTraceLogFd == INVALID_FD ||
736       LmpLlMessageTraceCounter >= kLogDumpEventPerFile) {
737     LmpLlMessageTraceLogFd = OpenLmpLlTraceLogFile();
738   }
739   if (LmpLlMessageTraceLogFd != INVALID_FD) {
740     p_bqr_event->WriteLmpLlTraceLogFile(LmpLlMessageTraceLogFd, length,
741                                         p_lmp_ll_message_event);
742   }
743 }
744 
745 // Open the LMP/LL message trace log file.
746 //
747 // @return a file descriptor of the LMP/LL message trace log file.
OpenLmpLlTraceLogFile()748 static int OpenLmpLlTraceLogFile() {
749   if (rename(kpLmpLlMessageTraceLogPath, kpLmpLlMessageTraceLastLogPath) != 0 &&
750       errno != ENOENT) {
751     log::error("Unable to rename '{}' to '{}' : {}", kpLmpLlMessageTraceLogPath,
752                kpLmpLlMessageTraceLastLogPath, strerror(errno));
753   }
754 
755   mode_t prevmask = umask(0);
756   int logfile_fd =
757       open(kpLmpLlMessageTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
758            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
759   umask(prevmask);
760   if (logfile_fd == INVALID_FD) {
761     log::error("Unable to open '{}' : {}", kpLmpLlMessageTraceLogPath,
762                strerror(errno));
763   } else {
764     LmpLlMessageTraceCounter = 0;
765   }
766   return logfile_fd;
767 }
768 
769 static int OpenBtSchedulingTraceLogFile();
770 
771 // Dump the Bluetooth Multi-profile/Coex scheduling information to a log file.
772 //
773 // @param length Lengths of the Bluetooth Multi-profile/Coex scheduling trace
774 //   event.
775 // @param p_bt_scheduling_event A pointer to the Bluetooth Multi-profile/Coex
776 //   scheduling trace event.
DumpBtScheduling(uint8_t length,const uint8_t * p_bt_scheduling_event)777 static void DumpBtScheduling(uint8_t length,
778                              const uint8_t* p_bt_scheduling_event) {
779   std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
780 
781   if (BtSchedulingTraceLogFd == INVALID_FD ||
782       BtSchedulingTraceCounter == kLogDumpEventPerFile) {
783     BtSchedulingTraceLogFd = OpenBtSchedulingTraceLogFile();
784   }
785   if (BtSchedulingTraceLogFd != INVALID_FD) {
786     p_bqr_event->WriteBtSchedulingTraceLogFile(BtSchedulingTraceLogFd, length,
787                                                p_bt_scheduling_event);
788   }
789 }
790 
791 // Open the Bluetooth Multi-profile/Coex scheduling trace log file.
792 //
793 // @return a file descriptor of the Bluetooth Multi-profile/Coex scheduling
794 //   trace log file.
OpenBtSchedulingTraceLogFile()795 static int OpenBtSchedulingTraceLogFile() {
796   if (rename(kpBtSchedulingTraceLogPath, kpBtSchedulingTraceLastLogPath) != 0 &&
797       errno != ENOENT) {
798     log::error("Unable to rename '{}' to '{}' : {}", kpBtSchedulingTraceLogPath,
799                kpBtSchedulingTraceLastLogPath, strerror(errno));
800   }
801 
802   mode_t prevmask = umask(0);
803   int logfile_fd =
804       open(kpBtSchedulingTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
805            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
806   umask(prevmask);
807   if (logfile_fd == INVALID_FD) {
808     log::error("Unable to open '{}' : {}", kpBtSchedulingTraceLogPath,
809                strerror(errno));
810   } else {
811     BtSchedulingTraceCounter = 0;
812   }
813   return logfile_fd;
814 }
815 
DebugDump(int fd)816 void DebugDump(int fd) {
817   dprintf(fd, "\nBT Quality Report Events: \n");
818 
819   if (kpBqrEventQueue.Empty()) {
820     dprintf(fd, "Event queue is empty.\n");
821     return;
822   }
823 
824   while (!kpBqrEventQueue.Empty()) {
825     std::unique_ptr<BqrVseSubEvt> p_event(kpBqrEventQueue.Dequeue());
826 
827     bool warning = (p_event->bqr_link_quality_event_.rssi < kCriWarnRssi ||
828                     p_event->bqr_link_quality_event_.unused_afh_channel_count >
829                         kCriWarnUnusedCh);
830 
831     std::stringstream ss_timestamp;
832     ss_timestamp << std::put_time(&p_event->tm_timestamp_, "%m-%d %H:%M:%S");
833 
834     dprintf(fd, "%c  %s %s\n", warning ? '*' : ' ', ss_timestamp.str().c_str(),
835             p_event->ToString().c_str());
836   }
837 
838   dprintf(fd, "\n");
839 }
840 
btif_get_remote_version(const RawAddress & bd_addr,uint8_t & lmp_version,uint16_t & manufacturer,uint16_t & lmp_sub_version)841 static void btif_get_remote_version(const RawAddress& bd_addr,
842                                     uint8_t& lmp_version,
843                                     uint16_t& manufacturer,
844                                     uint16_t& lmp_sub_version) {
845   bt_property_t prop;
846   bt_remote_version_t info;
847   uint8_t tmp_lmp_ver = 0;
848   uint16_t tmp_manufacturer = 0;
849   uint16_t tmp_lmp_subver = 0;
850   tBTM_STATUS status;
851 
852   status = BTM_ReadRemoteVersion(bd_addr, &tmp_lmp_ver, &tmp_manufacturer,
853                                  &tmp_lmp_subver);
854   if (status == BTM_SUCCESS &&
855       (tmp_lmp_ver || tmp_manufacturer || tmp_lmp_subver)) {
856     lmp_version = tmp_lmp_ver;
857     manufacturer = tmp_manufacturer;
858     lmp_sub_version = tmp_lmp_subver;
859     return;
860   }
861 
862   prop.type = BT_PROPERTY_REMOTE_VERSION_INFO;
863   prop.len = sizeof(bt_remote_version_t);
864   prop.val = (void*)&info;
865 
866   if (btif_storage_get_remote_device_property(&bd_addr, &prop) ==
867       BT_STATUS_SUCCESS) {
868     lmp_version = (uint8_t)info.version;
869     manufacturer = (uint16_t)info.manufacturer;
870     lmp_sub_version = (uint16_t)info.sub_ver;
871   }
872 }
873 
874 class BluetoothQualityReportInterfaceImpl
875     : public bluetooth::bqr::BluetoothQualityReportInterface {
876   ~BluetoothQualityReportInterfaceImpl() override = default;
877 
init(BluetoothQualityReportCallbacks * callbacks)878   void init(BluetoothQualityReportCallbacks* callbacks) override {
879     log::info("BluetoothQualityReportInterfaceImpl");
880     this->callbacks = callbacks;
881   }
882 
bqr_delivery_event(const RawAddress & bd_addr,const uint8_t * bqr_raw_data,uint32_t bqr_raw_data_len)883   void bqr_delivery_event(const RawAddress& bd_addr,
884                           const uint8_t* bqr_raw_data,
885                           uint32_t bqr_raw_data_len) override {
886     if (bqr_raw_data == NULL) {
887       log::error("bqr data is null");
888       return;
889     }
890 
891     std::vector<uint8_t> raw_data;
892     raw_data.insert(raw_data.begin(), bqr_raw_data,
893                     bqr_raw_data + bqr_raw_data_len);
894 
895     if (vendor_cap_supported_version < kBqrVersion5_0 &&
896         bqr_raw_data_len <
897             kLinkQualityParamTotalLen + kVersion5_0ParamsTotalLen) {
898       std::vector<uint8_t>::iterator it =
899           raw_data.begin() + kLinkQualityParamTotalLen;
900       /**
901        * Insert zeros as remote address and calibration count
902        * for BQR 5.0 incompatible devices
903        */
904       raw_data.insert(it, kVersion5_0ParamsTotalLen, 0);
905     }
906 
907     uint8_t lmp_ver = 0;
908     uint16_t lmp_subver = 0;
909     uint16_t manufacturer_id = 0;
910     btif_get_remote_version(bd_addr, lmp_ver, manufacturer_id, lmp_subver);
911 
912     log::info(
913         "len: {}, addr: {}, lmp_ver: {}, manufacturer_id: {}, lmp_subver: {}",
914         bqr_raw_data_len, bd_addr, lmp_ver, manufacturer_id, lmp_subver);
915 
916     if (callbacks == nullptr) {
917       log::error("callbacks is nullptr");
918       return;
919     }
920 
921     do_in_jni_thread(base::BindOnce(
922         &bluetooth::bqr::BluetoothQualityReportCallbacks::bqr_delivery_callback,
923         base::Unretained(callbacks), bd_addr, lmp_ver, lmp_subver,
924         manufacturer_id, std::move(raw_data)));
925   }
926 
927  private:
928   BluetoothQualityReportCallbacks* callbacks = nullptr;
929 };
930 
getBluetoothQualityReportInterface()931 BluetoothQualityReportInterface* getBluetoothQualityReportInterface() {
932   if (!bluetoothQualityReportInstance) {
933     bluetoothQualityReportInstance.reset(
934         new BluetoothQualityReportInterfaceImpl());
935   }
936 
937   return bluetoothQualityReportInstance.get();
938 }
939 
vendor_specific_event_callback(hci::VendorSpecificEventView vendor_specific_event_view)940 static void vendor_specific_event_callback(
941     hci::VendorSpecificEventView vendor_specific_event_view) {
942   auto bqr = hci::BqrEventView::CreateOptional(vendor_specific_event_view);
943   if (!bqr) {
944     return;
945   }
946   auto payload = vendor_specific_event_view.GetPayload();
947   std::vector<uint8_t> bytes{payload.begin(), payload.end()};
948 
949   uint8_t quality_report_id = static_cast<uint8_t>(bqr->GetQualityReportId());
950   uint8_t bqr_parameter_length = bytes.size();
951   const uint8_t* p_bqr_event = bytes.data();
952 
953   // The stream currently points to the BQR sub-event parameters
954   switch (quality_report_id) {
955     case bluetooth::bqr::QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE: {
956       auto lmp_view = hci::BqrLogDumpEventView::Create(*bqr);
957     }
958       if (bqr_parameter_length >= bluetooth::bqr::kLogDumpParamTotalLen) {
959         bluetooth::bqr::DumpLmpLlMessage(bqr_parameter_length, p_bqr_event);
960       } else {
961         log::info("Malformed LMP event of length {}", bqr_parameter_length);
962       }
963 
964       break;
965 
966     case bluetooth::bqr::QUALITY_REPORT_ID_BT_SCHEDULING_TRACE:
967       if (bqr_parameter_length >= bluetooth::bqr::kLogDumpParamTotalLen) {
968         bluetooth::bqr::DumpBtScheduling(bqr_parameter_length, p_bqr_event);
969       } else {
970         log::info("Malformed TRACE event of length {}", bqr_parameter_length);
971       }
972       break;
973 
974     default:
975       log::info("Unhandled BQR subevent 0x{:02x}", quality_report_id);
976   }
977 
978   CategorizeBqrEvent(bytes.size(), bytes.data());
979 }
980 
register_vse()981 void register_vse() {
982   bluetooth::shim::GetHciLayer()->RegisterVendorSpecificEventHandler(
983       hci::VseSubeventCode::BQR_EVENT,
984       to_bind_->Bind(vendor_specific_event_callback));
985 }
986 
unregister_vse()987 void unregister_vse() {
988   bluetooth::shim::GetHciLayer()->UnregisterVendorSpecificEventHandler(
989       hci::VseSubeventCode::BQR_EVENT);
990 }
991 
992 namespace testing {
set_lmp_trace_log_fd(int fd)993 void set_lmp_trace_log_fd(int fd) { LmpLlMessageTraceLogFd = fd; }
994 }  // namespace testing
995 
996 }  // namespace bqr
997 }  // namespace bluetooth
998