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