Loading system/btif/include/btif_bqr.h +126 −0 Original line number Diff line number Diff line Loading @@ -200,8 +200,10 @@ enum BqrQualityReportId : uint8_t { QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY = 0x03, QUALITY_REPORT_ID_SCO_VOICE_CHOPPY = 0x04, QUALITY_REPORT_ID_ROOT_INFLAMMATION = 0x05, QUALITY_REPORT_ID_ENERGY_MONITOR = 0x06, QUALITY_REPORT_ID_LE_AUDIO_CHOPPY = 0x07, QUALITY_REPORT_ID_CONNECT_FAIL = 0x08, QUALITY_REPORT_ID_RF_STATS = 0x09, QUALITY_REPORT_ID_VENDOR_SPECIFIC_QUALITY = 0x10, QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE = 0x11, QUALITY_REPORT_ID_BT_SCHEDULING_TRACE = 0x12, Loading Loading @@ -330,6 +332,112 @@ typedef struct { const uint8_t* vendor_specific_parameter; } BqrLinkQualityEvent; // Energy Monitor BQR event typedef struct { // Quality report ID. uint8_t quality_report_id; // Average current consumption of all activities consumed by the controller (mA) uint16_t avg_current_consume; // Total time in the idle (low power states, sleep) state. (ms) uint32_t idle_total_time; // Indicates how many times the controller enters the idle state. uint32_t idle_state_enter_count; // Total time in the active (inquiring, paging, ACL/SCO/eSCO/BIS/CIS traffic, processing any task) // state. (ms) uint32_t active_total_time; // Indicates how many times the controller enters the active states. uint32_t active_state_enter_count; // Total time in the BR/EDR specific Tx(Transmitting for ACL/SCO/eSCO traffic)state (ms) uint32_t bredr_tx_total_time; // Indicates how many times the controller enters the BR/EDR specific Tx state. uint32_t bredr_tx_state_enter_count; // Average Tx power level of all the BR/EDR link(s) (dBm) uint8_t bredr_tx_avg_power_lv; // Total time in the BR/EDR specific Rx (Receiving from ACL/SCO/eSCO traffic) state. (ms) uint32_t bredr_rx_total_time; // Indicates how many times the controller enters the BR/EDR specific Rx state. (ms) uint32_t bredr_rx_state_enter_count; // Total time in the LE specific Tx (Transmitting for either ACL/BIS/CIS or LE advertising // traffic) state (ms) uint32_t le_tx_total_time; // Indicates how many times the controller enters theLE specific Tx state. uint32_t le_tx_state_enter_count; // Average Tx power level of all the LE link(s) (dBm) uint8_t le_tx_avg_power_lv; // Total time in the LE specific Rx (Receiving from either ACL/BIS/CIS or LE scanning traffic) // state. (ms) uint32_t le_rx_total_time; // Indicates how many times the controller enters the LE specific Rx state uint32_t le_rx_state_enter_count; // The total time duration to collect power related information (ms) uint32_t tm_period; // The time duration of RX active in one chain uint32_t rx_active_one_chain_time; // The time duration of RX active in two chain uint32_t rx_active_two_chain_time; // The time duration of internal TX active in one chain uint32_t tx_ipa_active_one_chain_time; // The time duration of internal TX active in two chain uint32_t tx_ipa_active_two_chain_time; // The time duration of external TX active in one chain uint32_t tx_epa_active_one_chain_time; // The time duration of external TX active in two chain uint32_t tx_epa_active_two_chain_time; } __attribute__((__packed__)) BqrEnergyMonitorEvent; static constexpr uint8_t kEnergyMonitorParamTotalLen = sizeof(BqrEnergyMonitorEvent); // RF Stats BQR event typedef struct { // Quality report ID. uint8_t quality_report_id; // Extension for Further usage = 0x01 for BQRv6 uint8_t ext_info; // time period (ms) uint32_t tm_period; // Packet counter of iPA BF uint32_t tx_pw_ipa_bf; // Packet counter of ePA BF uint32_t tx_pw_epa_bf; // Packet counter of iPA Div uint32_t tx_pw_ipa_div; // Packet counter of ePA Div uint32_t tx_pw_epa_div; // Packet counter of RSSI chain > -50 dBm uint32_t rssi_ch_50; // Packet counter of RSSI chain between -50 dBm ~ >-55 dBm uint32_t rssi_ch_50_55; // Packet counter of RSSI chain between -55 dBm ~ >-60 dBm uint32_t rssi_ch_55_60; // Packet counter of RSSI chain between -60 dBm ~ >-65 dBm uint32_t rssi_ch_60_65; // Packet counter of RSSI chain between -65 dBm ~ >-70 dBm uint32_t rssi_ch_65_70; // Packet counter of RSSI chain between -70 dBm ~ >-75 dBm uint32_t rssi_ch_70_75; // Packet counter of RSSI chain between -75 dBm ~ >-80 dBm uint32_t rssi_ch_75_80; // Packet counter of RSSI chain between -80 dBm ~ >-85 dBm uint32_t rssi_ch_80_85; // Packet counter of RSSI chain between -85 dBm ~ >-90 dBm uint32_t rssi_ch_85_90; // Packet counter of RSSI chain < -90 dBm uint32_t rssi_ch_90; // Packet counter of RSSI delta < 2 dBm uint32_t rssi_delta_2_down; // Packet counter of RSSI delta between 2 dBm ~ 5 dBm uint32_t rssi_delta_2_5; // Packet counter of RSSI delta between 5 dBm ~ 8 dB uint32_t rssi_delta_5_8; // Packet counter of RSSI delta between 8 dBm ~ 11 dBm uint32_t rssi_delta_8_11; // Packet counter of RSSI delta > 11 dBm uint32_t rssi_delta_11_up; } __attribute__((__packed__)) BqrRFStatsEvent; // Total length of all parameters of the RF Stats event static constexpr uint8_t kRFStatsParamTotalLen = sizeof(BqrRFStatsEvent); // Log dump related BQR event typedef struct { // Quality report ID. Loading @@ -348,6 +456,20 @@ public: // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. void ParseBqrLinkQualityEvt(uint8_t length, const uint8_t* p_param_buf); // Parse the Energy Monitor BQR event. // // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. // // @return true if the event was parsed successfully, false otherwise. bool ParseBqrEnergyMonitorEvt(uint8_t length, const uint8_t* p_param_buf); // Parse the RF Stats BQR event. // // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. // // @return true if the event was parsed successfully, false otherwise. bool ParseBqrRFStatsEvt(uint8_t length, const uint8_t* p_param_buf); // Write the LMP/LL message trace to the log file. // // @param fd The File Descriptor of the log file. Loading @@ -372,6 +494,10 @@ public: virtual ~BqrVseSubEvt() = default; // Link Quality related BQR event BqrLinkQualityEvent bqr_link_quality_event_ = {}; // Energy Monitor BQR event BqrEnergyMonitorEvent bqr_energy_monitor_event_ = {}; // RF Stats BQR event BqrRFStatsEvent bqr_rf_stats_event_ = {}; // Log Dump related BQR event BqrLogDumpEvent bqr_log_dump_event_ = {}; // Local wall clock timestamp of receiving BQR VSE sub-event Loading system/btif/src/btif_bqr.cc +158 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <fcntl.h> #ifdef __ANDROID__ #include <statslog_bt.h> Loading Loading @@ -155,6 +156,79 @@ void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length, const uint8_t* p_param localtime_r(&now, &tm_timestamp_); } bool BqrVseSubEvt::ParseBqrEnergyMonitorEvt(uint8_t length, const uint8_t* p_param_buf) { if (length < kEnergyMonitorParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter than: " "{}", length, kEnergyMonitorParamTotalLen); return false; } STREAM_TO_UINT8(bqr_energy_monitor_event_.quality_report_id, p_param_buf); bqr_link_quality_event_.quality_report_id = bqr_energy_monitor_event_.quality_report_id; STREAM_TO_UINT16(bqr_energy_monitor_event_.avg_current_consume, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.idle_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.idle_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.active_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.active_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_tx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_tx_state_enter_count, p_param_buf); STREAM_TO_UINT8(bqr_energy_monitor_event_.bredr_tx_avg_power_lv, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_rx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_rx_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_tx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_tx_state_enter_count, p_param_buf); STREAM_TO_UINT8(bqr_energy_monitor_event_.le_tx_avg_power_lv, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_rx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_rx_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tm_period, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.rx_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.rx_active_two_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_ipa_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_ipa_active_two_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_epa_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_epa_active_two_chain_time, p_param_buf); return true; } bool BqrVseSubEvt::ParseBqrRFStatsEvt(uint8_t length, const uint8_t* p_param_buf) { if (length < kRFStatsParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter than: " "{}", length, kRFStatsParamTotalLen); return false; } STREAM_TO_UINT8(bqr_rf_stats_event_.quality_report_id, p_param_buf); bqr_link_quality_event_.quality_report_id = bqr_rf_stats_event_.quality_report_id; STREAM_TO_UINT8(bqr_rf_stats_event_.ext_info, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tm_period, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_ipa_bf, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_epa_bf, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_ipa_div, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_epa_div, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_50, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_50_55, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_55_60, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_60_65, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_65_70, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_70_75, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_75_80, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_80_85, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_85_90, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_90, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_2_down, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_2_5, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_5_8, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_8_11, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_11_up, p_param_buf); return true; } void BqrVseSubEvt::WriteLmpLlTraceLogFile(int fd, uint8_t length, const uint8_t* p_param_buf) { const auto now = system_clock::to_time_t(system_clock::now()); localtime_r(&now, &tm_timestamp_); Loading Loading @@ -226,7 +300,19 @@ std::string BqrVseSubEvt::ToString() const { << ", CRCError: " << std::to_string(bqr_link_quality_event_.crc_error_packets) << ", RxDuplicate: " << std::to_string(bqr_link_quality_event_.rx_duplicate_packets); } if (QUALITY_REPORT_ID_ENERGY_MONITOR == bqr_link_quality_event_.quality_report_id) { ss << ", TotalTime: " << std::to_string(bqr_energy_monitor_event_.tm_period) << ", ActiveTime: " << std::to_string(bqr_energy_monitor_event_.active_total_time) << ", IdleTime: " << std::to_string(bqr_energy_monitor_event_.idle_total_time) << ", AvgCurrent: " << std::to_string(bqr_energy_monitor_event_.avg_current_consume); } if (QUALITY_REPORT_ID_RF_STATS == bqr_link_quality_event_.quality_report_id) { ss << ", TotalTime: " << std::to_string(bqr_rf_stats_event_.tm_period) << ", TxiPABF: " << std::to_string(bqr_rf_stats_event_.tx_pw_ipa_bf) << ", TxePABF: " << std::to_string(bqr_rf_stats_event_.tx_pw_epa_bf) << ", TxiPADiv: " << std::to_string(bqr_rf_stats_event_.tx_pw_ipa_div) << ", TxePADiv: " << std::to_string(bqr_rf_stats_event_.tx_pw_epa_div); } return ss.str(); } Loading @@ -248,6 +334,10 @@ static std::string QualityReportIdToString(uint8_t quality_report_id) { return "LE Audio Choppy"; case QUALITY_REPORT_ID_CONNECT_FAIL: return "Connect Fail"; case QUALITY_REPORT_ID_ENERGY_MONITOR: return "Energy Monitor"; case QUALITY_REPORT_ID_RF_STATS: return "RF Stats"; default: return "Invalid"; } Loading Loading @@ -588,6 +678,9 @@ static void ConfigureBqrCmpl(uint32_t current_evt_mask) { } } static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddEnergyMonitorEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddRFStatsEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); // Categorize the incoming Bluetooth Quality Report. // Loading Loading @@ -631,6 +724,34 @@ static void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) { log::warn("Unexpected ID: 0x{:x}", quality_report_id); break; case QUALITY_REPORT_ID_ENERGY_MONITOR: if (length < kEnergyMonitorParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter " "than: {}", length, kEnergyMonitorParamTotalLen); return; } if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { AddEnergyMonitorEventToQueue(length, p_bqr_event); } break; case QUALITY_REPORT_ID_RF_STATS: if (length < kRFStatsParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter " "than: {}", length, kRFStatsParamTotalLen); return; } if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { AddRFStatsEventToQueue(length, p_bqr_event); } break; default: log::warn("Unknown ID: 0x{:x}", quality_report_id); break; Loading Loading @@ -705,6 +826,42 @@ static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_qua kpBqrEventQueue.Enqueue(p_bqr_event.release()); } static void AddEnergyMonitorEventToQueue(uint8_t length, const uint8_t* p_energy_monitor_event) { std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>(); if (!p_bqr_event->ParseBqrEnergyMonitorEvt(length, p_energy_monitor_event)) { log::warn("failed to parse BQR energy monitor event"); return; } BluetoothQualityReportInterface* bqrItf = getBluetoothQualityReportInterface(); if (bqrItf == NULL) { log::warn("failed to deliver BQR, bqrItf is NULL"); return; } bqrItf->bqr_delivery_event(RawAddress::kAny, p_energy_monitor_event, length); } static void AddRFStatsEventToQueue(uint8_t length, const uint8_t* p_rf_stats_event) { std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>(); if (!p_bqr_event->ParseBqrRFStatsEvt(length, p_rf_stats_event)) { log::warn("failed to parse BQR RF stats event"); return; } BluetoothQualityReportInterface* bqrItf = getBluetoothQualityReportInterface(); if (bqrItf == NULL) { log::warn("failed to deliver BQR, bqrItf is NULL"); return; } bqrItf->bqr_delivery_event(RawAddress::kAny, p_rf_stats_event, length); } static int OpenLmpLlTraceLogFile(); // Dump the LMP/LL message handshaking with the remote device to a log file. Loading Loading
system/btif/include/btif_bqr.h +126 −0 Original line number Diff line number Diff line Loading @@ -200,8 +200,10 @@ enum BqrQualityReportId : uint8_t { QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY = 0x03, QUALITY_REPORT_ID_SCO_VOICE_CHOPPY = 0x04, QUALITY_REPORT_ID_ROOT_INFLAMMATION = 0x05, QUALITY_REPORT_ID_ENERGY_MONITOR = 0x06, QUALITY_REPORT_ID_LE_AUDIO_CHOPPY = 0x07, QUALITY_REPORT_ID_CONNECT_FAIL = 0x08, QUALITY_REPORT_ID_RF_STATS = 0x09, QUALITY_REPORT_ID_VENDOR_SPECIFIC_QUALITY = 0x10, QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE = 0x11, QUALITY_REPORT_ID_BT_SCHEDULING_TRACE = 0x12, Loading Loading @@ -330,6 +332,112 @@ typedef struct { const uint8_t* vendor_specific_parameter; } BqrLinkQualityEvent; // Energy Monitor BQR event typedef struct { // Quality report ID. uint8_t quality_report_id; // Average current consumption of all activities consumed by the controller (mA) uint16_t avg_current_consume; // Total time in the idle (low power states, sleep) state. (ms) uint32_t idle_total_time; // Indicates how many times the controller enters the idle state. uint32_t idle_state_enter_count; // Total time in the active (inquiring, paging, ACL/SCO/eSCO/BIS/CIS traffic, processing any task) // state. (ms) uint32_t active_total_time; // Indicates how many times the controller enters the active states. uint32_t active_state_enter_count; // Total time in the BR/EDR specific Tx(Transmitting for ACL/SCO/eSCO traffic)state (ms) uint32_t bredr_tx_total_time; // Indicates how many times the controller enters the BR/EDR specific Tx state. uint32_t bredr_tx_state_enter_count; // Average Tx power level of all the BR/EDR link(s) (dBm) uint8_t bredr_tx_avg_power_lv; // Total time in the BR/EDR specific Rx (Receiving from ACL/SCO/eSCO traffic) state. (ms) uint32_t bredr_rx_total_time; // Indicates how many times the controller enters the BR/EDR specific Rx state. (ms) uint32_t bredr_rx_state_enter_count; // Total time in the LE specific Tx (Transmitting for either ACL/BIS/CIS or LE advertising // traffic) state (ms) uint32_t le_tx_total_time; // Indicates how many times the controller enters theLE specific Tx state. uint32_t le_tx_state_enter_count; // Average Tx power level of all the LE link(s) (dBm) uint8_t le_tx_avg_power_lv; // Total time in the LE specific Rx (Receiving from either ACL/BIS/CIS or LE scanning traffic) // state. (ms) uint32_t le_rx_total_time; // Indicates how many times the controller enters the LE specific Rx state uint32_t le_rx_state_enter_count; // The total time duration to collect power related information (ms) uint32_t tm_period; // The time duration of RX active in one chain uint32_t rx_active_one_chain_time; // The time duration of RX active in two chain uint32_t rx_active_two_chain_time; // The time duration of internal TX active in one chain uint32_t tx_ipa_active_one_chain_time; // The time duration of internal TX active in two chain uint32_t tx_ipa_active_two_chain_time; // The time duration of external TX active in one chain uint32_t tx_epa_active_one_chain_time; // The time duration of external TX active in two chain uint32_t tx_epa_active_two_chain_time; } __attribute__((__packed__)) BqrEnergyMonitorEvent; static constexpr uint8_t kEnergyMonitorParamTotalLen = sizeof(BqrEnergyMonitorEvent); // RF Stats BQR event typedef struct { // Quality report ID. uint8_t quality_report_id; // Extension for Further usage = 0x01 for BQRv6 uint8_t ext_info; // time period (ms) uint32_t tm_period; // Packet counter of iPA BF uint32_t tx_pw_ipa_bf; // Packet counter of ePA BF uint32_t tx_pw_epa_bf; // Packet counter of iPA Div uint32_t tx_pw_ipa_div; // Packet counter of ePA Div uint32_t tx_pw_epa_div; // Packet counter of RSSI chain > -50 dBm uint32_t rssi_ch_50; // Packet counter of RSSI chain between -50 dBm ~ >-55 dBm uint32_t rssi_ch_50_55; // Packet counter of RSSI chain between -55 dBm ~ >-60 dBm uint32_t rssi_ch_55_60; // Packet counter of RSSI chain between -60 dBm ~ >-65 dBm uint32_t rssi_ch_60_65; // Packet counter of RSSI chain between -65 dBm ~ >-70 dBm uint32_t rssi_ch_65_70; // Packet counter of RSSI chain between -70 dBm ~ >-75 dBm uint32_t rssi_ch_70_75; // Packet counter of RSSI chain between -75 dBm ~ >-80 dBm uint32_t rssi_ch_75_80; // Packet counter of RSSI chain between -80 dBm ~ >-85 dBm uint32_t rssi_ch_80_85; // Packet counter of RSSI chain between -85 dBm ~ >-90 dBm uint32_t rssi_ch_85_90; // Packet counter of RSSI chain < -90 dBm uint32_t rssi_ch_90; // Packet counter of RSSI delta < 2 dBm uint32_t rssi_delta_2_down; // Packet counter of RSSI delta between 2 dBm ~ 5 dBm uint32_t rssi_delta_2_5; // Packet counter of RSSI delta between 5 dBm ~ 8 dB uint32_t rssi_delta_5_8; // Packet counter of RSSI delta between 8 dBm ~ 11 dBm uint32_t rssi_delta_8_11; // Packet counter of RSSI delta > 11 dBm uint32_t rssi_delta_11_up; } __attribute__((__packed__)) BqrRFStatsEvent; // Total length of all parameters of the RF Stats event static constexpr uint8_t kRFStatsParamTotalLen = sizeof(BqrRFStatsEvent); // Log dump related BQR event typedef struct { // Quality report ID. Loading @@ -348,6 +456,20 @@ public: // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. void ParseBqrLinkQualityEvt(uint8_t length, const uint8_t* p_param_buf); // Parse the Energy Monitor BQR event. // // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. // // @return true if the event was parsed successfully, false otherwise. bool ParseBqrEnergyMonitorEvt(uint8_t length, const uint8_t* p_param_buf); // Parse the RF Stats BQR event. // // @param length Total length of all parameters contained in the sub-event. // @param p_param_buf A pointer to the parameters contained in the sub-event. // // @return true if the event was parsed successfully, false otherwise. bool ParseBqrRFStatsEvt(uint8_t length, const uint8_t* p_param_buf); // Write the LMP/LL message trace to the log file. // // @param fd The File Descriptor of the log file. Loading @@ -372,6 +494,10 @@ public: virtual ~BqrVseSubEvt() = default; // Link Quality related BQR event BqrLinkQualityEvent bqr_link_quality_event_ = {}; // Energy Monitor BQR event BqrEnergyMonitorEvent bqr_energy_monitor_event_ = {}; // RF Stats BQR event BqrRFStatsEvent bqr_rf_stats_event_ = {}; // Log Dump related BQR event BqrLogDumpEvent bqr_log_dump_event_ = {}; // Local wall clock timestamp of receiving BQR VSE sub-event Loading
system/btif/src/btif_bqr.cc +158 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include <bluetooth/log.h> #include <com_android_bluetooth_flags.h> #include <fcntl.h> #ifdef __ANDROID__ #include <statslog_bt.h> Loading Loading @@ -155,6 +156,79 @@ void BqrVseSubEvt::ParseBqrLinkQualityEvt(uint8_t length, const uint8_t* p_param localtime_r(&now, &tm_timestamp_); } bool BqrVseSubEvt::ParseBqrEnergyMonitorEvt(uint8_t length, const uint8_t* p_param_buf) { if (length < kEnergyMonitorParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter than: " "{}", length, kEnergyMonitorParamTotalLen); return false; } STREAM_TO_UINT8(bqr_energy_monitor_event_.quality_report_id, p_param_buf); bqr_link_quality_event_.quality_report_id = bqr_energy_monitor_event_.quality_report_id; STREAM_TO_UINT16(bqr_energy_monitor_event_.avg_current_consume, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.idle_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.idle_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.active_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.active_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_tx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_tx_state_enter_count, p_param_buf); STREAM_TO_UINT8(bqr_energy_monitor_event_.bredr_tx_avg_power_lv, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_rx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.bredr_rx_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_tx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_tx_state_enter_count, p_param_buf); STREAM_TO_UINT8(bqr_energy_monitor_event_.le_tx_avg_power_lv, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_rx_total_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.le_rx_state_enter_count, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tm_period, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.rx_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.rx_active_two_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_ipa_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_ipa_active_two_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_epa_active_one_chain_time, p_param_buf); STREAM_TO_UINT32(bqr_energy_monitor_event_.tx_epa_active_two_chain_time, p_param_buf); return true; } bool BqrVseSubEvt::ParseBqrRFStatsEvt(uint8_t length, const uint8_t* p_param_buf) { if (length < kRFStatsParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter than: " "{}", length, kRFStatsParamTotalLen); return false; } STREAM_TO_UINT8(bqr_rf_stats_event_.quality_report_id, p_param_buf); bqr_link_quality_event_.quality_report_id = bqr_rf_stats_event_.quality_report_id; STREAM_TO_UINT8(bqr_rf_stats_event_.ext_info, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tm_period, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_ipa_bf, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_epa_bf, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_ipa_div, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.tx_pw_epa_div, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_50, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_50_55, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_55_60, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_60_65, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_65_70, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_70_75, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_75_80, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_80_85, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_85_90, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_ch_90, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_2_down, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_2_5, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_5_8, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_8_11, p_param_buf); STREAM_TO_UINT32(bqr_rf_stats_event_.rssi_delta_11_up, p_param_buf); return true; } void BqrVseSubEvt::WriteLmpLlTraceLogFile(int fd, uint8_t length, const uint8_t* p_param_buf) { const auto now = system_clock::to_time_t(system_clock::now()); localtime_r(&now, &tm_timestamp_); Loading Loading @@ -226,7 +300,19 @@ std::string BqrVseSubEvt::ToString() const { << ", CRCError: " << std::to_string(bqr_link_quality_event_.crc_error_packets) << ", RxDuplicate: " << std::to_string(bqr_link_quality_event_.rx_duplicate_packets); } if (QUALITY_REPORT_ID_ENERGY_MONITOR == bqr_link_quality_event_.quality_report_id) { ss << ", TotalTime: " << std::to_string(bqr_energy_monitor_event_.tm_period) << ", ActiveTime: " << std::to_string(bqr_energy_monitor_event_.active_total_time) << ", IdleTime: " << std::to_string(bqr_energy_monitor_event_.idle_total_time) << ", AvgCurrent: " << std::to_string(bqr_energy_monitor_event_.avg_current_consume); } if (QUALITY_REPORT_ID_RF_STATS == bqr_link_quality_event_.quality_report_id) { ss << ", TotalTime: " << std::to_string(bqr_rf_stats_event_.tm_period) << ", TxiPABF: " << std::to_string(bqr_rf_stats_event_.tx_pw_ipa_bf) << ", TxePABF: " << std::to_string(bqr_rf_stats_event_.tx_pw_epa_bf) << ", TxiPADiv: " << std::to_string(bqr_rf_stats_event_.tx_pw_ipa_div) << ", TxePADiv: " << std::to_string(bqr_rf_stats_event_.tx_pw_epa_div); } return ss.str(); } Loading @@ -248,6 +334,10 @@ static std::string QualityReportIdToString(uint8_t quality_report_id) { return "LE Audio Choppy"; case QUALITY_REPORT_ID_CONNECT_FAIL: return "Connect Fail"; case QUALITY_REPORT_ID_ENERGY_MONITOR: return "Energy Monitor"; case QUALITY_REPORT_ID_RF_STATS: return "RF Stats"; default: return "Invalid"; } Loading Loading @@ -588,6 +678,9 @@ static void ConfigureBqrCmpl(uint32_t current_evt_mask) { } } static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddEnergyMonitorEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddRFStatsEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_quality_event); // Categorize the incoming Bluetooth Quality Report. // Loading Loading @@ -631,6 +724,34 @@ static void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) { log::warn("Unexpected ID: 0x{:x}", quality_report_id); break; case QUALITY_REPORT_ID_ENERGY_MONITOR: if (length < kEnergyMonitorParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter " "than: {}", length, kEnergyMonitorParamTotalLen); return; } if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { AddEnergyMonitorEventToQueue(length, p_bqr_event); } break; case QUALITY_REPORT_ID_RF_STATS: if (length < kRFStatsParamTotalLen) { log::fatal( "Parameter total length: {} is abnormal. It shall be not shorter " "than: {}", length, kRFStatsParamTotalLen); return; } if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { AddRFStatsEventToQueue(length, p_bqr_event); } break; default: log::warn("Unknown ID: 0x{:x}", quality_report_id); break; Loading Loading @@ -705,6 +826,42 @@ static void AddLinkQualityEventToQueue(uint8_t length, const uint8_t* p_link_qua kpBqrEventQueue.Enqueue(p_bqr_event.release()); } static void AddEnergyMonitorEventToQueue(uint8_t length, const uint8_t* p_energy_monitor_event) { std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>(); if (!p_bqr_event->ParseBqrEnergyMonitorEvt(length, p_energy_monitor_event)) { log::warn("failed to parse BQR energy monitor event"); return; } BluetoothQualityReportInterface* bqrItf = getBluetoothQualityReportInterface(); if (bqrItf == NULL) { log::warn("failed to deliver BQR, bqrItf is NULL"); return; } bqrItf->bqr_delivery_event(RawAddress::kAny, p_energy_monitor_event, length); } static void AddRFStatsEventToQueue(uint8_t length, const uint8_t* p_rf_stats_event) { std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>(); if (!p_bqr_event->ParseBqrRFStatsEvt(length, p_rf_stats_event)) { log::warn("failed to parse BQR RF stats event"); return; } BluetoothQualityReportInterface* bqrItf = getBluetoothQualityReportInterface(); if (bqrItf == NULL) { log::warn("failed to deliver BQR, bqrItf is NULL"); return; } bqrItf->bqr_delivery_event(RawAddress::kAny, p_rf_stats_event, length); } static int OpenLmpLlTraceLogFile(); // Dump the LMP/LL message handshaking with the remote device to a log file. Loading