diff options
-rw-r--r-- | service/java/com/android/server/wifi/WifiVendorHal.java | 95 | ||||
-rw-r--r-- | tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java | 82 |
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 |