Add StaLinkLayerStats V1_3
Gets additional scan related information from legacy_hal up to
framework.
Bug: 77603419
Test: compile, unit tests
Change-Id: I9c948166b640af192c8e6f85ed6c76719e0937a4
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 95fbf83..5e87c1c 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -7,7 +7,9 @@
enabled: true,
},
srcs: [
+ "types.hal",
"IWifi.hal",
+ "IWifiStaIface.hal",
],
interfaces: [
"android.hardware.wifi@1.0",
@@ -15,6 +17,10 @@
"android.hardware.wifi@1.2",
"android.hidl.base@1.0",
],
+ types: [
+ "StaLinkLayerRadioStats",
+ "StaLinkLayerStats",
+ ],
gen_java: true,
}
diff --git a/wifi/1.3/IWifiStaIface.hal b/wifi/1.3/IWifiStaIface.hal
new file mode 100644
index 0000000..0dc6128
--- /dev/null
+++ b/wifi/1.3/IWifiStaIface.hal
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 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@1.3;
+
+import @1.0::WifiStatus;
+import @1.2::IWifiStaIface;
+
+/**
+ * Interface used to represent a single STA iface.
+ *
+ * IWifiChip.createStaIface() may return a @1.3::IWifiStaIface when supported.
+ */
+interface IWifiStaIface extends @1.2::IWifiStaIface {
+ /**
+ * Retrieve the latest link layer stats.
+ * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if
+ * link layer stats collection hasn't been explicitly enabled.
+ *
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_STARTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ * @return stats Instance of |LinkLayerStats|.
+ */
+ getLinkLayerStats_1_3() generates (WifiStatus status, StaLinkLayerStats stats);
+};
diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp
index e793236..c88ddaa 100644
--- a/wifi/1.3/default/hidl_struct_util.cpp
+++ b/wifi/1.3/default/hidl_struct_util.cpp
@@ -785,7 +785,7 @@
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
- StaLinkLayerStats* hidl_stats) {
+ V1_3::StaLinkLayerStats* hidl_stats) {
if (!hidl_stats) {
return false;
}
@@ -826,16 +826,26 @@
hidl_stats->iface.wmeVoPktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
// radio legacy_stats conversion.
- std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
+ std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
for (const auto& legacy_radio_stats : legacy_stats.radios) {
- StaLinkLayerRadioStats hidl_radio_stats;
- hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
- hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
- hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
- hidl_radio_stats.onTimeInMsForScan =
+ V1_3::StaLinkLayerRadioStats hidl_radio_stats;
+ hidl_radio_stats.V1_0.onTimeInMs = legacy_radio_stats.stats.on_time;
+ hidl_radio_stats.V1_0.txTimeInMs = legacy_radio_stats.stats.tx_time;
+ hidl_radio_stats.V1_0.rxTimeInMs = legacy_radio_stats.stats.rx_time;
+ hidl_radio_stats.V1_0.onTimeInMsForScan =
legacy_radio_stats.stats.on_time_scan;
- hidl_radio_stats.txTimeInMsPerLevel =
+ hidl_radio_stats.V1_0.txTimeInMsPerLevel =
legacy_radio_stats.tx_time_per_levels;
+ hidl_radio_stats.onTimeInMsForNanScan =
+ legacy_radio_stats.stats.on_time_nbd;
+ hidl_radio_stats.onTimeInMsForBgScan =
+ legacy_radio_stats.stats.on_time_gscan;
+ hidl_radio_stats.onTimeInMsForRoamScan =
+ legacy_radio_stats.stats.on_time_roam_scan;
+ hidl_radio_stats.onTimeInMsForPnoScan =
+ legacy_radio_stats.stats.on_time_pno_scan;
+ hidl_radio_stats.onTimeInMsForHs20Scan =
+ legacy_radio_stats.stats.on_time_hs20;
hidl_radios_stats.push_back(hidl_radio_stats);
}
hidl_stats->radios = hidl_radios_stats;
diff --git a/wifi/1.3/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h
index e2ba00c..8df484d 100644
--- a/wifi/1.3/default/hidl_struct_util.h
+++ b/wifi/1.3/default/hidl_struct_util.h
@@ -24,6 +24,7 @@
#include <android/hardware/wifi/1.2/IWifiChip.h>
#include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
#include <android/hardware/wifi/1.2/types.h>
+#include <android/hardware/wifi/1.3/types.h>
#include "wifi_legacy_hal.h"
@@ -89,7 +90,7 @@
std::vector<StaScanData>* hidl_scan_datas);
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
- StaLinkLayerStats* hidl_stats);
+ V1_3::StaLinkLayerStats* hidl_stats);
bool convertLegacyRoamingCapabilitiesToHidl(
const legacy_hal::wifi_roaming_capabilities& legacy_caps,
StaRoamingCapabilities* hidl_caps);
diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
index 4cd3719..d600a2b 100644
--- a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
@@ -126,6 +126,118 @@
EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
hidl_iface_info2.channel);
}
+
+TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
+ legacy_hal::LinkLayerStats legacy_stats{};
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.iface.beacon_rx = rand();
+ legacy_stats.iface.rssi_mgmt = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
+
+ for (auto& radio : legacy_stats.radios) {
+ 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());
+ }
+ }
+
+ V1_3::StaLinkLayerStats converted{};
+ hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
+ &converted);
+ EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx);
+ EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
+ converted.iface.wmeBePktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
+ converted.iface.wmeBePktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
+ converted.iface.wmeBePktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
+ converted.iface.wmeBePktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
+ converted.iface.wmeBkPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
+ converted.iface.wmeBkPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
+ converted.iface.wmeBkPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
+ converted.iface.wmeBkPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
+ converted.iface.wmeViPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
+ converted.iface.wmeViPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
+ converted.iface.wmeViPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
+ converted.iface.wmeViPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
+ converted.iface.wmeVoPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
+ converted.iface.wmeVoPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
+ converted.iface.wmeVoPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
+ converted.iface.wmeVoPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
+ for (int i = 0; i < legacy_stats.radios.size(); i++) {
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
+ converted.radios[i].V1_0.onTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
+ converted.radios[i].V1_0.txTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
+ converted.radios[i].V1_0.rxTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
+ converted.radios[i].V1_0.onTimeInMsForScan);
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
+ converted.radios[i].V1_0.txTimeInMsPerLevel.size());
+ for (int j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
+ j++) {
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
+ converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
+ }
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
+ converted.radios[i].onTimeInMsForNanScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
+ converted.radios[i].onTimeInMsForBgScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
+ converted.radios[i].onTimeInMsForRoamScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
+ converted.radios[i].onTimeInMsForPnoScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
+ converted.radios[i].onTimeInMsForHs20Scan);
+ }
+}
} // namespace implementation
} // namespace V1_3
} // namespace wifi
diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp
index 63341df..b0fa1ae 100644
--- a/wifi/1.3/default/wifi_sta_iface.cpp
+++ b/wifi/1.3/default/wifi_sta_iface.cpp
@@ -152,6 +152,13 @@
hidl_status_cb);
}
+Return<void> WifiStaIface::getLinkLayerStats_1_3(
+ getLinkLayerStats_1_3_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getLinkLayerStatsInternal_1_3,
+ hidl_status_cb);
+}
+
Return<void> WifiStaIface::startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) {
@@ -445,8 +452,13 @@
return createWifiStatusFromLegacyError(legacy_status);
}
-std::pair<WifiStatus, StaLinkLayerStats>
+std::pair<WifiStatus, V1_0::StaLinkLayerStats>
WifiStaIface::getLinkLayerStatsInternal() {
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+WifiStaIface::getLinkLayerStatsInternal_1_3() {
legacy_hal::wifi_error legacy_status;
legacy_hal::LinkLayerStats legacy_stats;
std::tie(legacy_status, legacy_stats) =
@@ -454,7 +466,7 @@
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
- StaLinkLayerStats hidl_stats;
+ V1_3::StaLinkLayerStats hidl_stats;
if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
&hidl_stats)) {
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
diff --git a/wifi/1.3/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h
index 0fc61e2..bc3090f 100644
--- a/wifi/1.3/default/wifi_sta_iface.h
+++ b/wifi/1.3/default/wifi_sta_iface.h
@@ -19,7 +19,7 @@
#include <android-base/macros.h>
#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.2/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
#include <wifi_system/interface_tool.h>
@@ -36,7 +36,7 @@
/**
* HIDL interface object used to control a STA Iface instance.
*/
-class WifiStaIface : public V1_2::IWifiStaIface {
+class WifiStaIface : public V1_3::IWifiStaIface {
public:
WifiStaIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -75,6 +75,8 @@
disableLinkLayerStatsCollection_cb hidl_status_cb) override;
Return<void> getLinkLayerStats(
getLinkLayerStats_cb hidl_status_cb) override;
+ Return<void> getLinkLayerStats_1_3(
+ getLinkLayerStats_1_3_cb hidl_status_cb) override;
Return<void> startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) override;
@@ -130,7 +132,9 @@
WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
WifiStatus disableLinkLayerStatsCollectionInternal();
- std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+ std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
+ std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+ getLinkLayerStatsInternal_1_3();
WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
int32_t min_rssi);
WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
diff --git a/wifi/1.3/types.hal b/wifi/1.3/types.hal
new file mode 100644
index 0000000..4585ff3
--- /dev/null
+++ b/wifi/1.3/types.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018 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@1.3;
+
+import @1.0::StaLinkLayerRadioStats;
+import @1.0::StaLinkLayerIfaceStats;
+import @1.0::TimeStampInMs;
+
+struct StaLinkLayerRadioStats {
+ /**
+ * Baseline information as defined in HAL 1.0.
+ */
+ @1.0::StaLinkLayerRadioStats V1_0;
+
+ /**
+ * Total time for which the radio is awake due to NAN scan since boot or crash.
+ */
+ uint32_t onTimeInMsForNanScan;
+
+ /**
+ * Total time for which the radio is awake due to background scan since boot or crash.
+ */
+ uint32_t onTimeInMsForBgScan;
+
+ /**
+ * Total time for which the radio is awake due to roam scan since boot or crash.
+ */
+ uint32_t onTimeInMsForRoamScan;
+
+ /**
+ * Total time for which the radio is awake due to PNO scan since boot or crash.
+ */
+ uint32_t onTimeInMsForPnoScan;
+
+ /**
+ * Total time for which the radio is awake due to Hotspot 2.0 scans and GAS exchange since boot
+ * or crash.
+ */
+ uint32_t onTimeInMsForHs20Scan;
+};
+
+/**
+ * Link layer stats retrieved via |getLinkLayerStats|.
+ */
+struct StaLinkLayerStats {
+ StaLinkLayerIfaceStats iface;
+ vec<StaLinkLayerRadioStats> radios;
+ /**
+ * TimeStamp for each stats sample.
+ * This is the absolute milliseconds from boot when these stats were
+ * sampled.
+ */
+ TimeStampInMs timeStampInMs;
+};
\ No newline at end of file