diff options
Diffstat (limited to 'service')
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 8ab3a74a6..38da1578b 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 a704f10da..437d00261 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 { |