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