diff options
4 files changed, 122 insertions, 47 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 49edc366a..234b04799 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -27,7 +27,6 @@ import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT; -import static com.android.server.wifi.WifiHealthMonitor.SCAN_RSSI_VALID_TIME_MS; import android.annotation.IntDef; import android.annotation.NonNull; @@ -1875,6 +1874,7 @@ public class ClientModeImpl extends StateMachine { mWifiDiagnostics.dump(fd, pw, args); dumpIpClient(fd, pw, args); mWifiConnectivityManager.dump(fd, pw, args); + mWifiHealthMonitor.dump(fd, pw, args); mWifiInjector.getWakeupController().dump(fd, pw, args); mLinkProbeManager.dump(fd, pw, args); mWifiInjector.getWifiLastResortWatchdog().dump(fd, pw, args); @@ -2950,7 +2950,8 @@ public class ClientModeImpl extends StateMachine { if (blocklistReason != -1) { int networkId = (configuration == null) ? WifiConfiguration.INVALID_NETWORK_ID : configuration.networkId; - int scanRssi = mWifiConfigManager.findScanRssi(networkId, SCAN_RSSI_VALID_TIME_MS); + int scanRssi = mWifiConfigManager.findScanRssi(networkId, + mWifiHealthMonitor.getScanRssiValidTimeMs()); mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason); checkAbnormalConnectionFailureAndTakeBugReport(ssid); boolean isLowRssi = false; @@ -4062,7 +4063,8 @@ public class ClientModeImpl extends StateMachine { } mTargetNetworkId = netId; // Update scorecard while there is still state from existing connection - int scanRssi = mWifiConfigManager.findScanRssi(netId, SCAN_RSSI_VALID_TIME_MS); + int scanRssi = mWifiConfigManager.findScanRssi(netId, + mWifiHealthMonitor.getScanRssiValidTimeMs()); mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID); @@ -5470,7 +5472,8 @@ public class ClientModeImpl extends StateMachine { loge("CMD_START_ROAM and no config, bail out..."); break; } - int scanRssi = mWifiConfigManager.findScanRssi(netId, SCAN_RSSI_VALID_TIME_MS); + int scanRssi = mWifiConfigManager.findScanRssi(netId, + mWifiHealthMonitor.getScanRssiValidTimeMs()); mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID); setTargetBssid(config, bssid); mTargetNetworkId = netId; diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java index 0b0c68d88..065ef3fd0 100644 --- a/service/java/com/android/server/wifi/WifiHealthMonitor.java +++ b/service/java/com/android/server/wifi/WifiHealthMonitor.java @@ -48,6 +48,8 @@ import com.android.server.wifi.util.ScanResultUtil; import com.google.protobuf.InvalidProtocolBufferException; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -92,17 +94,14 @@ public class WifiHealthMonitor { private static final int MIN_NUM_BSSID_SCAN_2G = 2; // Minimum number of BSSIDs found above 2G with a normal scan private static final int MIN_NUM_BSSID_SCAN_ABOVE_2G = 2; - // Maximum scan RSSI valid time for scan RSSI search which is done by finding - // the maximum RSSI found among all valid scan detail entries of each network's scanDetailCache - // If a scanDetail is seen more than SCAN_RSSI_VALID_TIME_MS ago, - // it will not be considered valid anymore. - static final int SCAN_RSSI_VALID_TIME_MS = 6_000; + static final int DEFAULT_SCAN_RSSI_VALID_TIME_MS = 5_000; + static final int STATIONARY_SCAN_RSSI_VALID_TIME_MS = 20_000; // Minimum Tx speed in Mbps for disconnection stats collection // Disconnection events with Tx speed below this threshold are not // included in connection stats collection. static final int HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS = 54; - static final int HEALTH_MONITOR_COUNT_MIN_TX_RATE = 6; + static final int HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC = 2; private final Context mContext; private final WifiConfigManager mWifiConfigManager; private final WifiScoreCard mWifiScoreCard; @@ -126,6 +125,7 @@ public class WifiHealthMonitor { private int mNumNetworkSufficientRecentStatsOnly = 0; private int mNumNetworkSufficientRecentPrevStats = 0; private boolean mHasNewDataForWifiMetrics = false; + private int mDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; WifiHealthMonitor(Context context, WifiInjector wifiInjector, Clock clock, WifiConfigManager wifiConfigManager, WifiScoreCard wifiScoreCard, Handler handler, @@ -211,10 +211,21 @@ public class WifiHealthMonitor { */ public void setDeviceMobilityState(@DeviceMobilityState int newState) { logd("Device mobility state: " + newState); + mDeviceMobilityState = newState; mWifiSystemInfoStats.setMobilityState(newState); } /** + * Get the maximum scan RSSI valid time for scan RSSI search which is done by finding + * the maximum RSSI found among all valid scan detail entries of each network's scanDetailCache + * If a scanDetail was older than the returned value, it will not be considered valid. + */ + public int getScanRssiValidTimeMs() { + return (mDeviceMobilityState == WifiManager.DEVICE_MOBILITY_STATE_STATIONARY) + ? STATIONARY_SCAN_RSSI_VALID_TIME_MS : DEFAULT_SCAN_RSSI_VALID_TIME_MS; + } + + /** * Issue read request to prepare for post-boot detection. */ private void requestReadForPostBootDetection() { @@ -287,6 +298,34 @@ public class WifiHealthMonitor { mPostBootDetectionListener, mHandler); } + /** + * Dump the internal state of WifiHealthMonitor. + */ + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("Dump of WifiHealthMonitor"); + pw.println("WifiHealthMonitor - Log Begin ----"); + pw.println("System Info Stats"); + pw.println(mWifiSystemInfoStats); + pw.println("configured network connection stats"); + List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); + for (WifiConfiguration network : configuredNetworks) { + if (isInvalidConfiguredNetwork(network)) continue; + PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); + int cntName = WifiScoreCard.CNT_CONNECTION_ATTEMPT; + if (perNetwork.getStatsCurrBuild().getCount(cntName) > 0 + || perNetwork.getRecentStats().getCount(cntName) > 0) { + pw.println(mWifiScoreCard.lookupNetwork(network.SSID)); + } + } + pw.println("networks with failure increase: "); + pw.println(mFailureStatsIncrease); + pw.println("networks with failure drop: "); + pw.println(mFailureStatsDecrease); + pw.println("networks with high failure without previous stats: "); + pw.println(mFailureStatsHigh); + pw.println("WifiHealthMonitor - Log End ----"); + } + private synchronized void dailyDetectionHandler() { logd("Run daily detection"); // Clear daily detection result @@ -301,10 +340,9 @@ public class WifiHealthMonitor { scheduleDailyDetectionAlarm(DAILY_DETECTION_INTERVAL_MS); List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); for (WifiConfiguration network : configuredNetworks) { - if (isInValidConfiguredNetwork(network)) { + if (isInvalidConfiguredNetwork(network)) { continue; } - logd(network.SSID); PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); int detectionFlag = perNetwork.dailyDetection(mFailureStatsDecrease, @@ -319,10 +357,10 @@ public class WifiHealthMonitor { connectionDurationSec += perNetwork.getRecentStats().getCount( WifiScoreCard.CNT_CONNECTION_DURATION_SEC); - logd("before daily update: " + perNetwork.toString()); + logd("before daily update: " + perNetwork); // Update historical stats with dailyStats and clear dailyStats perNetwork.updateAfterDailyDetection(); - logd("after daily update: " + perNetwork.toString()); + logd("after daily update: " + perNetwork); } logd("total connection duration: " + connectionDurationSec); logd("#networks w/ sufficient recent stats: " + mNumNetworkSufficientRecentStatsOnly); @@ -413,7 +451,7 @@ public class WifiHealthMonitor { return stats; } - private boolean isInValidConfiguredNetwork(WifiConfiguration config) { + private boolean isInvalidConfiguredNetwork(WifiConfiguration config) { return (config == null || WifiManager.UNKNOWN_SSID.equals(config.SSID) || config.SSID == null); } @@ -454,7 +492,7 @@ public class WifiHealthMonitor { private void requestReadAllNetworks() { List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); for (WifiConfiguration network : configuredNetworks) { - if (isInValidConfiguredNetwork(network)) { + if (isInvalidConfiguredNetwork(network)) { continue; } logd(network.SSID); @@ -475,15 +513,15 @@ public class WifiHealthMonitor { private void updateAllNetworkAfterSwBuildChange() { List<WifiConfiguration> configuredNetworks = mWifiConfigManager.getConfiguredNetworks(); for (WifiConfiguration network : configuredNetworks) { - if (isInValidConfiguredNetwork(network)) { + if (isInvalidConfiguredNetwork(network)) { continue; } logd(network.SSID); WifiScoreCard.PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(network.SSID); - logd("before SW build update: " + perNetwork.toString()); + logd("before SW build update: " + perNetwork); perNetwork.updateAfterSwBuildChange(); - logd("after SW build update: " + perNetwork.toString()); + logd("after SW build update: " + perNetwork); } } @@ -575,6 +613,16 @@ public class WifiHealthMonitor { void incrementCount(@FailureReasonCode int reasonCode) { mCount[reasonCode]++; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < NUMBER_FAILURE_REASON_CODE; i++) { + if (mCount[i] == 0) continue; + sb.append(FAILURE_REASON_NAME[i]).append(": ").append(mCount[i]).append(" "); + } + return sb.toString(); + } } /** * A class maintaining current OS, Wifi APK, Wifi driver and firmware build version information. @@ -701,8 +749,8 @@ public class WifiHealthMonitor { return false; } - logd(" from Memory: " + mCurrSoftwareBuildInfo.toString()); - logd(" from SW: " + currSoftwareBuildInfo.toString()); + logd(" from Memory: " + mCurrSoftwareBuildInfo); + logd(" from SW: " + currSoftwareBuildInfo); return (!mCurrSoftwareBuildInfo.equals(currSoftwareBuildInfo)); } @@ -854,16 +902,19 @@ public class WifiHealthMonitor { StringBuilder sb = new StringBuilder(); if (mCurrSoftwareBuildInfo != null) { sb.append("current SW build: "); - sb.append(mCurrSoftwareBuildInfo.toString()); + sb.append(mCurrSoftwareBuildInfo); } if (mPrevSoftwareBuildInfo != null) { - sb.append(" previous SW build: "); - sb.append(mPrevSoftwareBuildInfo.toString()); + sb.append("\n"); + sb.append("previous SW build: "); + sb.append(mPrevSoftwareBuildInfo); } - sb.append(" currScanStats: "); - sb.append(mCurrScanStats.toString()); - sb.append(" prevScanStats: "); - sb.append(mPrevScanStats.toString()); + sb.append("\n"); + sb.append("currScanStats: "); + sb.append(mCurrScanStats); + sb.append("\n"); + sb.append("prevScanStats: "); + sb.append(mPrevScanStats); return sb.toString(); } } diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java index 071b9634d..346a8febe 100644 --- a/service/java/com/android/server/wifi/WifiScoreCard.java +++ b/service/java/com/android/server/wifi/WifiScoreCard.java @@ -20,8 +20,8 @@ import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS; import static android.net.wifi.WifiInfo.INVALID_RSSI; import static android.net.wifi.WifiInfo.LINK_SPEED_UNKNOWN; -import static com.android.server.wifi.WifiHealthMonitor.HEALTH_MONITOR_COUNT_MIN_TX_RATE; import static com.android.server.wifi.WifiHealthMonitor.HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS; +import static com.android.server.wifi.WifiHealthMonitor.HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC; import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_REJECTION; import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_TIMEOUT; import static com.android.server.wifi.WifiHealthMonitor.REASON_AUTH_FAILURE; @@ -70,6 +70,7 @@ import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -295,7 +296,7 @@ public class WifiScoreCard { wifiInfo.getRssi(), wifiInfo.getLinkSpeed()); perBssid.setNetworkConfigId(wifiInfo.getNetworkId()); - logd("BSSID update " + event.toString() + " ID: " + perBssid.id + " " + wifiInfo); + logd("BSSID update " + event + " ID: " + perBssid.id + " " + wifiInfo); } /** @@ -305,7 +306,7 @@ public class WifiScoreCard { private void updatePerNetwork(WifiScoreCardProto.Event event, String ssid, int rssi, int txSpeed, int failureReason) { PerNetwork perNetwork = lookupNetwork(ssid); - logd("network update " + event.toString() + ((ssid == null) ? " " : " " + logd("network update " + event + ((ssid == null) ? " " : " " + ssid) + " ID: " + perNetwork.id + " RSSI " + rssi + " txSpeed " + txSpeed); perNetwork.updateEventStats(event, rssi, txSpeed, failureReason); } @@ -335,12 +336,12 @@ public class WifiScoreCard { } private int geTxLinkSpeedWithSufficientTxRate(@NonNull ExtendedWifiInfo wifiInfo) { - double txRate = wifiInfo.getSuccessfulTxPacketsPerSecond() + int txRate = (int) Math.ceil(wifiInfo.getSuccessfulTxPacketsPerSecond() + wifiInfo.getLostTxPacketsPerSecond() - + wifiInfo.getRetriedTxPacketsPerSecond(); + + wifiInfo.getRetriedTxPacketsPerSecond()); int txSpeed = wifiInfo.getTxLinkSpeedMbps(); logd("txRate: " + txRate + " txSpeed: " + txSpeed); - return (txRate >= HEALTH_MONITOR_COUNT_MIN_TX_RATE) ? txSpeed : LINK_SPEED_UNKNOWN; + return (txRate >= HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC) ? txSpeed : LINK_SPEED_UNKNOWN; } /** Wait a few seconds before considering the roam successful */ @@ -915,15 +916,19 @@ public class WifiScoreCard { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(" LastRssiPollTime: " + mLastRssiPollTimeMs); + sb.append("SSID: ").append(ssid).append("\n"); + Calendar c = Calendar.getInstance(); + if (mLastRssiPollTimeMs != TS_NONE) { + sb.append(" LastRssiPollTime: "); + c.setTimeInMillis(mLastRssiPollTimeMs); + sb.append(String.format("%tm-%td %tH:%tM:%tS", c, c, c, c, c)); + } sb.append(" LastRssiPoll: " + mLastRssiPoll); sb.append(" LastTxSpeedPoll: " + mLastTxSpeedPoll); sb.append("\n"); - sb.append(" StatsRecent: " + mRecentStats.toString()); - sb.append("\n"); - sb.append(" StatsCurr: " + mStatsCurrBuild.toString()); - sb.append("\n"); - sb.append(" StatsPrev: " + mStatsPrevBuild.toString()); + sb.append(" StatsRecent: ").append(mRecentStats).append("\n"); + sb.append(" StatsCurr: ").append(mStatsCurrBuild).append("\n"); + sb.append(" StatsPrev: ").append(mStatsPrevBuild); return sb.toString(); } private void handleDisconnection() { @@ -1023,12 +1028,11 @@ public class WifiScoreCard { private void dailyDetectionDisconnectionEvent(FailureStats statsDec, FailureStats statsInc, FailureStats statsHigh) { // Skip daily detection if recentStats is not sufficient - if (mRecentStats.getCount(CNT_DISCONNECTION) - < mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()) { + int minConnectAttempt = mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt(); + if (mRecentStats.getCount(CNT_CONNECTION_ATTEMPT) < minConnectAttempt) { return; } - if (mStatsPrevBuild.getCount(CNT_DISCONNECTION) - < mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()) { + if (mStatsPrevBuild.getCount(CNT_CONNECTION_ATTEMPT) < minConnectAttempt) { recentStatsHighDetectionDisconnection(statsHigh); } else { statsDeltaDetectionDisconnection(statsDec, statsInc); @@ -1083,11 +1087,11 @@ public class WifiScoreCard { statsDeltaDetection(statsDec, statsInc, CNT_SHORT_CONNECTION_NONLOCAL, REASON_SHORT_CONNECTION_NONLOCAL, mDeviceConfigFacade.getShortConnectionNonlocalCountMin(), - CNT_DISCONNECTION); + CNT_CONNECTION_ATTEMPT); statsDeltaDetection(statsDec, statsInc, CNT_DISCONNECTION_NONLOCAL, REASON_DISCONNECTION_NONLOCAL, mDeviceConfigFacade.getDisconnectionNonlocalCountMin(), - CNT_DISCONNECTION); + CNT_CONNECTION_ATTEMPT); } private void recentStatsHighDetectionDisconnection(FailureStats statsHigh) { @@ -1139,7 +1143,7 @@ public class WifiScoreCard { // Check R1 / R2 >= ratioThr return ((stats1.getCount(countCode) + 1) * (stats2.getCount(refCountCode) + 2) * mDeviceConfigFacade.HEALTH_MONITOR_RATIO_THR_DENOMINATOR) - >= ((stats1.getCount(refCountCode) + 1) * (stats2.getCount(countCode) + 2) + >= ((stats1.getCount(refCountCode) + 2) * (stats2.getCount(countCode) + 1) * mDeviceConfigFacade.getHealthMonitorRatioThrNumerator()); } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java index 3342f93a1..5ba8dbadb 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java @@ -514,6 +514,23 @@ public class WifiHealthMonitorTest extends WifiBaseTest { } /** + * Test FailureStats class + */ + @Test + public void testFailureStats() throws Exception { + WifiHealthMonitor.FailureStats failureStats = new WifiHealthMonitor.FailureStats(); + failureStats.setCount(WifiHealthMonitor.REASON_AUTH_FAILURE, 10); + failureStats.incrementCount(WifiHealthMonitor.REASON_AUTH_FAILURE); + + String expectedString = "authentication failure: 11 "; + String unexpectedString = + WifiHealthMonitor.FAILURE_REASON_NAME[WifiHealthMonitor.REASON_ASSOC_REJECTION]; + assertEquals(11, failureStats.getCount(WifiHealthMonitor.REASON_AUTH_FAILURE)); + assertEquals(true, failureStats.toString().contains(expectedString)); + assertEquals(false, failureStats.toString().contains(unexpectedString)); + } + + /** * Check WestWorld logging after one daily detection with high non-local disconnection rate */ @Test |