• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <base/logging.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #ifdef __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