summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/DeviceConfigFacade.java92
-rw-r--r--service/java/com/android/server/wifi/WifiDiagnostics.java1
-rw-r--r--service/java/com/android/server/wifi/WifiHealthMonitor.java12
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java9
-rw-r--r--service/java/com/android/server/wifi/WifiScoreCard.java59
-rw-r--r--service/proto/src/metrics.proto3
6 files changed, 150 insertions, 26 deletions
diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java
index cfd2ad081..0e43a0891 100644
--- a/service/java/com/android/server/wifi/DeviceConfigFacade.java
+++ b/service/java/com/android/server/wifi/DeviceConfigFacade.java
@@ -107,7 +107,28 @@ public class DeviceConfigFacade {
// At low traffic, Rx link speed values below the following threshold
// are ignored because it could be due to low rate management frames
static final int DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS = 9;
-
+ // Default health monitor short connection duration threshold in ms
+ static final int DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS = 20_000;
+
+ // Default mask for abnormal disconnection reason codes.
+ // Each bit of mask corresponds to a reason code defined in 802.11 standard section 9.4.1.7
+ // For example, b0 for reason code 0, b1 for reason code 1, etc.
+ // Bits below are abnormal disconnection reasons and thus are set to 1
+ // b0: reserved (e.g., STA heartbeat failure)
+ // b2: invalid auth
+ // b4: disassociated due to inactivity
+ // b6 and b7: invalid class 2 and 3 frames
+ // b34: disassociated due to missing ACKs
+ static final long DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK = 0x4_0000_00d5L;
+ // Default maximum interval between last RSSI poll and disconnection
+ static final int DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS = 2_100;
+ // Default maximum interval between scan and connection attempt in non-stationary state
+ static final int DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS = 5_000;
+ // Default maximum interval between scan and connection attempt in stationary state
+ static final int DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS = 8_000;
+ // Default health monitor firmware alert valid time.
+ // -1 disables firmware alert time check
+ static final int DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS = -1;
// Cached values of fields updated via updateDeviceConfigFlags()
private boolean mIsAbnormalConnectionBugreportEnabled;
private int mAbnormalConnectionDurationMs;
@@ -150,6 +171,12 @@ public class DeviceConfigFacade {
private int mOverlappingConnectionDurationThresholdMs;
private int mTxLinkSpeedLowThresholdMbps;
private int mRxLinkSpeedLowThresholdMbps;
+ private int mHealthMonitorShortConnectionDurationThrMs;
+ private long mAbnormalDisconnectionReasonCodeMask;
+ private int mHealthMonitorRssiPollValidTimeMs;
+ private int mNonstationaryScanRssiValidTimeMs;
+ private int mStationaryScanRssiValidTimeMs;
+ private int mHealthMonitorFwAlertValidTimeMs;
public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) {
mContext = context;
@@ -278,6 +305,26 @@ public class DeviceConfigFacade {
mRxLinkSpeedLowThresholdMbps = DeviceConfig.getInt(NAMESPACE,
"rx_link_speed_low_threshold_mbps",
DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS);
+ mHealthMonitorShortConnectionDurationThrMs = DeviceConfig.getInt(NAMESPACE,
+ "health_monitor_short_connection_duration_thr_ms",
+ DEFAULT_HEALTH_MONITOR_SHORT_CONNECTION_DURATION_THR_MS);
+ mAbnormalDisconnectionReasonCodeMask = DeviceConfig.getLong(NAMESPACE,
+ "abnormal_disconnection_reason_code_mask",
+ DEFAULT_ABNORMAL_DISCONNECTION_REASON_CODE_MASK);
+ mHealthMonitorRssiPollValidTimeMs = DeviceConfig.getInt(NAMESPACE,
+ "health_monitor_rssi_poll_valid_time_ms",
+ DEFAULT_HEALTH_MONITOR_RSSI_POLL_VALID_TIME_MS);
+ mNonstationaryScanRssiValidTimeMs = DeviceConfig.getInt(NAMESPACE,
+ "nonstationary_scan_rssi_valid_time_ms",
+ DEFAULT_NONSTATIONARY_SCAN_RSSI_VALID_TIME_MS);
+ mStationaryScanRssiValidTimeMs = DeviceConfig.getInt(NAMESPACE,
+ "stationary_scan_rssi_valid_time_ms",
+ DEFAULT_STATIONARY_SCAN_RSSI_VALID_TIME_MS);
+ mHealthMonitorFwAlertValidTimeMs = DeviceConfig.getInt(NAMESPACE,
+ "health_monitor_fw_alert_valid_time_ms",
+ DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS);
+ mWifiMetrics.setHealthMonitorRssiPollValidTimeMs(mHealthMonitorRssiPollValidTimeMs);
+
}
private Set<String> getUnmodifiableSetQuoted(String key) {
@@ -583,4 +630,47 @@ public class DeviceConfigFacade {
public int getRxLinkSpeedLowThresholdMbps() {
return mRxLinkSpeedLowThresholdMbps;
}
+
+ /**
+ * Gets health monitor short connection duration threshold in ms
+ */
+ public int getHealthMonitorShortConnectionDurationThrMs() {
+ return mHealthMonitorShortConnectionDurationThrMs;
+ }
+
+ /**
+ * Gets abnormal disconnection reason code mask
+ */
+ public long getAbnormalDisconnectionReasonCodeMask() {
+ return mAbnormalDisconnectionReasonCodeMask;
+ }
+
+ /**
+ * Gets health monitor RSSI poll valid time in ms
+ */
+ public int getHealthMonitorRssiPollValidTimeMs() {
+ return mHealthMonitorRssiPollValidTimeMs;
+ }
+
+ /**
+ * Gets scan rssi valid time in ms when device is in non-stationary state
+ */
+ public int getNonstationaryScanRssiValidTimeMs() {
+ return mNonstationaryScanRssiValidTimeMs;
+ }
+
+ /**
+ * Gets scan rssi valid time in ms when device is in stationary state
+ */
+ public int getStationaryScanRssiValidTimeMs() {
+ return mStationaryScanRssiValidTimeMs;
+ }
+
+ /**
+ * Gets health monitor firmware alert valid time in ms,
+ * -1 disables firmware alert time check
+ */
+ public int getHealthMonitorFwAlertValidTimeMs() {
+ return mHealthMonitorFwAlertValidTimeMs;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index a2328cd26..db9b075a4 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -473,6 +473,7 @@ class WifiDiagnostics extends BaseWifiDiagnostics {
synchronized void onWifiAlert(int errorCode, @NonNull byte[] buffer) {
captureAlertData(errorCode, buffer);
mWifiMetrics.logFirmwareAlert(errorCode);
+ mWifiInjector.getWifiScoreCard().noteFirmwareAlert(errorCode);
}
/**
diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java
index 81076221b..bc1f9af01 100644
--- a/service/java/com/android/server/wifi/WifiHealthMonitor.java
+++ b/service/java/com/android/server/wifi/WifiHealthMonitor.java
@@ -94,14 +94,11 @@ 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;
- 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_MIN_TX_PACKET_PER_SEC = 2;
+ // Minimum Tx packet per seconds for disconnection stats collection
+ static final int HEALTH_MONITOR_MIN_TX_PACKET_PER_SEC = 4;
+
private final Context mContext;
private final WifiConfigManager mWifiConfigManager;
private final WifiScoreCard mWifiScoreCard;
@@ -222,7 +219,8 @@ public class WifiHealthMonitor {
*/
public int getScanRssiValidTimeMs() {
return (mDeviceMobilityState == WifiManager.DEVICE_MOBILITY_STATE_STATIONARY)
- ? STATIONARY_SCAN_RSSI_VALID_TIME_MS : DEFAULT_SCAN_RSSI_VALID_TIME_MS;
+ ? mDeviceConfigFacade.getStationaryScanRssiValidTimeMs() :
+ mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs();
}
/**
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 14dd86f84..72c52bdd2 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -6416,6 +6416,15 @@ public class WifiMetrics {
}
/**
+ * Sets health monitor RSSI poll valid time in ms
+ */
+ public void setHealthMonitorRssiPollValidTimeMs(int rssiPollValidTimeMs) {
+ synchronized (mLock) {
+ mExperimentValues.healthMonitorRssiPollValidTimeMs = rssiPollValidTimeMs;
+ }
+ }
+
+ /**
* Increment connection duration while link layer stats report are on
*/
public void incrementConnectionDuration(int timeDeltaLastTwoPollsMs,
diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java
index ca77e8396..64da835f0 100644
--- a/service/java/com/android/server/wifi/WifiScoreCard.java
+++ b/service/java/com/android/server/wifi/WifiScoreCard.java
@@ -70,7 +70,6 @@ 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;
@@ -102,11 +101,6 @@ public class WifiScoreCard {
public static final String PER_BSSID_DATA_NAME = "scorecard.proto";
public static final String PER_NETWORK_DATA_NAME = "perNetworkData";
- // Maximum connection duration in seconds to qualify short connection
- private static final int SHORT_CONNECTION_DURATION_MAX_SEC = 20;
- // Maximum interval between last RSSI poll and disconnection to qualify
- // disconnection stats collection.
- private static final int LAST_RSSI_POLL_MAX_INTERVAL_MS = 3_100;
static final int INSUFFICIENT_RECENT_STATS = 0;
static final int SUFFICIENT_RECENT_STATS_ONLY = 1;
@@ -233,6 +227,8 @@ public class WifiScoreCard {
private boolean mNonlocalDisconnection = false;
private int mDisconnectionReason;
+ private long mFirmwareAlertTimeMs = TS_NONE;
+
/**
* @param clock is the time source
* @param l2KeySeed is for making our L2Keys usable only on this device
@@ -292,6 +288,7 @@ public class WifiScoreCard {
mPolled = false;
mValidatedThisConnectionAtLeastOnce = false;
mNonlocalDisconnection = false;
+ mFirmwareAlertTimeMs = TS_NONE;
}
/**
@@ -410,6 +407,7 @@ public class WifiScoreCard {
mPolled = false;
mSsidPrev = mSsidCurr;
mSsidCurr = ssid;
+ mFirmwareAlertTimeMs = TS_NONE;
updatePerNetwork(Event.CONNECTION_ATTEMPT, ssid, scanRssi, LINK_SPEED_UNKNOWN,
UNKNOWN_REASON);
@@ -436,6 +434,14 @@ public class WifiScoreCard {
}
/**
+ * Record firmware alert timestamp and error code
+ */
+ public void noteFirmwareAlert(int errorCode) {
+ mFirmwareAlertTimeMs = mClock.getElapsedSinceBootMillis();
+ logd("firmware alert with error code: " + errorCode);
+ }
+
+ /**
* Updates the score card after a failed connection attempt
*
* @param wifiInfo object holding relevant values.
@@ -870,7 +876,7 @@ public class WifiScoreCard {
void updateEventStats(Event event, int rssi, int txSpeed, int failureReason) {
finishPendingRead();
- long currTimeMs = mClock.getWallClockMillis();
+ long currTimeMs = mClock.getElapsedSinceBootMillis();
switch (event) {
case SIGNAL_POLL:
mLastRssiPoll = rssi;
@@ -927,11 +933,9 @@ public class WifiScoreCard {
public String toString() {
StringBuilder sb = new StringBuilder();
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(mLastRssiPollTimeMs);
}
sb.append(" LastRssiPoll: " + mLastRssiPoll);
sb.append(" LastTxSpeedPoll: " + mLastTxSpeedPoll);
@@ -943,21 +947,33 @@ public class WifiScoreCard {
}
private void handleDisconnection() {
if (mConnectionSessionStartTimeMs > TS_NONE) {
- long currTimeMs = mClock.getWallClockMillis();
- int currSessionDurationSec = (int) ((currTimeMs
- - mConnectionSessionStartTimeMs) / 1000);
+ long currTimeMs = mClock.getElapsedSinceBootMillis();
+ int currSessionDurationMs = (int) (currTimeMs - mConnectionSessionStartTimeMs);
+ int currSessionDurationSec = currSessionDurationMs / 1000;
mRecentStats.accumulate(CNT_CONNECTION_DURATION_SEC, currSessionDurationSec);
long timeSinceLastRssiPollMs = currTimeMs - mLastRssiPollTimeMs;
- boolean hasRecentRssiPoll = (mLastRssiPollTimeMs > TS_NONE
- && timeSinceLastRssiPollMs <= LAST_RSSI_POLL_MAX_INTERVAL_MS);
+ boolean hasRecentRssiPoll = mLastRssiPollTimeMs > TS_NONE
+ && timeSinceLastRssiPollMs <= mDeviceConfigFacade
+ .getHealthMonitorRssiPollValidTimeMs();
if (hasRecentRssiPoll) {
mRecentStats.incrementCount(CNT_DISCONNECTION);
}
+ int fwAlertValidTimeMs = mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs();
+ long timeSinceLastFirmAlert = currTimeMs - mFirmwareAlertTimeMs;
+ boolean isInvalidFwAlertTime = mFirmwareAlertTimeMs == TS_NONE;
+ boolean disableFwAlertCheck = fwAlertValidTimeMs == -1;
+ boolean passFirmwareAlertCheck = disableFwAlertCheck ? true : (isInvalidFwAlertTime
+ ? false : timeSinceLastFirmAlert < fwAlertValidTimeMs);
+ boolean hasHighRssiOrHighTxSpeed =
+ mLastRssiPoll >= mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()
+ || mLastTxSpeedPoll >= HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS;
if (mNonlocalDisconnection && hasRecentRssiPoll
- && (mLastRssiPoll >= mDeviceConfigFacade.getHealthMonitorMinRssiThrDbm()
- || mLastTxSpeedPoll >= HEALTH_MONITOR_COUNT_TX_SPEED_MIN_MBPS)) {
+ && isAbnormalDisconnectionReason(mDisconnectionReason)
+ && passFirmwareAlertCheck
+ && hasHighRssiOrHighTxSpeed) {
mRecentStats.incrementCount(CNT_DISCONNECTION_NONLOCAL);
- if (currSessionDurationSec <= SHORT_CONNECTION_DURATION_MAX_SEC) {
+ if (currSessionDurationMs <= mDeviceConfigFacade
+ .getHealthMonitorShortConnectionDurationThrMs()) {
mRecentStats.incrementCount(CNT_SHORT_CONNECTION_NONLOCAL);
}
}
@@ -968,6 +984,13 @@ public class WifiScoreCard {
mConnectionSessionStartTimeMs = TS_NONE;
mLastRssiPollTimeMs = TS_NONE;
}
+
+ private boolean isAbnormalDisconnectionReason(int disconnectionReason) {
+ long mask = mDeviceConfigFacade.getAbnormalDisconnectionReasonCodeMask();
+ return disconnectionReason >= 0 && disconnectionReason <= 63
+ && ((mask >> disconnectionReason) & 0x1) == 0x1;
+ }
+
@NonNull NetworkConnectionStats getRecentStats() {
return mRecentStats;
}
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index 01ad65093..e7c0ec89a 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -2140,6 +2140,9 @@ message ExperimentValues {
// Threshold of CCA level above which to trigger a data stall in percentage
optional int32 data_stall_cca_level_thr = 9;
+
+ // Health monitor RSSI poll valid time in ms
+ optional int32 health_monitor_rssi_poll_valid_time_ms = 10;
}
message BssidBlocklistStats {