summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java11
-rw-r--r--service/java/com/android/server/wifi/WifiHealthMonitor.java99
-rw-r--r--service/java/com/android/server/wifi/WifiScoreCard.java42
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java17
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