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 __ANDROID__
21 #include <statslog_bt.h>
22 #endif
23 #include <stdio.h>
24 #include <sys/stat.h>
25
26 #include "btif/include/stack_manager.h"
27 #include "btif_bqr.h"
28 #include "btif_common.h"
29 #include "btif_storage.h"
30 #include "btm_api.h"
31 #include "btm_ble_api.h"
32 #include "common/leaky_bonded_queue.h"
33 #include "common/time_util.h"
34 #include "core_callbacks.h"
35 #include "osi/include/properties.h"
36 #include "raw_address.h"
37 #include "stack/btm/btm_dev.h"
38
39 namespace bluetooth {
40 namespace bqr {
41
42 using bluetooth::common::LeakyBondedQueue;
43 using std::chrono::system_clock;
44
45 // The instance of BQR event queue
46 static std::unique_ptr<LeakyBondedQueue<BqrVseSubEvt>> kpBqrEventQueue(
47 new LeakyBondedQueue<BqrVseSubEvt>(kBqrEventQueueSize));
48
49 static uint16_t vendor_cap_supported_version;
50
51 class BluetoothQualityReportInterfaceImpl;
52 std::unique_ptr<BluetoothQualityReportInterface> bluetoothQualityReportInstance;
53
ParseBqrLinkQualityEvt(uint8_t length,const uint8_t * p_param_buf)54 void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length,
55 const uint8_t* p_param_buf) {
56 if (length < kLinkQualityParamTotalLen) {
57 LOG(FATAL) << __func__
58 << ": Parameter total length: " << std::to_string(length)
59 << " is abnormal. It shall be not shorter than: "
60 << std::to_string(kLinkQualityParamTotalLen);
61 return;
62 }
63
64 STREAM_TO_UINT8(bqr_link_quality_event_.quality_report_id, p_param_buf);
65 STREAM_TO_UINT8(bqr_link_quality_event_.packet_types, p_param_buf);
66 STREAM_TO_UINT16(bqr_link_quality_event_.connection_handle, p_param_buf);
67 STREAM_TO_UINT8(bqr_link_quality_event_.connection_role, p_param_buf);
68 STREAM_TO_INT8(bqr_link_quality_event_.tx_power_level, p_param_buf);
69 STREAM_TO_INT8(bqr_link_quality_event_.rssi, p_param_buf);
70 STREAM_TO_UINT8(bqr_link_quality_event_.snr, p_param_buf);
71 STREAM_TO_UINT8(bqr_link_quality_event_.unused_afh_channel_count,
72 p_param_buf);
73 STREAM_TO_UINT8(bqr_link_quality_event_.afh_select_unideal_channel_count,
74 p_param_buf);
75 STREAM_TO_UINT16(bqr_link_quality_event_.lsto, p_param_buf);
76 STREAM_TO_UINT32(bqr_link_quality_event_.connection_piconet_clock,
77 p_param_buf);
78 STREAM_TO_UINT32(bqr_link_quality_event_.retransmission_count, p_param_buf);
79 STREAM_TO_UINT32(bqr_link_quality_event_.no_rx_count, p_param_buf);
80 STREAM_TO_UINT32(bqr_link_quality_event_.nak_count, p_param_buf);
81 STREAM_TO_UINT32(bqr_link_quality_event_.last_tx_ack_timestamp, p_param_buf);
82 STREAM_TO_UINT32(bqr_link_quality_event_.flow_off_count, p_param_buf);
83 STREAM_TO_UINT32(bqr_link_quality_event_.last_flow_on_timestamp, p_param_buf);
84 STREAM_TO_UINT32(bqr_link_quality_event_.buffer_overflow_bytes, p_param_buf);
85 STREAM_TO_UINT32(bqr_link_quality_event_.buffer_underflow_bytes, p_param_buf);
86 STREAM_TO_BDADDR(bqr_link_quality_event_.bdaddr, p_param_buf);
87 STREAM_TO_UINT8(bqr_link_quality_event_.cal_failed_item_count, p_param_buf);
88
89 if (vendor_cap_supported_version >= kBqrIsoVersion) {
90 if (length < kLinkQualityParamTotalLen + kISOLinkQualityParamTotalLen) {
91 LOG(WARNING) << __func__
92 << ": Parameter total length: " << std::to_string(length)
93 << " is abnormal. "
94 << "vendor_cap_supported_version: "
95 << vendor_cap_supported_version << " "
96 << " (>= "
97 << "kBqrIsoVersion=" << kBqrIsoVersion << "), "
98 << "It should not be shorter than: "
99 << std::to_string(kLinkQualityParamTotalLen +
100 kISOLinkQualityParamTotalLen);
101 } else {
102 STREAM_TO_UINT32(bqr_link_quality_event_.tx_total_packets, p_param_buf);
103 STREAM_TO_UINT32(bqr_link_quality_event_.tx_unacked_packets, p_param_buf);
104 STREAM_TO_UINT32(bqr_link_quality_event_.tx_flushed_packets, p_param_buf);
105 STREAM_TO_UINT32(bqr_link_quality_event_.tx_last_subevent_packets,
106 p_param_buf);
107 STREAM_TO_UINT32(bqr_link_quality_event_.crc_error_packets, p_param_buf);
108 STREAM_TO_UINT32(bqr_link_quality_event_.rx_duplicate_packets,
109 p_param_buf);
110 }
111 }
112
113 const auto now = system_clock::to_time_t(system_clock::now());
114 localtime_r(&now, &tm_timestamp_);
115 }
116
WriteLmpLlTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)117 void BqrVseSubEvt::WriteLmpLlTraceLogFile(int fd, uint8_t length,
118 const uint8_t* p_param_buf) {
119 const auto now = system_clock::to_time_t(system_clock::now());
120 localtime_r(&now, &tm_timestamp_);
121
122 STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
123 STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
124 length -= kLogDumpParamTotalLen;
125 bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
126
127 std::stringstream ss_log;
128 ss_log << "\n"
129 << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
130 << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
131 << " VSP: ";
132
133 TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
134 TEMP_FAILURE_RETRY(
135 write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
136 LmpLlMessageTraceCounter++;
137 }
138
WriteBtSchedulingTraceLogFile(int fd,uint8_t length,const uint8_t * p_param_buf)139 void BqrVseSubEvt::WriteBtSchedulingTraceLogFile(int fd, uint8_t length,
140 const uint8_t* p_param_buf) {
141 const auto now = system_clock::to_time_t(system_clock::now());
142 localtime_r(&now, &tm_timestamp_);
143
144 STREAM_TO_UINT8(bqr_log_dump_event_.quality_report_id, p_param_buf);
145 STREAM_TO_UINT16(bqr_log_dump_event_.connection_handle, p_param_buf);
146 length -= kLogDumpParamTotalLen;
147 bqr_log_dump_event_.vendor_specific_parameter = p_param_buf;
148
149 std::stringstream ss_log;
150 ss_log << "\n"
151 << std::put_time(&tm_timestamp_, "%m-%d %H:%M:%S ")
152 << "Handle: " << loghex(bqr_log_dump_event_.connection_handle)
153 << " VSP: ";
154
155 TEMP_FAILURE_RETRY(write(fd, ss_log.str().c_str(), ss_log.str().size()));
156 TEMP_FAILURE_RETRY(
157 write(fd, bqr_log_dump_event_.vendor_specific_parameter, length));
158 BtSchedulingTraceCounter++;
159 }
160
ToString() const161 std::string BqrVseSubEvt::ToString() const {
162 std::stringstream ss;
163 ss << QualityReportIdToString(bqr_link_quality_event_.quality_report_id)
164 << ", Handle: " << loghex(bqr_link_quality_event_.connection_handle)
165 << ", " << PacketTypeToString(bqr_link_quality_event_.packet_types) << ", "
166 << ((bqr_link_quality_event_.connection_role == 0) ? "Central"
167 : "Peripheral ")
168 << ", PwLv: " << std::to_string(bqr_link_quality_event_.tx_power_level)
169 << ", RSSI: " << std::to_string(bqr_link_quality_event_.rssi)
170 << ", SNR: " << std::to_string(bqr_link_quality_event_.snr)
171 << ", UnusedCh: "
172 << std::to_string(bqr_link_quality_event_.unused_afh_channel_count)
173 << ", UnidealCh: "
174 << std::to_string(bqr_link_quality_event_.afh_select_unideal_channel_count)
175 << ", ReTx: "
176 << std::to_string(bqr_link_quality_event_.retransmission_count)
177 << ", NoRX: " << std::to_string(bqr_link_quality_event_.no_rx_count)
178 << ", NAK: " << std::to_string(bqr_link_quality_event_.nak_count)
179 << ", FlowOff: " << std::to_string(bqr_link_quality_event_.flow_off_count)
180 << ", OverFlow: "
181 << std::to_string(bqr_link_quality_event_.buffer_overflow_bytes)
182 << ", UndFlow: "
183 << std::to_string(bqr_link_quality_event_.buffer_underflow_bytes)
184 << ", RemoteDevAddr: "
185 << bqr_link_quality_event_.bdaddr.ToColonSepHexString()
186 << ", CalFailedItems: "
187 << std::to_string(bqr_link_quality_event_.cal_failed_item_count);
188
189 if (vendor_cap_supported_version >= kBqrIsoVersion) {
190 ss << ", TxTotal: "
191 << std::to_string(bqr_link_quality_event_.tx_total_packets)
192 << ", TxUnAcked: "
193 << std::to_string(bqr_link_quality_event_.tx_unacked_packets)
194 << ", TxFlushed: "
195 << std::to_string(bqr_link_quality_event_.tx_flushed_packets)
196 << ", TxLastSubEvent: "
197 << std::to_string(bqr_link_quality_event_.tx_last_subevent_packets)
198 << ", CRCError: "
199 << std::to_string(bqr_link_quality_event_.crc_error_packets)
200 << ", RxDuplicate: "
201 << std::to_string(bqr_link_quality_event_.rx_duplicate_packets);
202 }
203
204 return ss.str();
205 }
206
QualityReportIdToString(uint8_t quality_report_id)207 std::string QualityReportIdToString(uint8_t quality_report_id) {
208 switch (quality_report_id) {
209 case QUALITY_REPORT_ID_MONITOR_MODE:
210 return "Monitoring";
211 case QUALITY_REPORT_ID_APPROACH_LSTO:
212 return "Approach LSTO";
213 case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
214 return "A2DP Choppy";
215 case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
216 return "SCO Choppy";
217 case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
218 return "LE Audio Choppy";
219 case QUALITY_REPORT_ID_CONNECT_FAIL:
220 return "Connect Fail";
221 default:
222 return "Invalid";
223 }
224 }
225
PacketTypeToString(uint8_t packet_type)226 std::string PacketTypeToString(uint8_t packet_type) {
227 switch (packet_type) {
228 case PACKET_TYPE_ID:
229 return "ID";
230 case PACKET_TYPE_NULL:
231 return "NULL";
232 case PACKET_TYPE_POLL:
233 return "POLL";
234 case PACKET_TYPE_FHS:
235 return "FHS";
236 case PACKET_TYPE_HV1:
237 return "HV1";
238 case PACKET_TYPE_HV2:
239 return "HV2";
240 case PACKET_TYPE_HV3:
241 return "HV3";
242 case PACKET_TYPE_DV:
243 return "DV";
244 case PACKET_TYPE_EV3:
245 return "EV3";
246 case PACKET_TYPE_EV4:
247 return "EV4";
248 case PACKET_TYPE_EV5:
249 return "EV5";
250 case PACKET_TYPE_2EV3:
251 return "2EV3";
252 case PACKET_TYPE_2EV5:
253 return "2EV5";
254 case PACKET_TYPE_3EV3:
255 return "3EV3";
256 case PACKET_TYPE_3EV5:
257 return "3EV5";
258 case PACKET_TYPE_DM1:
259 return "DM1";
260 case PACKET_TYPE_DH1:
261 return "DH1";
262 case PACKET_TYPE_DM3:
263 return "DM3";
264 case PACKET_TYPE_DH3:
265 return "DH3";
266 case PACKET_TYPE_DM5:
267 return "DM5";
268 case PACKET_TYPE_DH5:
269 return "DH5";
270 case PACKET_TYPE_AUX1:
271 return "AUX1";
272 case PACKET_TYPE_2DH1:
273 return "2DH1";
274 case PACKET_TYPE_2DH3:
275 return "2DH3";
276 case PACKET_TYPE_2DH5:
277 return "2DH5";
278 case PACKET_TYPE_3DH1:
279 return "3DH1";
280 case PACKET_TYPE_3DH3:
281 return "3DH3";
282 case PACKET_TYPE_3DH5:
283 return "3DH5";
284 case PACKET_TYPE_ISO:
285 return "ISO";
286 default:
287 return "UnKnown ";
288 }
289 }
290
EnableBtQualityReport(bool is_enable)291 void EnableBtQualityReport(bool is_enable) {
292 LOG(INFO) << __func__ << ": is_enable: " << logbool(is_enable);
293
294 char bqr_prop_evtmask[PROPERTY_VALUE_MAX] = {0};
295 char bqr_prop_interval_ms[PROPERTY_VALUE_MAX] = {0};
296 char bqr_prop_vnd_quality_mask[PROPERTY_VALUE_MAX] = {0};
297 char bqr_prop_vnd_trace_mask[PROPERTY_VALUE_MAX] = {0};
298 osi_property_get(kpPropertyEventMask, bqr_prop_evtmask, "");
299 osi_property_get(kpPropertyMinReportIntervalMs, bqr_prop_interval_ms, "");
300 osi_property_get(kpPropertyVndQualityMask, bqr_prop_vnd_quality_mask, "");
301 osi_property_get(kpPropertyVndTraceMask, bqr_prop_vnd_trace_mask, "");
302
303 if (strlen(bqr_prop_evtmask) == 0 || strlen(bqr_prop_interval_ms) == 0) {
304 LOG(WARNING) << __func__ << ": Bluetooth Quality Report is disabled."
305 << " bqr_prop_evtmask: " << bqr_prop_evtmask
306 << ", bqr_prop_interval_ms: " << bqr_prop_interval_ms;
307 return;
308 }
309
310 BqrConfiguration bqr_config = {};
311
312 if (is_enable) {
313 bqr_config.report_action = REPORT_ACTION_ADD;
314 bqr_config.quality_event_mask =
315 static_cast<uint32_t>(atoi(bqr_prop_evtmask));
316 bqr_config.minimum_report_interval_ms =
317 static_cast<uint16_t>(atoi(bqr_prop_interval_ms));
318 bqr_config.vnd_quality_mask =
319 static_cast<uint32_t>(atoi(bqr_prop_vnd_quality_mask));
320 bqr_config.vnd_trace_mask =
321 static_cast<uint32_t>(atoi(bqr_prop_vnd_trace_mask));
322 } else {
323 bqr_config.report_action = REPORT_ACTION_CLEAR;
324 bqr_config.quality_event_mask = kQualityEventMaskAllOff;
325 bqr_config.minimum_report_interval_ms = kMinReportIntervalNoLimit;
326 bqr_config.vnd_quality_mask = 0;
327 bqr_config.vnd_trace_mask = 0;
328 }
329
330 tBTM_BLE_VSC_CB cmn_vsc_cb;
331 BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
332 vendor_cap_supported_version = cmn_vsc_cb.version_supported;
333
334 LOG(INFO) << __func__
335 << ": Event Mask: " << loghex(bqr_config.quality_event_mask)
336 << ", Interval: " << bqr_config.minimum_report_interval_ms
337 << ", vendor_cap_supported_version: "
338 << vendor_cap_supported_version;
339 ConfigureBqr(bqr_config);
340 }
341
ConfigureBqr(const BqrConfiguration & bqr_config)342 void ConfigureBqr(const BqrConfiguration& bqr_config) {
343 if (bqr_config.report_action > REPORT_ACTION_CLEAR ||
344 bqr_config.quality_event_mask > kQualityEventMaskAll ||
345 bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) {
346 LOG(FATAL) << __func__ << ": Invalid Parameter"
347 << ", Action: " << bqr_config.report_action
348 << ", Mask: " << loghex(bqr_config.quality_event_mask)
349 << ", Interval: " << bqr_config.minimum_report_interval_ms;
350 return;
351 }
352
353 LOG(INFO) << __func__ << ": Action: "
354 << loghex(static_cast<uint8_t>(bqr_config.report_action))
355 << ", Mask: " << loghex(bqr_config.quality_event_mask)
356 << ", Interval: " << bqr_config.minimum_report_interval_ms;
357
358 uint8_t param[sizeof(BqrConfiguration)];
359 uint8_t* p_param = param;
360 UINT8_TO_STREAM(p_param, bqr_config.report_action);
361 UINT32_TO_STREAM(p_param, bqr_config.quality_event_mask);
362 UINT16_TO_STREAM(p_param, bqr_config.minimum_report_interval_ms);
363 if (vendor_cap_supported_version >= kBqrVndLogVersion) {
364 UINT32_TO_STREAM(p_param, bqr_config.vnd_quality_mask);
365 UINT32_TO_STREAM(p_param, bqr_config.vnd_trace_mask);
366 }
367
368 BTM_VendorSpecificCommand(HCI_CONTROLLER_BQR, p_param - param, param,
369 BqrVscCompleteCallback);
370 }
371
BqrVscCompleteCallback(tBTM_VSC_CMPL * p_vsc_cmpl_params)372 void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) {
373 if (p_vsc_cmpl_params->param_len < 1) {
374 LOG(ERROR) << __func__
375 << ": The length of returned parameters is less than 1";
376 return;
377 }
378
379 uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
380 uint8_t status = 0xff;
381 uint8_t command_complete_param_len = 5;
382 uint32_t current_vnd_quality_mask = 0;
383 uint32_t current_vnd_trace_mask = 0;
384 // [Return Parameter] | [Size] | [Purpose]
385 // Status | 1 octet | Command complete status
386 // Current_Quality_Event_Mask | 4 octets | Indicates current bit mask setting
387 // Vendor_Specific_Quality_Mask | 4 octets | vendor quality bit mask setting
388 // Vendor_Specific_Trace_Mask | 4 octets | vendor trace bit mask setting
389 STREAM_TO_UINT8(status, p_event_param_buf);
390 if (status != HCI_SUCCESS) {
391 LOG(ERROR) << __func__
392 << ": Fail to configure BQR. status: " << loghex(status);
393 return;
394 }
395
396 if (vendor_cap_supported_version >= kBqrVndLogVersion) {
397 command_complete_param_len = 13;
398 }
399
400 if (p_vsc_cmpl_params->param_len != command_complete_param_len) {
401 LOG(FATAL) << __func__
402 << ": The length of returned parameters is incorrect: "
403 << std::to_string(p_vsc_cmpl_params->param_len);
404 return;
405 }
406
407 uint32_t current_quality_event_mask = kQualityEventMaskAllOff;
408 STREAM_TO_UINT32(current_quality_event_mask, p_event_param_buf);
409
410 if (vendor_cap_supported_version >= kBqrVndLogVersion) {
411 STREAM_TO_UINT32(current_vnd_quality_mask, p_event_param_buf);
412 STREAM_TO_UINT32(current_vnd_trace_mask, p_event_param_buf);
413 }
414
415 LOG(INFO) << __func__
416 << ", current event mask: " << loghex(current_quality_event_mask)
417 << ", vendor quality: " << loghex(current_vnd_quality_mask)
418 << ", vendor trace: " << loghex(current_vnd_trace_mask);
419
420 ConfigureBqrCmpl(current_quality_event_mask);
421 }
422
ConfigBqrA2dpScoThreshold()423 void ConfigBqrA2dpScoThreshold() {
424 uint8_t param[20] = {0};
425 uint8_t sub_opcode = 0x16;
426 uint8_t* p_param = param;
427 uint16_t a2dp_choppy_threshold = 0;
428 uint16_t sco_choppy_threshold = 0;
429
430 char bqr_prop_threshold[PROPERTY_VALUE_MAX] = {0};
431 osi_property_get(kpPropertyChoppyThreshold, bqr_prop_threshold, "");
432
433 sscanf(bqr_prop_threshold, "%hu,%hu", &a2dp_choppy_threshold,
434 &sco_choppy_threshold);
435
436 LOG_WARN("a2dp_choppy_threshold: %d, sco_choppy_threshold: %d",
437 a2dp_choppy_threshold, sco_choppy_threshold);
438
439 UINT8_TO_STREAM(p_param, sub_opcode);
440
441 // A2dp glitch ID
442 UINT8_TO_STREAM(p_param, QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY);
443 // A2dp glitch config data length
444 UINT8_TO_STREAM(p_param, 2);
445 // A2dp glitch threshold
446 UINT16_TO_STREAM(p_param,
447 a2dp_choppy_threshold == 0 ? 1 : a2dp_choppy_threshold);
448
449 // Sco glitch ID
450 UINT8_TO_STREAM(p_param, QUALITY_REPORT_ID_SCO_VOICE_CHOPPY);
451 // Sco glitch config data length
452 UINT8_TO_STREAM(p_param, 2);
453 // Sco glitch threshold
454 UINT16_TO_STREAM(p_param,
455 sco_choppy_threshold == 0 ? 1 : sco_choppy_threshold);
456
457 BTM_VendorSpecificCommand(HCI_VS_HOST_LOG_OPCODE, p_param - param, param,
458 NULL);
459 }
460
ConfigureBqrCmpl(uint32_t current_evt_mask)461 void ConfigureBqrCmpl(uint32_t current_evt_mask) {
462 LOG(INFO) << __func__ << ": current_evt_mask: " << loghex(current_evt_mask);
463 // (Un)Register for VSE of Bluetooth Quality Report sub event
464 tBTM_STATUS btm_status = BTM_BT_Quality_Report_VSE_Register(
465 current_evt_mask > kQualityEventMaskAllOff, CategorizeBqrEvent);
466
467 bool isBqrEnabled =
468 bluetooth::common::InitFlags::IsBluetoothQualityReportCallbackEnabled();
469 if (isBqrEnabled && current_evt_mask > kQualityEventMaskAllOff) {
470 ConfigBqrA2dpScoThreshold();
471 }
472
473 if (btm_status != BTM_SUCCESS) {
474 LOG(ERROR) << __func__ << ": Fail to (un)register VSE of BQR sub event."
475 << " status: " << btm_status;
476 return;
477 }
478
479 if (LmpLlMessageTraceLogFd != INVALID_FD &&
480 (current_evt_mask & kQualityEventMaskLmpMessageTrace) == 0) {
481 LOG(INFO) << __func__ << ": Closing LMP/LL log file.";
482 close(LmpLlMessageTraceLogFd);
483 LmpLlMessageTraceLogFd = INVALID_FD;
484 }
485 if (BtSchedulingTraceLogFd != INVALID_FD &&
486 (current_evt_mask & kQualityEventMaskBtSchedulingTrace) == 0) {
487 LOG(INFO) << __func__ << ": Closing Scheduling log file.";
488 close(BtSchedulingTraceLogFd);
489 BtSchedulingTraceLogFd = INVALID_FD;
490 }
491 }
492
CategorizeBqrEvent(uint8_t length,const uint8_t * p_bqr_event)493 void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) {
494 if (length == 0) {
495 LOG(WARNING) << __func__ << ": Lengths of all of the parameters are zero.";
496 return;
497 }
498
499 uint8_t quality_report_id = p_bqr_event[0];
500 switch (quality_report_id) {
501 case QUALITY_REPORT_ID_MONITOR_MODE:
502 case QUALITY_REPORT_ID_APPROACH_LSTO:
503 case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
504 case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
505 case QUALITY_REPORT_ID_LE_AUDIO_CHOPPY:
506 case QUALITY_REPORT_ID_CONNECT_FAIL:
507 if (length < kLinkQualityParamTotalLen) {
508 LOG(FATAL) << __func__
509 << ": Parameter total length: " << std::to_string(length)
510 << " is abnormal. It shall be not shorter than: "
511 << std::to_string(kLinkQualityParamTotalLen);
512 return;
513 }
514
515 AddLinkQualityEventToQueue(length, p_bqr_event);
516 break;
517
518 // The Root Inflammation and Log Dump related event should be handled and
519 // intercepted already.
520 case QUALITY_REPORT_ID_VENDOR_SPECIFIC_QUALITY:
521 case QUALITY_REPORT_ID_ROOT_INFLAMMATION:
522 case QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE:
523 case QUALITY_REPORT_ID_BT_SCHEDULING_TRACE:
524 case QUALITY_REPORT_ID_CONTROLLER_DBG_INFO:
525 case QUALITY_REPORT_ID_VENDOR_SPECIFIC_TRACE:
526 LOG(WARNING) << __func__
527 << ": Unexpected ID: " << loghex(quality_report_id);
528 break;
529
530 default:
531 LOG(WARNING) << __func__ << ": Unknown ID: " << loghex(quality_report_id);
532 break;
533 }
534 }
535
AddLinkQualityEventToQueue(uint8_t length,const uint8_t * p_link_quality_event)536 void AddLinkQualityEventToQueue(uint8_t length,
537 const uint8_t* p_link_quality_event) {
538 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
539 RawAddress bd_addr;
540
541 p_bqr_event->ParseBqrLinkQualityEvt(length, p_link_quality_event);
542
543 LOG(WARNING) << *p_bqr_event;
544 GetInterfaceToProfiles()->events->invoke_link_quality_report_cb(
545 bluetooth::common::time_get_os_boottime_ms(),
546 p_bqr_event->bqr_link_quality_event_.quality_report_id,
547 p_bqr_event->bqr_link_quality_event_.rssi,
548 p_bqr_event->bqr_link_quality_event_.snr,
549 p_bqr_event->bqr_link_quality_event_.retransmission_count,
550 p_bqr_event->bqr_link_quality_event_.no_rx_count,
551 p_bqr_event->bqr_link_quality_event_.nak_count);
552
553 #ifdef __ANDROID__
554 int ret = stats_write(
555 BLUETOOTH_QUALITY_REPORT_REPORTED,
556 p_bqr_event->bqr_link_quality_event_.quality_report_id,
557 p_bqr_event->bqr_link_quality_event_.packet_types,
558 p_bqr_event->bqr_link_quality_event_.connection_handle,
559 p_bqr_event->bqr_link_quality_event_.connection_role,
560 p_bqr_event->bqr_link_quality_event_.tx_power_level,
561 p_bqr_event->bqr_link_quality_event_.rssi,
562 p_bqr_event->bqr_link_quality_event_.snr,
563 p_bqr_event->bqr_link_quality_event_.unused_afh_channel_count,
564 p_bqr_event->bqr_link_quality_event_.afh_select_unideal_channel_count,
565 p_bqr_event->bqr_link_quality_event_.lsto,
566 p_bqr_event->bqr_link_quality_event_.connection_piconet_clock,
567 p_bqr_event->bqr_link_quality_event_.retransmission_count,
568 p_bqr_event->bqr_link_quality_event_.no_rx_count,
569 p_bqr_event->bqr_link_quality_event_.nak_count,
570 p_bqr_event->bqr_link_quality_event_.last_tx_ack_timestamp,
571 p_bqr_event->bqr_link_quality_event_.flow_off_count,
572 p_bqr_event->bqr_link_quality_event_.last_flow_on_timestamp,
573 p_bqr_event->bqr_link_quality_event_.buffer_overflow_bytes,
574 p_bqr_event->bqr_link_quality_event_.buffer_underflow_bytes);
575 if (ret < 0) {
576 LOG(WARNING) << __func__ << ": failed to log BQR event to statsd, error "
577 << ret;
578 }
579 #else
580 // TODO(abps) Metrics for non-Android build
581 #endif
582 bool isBqrEnabled =
583 bluetooth::common::InitFlags::IsBluetoothQualityReportCallbackEnabled();
584 if (isBqrEnabled) {
585 BluetoothQualityReportInterface* bqrItf =
586 getBluetoothQualityReportInterface();
587
588 if (bqrItf != NULL) {
589 bd_addr = p_bqr_event->bqr_link_quality_event_.bdaddr;
590
591 if (!bd_addr.IsEmpty()) {
592 bqrItf->bqr_delivery_event(bd_addr, (uint8_t*)p_link_quality_event,
593 length);
594 } else {
595 LOG(WARNING) << __func__ << ": failed to deliver BQR, "
596 << "bdaddr is empty, no address in packet";
597 }
598 } else {
599 LOG(WARNING) << __func__ << ": failed to deliver BQR, bqrItf is NULL";
600 }
601 }
602
603 kpBqrEventQueue->Enqueue(p_bqr_event.release());
604 }
605
DumpLmpLlMessage(uint8_t length,const uint8_t * p_lmp_ll_message_event)606 void DumpLmpLlMessage(uint8_t length, const uint8_t* p_lmp_ll_message_event) {
607 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
608
609 if (LmpLlMessageTraceLogFd == INVALID_FD ||
610 LmpLlMessageTraceCounter >= kLogDumpEventPerFile) {
611 LmpLlMessageTraceLogFd = OpenLmpLlTraceLogFile();
612 }
613 if (LmpLlMessageTraceLogFd != INVALID_FD) {
614 p_bqr_event->WriteLmpLlTraceLogFile(LmpLlMessageTraceLogFd, length,
615 p_lmp_ll_message_event);
616 }
617 }
618
OpenLmpLlTraceLogFile()619 int OpenLmpLlTraceLogFile() {
620 if (rename(kpLmpLlMessageTraceLogPath, kpLmpLlMessageTraceLastLogPath) != 0 &&
621 errno != ENOENT) {
622 LOG(ERROR) << __func__ << ": Unable to rename '"
623 << kpLmpLlMessageTraceLogPath << "' to '"
624 << kpLmpLlMessageTraceLastLogPath << "' : " << strerror(errno);
625 }
626
627 mode_t prevmask = umask(0);
628 int logfile_fd =
629 open(kpLmpLlMessageTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
630 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
631 umask(prevmask);
632 if (logfile_fd == INVALID_FD) {
633 LOG(ERROR) << __func__ << ": Unable to open '" << kpLmpLlMessageTraceLogPath
634 << "' : " << strerror(errno);
635 } else {
636 LmpLlMessageTraceCounter = 0;
637 }
638 return logfile_fd;
639 }
640
DumpBtScheduling(uint8_t length,const uint8_t * p_bt_scheduling_event)641 void DumpBtScheduling(uint8_t length, const uint8_t* p_bt_scheduling_event) {
642 std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
643
644 if (BtSchedulingTraceLogFd == INVALID_FD ||
645 BtSchedulingTraceCounter == kLogDumpEventPerFile) {
646 BtSchedulingTraceLogFd = OpenBtSchedulingTraceLogFile();
647 }
648 if (BtSchedulingTraceLogFd != INVALID_FD) {
649 p_bqr_event->WriteBtSchedulingTraceLogFile(BtSchedulingTraceLogFd, length,
650 p_bt_scheduling_event);
651 }
652 }
653
OpenBtSchedulingTraceLogFile()654 int OpenBtSchedulingTraceLogFile() {
655 if (rename(kpBtSchedulingTraceLogPath, kpBtSchedulingTraceLastLogPath) != 0 &&
656 errno != ENOENT) {
657 LOG(ERROR) << __func__ << ": Unable to rename '"
658 << kpBtSchedulingTraceLogPath << "' to '"
659 << kpBtSchedulingTraceLastLogPath << "' : " << strerror(errno);
660 }
661
662 mode_t prevmask = umask(0);
663 int logfile_fd =
664 open(kpBtSchedulingTraceLogPath, O_WRONLY | O_CREAT | O_TRUNC,
665 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
666 umask(prevmask);
667 if (logfile_fd == INVALID_FD) {
668 LOG(ERROR) << __func__ << ": Unable to open '" << kpBtSchedulingTraceLogPath
669 << "' : " << strerror(errno);
670 } else {
671 BtSchedulingTraceCounter = 0;
672 }
673 return logfile_fd;
674 }
675
DebugDump(int fd)676 void DebugDump(int fd) {
677 dprintf(fd, "\nBT Quality Report Events: \n");
678
679 if (kpBqrEventQueue->Empty()) {
680 dprintf(fd, "Event queue is empty.\n");
681 return;
682 }
683
684 while (!kpBqrEventQueue->Empty()) {
685 std::unique_ptr<BqrVseSubEvt> p_event(kpBqrEventQueue->Dequeue());
686
687 bool warning = (p_event->bqr_link_quality_event_.rssi < kCriWarnRssi ||
688 p_event->bqr_link_quality_event_.unused_afh_channel_count >
689 kCriWarnUnusedCh);
690
691 std::stringstream ss_timestamp;
692 ss_timestamp << std::put_time(&p_event->tm_timestamp_, "%m-%d %H:%M:%S");
693
694 dprintf(fd, "%c %s %s\n", warning ? '*' : ' ', ss_timestamp.str().c_str(),
695 p_event->ToString().c_str());
696 }
697
698 dprintf(fd, "\n");
699 }
700
btif_get_remote_version(const RawAddress & bd_addr,uint8_t & lmp_version,uint16_t & manufacturer,uint16_t & lmp_sub_version)701 static void btif_get_remote_version(const RawAddress& bd_addr,
702 uint8_t& lmp_version,
703 uint16_t& manufacturer,
704 uint16_t& lmp_sub_version) {
705 bt_property_t prop;
706 bt_remote_version_t info;
707 uint8_t tmp_lmp_ver = 0;
708 uint16_t tmp_manufacturer = 0;
709 uint16_t tmp_lmp_subver = 0;
710 tBTM_STATUS status;
711
712 status = BTM_ReadRemoteVersion(bd_addr, &tmp_lmp_ver, &tmp_manufacturer,
713 &tmp_lmp_subver);
714 if (status == BTM_SUCCESS &&
715 (tmp_lmp_ver || tmp_manufacturer || tmp_lmp_subver)) {
716 lmp_version = tmp_lmp_ver;
717 manufacturer = tmp_manufacturer;
718 lmp_sub_version = tmp_lmp_subver;
719 return;
720 }
721
722 prop.type = BT_PROPERTY_REMOTE_VERSION_INFO;
723 prop.len = sizeof(bt_remote_version_t);
724 prop.val = (void*)&info;
725
726 if (btif_storage_get_remote_device_property(&bd_addr, &prop) ==
727 BT_STATUS_SUCCESS) {
728 lmp_version = (uint8_t)info.version;
729 manufacturer = (uint16_t)info.manufacturer;
730 lmp_sub_version = (uint16_t)info.sub_ver;
731 }
732 }
733
734 class BluetoothQualityReportInterfaceImpl
735 : public bluetooth::bqr::BluetoothQualityReportInterface {
736 ~BluetoothQualityReportInterfaceImpl() override = default;
737
init(BluetoothQualityReportCallbacks * callbacks)738 void init(BluetoothQualityReportCallbacks* callbacks) override {
739 LOG_INFO("BluetoothQualityReportInterfaceImpl ");
740 this->callbacks = callbacks;
741 }
742
bqr_delivery_event(const RawAddress & bd_addr,const uint8_t * bqr_raw_data,uint32_t bqr_raw_data_len)743 void bqr_delivery_event(const RawAddress& bd_addr,
744 const uint8_t* bqr_raw_data,
745 uint32_t bqr_raw_data_len) override {
746 if (bqr_raw_data == NULL) {
747 LOG_ERROR("bqr data is null");
748 return;
749 }
750
751 std::vector<uint8_t> raw_data;
752 raw_data.insert(raw_data.begin(), bqr_raw_data,
753 bqr_raw_data + bqr_raw_data_len);
754
755 uint8_t lmp_ver = 0;
756 uint16_t lmp_subver = 0;
757 uint16_t manufacturer_id = 0;
758 btif_get_remote_version(bd_addr, lmp_ver, manufacturer_id, lmp_subver);
759
760 LOG_INFO(
761 "len: %d, addr: %s, lmp_ver: %d, manufacturer_id: %d, lmp_subver: %d",
762 bqr_raw_data_len, ADDRESS_TO_LOGGABLE_CSTR(bd_addr), lmp_ver,
763 manufacturer_id, lmp_subver);
764
765 if (callbacks == nullptr) {
766 LOG_ERROR("callbacks is nullptr");
767 return;
768 }
769
770 do_in_jni_thread(
771 FROM_HERE,
772 base::Bind(&bluetooth::bqr::BluetoothQualityReportCallbacks::
773 bqr_delivery_callback,
774 base::Unretained(callbacks), bd_addr, lmp_ver, lmp_subver,
775 manufacturer_id, std::move(raw_data)));
776 }
777
778 private:
779 BluetoothQualityReportCallbacks* callbacks = nullptr;
780 };
781
getBluetoothQualityReportInterface()782 BluetoothQualityReportInterface* getBluetoothQualityReportInterface() {
783 if (!bluetoothQualityReportInstance) {
784 bluetoothQualityReportInstance.reset(
785 new BluetoothQualityReportInterfaceImpl());
786 }
787
788 return bluetoothQualityReportInstance.get();
789 }
790
791 } // namespace bqr
792 } // namespace bluetooth
793