diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl index cf68fc6bf4..a4192076d2 100644 --- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerIfaceStats.aidl @@ -34,16 +34,5 @@ package android.hardware.wifi; @VintfStability parcelable StaLinkLayerIfaceStats { - int beaconRx; - int avgRssiMgmt; - android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBePktStats; - android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBkPktStats; - android.hardware.wifi.StaLinkLayerIfacePacketStats wmeViPktStats; - android.hardware.wifi.StaLinkLayerIfacePacketStats wmeVoPktStats; - byte timeSliceDutyCycleInPercent; - android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats; - android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats; - android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats; - android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats; - android.hardware.wifi.StaPeerInfo[] peers; + android.hardware.wifi.StaLinkLayerLinkStats[] links; } diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl new file mode 100644 index 0000000000..714bba8e98 --- /dev/null +++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/StaLinkLayerLinkStats.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.wifi; +@VintfStability +parcelable StaLinkLayerLinkStats { + int linkId; + int beaconRx; + int avgRssiMgmt; + android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBePktStats; + android.hardware.wifi.StaLinkLayerIfacePacketStats wmeBkPktStats; + android.hardware.wifi.StaLinkLayerIfacePacketStats wmeViPktStats; + android.hardware.wifi.StaLinkLayerIfacePacketStats wmeVoPktStats; + byte timeSliceDutyCycleInPercent; + android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats; + android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats; + android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats; + android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats; + android.hardware.wifi.StaPeerInfo[] peers; +} diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl index 78f8caa6a7..3f8718fe74 100644 --- a/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl +++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerIfaceStats.aidl @@ -16,64 +16,13 @@ package android.hardware.wifi; -import android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats; -import android.hardware.wifi.StaLinkLayerIfacePacketStats; -import android.hardware.wifi.StaPeerInfo; +import android.hardware.wifi.StaLinkLayerLinkStats; /** - * Iface statistics for the current connection. + * Iface statistics for the current connection. Current connection may have + * single or multiple links. */ @VintfStability parcelable StaLinkLayerIfaceStats { - /** - * Number beacons received from the connected AP. - */ - int beaconRx; - /** - * Access Point Beacon and Management frames RSSI (averaged). - */ - int avgRssiMgmt; - /** - * WME Best Effort Access Category packet counters. - */ - StaLinkLayerIfacePacketStats wmeBePktStats; - /** - * WME Background Access Category packet counters. - */ - StaLinkLayerIfacePacketStats wmeBkPktStats; - /** - * WME Video Access Category packet counters. - */ - StaLinkLayerIfacePacketStats wmeViPktStats; - /** - * WME Voice Access Category packet counters. - */ - StaLinkLayerIfacePacketStats wmeVoPktStats; - /** - * Duty cycle for the iface. - * If this iface is being served using time slicing on a radio with one or more ifaces - * (i.e MCC), then the duty cycle assigned to this iface in %. - * If not using time slicing (i.e SCC or DBS), set to 100. - */ - byte timeSliceDutyCycleInPercent; - /** - * WME Best Effort (BE) Access Category (AC) contention time statistics. - */ - StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats; - /** - * WME Background (BK) Access Category (AC) contention time statistics. - */ - StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats; - /** - * WME Video (VI) Access Category (AC) contention time statistics. - */ - StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats; - /** - * WME Voice (VO) Access Category (AC) contention time statistics. - */ - StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats; - /** - * Per peer statistics. - */ - StaPeerInfo[] peers; + StaLinkLayerLinkStats[] links; } diff --git a/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl b/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl new file mode 100644 index 0000000000..cf1a867839 --- /dev/null +++ b/wifi/aidl/android/hardware/wifi/StaLinkLayerLinkStats.aidl @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.wifi; + +import android.hardware.wifi.StaLinkLayerIfaceContentionTimeStats; +import android.hardware.wifi.StaLinkLayerIfacePacketStats; +import android.hardware.wifi.StaPeerInfo; + +/** + * Per Link statistics for the current connection. For MLO, this is + * the statistics for one link in the connection. + */ +@VintfStability +parcelable StaLinkLayerLinkStats { + /** + * Identifier for the link within MLO. For single link operation this field + * is not relevant and can be set to 0. + */ + int linkId; + /** + * Number of beacons received from the connected AP on the link. + */ + int beaconRx; + /** + * Access Point Beacon and Management frames RSSI (averaged) on the link. + */ + int avgRssiMgmt; + /** + * WME Best Effort Access Category packet counters on the link. + */ + StaLinkLayerIfacePacketStats wmeBePktStats; + /** + * WME Background Access Category packet counters on the link. + */ + StaLinkLayerIfacePacketStats wmeBkPktStats; + /** + * WME Video Access Category packet counters on the link. + */ + StaLinkLayerIfacePacketStats wmeViPktStats; + /** + * WME Voice Access Category packet counters on the link. + */ + StaLinkLayerIfacePacketStats wmeVoPktStats; + /** + * Duty cycle for the link. + * If this link is being served using time slicing on a radio with one or + * more links then the duty cycle assigned to this link in %. If not using + * time slicing, set to 100. + */ + byte timeSliceDutyCycleInPercent; + /** + * WME Best Effort (BE) Access Category (AC) contention time statistics on + * the link. + */ + StaLinkLayerIfaceContentionTimeStats wmeBeContentionTimeStats; + /** + * WME Background (BK) Access Category (AC) contention time statistics on + * the link. + */ + StaLinkLayerIfaceContentionTimeStats wmeBkContentionTimeStats; + /** + * WME Video (VI) Access Category (AC) contention time statistics on the + * link. + */ + StaLinkLayerIfaceContentionTimeStats wmeViContentionTimeStats; + /** + * WME Voice (VO) Access Category (AC) contention time statistics on the + * link. + */ + StaLinkLayerIfaceContentionTimeStats wmeVoContentionTimeStats; + /** + * Per peer statistics for the link. + */ + StaPeerInfo[] peers; +} 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/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp index 4a69c2426b..c2de0122d7 100644 --- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp +++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp @@ -112,6 +112,285 @@ TEST_F(AidlStructUtilTest, CanConvertLegacyWifiMacInfosToAidlWithTwoMac) { EXPECT_EQ(static_cast(legacy_iface_info2.channel), aidl_iface_info2.channel); } +TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerMlStatsToAidl) { + legacy_hal::LinkLayerMlStats legacy_ml_stats{}; + // Add two radio stats + legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); + // Add two links. + legacy_ml_stats.links.push_back(legacy_hal::LinkStats{}); + legacy_ml_stats.links.push_back(legacy_hal::LinkStats{}); + // Set stats for each link. + for (legacy_hal::LinkStats& link : legacy_ml_stats.links) { + link.peers.push_back(legacy_hal::WifiPeerInfo{}); + link.peers.push_back(legacy_hal::WifiPeerInfo{}); + link.stat.beacon_rx = rand(); + link.stat.rssi_mgmt = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].retries = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = rand(); + + link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].retries = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand(); + link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = rand(); + + link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].retries = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = rand(); + + link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].retries = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand(); + link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = rand(); + + link.stat.time_slicing_duty_cycle_percent = rand(); + link.stat.num_peers = 2; + + // Set peer stats for each of the peers. + for (auto& peer : link.peers) { + peer.peer_info.bssload.sta_count = rand(); + peer.peer_info.bssload.chan_util = rand(); + wifi_rate_stat rate_stat1 = { + .rate = {3, 1, 2, 5, 0, 0}, + .tx_mpdu = 0, + .rx_mpdu = 1, + .mpdu_lost = 2, + .retries = 3, + .retries_short = 4, + .retries_long = 5, + }; + wifi_rate_stat rate_stat2 = { + .rate = {2, 2, 1, 6, 0, 1}, + .tx_mpdu = 6, + .rx_mpdu = 7, + .mpdu_lost = 8, + .retries = 9, + .retries_short = 10, + .retries_long = 11, + }; + peer.rate_stats.push_back(rate_stat1); + peer.rate_stats.push_back(rate_stat2); + } + } + // Set radio stats + for (auto& radio : legacy_ml_stats.radios) { + radio.stats.radio = rand(); + radio.stats.on_time = rand(); + radio.stats.tx_time = rand(); + radio.stats.rx_time = rand(); + radio.stats.on_time_scan = rand(); + radio.stats.on_time_nbd = rand(); + radio.stats.on_time_gscan = rand(); + radio.stats.on_time_roam_scan = rand(); + radio.stats.on_time_pno_scan = rand(); + radio.stats.on_time_hs20 = rand(); + for (int i = 0; i < 4; i++) { + radio.tx_time_per_levels.push_back(rand()); + } + + legacy_hal::wifi_channel_stat channel_stat1 = { + .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0}, + .on_time = 0x1111, + .cca_busy_time = 0x55, + }; + legacy_hal::wifi_channel_stat channel_stat2 = { + .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0}, + .on_time = 0x2222, + .cca_busy_time = 0x66, + }; + radio.channel_stats.push_back(channel_stat1); + radio.channel_stats.push_back(channel_stat2); + } + // Convert to AIDL + StaLinkLayerStats converted{}; + aidl_struct_util::convertLegacyLinkLayerMlStatsToAidl(legacy_ml_stats, &converted); + // Validate + int l = 0; + for (legacy_hal::LinkStats& link : legacy_ml_stats.links) { + EXPECT_EQ(link.stat.link_id, (uint8_t)converted.iface.links[l].linkId); + EXPECT_EQ(link.stat.beacon_rx, (uint32_t)converted.iface.links[l].beaconRx); + EXPECT_EQ(link.stat.rssi_mgmt, converted.iface.links[l].avgRssiMgmt); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].rx_mpdu, + converted.iface.links[l].wmeBePktStats.rxMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].tx_mpdu, + converted.iface.links[l].wmeBePktStats.txMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].mpdu_lost, + converted.iface.links[l].wmeBePktStats.lostMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].retries, + converted.iface.links[l].wmeBePktStats.retries); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_min, + (uint32_t)converted.iface.links[l] + .wmeBeContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_max, + (uint32_t)converted.iface.links[l] + .wmeBeContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_time_avg, + (uint32_t)converted.iface.links[l] + .wmeBeContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BE].contention_num_samples, + (uint32_t)converted.iface.links[l].wmeBeContentionTimeStats.contentionNumSamples); + + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].rx_mpdu, + converted.iface.links[l].wmeBkPktStats.rxMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].tx_mpdu, + converted.iface.links[l].wmeBkPktStats.txMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].mpdu_lost, + converted.iface.links[l].wmeBkPktStats.lostMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].retries, + converted.iface.links[l].wmeBkPktStats.retries); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_min, + (uint32_t)converted.iface.links[l] + .wmeBkContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_max, + (uint32_t)converted.iface.links[l] + .wmeBkContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_time_avg, + (uint32_t)converted.iface.links[l] + .wmeBkContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_BK].contention_num_samples, + (uint32_t)converted.iface.links[l].wmeBkContentionTimeStats.contentionNumSamples); + + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].rx_mpdu, + converted.iface.links[l].wmeViPktStats.rxMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].tx_mpdu, + converted.iface.links[l].wmeViPktStats.txMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].mpdu_lost, + converted.iface.links[l].wmeViPktStats.lostMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].retries, + converted.iface.links[l].wmeViPktStats.retries); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_min, + (uint32_t)converted.iface.links[l] + .wmeViContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_max, + (uint32_t)converted.iface.links[l] + .wmeViContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_time_avg, + (uint32_t)converted.iface.links[l] + .wmeViContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VI].contention_num_samples, + (uint32_t)converted.iface.links[l].wmeViContentionTimeStats.contentionNumSamples); + + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].rx_mpdu, + converted.iface.links[l].wmeVoPktStats.rxMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].tx_mpdu, + converted.iface.links[l].wmeVoPktStats.txMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].mpdu_lost, + converted.iface.links[l].wmeVoPktStats.lostMpdu); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].retries, + converted.iface.links[l].wmeVoPktStats.retries); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_min, + (uint32_t)converted.iface.links[l] + .wmeVoContentionTimeStats.contentionTimeMinInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_max, + (uint32_t)converted.iface.links[l] + .wmeVoContentionTimeStats.contentionTimeMaxInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_time_avg, + (uint32_t)converted.iface.links[l] + .wmeVoContentionTimeStats.contentionTimeAvgInUsec); + EXPECT_EQ(link.stat.ac[legacy_hal::WIFI_AC_VO].contention_num_samples, + (uint32_t)converted.iface.links[l].wmeVoContentionTimeStats.contentionNumSamples); + + EXPECT_EQ(link.stat.time_slicing_duty_cycle_percent, + converted.iface.links[l].timeSliceDutyCycleInPercent); + + EXPECT_EQ(link.peers.size(), converted.iface.links[l].peers.size()); + for (size_t i = 0; i < link.peers.size(); i++) { + EXPECT_EQ(link.peers[i].peer_info.bssload.sta_count, + converted.iface.links[l].peers[i].staCount); + EXPECT_EQ(link.peers[i].peer_info.bssload.chan_util, + converted.iface.links[l].peers[i].chanUtil); + for (size_t j = 0; j < link.peers[i].rate_stats.size(); j++) { + EXPECT_EQ( + link.peers[i].rate_stats[j].rate.preamble, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.preamble); + EXPECT_EQ(link.peers[i].rate_stats[j].rate.nss, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.nss); + EXPECT_EQ(link.peers[i].rate_stats[j].rate.bw, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rateInfo.bw); + EXPECT_EQ(link.peers[i].rate_stats[j].rate.rateMcsIdx, + (uint32_t)converted.iface.links[l] + .peers[i] + .rateStats[j] + .rateInfo.rateMcsIdx); + EXPECT_EQ(link.peers[i].rate_stats[j].tx_mpdu, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].txMpdu); + EXPECT_EQ(link.peers[i].rate_stats[j].rx_mpdu, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].rxMpdu); + EXPECT_EQ(link.peers[i].rate_stats[j].mpdu_lost, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].mpduLost); + EXPECT_EQ(link.peers[i].rate_stats[j].retries, + (uint32_t)converted.iface.links[l].peers[i].rateStats[j].retries); + } + } + ++l; + } // loop over links + + EXPECT_EQ(legacy_ml_stats.radios.size(), converted.radios.size()); + for (size_t i = 0; i < legacy_ml_stats.radios.size(); i++) { + EXPECT_EQ(legacy_ml_stats.radios[i].stats.radio, converted.radios[i].radioId); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time, + (uint32_t)converted.radios[i].onTimeInMs); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.tx_time, + (uint32_t)converted.radios[i].txTimeInMs); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.rx_time, + (uint32_t)converted.radios[i].rxTimeInMs); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_scan, + (uint32_t)converted.radios[i].onTimeInMsForScan); + EXPECT_EQ(legacy_ml_stats.radios[i].tx_time_per_levels.size(), + converted.radios[i].txTimeInMsPerLevel.size()); + for (size_t j = 0; j < legacy_ml_stats.radios[i].tx_time_per_levels.size(); j++) { + EXPECT_EQ(legacy_ml_stats.radios[i].tx_time_per_levels[j], + (uint32_t)converted.radios[i].txTimeInMsPerLevel[j]); + } + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_nbd, + (uint32_t)converted.radios[i].onTimeInMsForNanScan); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_gscan, + (uint32_t)converted.radios[i].onTimeInMsForBgScan); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_roam_scan, + (uint32_t)converted.radios[i].onTimeInMsForRoamScan); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_pno_scan, + (uint32_t)converted.radios[i].onTimeInMsForPnoScan); + EXPECT_EQ(legacy_ml_stats.radios[i].stats.on_time_hs20, + (uint32_t)converted.radios[i].onTimeInMsForHs20Scan); + EXPECT_EQ(legacy_ml_stats.radios[i].channel_stats.size(), + converted.radios[i].channelStats.size()); + for (size_t k = 0; k < legacy_ml_stats.radios[i].channel_stats.size(); k++) { + auto& legacy_channel_st = legacy_ml_stats.radios[i].channel_stats[k]; + EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20, + converted.radios[i].channelStats[k].channel.width); + EXPECT_EQ(legacy_channel_st.channel.center_freq, + converted.radios[i].channelStats[k].channel.centerFreq); + EXPECT_EQ(legacy_channel_st.channel.center_freq0, + converted.radios[i].channelStats[k].channel.centerFreq0); + EXPECT_EQ(legacy_channel_st.channel.center_freq1, + converted.radios[i].channelStats[k].channel.centerFreq1); + EXPECT_EQ(legacy_channel_st.cca_busy_time, + (uint32_t)converted.radios[i].channelStats[k].ccaBusyTimeInMs); + EXPECT_EQ(legacy_channel_st.on_time, + (uint32_t)converted.radios[i].channelStats[k].onTimeInMs); + } + } +} + TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerStatsToAidl) { legacy_hal::LinkLayerStats legacy_stats{}; legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{}); @@ -215,78 +494,79 @@ TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerStatsToAidl) { StaLinkLayerStats converted{}; aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &converted); - EXPECT_EQ(legacy_stats.iface.beacon_rx, (uint32_t)converted.iface.beaconRx); - EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt); + EXPECT_EQ(0, converted.iface.links[0].linkId); + EXPECT_EQ(legacy_stats.iface.beacon_rx, (uint32_t)converted.iface.links[0].beaconRx); + EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.links[0].avgRssiMgmt); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu, - converted.iface.wmeBePktStats.rxMpdu); + converted.iface.links[0].wmeBePktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu, - converted.iface.wmeBePktStats.txMpdu); + converted.iface.links[0].wmeBePktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost, - converted.iface.wmeBePktStats.lostMpdu); + converted.iface.links[0].wmeBePktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries, - converted.iface.wmeBePktStats.retries); + converted.iface.links[0].wmeBePktStats.retries); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min, - (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMinInUsec); + (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeMinInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max, - (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec); + (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeMaxInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg, - (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec); + (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionTimeAvgInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples, - (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionNumSamples); + (uint32_t)converted.iface.links[0].wmeBeContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu, - converted.iface.wmeBkPktStats.rxMpdu); + converted.iface.links[0].wmeBkPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu, - converted.iface.wmeBkPktStats.txMpdu); + converted.iface.links[0].wmeBkPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost, - converted.iface.wmeBkPktStats.lostMpdu); + converted.iface.links[0].wmeBkPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries, - converted.iface.wmeBkPktStats.retries); + converted.iface.links[0].wmeBkPktStats.retries); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min, - (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMinInUsec); + (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeMinInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max, - (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec); + (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeMaxInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg, - (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec); + (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionTimeAvgInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples, - (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionNumSamples); + (uint32_t)converted.iface.links[0].wmeBkContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu, - converted.iface.wmeViPktStats.rxMpdu); + converted.iface.links[0].wmeViPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu, - converted.iface.wmeViPktStats.txMpdu); + converted.iface.links[0].wmeViPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost, - converted.iface.wmeViPktStats.lostMpdu); + converted.iface.links[0].wmeViPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries, - converted.iface.wmeViPktStats.retries); + converted.iface.links[0].wmeViPktStats.retries); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min, - (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMinInUsec); + (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeMinInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max, - (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec); + (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeMaxInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg, - (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec); + (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionTimeAvgInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples, - (uint32_t)converted.iface.wmeViContentionTimeStats.contentionNumSamples); + (uint32_t)converted.iface.links[0].wmeViContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu, - converted.iface.wmeVoPktStats.rxMpdu); + converted.iface.links[0].wmeVoPktStats.rxMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu, - converted.iface.wmeVoPktStats.txMpdu); + converted.iface.links[0].wmeVoPktStats.txMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost, - converted.iface.wmeVoPktStats.lostMpdu); + converted.iface.links[0].wmeVoPktStats.lostMpdu); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries, - converted.iface.wmeVoPktStats.retries); + converted.iface.links[0].wmeVoPktStats.retries); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min, - (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMinInUsec); + (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeMinInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max, - (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec); + (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeMaxInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg, - (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec); + (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionTimeAvgInUsec); EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples, - (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionNumSamples); + (uint32_t)converted.iface.links[0].wmeVoContentionTimeStats.contentionNumSamples); EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent, - converted.iface.timeSliceDutyCycleInPercent); + converted.iface.links[0].timeSliceDutyCycleInPercent); EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size()); for (size_t i = 0; i < legacy_stats.radios.size(); i++) { @@ -331,29 +611,29 @@ TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerStatsToAidl) { } } - EXPECT_EQ(legacy_stats.peers.size(), converted.iface.peers.size()); + EXPECT_EQ(legacy_stats.peers.size(), converted.iface.links[0].peers.size()); for (size_t i = 0; i < legacy_stats.peers.size(); i++) { EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.sta_count, - converted.iface.peers[i].staCount); + converted.iface.links[0].peers[i].staCount); EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.chan_util, - converted.iface.peers[i].chanUtil); + converted.iface.links[0].peers[i].chanUtil); for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) { EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble, - (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.preamble); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.preamble); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.nss, - (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.nss); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.bw, - (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.bw); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx, - (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rateInfo.rateMcsIdx); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu, - (uint32_t)converted.iface.peers[i].rateStats[j].txMpdu); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].txMpdu); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu, - (uint32_t)converted.iface.peers[i].rateStats[j].rxMpdu); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].rxMpdu); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].mpdu_lost, - (uint32_t)converted.iface.peers[i].rateStats[j].mpduLost); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].mpduLost); EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].retries, - (uint32_t)converted.iface.peers[i].rateStats[j].retries); + (uint32_t)converted.iface.links[0].peers[i].rateStats[j].retries); } } } 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()}; diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp index ef7e2747c9..5e55315781 100644 --- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp +++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp @@ -145,7 +145,7 @@ TEST_P(WifiStaIfaceAidlTest, GetLinkLayerStats) { std::shared_ptr iface; auto status = createStaIface(&iface); if (status.isOk()) { - EXPECT_GT(link_layer_stats.iface.timeSliceDutyCycleInPercent, 0); + EXPECT_GT(link_layer_stats.iface.links[0].timeSliceDutyCycleInPercent, 0); } // Disable link layer stats collection.