diff options
author | xshu <xshu@google.com> | 2019-08-16 15:14:39 -0700 |
---|---|---|
committer | xshu <xshu@google.com> | 2019-10-30 14:09:22 -0700 |
commit | 49c4d5dc84ba7d4a747c511204d41bf28c47cfc5 (patch) | |
tree | a35de2e57726ce30740abe8f06bfc566daba760b /service | |
parent | 2b8e1b52a3b01fea570b309693ed1b7842338a64 (diff) |
hooking up BssidBlocklistMonitor
Replaces the existing bssid blocklist logic in
WifiConnectivityManager, and also extends bssid blocklist logic to
check for authentication, dhcp, and no internet failures.
Bug: 139287182
Test: atest FrameworksWifiTests
Test: unit tests and manually verified on device with dumpsys log.
Change-Id: I1757acd45300287ffed1a8c61a03f122bb3c37e7
Diffstat (limited to 'service')
4 files changed, 79 insertions, 218 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 35f60f5bf..bb1bb2abd 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -150,6 +150,11 @@ public class ClientModeImpl extends StateMachine { @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100; @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200; @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000; + + // Association rejection reason codes + @VisibleForTesting + protected static final int REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; + private static final String TAG = "WifiClientModeImpl"; private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; @@ -196,6 +201,7 @@ public class ClientModeImpl extends StateMachine { private final WifiPermissionsUtil mWifiPermissionsUtil; private final WifiConfigManager mWifiConfigManager; private final WifiConnectivityManager mWifiConnectivityManager; + private final BssidBlocklistMonitor mBssidBlocklistMonitor; private ConnectivityManager mCm; private BaseWifiDiagnostics mWifiDiagnostics; private final boolean mP2pSupported; @@ -741,7 +747,7 @@ public class ClientModeImpl extends StateMachine { mWifiInfo = new ExtendedWifiInfo(); mSupplicantStateTracker = supplicantStateTracker; mWifiConnectivityManager = mWifiInjector.makeWifiConnectivityManager(this); - + mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor(); mLinkProperties = new LinkProperties(); mMcastLockManagerFilterController = new McastLockManagerFilterController(); @@ -2710,6 +2716,17 @@ public class ClientModeImpl extends StateMachine { if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) { mWifiScoreCard.noteConnectionFailure(mWifiInfo, level2FailureCode, connectivityFailureCode); + String bssid = mLastBssid == null ? mTargetRoamBSSID : mLastBssid; + String ssid = mWifiInfo.getSSID(); + if (WifiSsid.NONE.equals(ssid)) { + ssid = getTargetSsid(); + } + int bssidBlocklistMonitorReason = convertToBssidBlocklistMonitorFailureReason( + level2FailureCode, level2FailureReason); + if (bssidBlocklistMonitorReason != -1) { + mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, + bssidBlocklistMonitorReason); + } } // if connected, this should be non-null. WifiConfiguration configuration = getCurrentWifiConfiguration(); @@ -2728,6 +2745,32 @@ public class ClientModeImpl extends StateMachine { handleConnectionAttemptEndForDiagnostics(level2FailureCode); } + private int convertToBssidBlocklistMonitorFailureReason( + int level2FailureCode, int failureReason) { + switch (level2FailureCode) { + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: + return BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT; + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: + if (failureReason == WifiMetricsProto.ConnectionEvent + .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) { + return BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA; + } + return BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION; + case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: + if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) { + return BssidBlocklistMonitor.REASON_WRONG_PASSWORD; + } else if (failureReason == WifiMetricsProto.ConnectionEvent + .AUTH_FAILURE_EAP_FAILURE) { + return BssidBlocklistMonitor.REASON_EAP_FAILURE; + } + return BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE; + case WifiMetrics.ConnectionEvent.FAILURE_DHCP: + return BssidBlocklistMonitor.REASON_DHCP_FAILURE; + default: + return -1; + } + } + private void handleIPv4Success(DhcpResults dhcpResults) { if (mVerboseLoggingEnabled) { logd("handleIPv4Success <" + dhcpResults.toString() + ">"); @@ -2757,6 +2800,7 @@ public class ClientModeImpl extends StateMachine { mWifiInfo.setTrusted(config.trusted); mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.getLeaseDuration()); + mBssidBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid); } // Set meteredHint if DHCP result says network is metered @@ -3424,6 +3468,8 @@ public class ClientModeImpl extends StateMachine { boolean handleStatus = HANDLED; int callbackIdentifier = -1; + int level2FailureReason = + WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN; switch (message.what) { case WifiMonitor.ASSOCIATION_REJECTION_EVENT: mWifiDiagnostics.captureBugReportData( @@ -3438,23 +3484,23 @@ public class ClientModeImpl extends StateMachine { // If BSSID is null, use the target roam BSSID bssid = mTargetRoamBSSID; } - if (bssid != null) { - // If we have a BSSID, tell configStore to black list it - mDidBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, false, - reasonCode); - } mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, WifiConfiguration.NetworkSelectionStatus .DISABLED_ASSOCIATION_REJECTION); mWifiConfigManager.setRecentFailureAssociationStatus(mTargetNetworkId, reasonCode); + + if (reasonCode == REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { + level2FailureReason = WifiMetricsProto.ConnectionEvent + .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA; + } // If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. reportConnectionAttemptEnd( timedOut ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN); + level2FailureReason); mWifiInjector.getWifiLastResortWatchdog() .noteConnectionFailureAndTriggerIfNeeded( getTargetSsid(), bssid, @@ -3489,7 +3535,6 @@ public class ClientModeImpl extends StateMachine { mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId); //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. - int level2FailureReason; switch (reasonCode) { case WifiManager.ERROR_AUTH_FAILURE_NONE: level2FailureReason = @@ -3663,6 +3708,7 @@ public class ClientModeImpl extends StateMachine { mWifiScoreCard.noteConnectionAttempt(mWifiInfo); mTargetNetworkId = netId; setTargetBssid(config, bssid); + mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID); reportConnectionAttemptStart(config, mTargetRoamBSSID, WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); @@ -3802,7 +3848,6 @@ public class ClientModeImpl extends StateMachine { mWifiInfo.setFrequency(scanResult.frequency); } } - mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA' if (config.enterpriseConfig != null @@ -4209,6 +4254,7 @@ public class ClientModeImpl extends StateMachine { mCountryCode.setReadyForChange(false); mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo, mNetworkAgent.netId); + mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid); } @Override @@ -4795,10 +4841,10 @@ public class ClientModeImpl extends StateMachine { mWifiInfo.setBSSID(mLastBssid); mWifiInfo.setNetworkId(mLastNetworkId); int reasonCode = message.arg2; - mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); sendNetworkStateChangeBroadcast(mLastBssid); // Successful framework roam! (probably) + mBssidBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid); reportConnectionAttemptEnd( WifiMetrics.ConnectionEvent.FAILURE_NONE, WifiMetricsProto.ConnectionEvent.HLF_NONE, @@ -4929,6 +4975,10 @@ public class ClientModeImpl extends StateMachine { config.networkId, DISABLED_NO_INTERNET_TEMPORARY); } + mBssidBlocklistMonitor.handleBssidConnectionFailure( + mLastBssid, config.SSID, + BssidBlocklistMonitor + .REASON_NETWORK_VALIDATION_FAILURE); } } } @@ -4940,6 +4990,7 @@ public class ClientModeImpl extends StateMachine { mWifiDiagnostics.reportConnectionEvent( WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); mWifiScoreCard.noteValidationSuccess(mWifiInfo); + mBssidBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid); config = getCurrentWifiConfiguration(); if (config != null) { // re-enable autojoin diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index b1d0a05fe..c77275ea0 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -43,12 +43,10 @@ import com.android.server.wifi.util.ScanResultUtil; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -147,6 +145,7 @@ public class WifiConnectivityManager { private final ScoringParams mScoringParams; private final LocalLog mLocalLog; private final LinkedList<Long> mConnectionAttemptTimeStamps; + private final BssidBlocklistMonitor mBssidBlocklistMonitor; private WifiScanner mScanner; private boolean mDbg = false; @@ -182,24 +181,6 @@ public class WifiConnectivityManager { private int mRssiScoreSlope; private int mPnoScanIntervalMs; - // BSSID blacklist - @VisibleForTesting - public static final int BSSID_BLACKLIST_THRESHOLD = 3; - @VisibleForTesting - public static final int BSSID_BLACKLIST_EXPIRE_TIME_MS = 5 * 60 * 1000; - private static class BssidBlacklistStatus { - // Number of times this BSSID has been rejected for association. - public int counter; - public boolean isBlacklisted; - public long blacklistedTimeStamp = RESET_TIME_STAMP; - } - private Map<String, BssidBlacklistStatus> mBssidBlacklist = - new HashMap<>(); - - // Association failure reason codes - @VisibleForTesting - public static final int REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; - // A helper to log debugging information in the local log buffer, which can // be retrieved in bugreport. private void localLog(String log) { @@ -257,8 +238,9 @@ public class WifiConnectivityManager { * false - if no candidate is selected by WifiNetworkSelector */ private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) { - // Check if any blacklisted BSSIDs can be freed. - refreshBssidBlacklist(); + // Check if any blocklisted BSSIDs can be freed. + HashSet<String> bssidBlocklist = + new HashSet<>(mBssidBlocklistMonitor.updateAndGetBssidBlocklist()); if (mStateMachine.isSupplicantTransientState()) { localLog(listenerName @@ -270,7 +252,7 @@ public class WifiConnectivityManager { localLog(listenerName + " onResults: start network selection"); WifiConfiguration candidate = - mNetworkSelector.selectNetwork(scanDetails, buildBssidBlacklist(), mWifiInfo, + mNetworkSelector.selectNetwork(scanDetails, bssidBlocklist, mWifiInfo, mStateMachine.isConnected(), mStateMachine.isDisconnected(), mUntrustedConnectionAllowed); mWifiLastResortWatchdog.updateAvailableNetworks( @@ -626,6 +608,7 @@ public class WifiConnectivityManager { // Listen to WifiConfigManager network update events mConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener()); + mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor(); } /** Returns maximum PNO score, before any awards/bonuses. */ @@ -1237,10 +1220,14 @@ public class WifiConnectivityManager { * Handler to prepare for connection to a user or app specified network */ public void prepareForForcedConnection(int netId) { - localLog("prepareForForcedConnection: netId=" + netId); + WifiConfiguration config = mConfigManager.getConfiguredNetwork(netId); + if (config == null) { + return; + } + localLog("prepareForForcedConnection: SSID=" + config.SSID); clearConnectionAttemptTimeStamps(); - clearBssidBlacklist(); + mBssidBlocklistMonitor.clearBssidBlocklistForSsid(config.SSID); } /** @@ -1254,175 +1241,6 @@ public class WifiConnectivityManager { } /** - * Update the BSSID blacklist when a BSSID is enabled or disabled - * - * @param bssid the bssid to be enabled/disabled - * @param enable -- true enable the bssid - * -- false disable the bssid - * @param reasonCode enable/disable reason code - * @return true if blacklist is updated; false otherwise - */ - private boolean updateBssidBlacklist(String bssid, boolean enable, int reasonCode) { - // Remove the bssid from blacklist when it is enabled. - if (enable) { - return mBssidBlacklist.remove(bssid) != null; - } - - // Do not update BSSID blacklist with information if this is the only - // BSSID for its SSID. By ignoring it we will cause additional failures - // which will trigger Watchdog. - if (mWifiLastResortWatchdog.shouldIgnoreBssidUpdate(bssid)) { - localLog("Ignore update Bssid Blacklist since Watchdog trigger is activated"); - return false; - } - - // Update the bssid's blacklist status when it is disabled because of - // association rejection. - BssidBlacklistStatus status = mBssidBlacklist.get(bssid); - if (status == null) { - // First time for this BSSID - status = new BssidBlacklistStatus(); - mBssidBlacklist.put(bssid, status); - } - - status.blacklistedTimeStamp = mClock.getElapsedSinceBootMillis(); - status.counter++; - if (!status.isBlacklisted) { - if (status.counter >= BSSID_BLACKLIST_THRESHOLD - || reasonCode == REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA) { - status.isBlacklisted = true; - return true; - } - } - return false; - } - - /** - * Track whether a BSSID should be enabled or disabled for WifiNetworkSelector - * - * @param bssid the bssid to be enabled/disabled - * @param enable -- true enable the bssid - * -- false disable the bssid - * @param reasonCode enable/disable reason code - * @return true if blacklist is updated; false otherwise - */ - public boolean trackBssid(String bssid, boolean enable, int reasonCode) { - localLog("trackBssid: " + (enable ? "enable " : "disable ") + bssid + " reason code " - + reasonCode); - - if (bssid == null) { - return false; - } - - if (!updateBssidBlacklist(bssid, enable, reasonCode)) { - return false; - } - - // Blacklist was updated, so update firmware roaming configuration. - updateFirmwareRoamingConfiguration(); - - if (!enable) { - // Disabling a BSSID can happen when connection to the AP was rejected. - // We start another scan immediately so that WifiNetworkSelector can - // give us another candidate to connect to. - startConnectivityScan(SCAN_IMMEDIATELY); - } - - return true; - } - - /** - * Check whether a bssid is disabled - */ - @VisibleForTesting - public boolean isBssidDisabled(String bssid) { - BssidBlacklistStatus status = mBssidBlacklist.get(bssid); - return status == null ? false : status.isBlacklisted; - } - - /** - * Compile and return a hashset of the blacklisted BSSIDs - */ - private HashSet<String> buildBssidBlacklist() { - HashSet<String> blacklistedBssids = new HashSet<String>(); - for (String bssid : mBssidBlacklist.keySet()) { - if (isBssidDisabled(bssid)) { - blacklistedBssids.add(bssid); - } - } - - return blacklistedBssids; - } - - /** - * Update firmware roaming configuration if the firmware roaming feature is supported. - * Compile and write the BSSID blacklist only. TODO(b/36488259): SSID whitelist is always - * empty for now. - */ - private void updateFirmwareRoamingConfiguration() { - if (!mConnectivityHelper.isFirmwareRoamingSupported()) { - return; - } - - int maxBlacklistSize = mConnectivityHelper.getMaxNumBlacklistBssid(); - if (maxBlacklistSize < 0) { - Log.wtf(TAG, "Invalid max BSSID blacklist size: " + maxBlacklistSize); - return; - } else if (maxBlacklistSize == 0) { - Log.d(TAG, "Skip setting firmware roaming configuration" + - " since max BSSID blacklist size is zero"); - return; - } - - ArrayList<String> blacklistedBssids = new ArrayList<String>(buildBssidBlacklist()); - int blacklistSize = blacklistedBssids.size(); - - if (blacklistSize > maxBlacklistSize) { - Log.wtf(TAG, "Attempt to write " + blacklistSize + " blacklisted BSSIDs, max size is " - + maxBlacklistSize); - - blacklistedBssids = new ArrayList<String>(blacklistedBssids.subList(0, - maxBlacklistSize)); - localLog("Trim down BSSID blacklist size from " + blacklistSize + " to " - + blacklistedBssids.size()); - } - - if (!mConnectivityHelper.setFirmwareRoamingConfiguration(blacklistedBssids, - new ArrayList<String>())) { // TODO(b/36488259): SSID whitelist management. - localLog("Failed to set firmware roaming configuration."); - } - } - - /** - * Refresh the BSSID blacklist - * - * Go through the BSSID blacklist and check if a BSSID has been blacklisted for - * BSSID_BLACKLIST_EXPIRE_TIME_MS. If yes, re-enable it. - */ - private void refreshBssidBlacklist() { - if (mBssidBlacklist.isEmpty()) { - return; - } - - boolean updated = false; - Iterator<BssidBlacklistStatus> iter = mBssidBlacklist.values().iterator(); - Long currentTimeStamp = mClock.getElapsedSinceBootMillis(); - - while (iter.hasNext()) { - BssidBlacklistStatus status = iter.next(); - if (status.isBlacklisted && ((currentTimeStamp - status.blacklistedTimeStamp) - >= BSSID_BLACKLIST_EXPIRE_TIME_MS)) { - iter.remove(); - updated = true; - } - } - - if (updated) { - updateFirmwareRoamingConfiguration(); - } - } - - /** * Helper method to populate WifiScanner handle. This is done lazily because * WifiScanningService is started after WifiService. */ @@ -1434,15 +1252,6 @@ public class WifiConnectivityManager { mScanner.registerScanListener(mAllSingleScanListener); } - - /** - * Clear the BSSID blacklist - */ - private void clearBssidBlacklist() { - mBssidBlacklist.clear(); - updateFirmwareRoamingConfiguration(); - } - /** * Start WifiConnectivityManager */ @@ -1450,7 +1259,7 @@ public class WifiConnectivityManager { if (mRunning) return; retrieveWifiScanner(); mConnectivityHelper.getFirmwareRoamingInfo(); - clearBssidBlacklist(); + mBssidBlocklistMonitor.clearBssidBlocklist(); mRunning = true; } @@ -1461,7 +1270,7 @@ public class WifiConnectivityManager { if (!mRunning) return; mRunning = false; stopConnectivityScan(); - clearBssidBlacklist(); + mBssidBlocklistMonitor.clearBssidBlocklist(); resetLastPeriodicSingleScanTimeStamp(); mOpenNetworkNotifier.clearPendingNotification(true /* resetRepeatDelay */); mLastConnectionAttemptBssid = null; @@ -1524,5 +1333,6 @@ public class WifiConnectivityManager { pw.println("WifiConnectivityManager - Log End ----"); mOpenNetworkNotifier.dump(fd, pw, args); mCarrierNetworkConfig.dump(fd, pw, args); + mBssidBlocklistMonitor.dump(fd, pw, args); } } diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java index 18f447aac..efc59e64b 100644 --- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java +++ b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java @@ -116,7 +116,7 @@ public class WifiLastResortWatchdog { // did not fix the problem private boolean mWatchdogFixedWifi = true; private long mLastStartConnectTime = 0; - private Handler mHandler; + private final Handler mHandler; private final WifiThreadRunner mWifiThreadRunner; private boolean mWatchdogFeatureEnabled = true; diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index a875cd6c3..070c56a1d 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -1087,8 +1087,8 @@ public class WifiMetrics { /** * End a Connection event record. Call when wifi connection attempt succeeds or fails. - * If a Connection event has not been started and is active when .end is called, a new one is - * created with zero duration. + * If a Connection event has not been started and is active when .end is called, then this + * method will do nothing. * * @param level2FailureCode Level 2 failure code returned by supplicant * @param connectivityFailureCode WifiMetricsProto.ConnectionEvent.HLF_X |