summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiVendorHal.java95
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java82
2 files changed, 133 insertions, 44 deletions
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index 8851c7833..1c3ab48a1 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -34,6 +34,7 @@ import android.hardware.wifi.V1_0.RttType;
import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask;
import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters;
import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
+import android.hardware.wifi.V1_0.StaLinkLayerStats;
import android.hardware.wifi.V1_0.StaRoamingConfig;
import android.hardware.wifi.V1_0.StaRoamingState;
import android.hardware.wifi.V1_0.StaScanData;
@@ -622,55 +623,67 @@ public class WifiVendorHal {
* @return the statistics, or null if unable to do so
*/
public WifiLinkLayerStats getWifiLinkLayerStats() {
+ class AnswerBox {
+ public StaLinkLayerStats value = null;
+ }
+ AnswerBox answer = new AnswerBox();
synchronized (sLock) {
try {
if (mIWifiStaIface == null) return null;
- WifiLinkLayerStats out = new WifiLinkLayerStats();
- MutableBoolean answerBox = new MutableBoolean(false);
mIWifiStaIface.getLinkLayerStats((status, stats) -> {
- if (!ok(status)) return;
- out.status = 0; // TODO
- out.SSID = null; // TODO
- out.BSSID = null; // TODO
- out.beacon_rx = stats.iface.beaconRx;
- out.rssi_mgmt = stats.iface.avgRssiMgmt;
- /* WME Best Effort Access Category */
- out.rxmpdu_be = stats.iface.wmeBePktStats.rxMpdu;
- out.txmpdu_be = stats.iface.wmeBePktStats.txMpdu;
- out.lostmpdu_be = stats.iface.wmeBePktStats.lostMpdu;
- out.retries_be = stats.iface.wmeBePktStats.retries;
- /* WME Background Access Category */
- out.rxmpdu_bk = stats.iface.wmeBkPktStats.rxMpdu;
- out.txmpdu_bk = stats.iface.wmeBkPktStats.txMpdu;
- out.lostmpdu_bk = stats.iface.wmeBkPktStats.lostMpdu;
- out.retries_bk = stats.iface.wmeBkPktStats.retries;
- /* WME Video Access Category */
- out.rxmpdu_vi = stats.iface.wmeViPktStats.rxMpdu;
- out.txmpdu_vi = stats.iface.wmeViPktStats.txMpdu;
- out.lostmpdu_vi = stats.iface.wmeViPktStats.lostMpdu;
- out.retries_vi = stats.iface.wmeViPktStats.retries;
- /* WME Voice Access Category */
- out.rxmpdu_vo = stats.iface.wmeVoPktStats.rxMpdu;
- out.txmpdu_vo = stats.iface.wmeVoPktStats.txMpdu;
- out.lostmpdu_vo = stats.iface.wmeVoPktStats.lostMpdu;
- out.retries_vo = stats.iface.wmeVoPktStats.retries;
- out.on_time = stats.radio.onTimeInMs;
- out.tx_time = stats.radio.txTimeInMs;
- out.tx_time_per_level = new int[stats.radio.txTimeInMsPerLevel.size()];
- for (int i = 0; i < out.tx_time_per_level.length; i++) {
- out.tx_time_per_level[i] = stats.radio.txTimeInMsPerLevel.get(i);
- }
- out.rx_time = stats.radio.rxTimeInMs;
- out.on_time_scan = stats.radio.onTimeInMsForScan;
- answerBox.value = true;
- }
- );
- return answerBox.value ? out : null;
+ if (!ok(status)) return;
+ answer.value = stats;
+ });
} catch (RemoteException e) {
handleRemoteException(e);
return null;
}
}
+ WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats(answer.value);
+ return stats;
+ }
+
+ /**
+ * Makes the framework version of link layer stats from the hal version.
+ */
+ @VisibleForTesting
+ static WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) {
+ if (stats == null) return null;
+ WifiLinkLayerStats out = new WifiLinkLayerStats();
+ // unpopulated: out.status, out.SSID, out.BSSID
+ out.beacon_rx = stats.iface.beaconRx;
+ out.rssi_mgmt = stats.iface.avgRssiMgmt;
+ // Statistics are broken out by Wireless Multimedia Extensions categories
+ // WME Best Effort Access Category
+ out.rxmpdu_be = stats.iface.wmeBePktStats.rxMpdu;
+ out.txmpdu_be = stats.iface.wmeBePktStats.txMpdu;
+ out.lostmpdu_be = stats.iface.wmeBePktStats.lostMpdu;
+ out.retries_be = stats.iface.wmeBePktStats.retries;
+ // WME Background Access Category
+ out.rxmpdu_bk = stats.iface.wmeBkPktStats.rxMpdu;
+ out.txmpdu_bk = stats.iface.wmeBkPktStats.txMpdu;
+ out.lostmpdu_bk = stats.iface.wmeBkPktStats.lostMpdu;
+ out.retries_bk = stats.iface.wmeBkPktStats.retries;
+ // WME Video Access Category
+ out.rxmpdu_vi = stats.iface.wmeViPktStats.rxMpdu;
+ out.txmpdu_vi = stats.iface.wmeViPktStats.txMpdu;
+ out.lostmpdu_vi = stats.iface.wmeViPktStats.lostMpdu;
+ out.retries_vi = stats.iface.wmeViPktStats.retries;
+ // WME Voice Access Category
+ out.rxmpdu_vo = stats.iface.wmeVoPktStats.rxMpdu;
+ out.txmpdu_vo = stats.iface.wmeVoPktStats.txMpdu;
+ out.lostmpdu_vo = stats.iface.wmeVoPktStats.lostMpdu;
+ out.retries_vo = stats.iface.wmeVoPktStats.retries;
+ out.on_time = stats.radio.onTimeInMs;
+ out.tx_time = stats.radio.txTimeInMs;
+ out.tx_time_per_level = new int[stats.radio.txTimeInMsPerLevel.size()];
+ for (int i = 0; i < out.tx_time_per_level.length; i++) {
+ out.tx_time_per_level[i] = stats.radio.txTimeInMsPerLevel.get(i);
+ }
+ out.rx_time = stats.radio.rxTimeInMs;
+ out.on_time_scan = stats.radio.onTimeInMsForScan;
+ // unused: stats.timeStampInMs;
+ return out;
}
@VisibleForTesting
@@ -678,7 +691,7 @@ public class WifiVendorHal {
/**
* Enables the linkLayerStats in the Hal.
- * <p>
+ *
* This is called unconditionally whenever we create a STA interface.
*/
private void enableLinkLayerStats() {
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index f6f4240de..9bf3509c2 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -29,6 +29,9 @@ import android.hardware.wifi.V1_0.RttConfig;
import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities;
import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities;
import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
+import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats;
+import android.hardware.wifi.V1_0.StaLinkLayerRadioStats;
+import android.hardware.wifi.V1_0.StaLinkLayerStats;
import android.hardware.wifi.V1_0.StaScanData;
import android.hardware.wifi.V1_0.StaScanDataFlagMask;
import android.hardware.wifi.V1_0.StaScanResult;
@@ -47,6 +50,7 @@ import android.hardware.wifi.V1_0.WifiStatusCode;
import android.net.apf.ApfCapabilities;
import android.net.wifi.RttManager;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiLinkLayerStats;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
@@ -565,7 +569,7 @@ public class WifiVendorHalTest {
/**
* Test enablement of link layer stats after startup
- * <p>
+ *
* Request link layer stats before HAL start
* - should not make it to the HAL layer
* Start the HAL in STA mode
@@ -590,7 +594,7 @@ public class WifiVendorHalTest {
/**
* Test that link layer stats are not enabled and harmless in AP mode
- * <p>
+ *
* Start the HAL in AP mode
* - stats should not be enabled
* Request link layer stats
@@ -610,7 +614,79 @@ public class WifiVendorHalTest {
verify(mIWifiStaIface, never()).getLinkLayerStats(any());
}
- // TODO(b/34900534) add test for correct MOVE CORRESPONDING of fields
+ /**
+ * Test that the link layer stats fields are populated correctly.
+ *
+ * This is done by filling with random values and then using toString on the
+ * original and converted values, comparing just the numerics in the result.
+ * This makes the assumption that the fields are in the same order in both string
+ * representations, which is not quite true. So apply some fixups before the final
+ * comparison.
+ */
+ @Test
+ public void testLinkLayerStatsAssignment() throws Exception {
+ Random r = new Random(1775968256);
+ StaLinkLayerStats stats = new StaLinkLayerStats();
+ randomizePacketStats(r, stats.iface.wmeBePktStats);
+ randomizePacketStats(r, stats.iface.wmeBkPktStats);
+ randomizePacketStats(r, stats.iface.wmeViPktStats);
+ randomizePacketStats(r, stats.iface.wmeVoPktStats);
+ randomizeRadioStats(r, stats.radio);
+ stats.timeStampInMs = 42; // currently dropped in conversion
+
+ String expected = numbersOnly(stats.toString());
+
+ WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats(stats);
+
+ String actual = numbersOnly(converted.toString());
+
+ // Do the required fixups to the both expected and actual
+ expected = rmValue(expected, stats.radio.rxTimeInMs);
+ expected = rmValue(expected, stats.radio.onTimeInMsForScan);
+
+ actual = rmValue(actual, stats.radio.rxTimeInMs);
+ actual = rmValue(actual, stats.radio.onTimeInMsForScan);
+ actual = actual + "42 ";
+
+ // The remaining fields should agree
+ assertEquals(expected, actual);
+ }
+
+ /** Just the digits with delimiting spaces, please */
+ private static String numbersOnly(String s) {
+ return s.replaceAll("[^0-9]+", " ");
+ }
+
+ /** Remove the given value from the space-delimited string, or die trying. */
+ private static String rmValue(String s, long value) throws Exception {
+ String ans = s.replaceAll(" " + value + " ", " ");
+ assertNotEquals(s, ans);
+ return ans;
+ }
+
+ /**
+ * Populate packet stats with non-negative random values
+ */
+ private static void randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats) {
+ pstats.rxMpdu = r.nextLong() & 0xFFFFFFFFFFL; // more than 32 bits
+ pstats.txMpdu = r.nextLong() & 0xFFFFFFFFFFL;
+ pstats.lostMpdu = r.nextLong() & 0xFFFFFFFFFFL;
+ pstats.retries = r.nextLong() & 0xFFFFFFFFFFL;
+ }
+
+ /**
+ * Populate radio stats with non-negative random values
+ */
+ private static void randomizeRadioStats(Random r, StaLinkLayerRadioStats rstats) {
+ rstats.onTimeInMs = r.nextInt() & 0xFFFFFF;
+ rstats.txTimeInMs = r.nextInt() & 0xFFFFFF;
+ for (int i = 0; i < 4; i++) {
+ Integer v = r.nextInt() & 0xFFFFFF;
+ rstats.txTimeInMsPerLevel.add(v);
+ }
+ rstats.rxTimeInMs = r.nextInt() & 0xFFFFFF;
+ rstats.onTimeInMsForScan = r.nextInt() & 0xFFFFFF;
+ }
/**
* Test that getFirmwareVersion() and getDriverVersion() work