From 5f30d333d2c4bd021de7d0c1b4eddb061cf1d314 Mon Sep 17 00:00:00 2001 From: Mahesh KKV Date: Wed, 26 Oct 2022 14:07:44 -0700 Subject: [PATCH] wifi: Add Support for Multi-Link Layer stats in shim layer With MLO, WiFi 7 supports establishing multiple links between the Station and Access Point. Each of the link has its own stats. To maintain backward compatibility, if multi link stats is not supported by vendor, always fallback to single link layer stats. Bug: 246988155 Test: hardware/interfaces/wifi/aidl/default/tests/runtests.sh Change-Id: Iede8ce771f0e58975222808b1870e5e2e179384c --- wifi/aidl/default/aidl_struct_util.cpp | 173 +++++++++++++++++++------ wifi/aidl/default/aidl_struct_util.h | 2 + wifi/aidl/default/wifi_legacy_hal.cpp | 117 ++++++++++++++++- wifi/aidl/default/wifi_legacy_hal.h | 20 ++- wifi/aidl/default/wifi_sta_iface.cpp | 15 ++- 5 files changed, 276 insertions(+), 51 deletions(-) diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp index ec8b3968f2..fe7579b234 100644 --- a/wifi/aidl/default/aidl_struct_util.cpp +++ b/wifi/aidl/default/aidl_struct_util.cpp @@ -940,69 +940,158 @@ bool convertLegacyLinkLayerRadioStatsToAidl( return true; } +bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats, + StaLinkLayerStats* aidl_stats) { + if (!aidl_stats) { + return false; + } + *aidl_stats = {}; + std::vector links; + // Iterate over each links + for (const auto& link : legacy_ml_stats.links) { + StaLinkLayerLinkStats linkStats = {}; + linkStats.linkId = link.stat.link_id; + linkStats.beaconRx = link.stat.beacon_rx; + linkStats.avgRssiMgmt = link.stat.rssi_mgmt; + linkStats.wmeBePktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + linkStats.wmeBePktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + linkStats.wmeBePktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + linkStats.wmeBePktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_BE].retries; + linkStats.wmeBeContentionTimeStats.contentionTimeMinInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min; + linkStats.wmeBeContentionTimeStats.contentionTimeMaxInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max; + linkStats.wmeBeContentionTimeStats.contentionTimeAvgInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg; + linkStats.wmeBeContentionTimeStats.contentionNumSamples = + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples; + linkStats.wmeBkPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + linkStats.wmeBkPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + linkStats.wmeBkPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + linkStats.wmeBkPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_BK].retries; + linkStats.wmeBkContentionTimeStats.contentionTimeMinInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min; + linkStats.wmeBkContentionTimeStats.contentionTimeMaxInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max; + linkStats.wmeBkContentionTimeStats.contentionTimeAvgInUsec = + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg; + linkStats.wmeBkContentionTimeStats.contentionNumSamples = + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples; + linkStats.wmeViPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + linkStats.wmeViPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + linkStats.wmeViPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + linkStats.wmeViPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_VI].retries; + linkStats.wmeViContentionTimeStats.contentionTimeMinInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min; + linkStats.wmeViContentionTimeStats.contentionTimeMaxInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max; + linkStats.wmeViContentionTimeStats.contentionTimeAvgInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg; + linkStats.wmeViContentionTimeStats.contentionNumSamples = + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples; + linkStats.wmeVoPktStats.rxMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + linkStats.wmeVoPktStats.txMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + linkStats.wmeVoPktStats.lostMpdu = link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + linkStats.wmeVoPktStats.retries = link.stat.ac[legacy_hal::WIFI_AC_VO].retries; + linkStats.wmeVoContentionTimeStats.contentionTimeMinInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min; + linkStats.wmeVoContentionTimeStats.contentionTimeMaxInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max; + linkStats.wmeVoContentionTimeStats.contentionTimeAvgInUsec = + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg; + linkStats.wmeVoContentionTimeStats.contentionNumSamples = + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples; + linkStats.timeSliceDutyCycleInPercent = link.stat.time_slicing_duty_cycle_percent; + // peer info legacy_stats conversion. + std::vector aidl_peers_info_stats; + for (const auto& legacy_peer_info_stats : link.peers) { + StaPeerInfo aidl_peer_info_stats; + if (!convertLegacyPeerInfoStatsToAidl(legacy_peer_info_stats, &aidl_peer_info_stats)) { + return false; + } + aidl_peers_info_stats.push_back(aidl_peer_info_stats); + } + linkStats.peers = aidl_peers_info_stats; + // Push link stats to aidl stats. + links.push_back(linkStats); + } + aidl_stats->iface.links = links; + // radio legacy_stats conversion. + std::vector aidl_radios_stats; + for (const auto& legacy_radio_stats : legacy_ml_stats.radios) { + StaLinkLayerRadioStats aidl_radio_stats; + if (!convertLegacyLinkLayerRadioStatsToAidl(legacy_radio_stats, &aidl_radio_stats)) { + return false; + } + aidl_radios_stats.push_back(aidl_radio_stats); + } + aidl_stats->radios = aidl_radios_stats; + aidl_stats->timeStampInMs = ::android::uptimeMillis(); + + return true; +} + bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats, StaLinkLayerStats* aidl_stats) { if (!aidl_stats) { return false; } *aidl_stats = {}; + std::vector links; + StaLinkLayerLinkStats linkStats = {}; // iface legacy_stats conversion. - aidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx; - aidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; - aidl_stats->iface.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; - aidl_stats->iface.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; - aidl_stats->iface.wmeBePktStats.lostMpdu = - legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; - aidl_stats->iface.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; - aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec = + linkStats.linkId = 0; + linkStats.beaconRx = legacy_stats.iface.beacon_rx; + linkStats.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + linkStats.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + linkStats.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + linkStats.wmeBePktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + linkStats.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; + linkStats.wmeBeContentionTimeStats.contentionTimeMinInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min; - aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec = + linkStats.wmeBeContentionTimeStats.contentionTimeMaxInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max; - aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec = + linkStats.wmeBeContentionTimeStats.contentionTimeAvgInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg; - aidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples = + linkStats.wmeBeContentionTimeStats.contentionNumSamples = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples; - aidl_stats->iface.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; - aidl_stats->iface.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; - aidl_stats->iface.wmeBkPktStats.lostMpdu = - legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; - aidl_stats->iface.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; - aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec = + linkStats.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + linkStats.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + linkStats.wmeBkPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + linkStats.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; + linkStats.wmeBkContentionTimeStats.contentionTimeMinInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min; - aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec = + linkStats.wmeBkContentionTimeStats.contentionTimeMaxInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max; - aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec = + linkStats.wmeBkContentionTimeStats.contentionTimeAvgInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg; - aidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples = + linkStats.wmeBkContentionTimeStats.contentionNumSamples = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples; - aidl_stats->iface.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; - aidl_stats->iface.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; - aidl_stats->iface.wmeViPktStats.lostMpdu = - legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; - aidl_stats->iface.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; - aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec = + linkStats.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + linkStats.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + linkStats.wmeViPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + linkStats.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; + linkStats.wmeViContentionTimeStats.contentionTimeMinInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min; - aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec = + linkStats.wmeViContentionTimeStats.contentionTimeMaxInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max; - aidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec = + linkStats.wmeViContentionTimeStats.contentionTimeAvgInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg; - aidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples = + linkStats.wmeViContentionTimeStats.contentionNumSamples = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples; - aidl_stats->iface.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; - aidl_stats->iface.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; - aidl_stats->iface.wmeVoPktStats.lostMpdu = - legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; - aidl_stats->iface.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; - aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec = + linkStats.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + linkStats.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + linkStats.wmeVoPktStats.lostMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + linkStats.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + linkStats.wmeVoContentionTimeStats.contentionTimeMinInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min; - aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec = + linkStats.wmeVoContentionTimeStats.contentionTimeMaxInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max; - aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec = + linkStats.wmeVoContentionTimeStats.contentionTimeAvgInUsec = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg; - aidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples = + linkStats.wmeVoContentionTimeStats.contentionNumSamples = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples; - aidl_stats->iface.timeSliceDutyCycleInPercent = - legacy_stats.iface.info.time_slicing_duty_cycle_percent; + linkStats.timeSliceDutyCycleInPercent = legacy_stats.iface.info.time_slicing_duty_cycle_percent; // peer info legacy_stats conversion. std::vector aidl_peers_info_stats; for (const auto& legacy_peer_info_stats : legacy_stats.peers) { @@ -1012,7 +1101,9 @@ bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_ } aidl_peers_info_stats.push_back(aidl_peer_info_stats); } - aidl_stats->iface.peers = aidl_peers_info_stats; + linkStats.peers = aidl_peers_info_stats; + links.push_back(linkStats); + aidl_stats->iface.links = links; // radio legacy_stats conversion. std::vector aidl_radios_stats; for (const auto& legacy_radio_stats : legacy_stats.radios) { diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h index d8e1fd48aa..ac86755382 100644 --- a/wifi/aidl/default/aidl_struct_util.h +++ b/wifi/aidl/default/aidl_struct_util.h @@ -89,6 +89,8 @@ bool convertLegacyGscanResultToAidl(const legacy_hal::wifi_scan_result& legacy_s bool convertLegacyVectorOfCachedGscanResultsToAidl( const std::vector& legacy_cached_scan_results, std::vector* aidl_scan_datas); +bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats, + StaLinkLayerStats* aidl_stats); bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats, StaLinkLayerStats* aidl_stats); bool convertLegacyRoamingCapabilitiesToAidl( diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp index e4883d19f3..83f368e0bf 100644 --- a/wifi/aidl/default/wifi_legacy_hal.cpp +++ b/wifi/aidl/default/wifi_legacy_hal.cpp @@ -119,6 +119,16 @@ void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, } } +// Callback to be invoked for Multi link layer stats results. +std::function + on_link_layer_ml_stats_result_internal_callback; +void onSyncLinkLayerMlStatsResult(wifi_request_id id, wifi_iface_ml_stat* iface_ml_stat, + int num_radios, wifi_radio_stat* radio_stat) { + if (on_link_layer_ml_stats_result_internal_callback) { + on_link_layer_ml_stats_result_internal_callback(id, iface_ml_stat, num_radios, radio_stat); + } +} + // Callback to be invoked for rssi threshold breach. std::function on_rssi_threshold_breached_internal_callback; @@ -682,10 +692,44 @@ wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) { &clear_mask_rsp, 1, &stop_rsp); } -std::pair WifiLegacyHal::getLinkLayerStats( - const std::string& iface_name) { - LinkLayerStats link_stats{}; +// Copies wifi_peer_info* to vector and returns poiner to next element. +wifi_peer_info* WifiLegacyHal::copyPeerInfo(wifi_peer_info* peer_ptr, + std::vector peers) { + WifiPeerInfo peer; + peer.peer_info = *peer_ptr; + if (peer_ptr->num_rate > 0) { + // Copy the rate stats. + peer.rate_stats.assign(peer_ptr->rate_stats, peer_ptr->rate_stats + peer_ptr->num_rate); + } + peer.peer_info.num_rate = 0; + // Push peer info. + peers.push_back(peer); + // Return the address of next peer info. + return (wifi_peer_info*)((u8*)peer_ptr + sizeof(wifi_peer_info) + + (sizeof(wifi_rate_stat) * peer_ptr->num_rate)); +} +// Copies wifi_link_stat* to vector and returns poiner to next element. +wifi_link_stat* WifiLegacyHal::copyLinkStat(wifi_link_stat* stat_ptr, + std::vector stats) { + LinkStats linkStat; + linkStat.stat = *stat_ptr; + wifi_peer_info* l_peer_info_stats_ptr = stat_ptr->peer_info; + for (uint32_t i = 0; i < linkStat.stat.num_peers; i++) { + l_peer_info_stats_ptr = copyPeerInfo(l_peer_info_stats_ptr, linkStat.peers); + } + // Copied all peers to linkStat.peers. + linkStat.stat.num_peers = 0; + // Push link stat. + stats.push_back(linkStat); + // Read all peers, return the address of next wifi_link_stat. + return (wifi_link_stat*)l_peer_info_stats_ptr; +} + +wifi_error WifiLegacyHal::getLinkLayerStats(const std::string& iface_name, + LinkLayerStats& link_stats, + LinkLayerMlStats& link_ml_stats) { LinkLayerStats* link_stats_ptr = &link_stats; + link_stats_ptr->valid = false; on_link_layer_stats_result_internal_callback = [&link_stats_ptr]( wifi_request_id /* id */, @@ -694,6 +738,7 @@ std::pair WifiLegacyHal::getLinkLayerStats( wifi_radio_stat* radio_stats_ptr) { wifi_radio_stat* l_radio_stats_ptr; wifi_peer_info* l_peer_info_stats_ptr; + link_stats_ptr->valid = true; if (iface_stats_ptr != nullptr) { link_stats_ptr->iface = *iface_stats_ptr; @@ -751,10 +796,69 @@ std::pair WifiLegacyHal::getLinkLayerStats( } }; - wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name), - {onSyncLinkLayerStatsResult}); + LinkLayerMlStats* link_ml_stats_ptr = &link_ml_stats; + link_ml_stats_ptr->valid = false; + + on_link_layer_ml_stats_result_internal_callback = + [this, &link_ml_stats_ptr](wifi_request_id /* id */, + wifi_iface_ml_stat* iface_ml_stats_ptr, int num_radios, + wifi_radio_stat* radio_stats_ptr) { + wifi_radio_stat* l_radio_stats_ptr; + wifi_link_stat* l_link_stat_ptr; + link_ml_stats_ptr->valid = true; + + if (iface_ml_stats_ptr != nullptr && iface_ml_stats_ptr->num_links > 0) { + // Copy stats from wifi_iface_ml_stat to LinkLayerMlStats, + // - num_links * links[] to vector of links. + // - num_peers * peer_info[] to vector of links[i].peers. + link_ml_stats_ptr->iface = *iface_ml_stats_ptr; + l_link_stat_ptr = iface_ml_stats_ptr->links; + for (int l = 0; l < iface_ml_stats_ptr->num_links; ++l) { + l_link_stat_ptr = copyLinkStat(l_link_stat_ptr, link_ml_stats_ptr->links); + } + } else { + LOG(ERROR) << "Invalid iface stats in link layer stats"; + } + if (num_radios <= 0 || radio_stats_ptr == nullptr) { + LOG(ERROR) << "Invalid radio stats in link layer stats"; + return; + } + l_radio_stats_ptr = radio_stats_ptr; + for (int i = 0; i < num_radios; i++) { + LinkLayerRadioStats radio; + + radio.stats = *l_radio_stats_ptr; + // Copy over the tx level array to the separate vector. + if (l_radio_stats_ptr->num_tx_levels > 0 && + l_radio_stats_ptr->tx_time_per_levels != nullptr) { + radio.tx_time_per_levels.assign(l_radio_stats_ptr->tx_time_per_levels, + l_radio_stats_ptr->tx_time_per_levels + + l_radio_stats_ptr->num_tx_levels); + } + radio.stats.num_tx_levels = 0; + radio.stats.tx_time_per_levels = nullptr; + /* Copy over the channel stat to separate vector */ + if (l_radio_stats_ptr->num_channels > 0) { + /* Copy the channel stats */ + radio.channel_stats.assign( + l_radio_stats_ptr->channels, + l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels); + } + link_ml_stats_ptr->radios.push_back(radio); + l_radio_stats_ptr = + (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) + + (sizeof(wifi_channel_stat) * + l_radio_stats_ptr->num_channels)); + } + }; + + wifi_error status = global_func_table_.wifi_get_link_stats( + 0, getIfaceHandle(iface_name), + {onSyncLinkLayerStatsResult, onSyncLinkLayerMlStatsResult}); on_link_layer_stats_result_internal_callback = nullptr; - return {status, link_stats}; + on_link_layer_ml_stats_result_internal_callback = nullptr; + + return status; } wifi_error WifiLegacyHal::startRssiMonitoring( @@ -1624,6 +1728,7 @@ void WifiLegacyHal::invalidate() { on_gscan_event_internal_callback = nullptr; on_gscan_full_result_internal_callback = nullptr; on_link_layer_stats_result_internal_callback = nullptr; + on_link_layer_ml_stats_result_internal_callback = nullptr; on_rssi_threshold_breached_internal_callback = nullptr; on_ring_buffer_data_internal_callback = nullptr; on_error_alert_internal_callback = nullptr; diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h index 33ed359baa..c40118e233 100644 --- a/wifi/aidl/default/wifi_legacy_hal.h +++ b/wifi/aidl/default/wifi_legacy_hal.h @@ -363,7 +363,21 @@ struct LinkLayerStats { wifi_iface_stat iface; std::vector radios; std::vector peers; + bool valid; }; + +struct LinkStats { + wifi_link_stat stat; + std::vector peers; +}; + +struct LinkLayerMlStats { + wifi_iface_ml_stat iface; + std::vector links; + std::vector radios; + bool valid; +}; + #pragma GCC diagnostic pop // The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and @@ -537,7 +551,9 @@ class WifiLegacyHal { // Link layer stats functions. wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug); wifi_error disableLinkLayerStats(const std::string& iface_name); - std::pair getLinkLayerStats(const std::string& iface_name); + wifi_error getLinkLayerStats(const std::string& iface_name, + legacy_hal::LinkLayerStats& legacy_stats, + legacy_hal::LinkLayerMlStats& legacy_ml_stats); // RSSI monitor functions. wifi_error startRssiMonitoring( const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi, @@ -710,6 +726,8 @@ class WifiLegacyHal { // Handles wifi (error) status of Virtual interface create/delete wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname, wifi_error status); + wifi_link_stat* copyLinkStat(wifi_link_stat* stat_ptr, std::vector stats); + wifi_peer_info* copyPeerInfo(wifi_peer_info* peer_ptr, std::vector peers); // Global function table of legacy HAL. wifi_hal_fn global_func_table_; diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp index 57384bf4dd..08ed9d2b5c 100644 --- a/wifi/aidl/default/wifi_sta_iface.cpp +++ b/wifi/aidl/default/wifi_sta_iface.cpp @@ -404,13 +404,22 @@ ndk::ScopedAStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { std::pair WifiStaIface::getLinkLayerStatsInternal() { legacy_hal::wifi_error legacy_status; - legacy_hal::LinkLayerStats legacy_stats; - std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_); + legacy_hal::LinkLayerStats legacy_stats{}; + legacy_hal::LinkLayerMlStats legacy_ml_stats{}; + legacy_status = legacy_hal_.lock()->getLinkLayerStats(ifname_, legacy_stats, legacy_ml_stats); if (legacy_status != legacy_hal::WIFI_SUCCESS) { return {StaLinkLayerStats{}, createWifiStatusFromLegacyError(legacy_status)}; } StaLinkLayerStats aidl_stats; - if (!aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &aidl_stats)) { + if (legacy_stats.valid) { + if (!aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &aidl_stats)) { + return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)}; + } + } else if (legacy_ml_stats.valid) { + if (!aidl_struct_util::convertLegacyLinkLayerMlStatsToAidl(legacy_ml_stats, &aidl_stats)) { + return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)}; + } + } else { return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)}; } return {aidl_stats, ndk::ScopedAStatus::ok()};