summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Shi <kaishi@google.com>2020-03-24 21:31:16 -0700
committerKai Shi <kaishi@google.com>2020-03-31 20:59:16 -0700
commitae5308b028fe16a583b845e66f660ba754ab75c8 (patch)
tree79a29aba94648691cd5ba1deaa4ef62991ced5ad
parentc1c826ed5ac9b389852771df6a8ac88d71f59151 (diff)
Take bugReport when it hits abnormal connection/disconnection
Take bug report in user debug build when it hits a large number of abnormal connection failures or disconnections. Its trigger threshold is higher than that for high failure detection events reported in WifiHealthMonitor metrics. The capture rate is further throttled by bugReportMinWindowMs which is configurable through deviceConfig. Bug: 152354782 Test: atest com.android.server.wifi Change-Id: I80c72a1e86e6b0af591915b84a16caaaede8f556
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java40
-rw-r--r--service/java/com/android/server/wifi/DeviceConfigFacade.java60
-rw-r--r--service/java/com/android/server/wifi/WifiDiagnostics.java4
-rw-r--r--service/java/com/android/server/wifi/WifiHealthMonitor.java10
-rw-r--r--service/java/com/android/server/wifi/WifiScoreCard.java123
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java25
-rw-r--r--tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java16
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java7
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java22
9 files changed, 238 insertions, 69 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 588564ed9..598ee74ce 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -1583,6 +1583,32 @@ public class ClientModeImpl extends StateMachine {
sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE);
}
+ private void checkAbnormalConnectionFailureAndTakeBugReport(String ssid) {
+ if (mWifiInjector.getDeviceConfigFacade()
+ .isAbnormalConnectionFailureBugreportEnabled()) {
+ int reasonCode = mWifiScoreCard.detectAbnormalConnectionFailure(ssid);
+ if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) {
+ String bugTitle = "Wi-Fi BugReport";
+ String bugDetail = "Detect abnormal "
+ + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
+ takeBugReport(bugTitle, bugDetail);
+ }
+ }
+ }
+
+ private void checkAbnormalDisconnectionAndTakeBugReport() {
+ if (mWifiInjector.getDeviceConfigFacade()
+ .isAbnormalDisconnectionBugreportEnabled()) {
+ int reasonCode = mWifiScoreCard.detectAbnormalDisconnection();
+ if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) {
+ String bugTitle = "Wi-Fi BugReport";
+ String bugDetail = "Detect abnormal "
+ + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
+ takeBugReport(bugTitle, bugDetail);
+ }
+ }
+ }
+
/**
* Initiates a system-level bugreport, in a non-blocking fashion.
*/
@@ -2731,6 +2757,7 @@ public class ClientModeImpl extends StateMachine {
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mLastSimBasedConnectionCarrierName = null;
+ checkAbnormalDisconnectionAndTakeBugReport();
mWifiScoreCard.resetConnectionState();
mWifiDataStall.reset();
updateL2KeyAndGroupHint();
@@ -2901,18 +2928,7 @@ public class ClientModeImpl extends StateMachine {
: configuration.networkId;
int scanRssi = mWifiConfigManager.findScanRssi(networkId, SCAN_RSSI_VALID_TIME_MS);
mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason);
- boolean isNonWrongPwdAuthFailure =
- blocklistReason == BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE
- || blocklistReason == BssidBlocklistMonitor.REASON_EAP_FAILURE;
- boolean isEnterpriseNetwork = configuration != null && configuration.isEnterprise();
- if (isNonWrongPwdAuthFailure && isEnterpriseNetwork && mWifiInjector
- .getDeviceConfigFacade().isAbnormalEapAuthFailureBugreportEnabled()
- && mWifiScoreCard.detectAbnormalAuthFailure(ssid)) {
- String bugTitle = "Wi-Fi BugReport";
- String bugDetail = "Abnormal authentication failure with enterprise network";
- mWifiDiagnostics.takeBugReport(bugTitle, bugDetail);
- }
-
+ checkAbnormalConnectionFailureAndTakeBugReport(ssid);
boolean isLowRssi = false;
int sufficientRssi = getSufficientRssi(networkId, bssid);
if (scanRssi != WifiInfo.INVALID_RSSI && sufficientRssi != WifiInfo.INVALID_RSSI) {
diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java
index 7ea346c80..67cc01ce9 100644
--- a/service/java/com/android/server/wifi/DeviceConfigFacade.java
+++ b/service/java/com/android/server/wifi/DeviceConfigFacade.java
@@ -67,12 +67,12 @@ public class DeviceConfigFacade {
public static final int DEFAULT_RX_PACKET_PER_SECOND_THR = 1;
// Default high threshold values for various connection/disconnection cases
// All of them are in percent with respect to connection attempts
- static final int DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT = 30;
- static final int DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT = 20;
- static final int DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT = 20;
- static final int DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT = 20;
- static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT = 15;
- static final int DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT = 20;
+ static final int DEFAULT_CONNECTION_FAILURE_HIGH_THR_PERCENT = 40;
+ static final int DEFAULT_ASSOC_REJECTION_HIGH_THR_PERCENT = 30;
+ static final int DEFAULT_ASSOC_TIMEOUT_HIGH_THR_PERCENT = 30;
+ static final int DEFAULT_AUTH_FAILURE_HIGH_THR_PERCENT = 30;
+ static final int DEFAULT_SHORT_CONNECTION_NONLOCAL_HIGH_THR_PERCENT = 20;
+ static final int DEFAULT_DISCONNECTION_NONLOCAL_HIGH_THR_PERCENT = 25;
// Default health monitor abnormal count minimum for various cases
static final int DEFAULT_CONNECTION_FAILURE_COUNT_MIN = 6;
static final int DEFAULT_ASSOC_REJECTION_COUNT_MIN = 3;
@@ -90,6 +90,11 @@ public class DeviceConfigFacade {
static final int DEFAULT_HEALTH_MONITOR_MIN_RSSI_THR_DBM = -68;
// Default minimum number of connection attempts to qualify daily detection
static final int DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT = 10;
+ // Default minimum wait time between two bug report captures
+ static final int DEFAULT_BUG_REPORT_MIN_WINDOW_MS = 3_600_000;
+ // Default report-high threshold to take-bug-report threshold ratio.
+ // It should be larger than 1 since the bar to take bugreport should be higher.
+ static final int DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO = 2;
// Cached values of fields updated via updateDeviceConfigFlags()
private boolean mIsAbnormalConnectionBugreportEnabled;
@@ -122,8 +127,11 @@ public class DeviceConfigFacade {
private Set<String> mRandomizationFlakySsidHotlist;
private Set<String> mAggressiveMacRandomizationSsidAllowlist;
private Set<String> mAggressiveMacRandomizationSsidBlocklist;
- private boolean mIsAbnormalEapAuthFailureBugreportEnabled;
+ private boolean mIsAbnormalConnectionFailureBugreportEnabled;
+ private boolean mIsAbnormalDisconnectionBugreportEnabled;
private int mHealthMonitorMinNumConnectionAttempt;
+ private int mBugReportMinWindowMs;
+ private int mBugReportThresholdExtraRatio;
public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) {
mContext = context;
@@ -224,11 +232,19 @@ public class DeviceConfigFacade {
mAggressiveMacRandomizationSsidBlocklist =
getUnmodifiableSetQuoted("aggressive_randomization_ssid_blocklist");
- mIsAbnormalEapAuthFailureBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
- "abnormal_eap_auth_failure_bugreport_enabled", false);
+ mIsAbnormalConnectionFailureBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
+ "abnormal_connection_failure_bugreport_enabled", false);
+ mIsAbnormalDisconnectionBugreportEnabled = DeviceConfig.getBoolean(NAMESPACE,
+ "abnormal_disconnection_bugreport_enabled", false);
mHealthMonitorMinNumConnectionAttempt = DeviceConfig.getInt(NAMESPACE,
"health_monitor_min_num_connection_attempt",
DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT);
+ mBugReportMinWindowMs = DeviceConfig.getInt(NAMESPACE,
+ "bug_report_min_window_ms",
+ DEFAULT_BUG_REPORT_MIN_WINDOW_MS);
+ mBugReportThresholdExtraRatio = DeviceConfig.getInt(NAMESPACE,
+ "report_bug_report_threshold_extra_ratio",
+ DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO);
}
private Set<String> getUnmodifiableSetQuoted(String key) {
@@ -458,12 +474,18 @@ public class DeviceConfigFacade {
public Set<String> getAggressiveMacRandomizationSsidBlocklist() {
return mAggressiveMacRandomizationSsidBlocklist;
}
+ /**
+ * Gets the feature flag for reporting abnormal connection failure.
+ */
+ public boolean isAbnormalConnectionFailureBugreportEnabled() {
+ return mIsAbnormalConnectionFailureBugreportEnabled;
+ }
/**
- * Gets the feature flag for reporting abnormal EAP authentication failure.
+ * Gets the feature flag for reporting abnormal disconnection.
*/
- public boolean isAbnormalEapAuthFailureBugreportEnabled() {
- return mIsAbnormalEapAuthFailureBugreportEnabled;
+ public boolean isAbnormalDisconnectionBugreportEnabled() {
+ return mIsAbnormalDisconnectionBugreportEnabled;
}
/**
@@ -472,4 +494,18 @@ public class DeviceConfigFacade {
public int getHealthMonitorMinNumConnectionAttempt() {
return mHealthMonitorMinNumConnectionAttempt;
}
+
+ /**
+ * Gets minimum wait time between two bug report captures
+ */
+ public int getBugReportMinWindowMs() {
+ return mBugReportMinWindowMs;
+ }
+
+ /**
+ * Gets the extra ratio of threshold to trigger bug report.
+ */
+ public int getBugReportThresholdExtraRatio() {
+ return mBugReportThresholdExtraRatio;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index 05c4df634..4ac982063 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -108,7 +108,6 @@ class WifiDiagnostics extends BaseWifiDiagnostics {
public static final long MIN_DUMP_TIME_WINDOW_MILLIS = 10 * 60 * 1000; // 10 mins
private long mLastBugReportTime;
- static final long MIN_BUG_REPORT_TIME_WINDOW_MILLIS = 60 * 60 * 1000; // 60 mins
@VisibleForTesting public static final String FIRMWARE_DUMP_SECTION_HEADER =
"FW Memory dump";
@@ -302,7 +301,8 @@ class WifiDiagnostics extends BaseWifiDiagnostics {
return;
}
long currentTime = mClock.getWallClockMillis();
- if ((currentTime - mLastBugReportTime) < MIN_BUG_REPORT_TIME_WINDOW_MILLIS
+ if ((currentTime - mLastBugReportTime)
+ < mWifiInjector.getDeviceConfigFacade().getBugReportMinWindowMs()
&& mLastBugReportTime > 0) {
return;
}
diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java
index b85fa5fbe..123c576bd 100644
--- a/service/java/com/android/server/wifi/WifiHealthMonitor.java
+++ b/service/java/com/android/server/wifi/WifiHealthMonitor.java
@@ -524,6 +524,7 @@ public class WifiHealthMonitor {
mWifiSystemInfoStats.clearAll();
}
+ public static final int REASON_NO_FAILURE = -1;
public static final int REASON_ASSOC_REJECTION = 0;
public static final int REASON_ASSOC_TIMEOUT = 1;
public static final int REASON_AUTH_FAILURE = 2;
@@ -531,7 +532,16 @@ public class WifiHealthMonitor {
public static final int REASON_DISCONNECTION_NONLOCAL = 4;
public static final int REASON_SHORT_CONNECTION_NONLOCAL = 5;
public static final int NUMBER_FAILURE_REASON_CODE = 6;
+ public static final String[] FAILURE_REASON_NAME = {
+ "association rejection failure",
+ "association timeout failure",
+ "authentication failure",
+ "connection failure",
+ "disconnection",
+ "short connection"
+ };
@IntDef(prefix = { "REASON_" }, value = {
+ REASON_NO_FAILURE,
REASON_ASSOC_REJECTION,
REASON_ASSOC_TIMEOUT,
REASON_AUTH_FAILURE,
diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java
index 79c9ccb24..61a8435ed 100644
--- a/service/java/com/android/server/wifi/WifiScoreCard.java
+++ b/service/java/com/android/server/wifi/WifiScoreCard.java
@@ -27,6 +27,7 @@ import static com.android.server.wifi.WifiHealthMonitor.REASON_ASSOC_TIMEOUT;
import static com.android.server.wifi.WifiHealthMonitor.REASON_AUTH_FAILURE;
import static com.android.server.wifi.WifiHealthMonitor.REASON_CONNECTION_FAILURE;
import static com.android.server.wifi.WifiHealthMonitor.REASON_DISCONNECTION_NONLOCAL;
+import static com.android.server.wifi.WifiHealthMonitor.REASON_NO_FAILURE;
import static com.android.server.wifi.WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL;
import android.annotation.IntDef;
@@ -104,10 +105,6 @@ public class WifiScoreCard {
// disconnection stats collection.
private static final int LAST_RSSI_POLL_MAX_INTERVAL_MS = 3_100;
- // Minimum number of connection attempts to qualify abnormal auth detection
- static final int MIN_NUM_CONNECTION_ATTEMPT_ABNORMAL_AUTH_FAILURE = 5;
- static final int FAILURE_PERCENT_THRESHOLD_ABNORMAL_AUTH_FAILURE = 80;
-
static final int INSUFFICIENT_RECENT_STATS = 0;
static final int SUFFICIENT_RECENT_STATS_ONLY = 1;
static final int SUFFICIENT_RECENT_PREV_STATS = 2;
@@ -258,7 +255,7 @@ public class WifiScoreCard {
* Handle network disconnection or shutdown event
*/
public void resetConnectionState() {
- String ssidDisconnected = (mAttemptingSwitch) ? mSsidPrev : mSsidCurr;
+ String ssidDisconnected = mAttemptingSwitch ? mSsidPrev : mSsidCurr;
updatePerNetwork(Event.DISCONNECTION, ssidDisconnected, INVALID_RSSI, LINK_SPEED_UNKNOWN,
UNKNOWN_REASON);
if (mVerboseLoggingEnabled && mTsConnectionAttemptStart > TS_NONE && !mAttemptingSwitch) {
@@ -565,20 +562,90 @@ public class WifiScoreCard {
}
/**
- * Detect abnormal authentication failure at high RSSI with enough connection attempts
- * and high failure rate
- * @return true if abnormal auth failure is detected, false otherwise
+ * Detect abnormal disconnection at high RSSI with a high rate
*/
- public boolean detectAbnormalAuthFailure(String ssid) {
+ public int detectAbnormalDisconnection() {
+ String ssid = mAttemptingSwitch ? mSsidPrev : mSsidCurr;
PerNetwork perNetwork = lookupNetwork(ssid);
NetworkConnectionStats recentStats = perNetwork.getRecentStats();
- logd("detectAbnormalAuthFailure: " + recentStats.toString());
- int numAuthFailure = recentStats.getCount(CNT_AUTHENTICATION_FAILURE);
- int numAttempt = recentStats.getCount(CNT_CONNECTION_ATTEMPT);
- boolean hasEnoughAttempt = numAttempt >= MIN_NUM_CONNECTION_ATTEMPT_ABNORMAL_AUTH_FAILURE;
- boolean isAuthFailureRateHigh = (numAuthFailure * 100)
- >= (numAttempt * FAILURE_PERCENT_THRESHOLD_ABNORMAL_AUTH_FAILURE);
- return hasEnoughAttempt && isAuthFailureRateHigh;
+ if (recentStats.getRecentCountCode() == CNT_SHORT_CONNECTION_NONLOCAL) {
+ return detectAbnormalFailureReason(recentStats, CNT_SHORT_CONNECTION_NONLOCAL,
+ REASON_SHORT_CONNECTION_NONLOCAL,
+ mDeviceConfigFacade.getShortConnectionNonlocalHighThrPercent(),
+ mDeviceConfigFacade.getShortConnectionNonlocalCountMin(),
+ CNT_DISCONNECTION);
+ } else if (recentStats.getRecentCountCode() == CNT_DISCONNECTION_NONLOCAL) {
+ return detectAbnormalFailureReason(recentStats, CNT_DISCONNECTION_NONLOCAL,
+ REASON_DISCONNECTION_NONLOCAL,
+ mDeviceConfigFacade.getDisconnectionNonlocalHighThrPercent(),
+ mDeviceConfigFacade.getDisconnectionNonlocalCountMin(),
+ CNT_DISCONNECTION);
+ } else {
+ return REASON_NO_FAILURE;
+ }
+ }
+
+ /**
+ * Detect abnormal connection failure at high RSSI with a high rate
+ */
+ public int detectAbnormalConnectionFailure(String ssid) {
+ PerNetwork perNetwork = lookupNetwork(ssid);
+ NetworkConnectionStats recentStats = perNetwork.getRecentStats();
+ int recentCountCode = recentStats.getRecentCountCode();
+ if (recentCountCode == CNT_AUTHENTICATION_FAILURE) {
+ return detectAbnormalFailureReason(recentStats, CNT_AUTHENTICATION_FAILURE,
+ REASON_AUTH_FAILURE,
+ mDeviceConfigFacade.getAuthFailureHighThrPercent(),
+ mDeviceConfigFacade.getAuthFailureCountMin(),
+ CNT_CONNECTION_ATTEMPT);
+ } else if (recentCountCode == CNT_ASSOCIATION_REJECTION) {
+ return detectAbnormalFailureReason(recentStats, CNT_ASSOCIATION_REJECTION,
+ REASON_ASSOC_REJECTION,
+ mDeviceConfigFacade.getAssocRejectionHighThrPercent(),
+ mDeviceConfigFacade.getAssocRejectionCountMin(),
+ CNT_CONNECTION_ATTEMPT);
+ } else if (recentCountCode == CNT_ASSOCIATION_TIMEOUT) {
+ return detectAbnormalFailureReason(recentStats, CNT_ASSOCIATION_TIMEOUT,
+ REASON_ASSOC_TIMEOUT,
+ mDeviceConfigFacade.getAssocTimeoutHighThrPercent(),
+ mDeviceConfigFacade.getAssocTimeoutCountMin(),
+ CNT_CONNECTION_ATTEMPT);
+ } else if (recentCountCode == CNT_CONNECTION_FAILURE) {
+ return detectAbnormalFailureReason(recentStats, CNT_CONNECTION_FAILURE,
+ REASON_CONNECTION_FAILURE,
+ mDeviceConfigFacade.getConnectionFailureHighThrPercent(),
+ mDeviceConfigFacade.getConnectionFailureCountMin(),
+ CNT_CONNECTION_ATTEMPT);
+ } else {
+ return REASON_NO_FAILURE;
+ }
+ }
+
+ private int detectAbnormalFailureReason(NetworkConnectionStats stats, int countCode,
+ int reasonCode, int highThresholdPercent, int minCount, int refCountCode) {
+ // To detect abnormal failure which may trigger bugReport,
+ // increase the detection threshold by thresholdRatio
+ int thresholdRatio =
+ mDeviceConfigFacade.getBugReportThresholdExtraRatio();
+ if (isHighPercentageAndEnoughCount(stats, countCode, reasonCode,
+ highThresholdPercent * thresholdRatio,
+ minCount * thresholdRatio,
+ refCountCode)) {
+ return reasonCode;
+ } else {
+ return REASON_NO_FAILURE;
+ }
+ }
+
+ private boolean isHighPercentageAndEnoughCount(NetworkConnectionStats stats, int countCode,
+ int reasonCode, int highThresholdPercent, int minCount, int refCountCode) {
+ highThresholdPercent = Math.min(highThresholdPercent, 100);
+ // Use Laplace's rule of succession, useful especially for a small
+ // connection attempt count
+ // R = (f+1)/(n+2) with a pseudo count of 2 (one for f and one for s)
+ return ((stats.getCount(countCode) >= minCount)
+ && ((stats.getCount(countCode) + 1) * 100)
+ >= (highThresholdPercent * (stats.getCount(refCountCode) + 2)));
}
final class PerBssid extends MemoryStoreAccessBase {
@@ -999,12 +1066,8 @@ public class WifiScoreCard {
private boolean recentStatsHighDetection(FailureStats statsHigh, int countCode,
int reasonCode, int highThresholdPercent, int minCount, int refCountCode) {
- // Use Laplace's rule of succession, useful especially for a small
- // connection attempt count
- // R = (f+1)/(n+2) with a pseudo count of 2 (one for f and one for s)
- if ((((mRecentStats.getCount(countCode) + 1) * 100)
- >= (highThresholdPercent * (mRecentStats.getCount(refCountCode) + 2)))
- && (mRecentStats.getCount(countCode) >= minCount)) {
+ if (isHighPercentageAndEnoughCount(mRecentStats, countCode, reasonCode,
+ highThresholdPercent, minCount, refCountCode)) {
statsHigh.incrementCount(reasonCode);
return true;
}
@@ -1152,6 +1215,7 @@ public class WifiScoreCard {
}
// Codes for various connection related counts
+ public static final int CNT_INVALID = -1;
public static final int CNT_CONNECTION_ATTEMPT = 0;
public static final int CNT_CONNECTION_FAILURE = 1;
public static final int CNT_CONNECTION_DURATION_SEC = 2;
@@ -1194,7 +1258,7 @@ public class WifiScoreCard {
*/
public static class NetworkConnectionStats {
private final int[] mCount = new int[NUMBER_CONNECTION_CNT_CODE];
-
+ private int mRecentCountCode = CNT_INVALID;
/**
* Copy all values
* @param src is the source of copy
@@ -1203,6 +1267,7 @@ public class WifiScoreCard {
for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) {
mCount[i] = src.getCount(i);
}
+ mRecentCountCode = src.mRecentCountCode;
}
/**
@@ -1212,6 +1277,7 @@ public class WifiScoreCard {
for (int i = 0; i < NUMBER_CONNECTION_CNT_CODE; i++) {
mCount[i] = 0;
}
+ mRecentCountCode = CNT_INVALID;
}
/**
@@ -1224,12 +1290,13 @@ public class WifiScoreCard {
}
/**
- * Set counterer value
+ * Set counter value
* @param countCode is the selected counter
* @param cnt is the value set to the selected counter
*/
public void setCount(@ConnectionCountCode int countCode, int cnt) {
mCount[countCode] = cnt;
+ mRecentCountCode = countCode;
}
/**
@@ -1238,6 +1305,14 @@ public class WifiScoreCard {
*/
public void incrementCount(@ConnectionCountCode int countCode) {
mCount[countCode]++;
+ mRecentCountCode = countCode;
+ }
+
+ /**
+ * Got the recent count code
+ */
+ public int getRecentCountCode() {
+ return mRecentCountCode;
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index d912020e9..6d0b911f1 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -551,7 +551,12 @@ public class ClientModeImplTest extends WifiBaseTest {
mConnectedNetwork = spy(WifiConfigurationTestUtil.createOpenNetwork());
when(mNullAsyncChannel.sendMessageSynchronously(any())).thenReturn(null);
when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(new Pair<>(null, null));
- when(mDeviceConfigFacade.isAbnormalEapAuthFailureBugreportEnabled()).thenReturn(true);
+ when(mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()).thenReturn(true);
+ when(mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()).thenReturn(true);
+ when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
+ .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
+ when(mWifiScoreCard.detectAbnormalDisconnection())
+ .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
when(mThroughputPredictor.predictMaxTxThroughput(any())).thenReturn(90);
when(mThroughputPredictor.predictMaxRxThroughput(any())).thenReturn(80);
}
@@ -1724,8 +1729,6 @@ public class ClientModeImplTest extends WifiBaseTest {
verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));
- verify(mWifiScoreCard, never()).detectAbnormalAuthFailure(any());
-
assertEquals("DisconnectedState", getCurrentState().getName());
}
@@ -1757,6 +1760,8 @@ public class ClientModeImplTest extends WifiBaseTest {
.startMocking();
when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true);
+ when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
+ .thenReturn(WifiHealthMonitor.REASON_AUTH_FAILURE);
mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
@@ -1767,8 +1772,9 @@ public class ClientModeImplTest extends WifiBaseTest {
WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED, config);
verify(mDataTelephonyManager).resetCarrierKeysForImsiEncryption();
mockSession.finishMocking();
- verify(mWifiScoreCard).detectAbnormalAuthFailure(anyString());
- verify(mDeviceConfigFacade).isAbnormalEapAuthFailureBugreportEnabled();
+ verify(mDeviceConfigFacade).isAbnormalConnectionFailureBugreportEnabled();
+ verify(mWifiScoreCard).detectAbnormalConnectionFailure(anyString());
+ verify(mWifiDiagnostics).takeBugReport(anyString(), anyString());
}
/**
@@ -1799,8 +1805,6 @@ public class ClientModeImplTest extends WifiBaseTest {
mLooper.dispatchAll();
verify(mDataTelephonyManager, never()).resetCarrierKeysForImsiEncryption();
- verify(mWifiScoreCard).detectAbnormalAuthFailure(null);
- verify(mDeviceConfigFacade).isAbnormalEapAuthFailureBugreportEnabled();
}
/**
@@ -1828,8 +1832,6 @@ public class ClientModeImplTest extends WifiBaseTest {
verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
eq(WifiConfiguration.NetworkSelectionStatus
.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION));
- verify(mWifiScoreCard, never()).detectAbnormalAuthFailure(null);
- verify(mDeviceConfigFacade, never()).isAbnormalEapAuthFailureBugreportEnabled();
}
@Test
@@ -1851,6 +1853,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mLooper.dispatchAll();
assertEquals("DisconnectedState", getCurrentState().getName());
+ verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString());
}
@@ -1865,6 +1868,8 @@ public class ClientModeImplTest extends WifiBaseTest {
@Test
public void disconnect() throws Exception {
+ when(mWifiScoreCard.detectAbnormalDisconnection())
+ .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL);
InOrder inOrderWifiLockManager = inOrder(mWifiLockManager);
connect();
inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(true);
@@ -1879,6 +1884,8 @@ public class ClientModeImplTest extends WifiBaseTest {
verify(mWifiNetworkSuggestionsManager).handleDisconnect(any(), any());
assertEquals("DisconnectedState", getCurrentState().getName());
inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(false);
+ verify(mWifiScoreCard).detectAbnormalDisconnection();
+ verify(mWifiDiagnostics).takeBugReport(anyString(), anyString());
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
index d6a05c7a3..b7136d986 100644
--- a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
@@ -170,9 +170,12 @@ public class DeviceConfigFacadeTest extends WifiBaseTest {
mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist());
assertEquals(Collections.emptySet(),
mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist());
- assertEquals(false, mDeviceConfigFacade.isAbnormalEapAuthFailureBugreportEnabled());
+ assertEquals(false, mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled());
+ assertEquals(false, mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled());
assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT,
mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt());
+ assertEquals(DeviceConfigFacade.DEFAULT_BUG_REPORT_MIN_WINDOW_MS,
+ mDeviceConfigFacade.getBugReportMinWindowMs());
}
/**
@@ -242,10 +245,15 @@ public class DeviceConfigFacadeTest extends WifiBaseTest {
anyString())).thenReturn(testSsidList);
when(DeviceConfig.getString(anyString(), eq("aggressive_randomization_ssid_blocklist"),
anyString())).thenReturn(testSsidList);
- when(DeviceConfig.getBoolean(anyString(), eq("abnormal_eap_auth_failure_bugreport_enabled"),
+ when(DeviceConfig.getBoolean(anyString(),
+ eq("abnormal_connection_failure_bugreport_enabled"),
+ anyBoolean())).thenReturn(true);
+ when(DeviceConfig.getBoolean(anyString(), eq("abnormal_disconnection_bugreport_enabled"),
anyBoolean())).thenReturn(true);
when(DeviceConfig.getInt(anyString(), eq("health_monitor_min_num_connection_attempt"),
anyInt())).thenReturn(20);
+ when(DeviceConfig.getInt(anyString(), eq("bug_report_min_window_ms"),
+ anyInt())).thenReturn(1000);
mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null);
@@ -285,7 +293,9 @@ public class DeviceConfigFacadeTest extends WifiBaseTest {
mDeviceConfigFacade.getAggressiveMacRandomizationSsidAllowlist());
assertEquals(testSsidSet,
mDeviceConfigFacade.getAggressiveMacRandomizationSsidBlocklist());
- assertEquals(true, mDeviceConfigFacade.isAbnormalEapAuthFailureBugreportEnabled());
+ assertEquals(true, mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled());
+ assertEquals(true, mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled());
assertEquals(20, mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt());
+ assertEquals(1000, mDeviceConfigFacade.getBugReportMinWindowMs());
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
index acfc78d7e..6b235b9f7 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
@@ -64,6 +64,7 @@ public class WifiDiagnosticsTest extends WifiBaseTest {
@Mock BuildProperties mBuildProperties;
@Mock Context mContext;
@Mock WifiInjector mWifiInjector;
+ @Mock DeviceConfigFacade mDeviceConfigFacade;
@Spy FakeWifiLog mLog;
@Mock LastMileLogger mLastMileLogger;
@Mock Runtime mJavaRuntime;
@@ -86,6 +87,7 @@ public class WifiDiagnosticsTest extends WifiBaseTest {
private static final int[] FATAL_FW_ALERT_LIST = {256, 257, 258};
/** Mock a non fatal firmware alert */
private static final int NON_FATAL_FW_ALERT = 0;
+ private static final int BUG_REPORT_MIN_WINDOW_MS = 3600_000;
private WifiNative.RingBufferStatus mFakeRbs;
/**
@@ -131,7 +133,8 @@ public class WifiDiagnosticsTest extends WifiBaseTest {
when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
when(mWifiInjector.getJavaRuntime()).thenReturn(mJavaRuntime);
when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
-
+ when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
+ when(mDeviceConfigFacade.getBugReportMinWindowMs()).thenReturn(BUG_REPORT_MIN_WINDOW_MS);
mWifiDiagnostics = new WifiDiagnostics(
mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock);
mWifiNative.enableVerboseLogging(0);
@@ -888,7 +891,7 @@ public class WifiDiagnosticsTest extends WifiBaseTest {
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
// 2nd attempt should fail
- when(mClock.getWallClockMillis()).thenReturn(1000_000L);
+ when(mClock.getWallClockMillis()).thenReturn(BUG_REPORT_MIN_WINDOW_MS - 20L);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
index e98b03acf..d6dc020b9 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreCardTest.java
@@ -154,6 +154,7 @@ public class WifiScoreCardTest extends WifiBaseTest {
DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_RATIO_THR_NUMERATOR);
when(mDeviceConfigFacade.getHealthMonitorMinNumConnectionAttempt()).thenReturn(
DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_MIN_NUM_CONNECTION_ATTEMPT);
+ when(mDeviceConfigFacade.getBugReportThresholdExtraRatio()).thenReturn(1);
mWifiScoreCard.enableVerboseLogging(true);
}
@@ -1106,6 +1107,8 @@ public class WifiScoreCardTest extends WifiBaseTest {
perNetwork.updateAfterDailyDetection();
checkShortConnectionExample(perNetwork.getRecentStats(), 1);
checkShortConnectionExample(perNetwork.getStatsPrevBuild(), 0);
+ assertEquals(WifiHealthMonitor.REASON_NO_FAILURE,
+ mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID()));
}
/**
@@ -1131,11 +1134,13 @@ public class WifiScoreCardTest extends WifiBaseTest {
// Add >2x failures after the SW build change
int numBadConnectionDays = 4;
for (int i = 0; i < numBadConnectionDays; i++) {
- makeRecentStatsWithShortConnection();
makeRecentStatsWithAssocTimeOut();
makeRecentStatsWithAuthFailure();
+ makeRecentStatsWithShortConnection();
}
+ assertEquals(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL,
+ mWifiScoreCard.detectAbnormalDisconnection());
FailureStats statsDec = new FailureStats();
FailureStats statsInc = new FailureStats();
FailureStats statsHigh = new FailureStats();
@@ -1175,6 +1180,8 @@ public class WifiScoreCardTest extends WifiBaseTest {
checkStatsDeltaExample(statsDec, 0);
checkStatsDeltaExample(statsInc, 0);
checkStatsDeltaExample(statsHigh, 0);
+ assertEquals(WifiHealthMonitor.REASON_NO_FAILURE,
+ mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID()));
}
/**
@@ -1197,10 +1204,12 @@ public class WifiScoreCardTest extends WifiBaseTest {
for (int i = 0; i < numGoodConnectionDays; i++) {
makeRecentStatsWithGoodConnection();
}
- makeRecentStatsWithShortConnection();
makeRecentStatsWithAssocTimeOut();
makeRecentStatsWithAuthFailure();
+ makeRecentStatsWithShortConnection();
+ assertEquals(WifiHealthMonitor.REASON_NO_FAILURE,
+ mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID()));
FailureStats statsDec = new FailureStats();
FailureStats statsInc = new FailureStats();
FailureStats statsHigh = new FailureStats();
@@ -1215,9 +1224,11 @@ public class WifiScoreCardTest extends WifiBaseTest {
PerNetwork perNetwork = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID());
makeRecentStatsWithShortConnection(); // Day 1
- makeRecentStatsWithAssocTimeOut();
makeRecentStatsWithAuthFailure();
+ makeRecentStatsWithAssocTimeOut();
+ assertEquals(WifiHealthMonitor.REASON_ASSOC_TIMEOUT,
+ mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID()));
FailureStats statsDec = new FailureStats();
FailureStats statsInc = new FailureStats();
FailureStats statsHigh = new FailureStats();
@@ -1226,12 +1237,13 @@ public class WifiScoreCardTest extends WifiBaseTest {
checkStatsDeltaExample(statsDec, 0);
checkStatsDeltaExample(statsInc, 0);
checkStatsDeltaExample(statsHigh, 1);
- assertEquals(false, mWifiScoreCard.detectAbnormalAuthFailure(mWifiInfo.getSSID()));
}
@Test
public void testHighAuthFailureRate() throws Exception {
+ makeRecentStatsWithGoodConnection();
makeRecentStatsWithAuthFailure();
- assertEquals(true, mWifiScoreCard.detectAbnormalAuthFailure(mWifiInfo.getSSID()));
+ assertEquals(WifiHealthMonitor.REASON_AUTH_FAILURE,
+ mWifiScoreCard.detectAbnormalConnectionFailure(mWifiInfo.getSSID()));
}
}