diff options
Diffstat (limited to 'service/java/com/android/server/wifi/WifiLastResortWatchdog.java')
-rw-r--r-- | service/java/com/android/server/wifi/WifiLastResortWatchdog.java | 831 |
1 files changed, 0 insertions, 831 deletions
diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java deleted file mode 100644 index 9846747f6..000000000 --- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wifi; - -import android.content.Context; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.text.TextUtils; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.wifi.resources.R; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This Class is a Work-In-Progress, intended behavior is as follows: - * Essentially this class automates a user toggling 'Airplane Mode' when WiFi "won't work". - * IF each available saved network has failed connecting more times than the FAILURE_THRESHOLD - * THEN Watchdog will restart Supplicant, wifi driver and return ClientModeImpl to InitialState. - */ -public class WifiLastResortWatchdog { - private static final String TAG = "WifiLastResortWatchdog"; - private boolean mVerboseLoggingEnabled = false; - /** - * Association Failure code - */ - public static final int FAILURE_CODE_ASSOCIATION = 1; - /** - * Authentication Failure code - */ - public static final int FAILURE_CODE_AUTHENTICATION = 2; - /** - * Dhcp Failure code - */ - public static final int FAILURE_CODE_DHCP = 3; - /** - * Maximum number of scan results received since we last saw a BSSID. - * If it is not seen before this limit is reached, the network is culled - */ - public static final int MAX_BSSID_AGE = 10; - /** - * BSSID used to increment failure counts against ALL bssids associated with a particular SSID - */ - public static final String BSSID_ANY = "any"; - /** - * Failure count that each available networks must meet to possibly trigger the Watchdog - */ - public static final int FAILURE_THRESHOLD = 7; - public static final String BUGREPORT_TITLE = "Wifi watchdog triggered"; - public static final double PROB_TAKE_BUGREPORT_DEFAULT = 1; - - // Number of milliseconds to wait before re-enable Watchdog triger - @VisibleForTesting - public static final long LAST_TRIGGER_TIMEOUT_MILLIS = 2 * 3600 * 1000; // 2 hours - - - /** - * Cached WifiConfigurations of available networks seen within MAX_BSSID_AGE scan results - * Key:BSSID, Value:Counters of failure types - */ - private Map<String, AvailableNetworkFailureCount> mRecentAvailableNetworks = new HashMap<>(); - - /** - * Map of SSID to <FailureCount, AP count>, used to count failures & number of access points - * belonging to an SSID. - */ - private Map<String, Pair<AvailableNetworkFailureCount, Integer>> mSsidFailureCount = - new HashMap<>(); - - /* List of failure BSSID */ - private Set<String> mBssidFailureList = new HashSet<>(); - - // Tracks: if ClientModeImpl is in ConnectedState - private boolean mWifiIsConnected = false; - // Is Watchdog allowed to trigger now? Set to false after triggering. Set to true after - // successfully connecting or a new network (SSID) becomes available to connect to. - private boolean mWatchdogAllowedToTrigger = true; - private long mTimeLastTrigger = 0; - private String mSsidLastTrigger = null; - - private WifiInjector mWifiInjector; - private WifiMetrics mWifiMetrics; - private ClientModeImpl mClientModeImpl; - private Looper mClientModeImplLooper; - private double mBugReportProbability = PROB_TAKE_BUGREPORT_DEFAULT; - private Clock mClock; - private Context mContext; - private DeviceConfigFacade mDeviceConfigFacade; - // If any connection failure happened after watchdog triggering restart then assume watchdog - // did not fix the problem - private boolean mWatchdogFixedWifi = true; - private long mLastStartConnectTime = 0; - private final Handler mHandler; - private final WifiThreadRunner mWifiThreadRunner; - - private Boolean mWatchdogFeatureEnabled = null; - - /** - * Local log used for debugging any WifiLastResortWatchdog issues. - */ - private final LocalLog mLocalLog = new LocalLog(100); - - WifiLastResortWatchdog(WifiInjector wifiInjector, Context context, Clock clock, - WifiMetrics wifiMetrics, ClientModeImpl clientModeImpl, Looper clientModeImplLooper, - DeviceConfigFacade deviceConfigFacade, WifiThreadRunner wifiThreadRunner) { - mWifiInjector = wifiInjector; - mClock = clock; - mWifiMetrics = wifiMetrics; - mClientModeImpl = clientModeImpl; - mClientModeImplLooper = clientModeImplLooper; - mContext = context; - mDeviceConfigFacade = deviceConfigFacade; - mWifiThreadRunner = wifiThreadRunner; - mHandler = new Handler(clientModeImplLooper) { - public void handleMessage(Message msg) { - processMessage(msg); - } - }; - } - - /** - * Returns handler for L2 events from supplicant. - * @return Handler - */ - public Handler getHandler() { - return mHandler; - } - - /** - * Refreshes when the last CMD_START_CONNECT is triggered. - */ - public void noteStartConnectTime() { - mHandler.post(() -> { - mLastStartConnectTime = mClock.getElapsedSinceBootMillis(); - }); - } - - private void processMessage(Message msg) { - switch (msg.what) { - case WifiMonitor.NETWORK_CONNECTION_EVENT: - // Trigger bugreport for successful connections that take abnormally long - if (mDeviceConfigFacade.isAbnormalConnectionBugreportEnabled() - && mLastStartConnectTime > 0) { - long durationMs = mClock.getElapsedSinceBootMillis() - mLastStartConnectTime; - long abnormalConnectionDurationMs = - mDeviceConfigFacade.getAbnormalConnectionDurationMs(); - if (durationMs > abnormalConnectionDurationMs) { - final String bugTitle = "Wi-Fi Bugreport: Abnormal connection time"; - final String bugDetail = "Expected connection to take less than " - + abnormalConnectionDurationMs + " milliseconds. " - + "Actually took " + durationMs + " milliseconds."; - logv("Triggering bug report for abnormal connection time."); - mWifiThreadRunner.post(() -> - mClientModeImpl.takeBugReport(bugTitle, bugDetail)); - } - } - // Should reset last connection time after each connection regardless if bugreport - // is enabled or not. - mLastStartConnectTime = 0; - break; - default: - return; - } - } - - /** - * Refreshes recentAvailableNetworks with the latest available networks - * Adds new networks, removes old ones that have timed out. Should be called after Wifi - * framework decides what networks it is potentially connecting to. - * @param availableNetworks ScanDetail & Config list of potential connection - * candidates - */ - public void updateAvailableNetworks( - List<Pair<ScanDetail, WifiConfiguration>> availableNetworks) { - // Add new networks to mRecentAvailableNetworks - if (availableNetworks != null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateAvailableNetworks: size = " + availableNetworks.size()); - } - for (Pair<ScanDetail, WifiConfiguration> pair : availableNetworks) { - final ScanDetail scanDetail = pair.first; - final WifiConfiguration config = pair.second; - ScanResult scanResult = scanDetail.getScanResult(); - if (scanResult == null) continue; - String bssid = scanResult.BSSID; - String ssid = "\"" + scanDetail.getSSID() + "\""; - if (mVerboseLoggingEnabled) { - Log.v(TAG, " " + bssid + ": " + scanDetail.getSSID()); - } - // Cache the scanResult & WifiConfig - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - // New network is available - availableNetworkFailureCount = new AvailableNetworkFailureCount(config); - availableNetworkFailureCount.ssid = ssid; - - // Count AP for this SSID - Pair<AvailableNetworkFailureCount, Integer> ssidFailsAndApCount = - mSsidFailureCount.get(ssid); - if (ssidFailsAndApCount == null) { - // This is a new SSID, create new FailureCount for it and set AP count to 1 - ssidFailsAndApCount = Pair.create(new AvailableNetworkFailureCount(config), - 1); - // Do not re-enable Watchdog in LAST_TRIGGER_TIMEOUT_MILLIS - // after last time Watchdog be triggered - if (!mWatchdogAllowedToTrigger && (mTimeLastTrigger == 0 - || (mClock.getElapsedSinceBootMillis() - mTimeLastTrigger) - >= LAST_TRIGGER_TIMEOUT_MILLIS)) { - localLog("updateAvailableNetworks: setWatchdogTriggerEnabled to true"); - setWatchdogTriggerEnabled(true); - } - } else { - final Integer numberOfAps = ssidFailsAndApCount.second; - // This is not a new SSID, increment the AP count for it - ssidFailsAndApCount = Pair.create(ssidFailsAndApCount.first, - numberOfAps + 1); - } - mSsidFailureCount.put(ssid, ssidFailsAndApCount); - } - // refresh config if it is not null - if (config != null) { - availableNetworkFailureCount.config = config; - } - // If we saw a network, set its Age to -1 here, aging iteration will set it to 0 - availableNetworkFailureCount.age = -1; - mRecentAvailableNetworks.put(bssid, availableNetworkFailureCount); - } - } - - // Iterate through available networks updating timeout counts & removing networks. - Iterator<Map.Entry<String, AvailableNetworkFailureCount>> it = - mRecentAvailableNetworks.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, AvailableNetworkFailureCount> entry = it.next(); - if (entry.getValue().age < MAX_BSSID_AGE - 1) { - entry.getValue().age++; - } else { - // Decrement this SSID : AP count - String ssid = entry.getValue().ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = - mSsidFailureCount.get(ssid); - if (ssidFails != null) { - Integer apCount = ssidFails.second - 1; - if (apCount > 0) { - ssidFails = Pair.create(ssidFails.first, apCount); - mSsidFailureCount.put(ssid, ssidFails); - } else { - mSsidFailureCount.remove(ssid); - } - } else { - Log.d(TAG, "updateAvailableNetworks: SSID to AP count mismatch for " + ssid); - } - it.remove(); - } - } - if (mVerboseLoggingEnabled) Log.v(TAG, toString()); - } - - /** - * Increments the failure reason count for the given bssid. Performs a check to see if we have - * exceeded a failure threshold for all available networks, and executes the last resort restart - * @param bssid of the network that has failed connection, can be "any" - * @param reason Message id from ClientModeImpl for this failure - * @return true if watchdog triggers, returned for test visibility - */ - public boolean noteConnectionFailureAndTriggerIfNeeded(String ssid, String bssid, int reason) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "noteConnectionFailureAndTriggerIfNeeded: [" + ssid + ", " + bssid + ", " - + reason + "]"); - } - - // Update failure count for the failing network - updateFailureCountForNetwork(ssid, bssid, reason); - - // If watchdog is not allowed to trigger it means a wifi restart is already triggered - if (!mWatchdogAllowedToTrigger) { - mWifiMetrics.incrementWatchdogTotalConnectionFailureCountAfterTrigger(); - mWatchdogFixedWifi = false; - } - // Have we met conditions to trigger the Watchdog Wifi restart? - boolean isRestartNeeded = checkTriggerCondition(); - if (mVerboseLoggingEnabled) { - Log.v(TAG, "isRestartNeeded = " + isRestartNeeded); - } - if (isRestartNeeded) { - if (getWifiWatchdogFeature()) { - // Stop the watchdog from triggering until re-enabled - localLog("Trigger recovery: setWatchdogTriggerEnabled to false"); - setWatchdogTriggerEnabled(false); - mWatchdogFixedWifi = true; - loge("Watchdog triggering recovery"); - mSsidLastTrigger = ssid; - mTimeLastTrigger = mClock.getElapsedSinceBootMillis(); - localLog(toString()); - mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG); - incrementWifiMetricsTriggerCounts(); - } else { - // auto bugreport if issue happens - loge("bugreport notification"); - setWatchdogTriggerEnabled(false); - takeBugReportWithCurrentProbability("Wifi Watchdog bite"); - } - } - return isRestartNeeded; - } - - /** - * Handles transitions entering and exiting ClientModeImpl ConnectedState - * Used to track wifistate, and perform watchdog count resetting - * @param isEntering true if called from ConnectedState.enter(), false for exit() - */ - public void connectedStateTransition(boolean isEntering) { - logv("connectedStateTransition: isEntering = " + isEntering); - - mWifiIsConnected = isEntering; - if (!isEntering) { - return; - } - if (!mWatchdogAllowedToTrigger && mWatchdogFixedWifi - && getWifiWatchdogFeature() - && checkIfAtleastOneNetworkHasEverConnected() - && checkIfConnectedBackToSameSsid() - && checkIfConnectedBssidHasEverFailed()) { - takeBugReportWithCurrentProbability("Wifi fixed after restart"); - // WiFi has connected after a Watchdog trigger, without any new networks becoming - // available, log a Watchdog success in wifi metrics - mWifiMetrics.incrementNumLastResortWatchdogSuccesses(); - long durationMs = mClock.getElapsedSinceBootMillis() - mTimeLastTrigger; - mWifiMetrics.setWatchdogSuccessTimeDurationMs(durationMs); - } - // If the watchdog trigger was disabled (it triggered), connecting means we did - // something right, re-enable it so it can fire again. - localLog("connectedStateTransition: setWatchdogTriggerEnabled to true"); - setWatchdogTriggerEnabled(true); - } - - /** - * Helper function to check if device connected to BSSID - * which is in BSSID failure list after watchdog trigger. - */ - private boolean checkIfConnectedBssidHasEverFailed() { - return mBssidFailureList.contains(mClientModeImpl.getWifiInfo().getBSSID()); - } - - /** - * Helper function to check if device connect back to same - * SSID after watchdog trigger - */ - private boolean checkIfConnectedBackToSameSsid() { - if (TextUtils.equals(mSsidLastTrigger, mClientModeImpl.getWifiInfo().getSSID())) { - return true; - } - localLog("checkIfConnectedBackToSameSsid: different SSID be connected"); - return false; - } - - /** - * Triggers a wifi specific bugreport with a based on the current trigger probability. - * @param bugDetail description of the bug - */ - private void takeBugReportWithCurrentProbability(String bugDetail) { - if (mBugReportProbability <= Math.random()) { - return; - } - (new Handler(mClientModeImplLooper)).post(() -> { - mClientModeImpl.takeBugReport(BUGREPORT_TITLE, bugDetail); - }); - } - - /** - * Increments the failure reason count for the given network, in 'mSsidFailureCount' - * Failures are counted per SSID, either; by using the ssid string when the bssid is "any" - * or by looking up the ssid attached to a specific bssid - * An unused set of counts is also kept which is bssid specific, in 'mRecentAvailableNetworks' - * @param ssid of the network that has failed connection - * @param bssid of the network that has failed connection, can be "any" - * @param reason Message id from ClientModeImpl for this failure - */ - private void updateFailureCountForNetwork(String ssid, String bssid, int reason) { - logv("updateFailureCountForNetwork: [" + ssid + ", " + bssid + ", " - + reason + "]"); - if (BSSID_ANY.equals(bssid)) { - incrementSsidFailureCount(ssid, reason); - } else { - // Bssid count is actually unused except for logging purposes - // SSID count is incremented within the BSSID counting method - incrementBssidFailureCount(ssid, bssid, reason); - mBssidFailureList.add(bssid); - } - } - - /** - * Update the per-SSID failure count - * @param ssid the ssid to increment failure count for - * @param reason the failure type to increment count for - */ - private void incrementSsidFailureCount(String ssid, int reason) { - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "updateFailureCountForNetwork: No networks for ssid = " + ssid); - return; - } - AvailableNetworkFailureCount failureCount = ssidFails.first; - failureCount.incrementFailureCount(reason); - } - - /** - * Update the per-BSSID failure count - * @param bssid the bssid to increment failure count for - * @param reason the failure type to increment count for - */ - private void incrementBssidFailureCount(String ssid, String bssid, int reason) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - Log.d(TAG, "updateFailureCountForNetwork: Unable to find Network [" + ssid - + ", " + bssid + "]"); - return; - } - if (!availableNetworkFailureCount.ssid.equals(ssid)) { - Log.d(TAG, "updateFailureCountForNetwork: Failed connection attempt has" - + " wrong ssid. Failed [" + ssid + ", " + bssid + "], buffered [" - + availableNetworkFailureCount.ssid + ", " + bssid + "]"); - return; - } - if (availableNetworkFailureCount.config == null) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "updateFailureCountForNetwork: network has no config [" - + ssid + ", " + bssid + "]"); - } - } - availableNetworkFailureCount.incrementFailureCount(reason); - incrementSsidFailureCount(ssid, reason); - } - - /** - * Helper function to check if we should ignore BSSID update. - * @param bssid BSSID of the access point - * @return true if we should ignore BSSID update - */ - public boolean shouldIgnoreBssidUpdate(String bssid) { - return mWatchdogAllowedToTrigger - && isBssidOnlyApOfSsid(bssid) - && isSingleSsidRecorded() - && checkIfAtleastOneNetworkHasEverConnected(); - } - - /** - * Helper function to check if we should ignore SSID update. - * @return true if should ignore SSID update - */ - public boolean shouldIgnoreSsidUpdate() { - return mWatchdogAllowedToTrigger - && isSingleSsidRecorded() - && checkIfAtleastOneNetworkHasEverConnected(); - } - - /** - * Check the specified BSSID is the only BSSID for its corresponding SSID. - * @param bssid BSSID of the access point - * @return true if only BSSID for its corresponding SSID be observed - */ - private boolean isBssidOnlyApOfSsid(String bssid) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - return false; - } - String ssid = availableNetworkFailureCount.ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "isOnlyBssidAvailable: Could not find SSID count for " + ssid); - return false; - } - if (ssidFails.second != 1) { - return false; - } - return true; - } - - /** - * Check there is only single SSID be observed. - * @return true if only single SSID be observed. - */ - private boolean isSingleSsidRecorded() { - return (mSsidFailureCount.size() == 1); - } - - /** - * Check trigger condition: For all available networks, have we met a failure threshold for each - * of them, and have previously connected to at-least one of the available networks - * @return is the trigger condition true - */ - private boolean checkTriggerCondition() { - if (mVerboseLoggingEnabled) Log.v(TAG, "checkTriggerCondition."); - // Don't check Watchdog trigger if wifi is in a connected state - // (This should not occur, but we want to protect against any race conditions) - if (mWifiIsConnected) return false; - // Don't check Watchdog trigger if trigger is not enabled - if (!mWatchdogAllowedToTrigger) return false; - - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - if (!isOverFailureThreshold(entry.getKey())) { - // This available network is not over failure threshold, meaning we still have a - // network to try connecting to - return false; - } - } - // We have met the failure count for every available network. - // Trigger restart if there exists at-least one network that we have previously connected. - boolean atleastOneNetworkHasEverConnected = checkIfAtleastOneNetworkHasEverConnected(); - logv("checkTriggerCondition: return = " + atleastOneNetworkHasEverConnected); - return checkIfAtleastOneNetworkHasEverConnected(); - } - - private boolean checkIfAtleastOneNetworkHasEverConnected() { - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - if (entry.getValue().config != null - && entry.getValue().config.getNetworkSelectionStatus().hasEverConnected()) { - return true; - } - } - return false; - } - - /** - * Update WifiMetrics with various Watchdog stats (trigger counts, failed network counts) - */ - private void incrementWifiMetricsTriggerCounts() { - if (mVerboseLoggingEnabled) Log.v(TAG, "incrementWifiMetricsTriggerCounts."); - mWifiMetrics.incrementNumLastResortWatchdogTriggers(); - mWifiMetrics.addCountToNumLastResortWatchdogAvailableNetworksTotal( - mSsidFailureCount.size()); - // Number of networks over each failure type threshold, present at trigger time - int badAuth = 0; - int badAssoc = 0; - int badDhcp = 0; - int badSum = 0; - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry - : mSsidFailureCount.entrySet()) { - badSum = entry.getValue().first.associationRejection - + entry.getValue().first.authenticationFailure - + entry.getValue().first.dhcpFailure; - // count as contributor if over half of badSum. - if (badSum >= FAILURE_THRESHOLD) { - badAssoc += (entry.getValue().first.associationRejection >= badSum / 2) ? 1 : 0; - badAuth += (entry.getValue().first.authenticationFailure >= badSum / 2) ? 1 : 0; - badDhcp += (entry.getValue().first.dhcpFailure >= badSum / 2) ? 1 : 0; - } - } - if (badAuth > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadAuthenticationNetworksTotal(badAuth); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAuthentication(); - } - if (badAssoc > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadAssociationNetworksTotal(badAssoc); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadAssociation(); - } - if (badDhcp > 0) { - mWifiMetrics.addCountToNumLastResortWatchdogBadDhcpNetworksTotal(badDhcp); - mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadDhcp(); - } - } - - /** - * Clear all failure counts - */ - public void clearAllFailureCounts() { - if (mVerboseLoggingEnabled) Log.v(TAG, "clearAllFailureCounts."); - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue(); - failureCount.resetCounts(); - } - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry - : mSsidFailureCount.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue().first; - failureCount.resetCounts(); - } - mBssidFailureList.clear(); - } - /** - * Gets the buffer of recently available networks - */ - Map<String, AvailableNetworkFailureCount> getRecentAvailableNetworks() { - return mRecentAvailableNetworks; - } - - /** - * Activates or deactivates the Watchdog trigger. Counting and network buffering still occurs - * @param enable true to enable the Watchdog trigger, false to disable it - */ - private void setWatchdogTriggerEnabled(boolean enable) { - if (mVerboseLoggingEnabled) Log.v(TAG, "setWatchdogTriggerEnabled: enable = " + enable); - // Reset failure counts before actives watchdog - if (enable) { - clearAllFailureCounts(); - } - mWatchdogAllowedToTrigger = enable; - } - - /** - * Prints all networks & counts within mRecentAvailableNetworks to string - */ - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("mWatchdogFeatureEnabled: ").append(getWifiWatchdogFeature()); - sb.append("\nmWatchdogAllowedToTrigger: ").append(mWatchdogAllowedToTrigger); - sb.append("\nmWifiIsConnected: ").append(mWifiIsConnected); - sb.append("\nmRecentAvailableNetworks: ").append(mRecentAvailableNetworks.size()); - for (Map.Entry<String, AvailableNetworkFailureCount> entry - : mRecentAvailableNetworks.entrySet()) { - sb.append("\n ").append(entry.getKey()).append(": ").append(entry.getValue()) - .append(", Age: ").append(entry.getValue().age); - } - sb.append("\nmSsidFailureCount:"); - for (Map.Entry<String, Pair<AvailableNetworkFailureCount, Integer>> entry : - mSsidFailureCount.entrySet()) { - final AvailableNetworkFailureCount failureCount = entry.getValue().first; - final Integer apCount = entry.getValue().second; - sb.append("\n").append(entry.getKey()).append(": ").append(apCount).append(",") - .append(failureCount.toString()); - } - return sb.toString(); - } - - /** - * @param bssid bssid to check the failures for - * @return true if sum of failure count is over FAILURE_THRESHOLD - */ - public boolean isOverFailureThreshold(String bssid) { - return (getFailureCount(bssid, FAILURE_CODE_ASSOCIATION) - + getFailureCount(bssid, FAILURE_CODE_AUTHENTICATION) - + getFailureCount(bssid, FAILURE_CODE_DHCP)) >= FAILURE_THRESHOLD; - } - - /** - * Get the failure count for a specific bssid. This actually checks the ssid attached to the - * BSSID and returns the SSID count - * @param reason failure reason to get count for - */ - public int getFailureCount(String bssid, int reason) { - AvailableNetworkFailureCount availableNetworkFailureCount = - mRecentAvailableNetworks.get(bssid); - if (availableNetworkFailureCount == null) { - return 0; - } - String ssid = availableNetworkFailureCount.ssid; - Pair<AvailableNetworkFailureCount, Integer> ssidFails = mSsidFailureCount.get(ssid); - if (ssidFails == null) { - Log.d(TAG, "getFailureCount: Could not find SSID count for " + ssid); - return 0; - } - final AvailableNetworkFailureCount failCount = ssidFails.first; - switch (reason) { - case FAILURE_CODE_ASSOCIATION: - return failCount.associationRejection; - case FAILURE_CODE_AUTHENTICATION: - return failCount.authenticationFailure; - case FAILURE_CODE_DHCP: - return failCount.dhcpFailure; - default: - return 0; - } - } - - /** - * Sets whether wifi watchdog should trigger recovery - */ - public void setWifiWatchdogFeature(boolean enable) { - logv("setWifiWatchdogFeature: " + enable); - mWatchdogFeatureEnabled = enable; - // for debugging purpose, reset mWatchdogAllowedToTrigger as well - setWatchdogTriggerEnabled(true); - } - - /** - * Returns whether wifi watchdog should trigger recovery. - */ - public boolean getWifiWatchdogFeature() { - if (mWatchdogFeatureEnabled == null) { - mWatchdogFeatureEnabled = mContext.getResources().getBoolean( - R.bool.config_wifi_watchdog_enabled); - } - return mWatchdogFeatureEnabled; - } - - protected void enableVerboseLogging(int verbose) { - if (verbose > 0) { - mVerboseLoggingEnabled = true; - } else { - mVerboseLoggingEnabled = false; - } - } - - @VisibleForTesting - protected void setBugReportProbability(double newProbability) { - mBugReportProbability = newProbability; - } - - /** - * This class holds the failure counts for an 'available network' (one of the potential - * candidates for connection, as determined by framework). - */ - public static class AvailableNetworkFailureCount { - /** - * WifiConfiguration associated with this network. Can be null for Ephemeral networks - */ - public WifiConfiguration config; - /** - * SSID of the network (from ScanDetail) - */ - public String ssid = ""; - /** - * Number of times network has failed due to Association Rejection - */ - public int associationRejection = 0; - /** - * Number of times network has failed due to Authentication Failure or SSID_TEMP_DISABLED - */ - public int authenticationFailure = 0; - /** - * Number of times network has failed due to DHCP failure - */ - public int dhcpFailure = 0; - /** - * Number of scanResults since this network was last seen - */ - public int age = 0; - - AvailableNetworkFailureCount(WifiConfiguration configParam) { - this.config = configParam; - } - - /** - * @param reason failure reason to increment count for - */ - public void incrementFailureCount(int reason) { - switch (reason) { - case FAILURE_CODE_ASSOCIATION: - associationRejection++; - break; - case FAILURE_CODE_AUTHENTICATION: - authenticationFailure++; - break; - case FAILURE_CODE_DHCP: - dhcpFailure++; - break; - default: //do nothing - } - } - - /** - * Set all failure counts for this network to 0 - */ - void resetCounts() { - associationRejection = 0; - authenticationFailure = 0; - dhcpFailure = 0; - } - - public String toString() { - return ssid + " HasEverConnected: " + ((config != null) - ? config.getNetworkSelectionStatus().hasEverConnected() : "null_config") - + ", Failures: {" - + "Assoc: " + associationRejection - + ", Auth: " + authenticationFailure - + ", Dhcp: " + dhcpFailure - + "}"; - } - } - - /** - * Helper function for logging into local log buffer. - */ - private void localLog(String s) { - mLocalLog.log(s); - } - - private void logv(String s) { - mLocalLog.log(s); - if (mVerboseLoggingEnabled) { - Log.v(TAG, s); - } - } - - private void loge(String s) { - mLocalLog.log(s); - Log.e(TAG, s); - } - - /** - * Dump the local log buffer and other internal state of WifiLastResortWatchdog. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Dump of WifiLastResortWatchdog"); - pw.println("WifiLastResortWatchdog - Log Begin ----"); - mLocalLog.dump(fd, pw, args); - pw.println("WifiLastResortWatchdog - Log End ----"); - } -} |