WifiLastResortWatchdog.java revision 09abbe29be6e552a2531b0367bd6d29647d33767
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import android.net.wifi.ScanResult; 20import android.net.wifi.WifiConfiguration; 21import android.util.Log; 22import android.util.Pair; 23 24import java.util.HashMap; 25import java.util.Iterator; 26import java.util.List; 27import java.util.Map; 28 29/** 30 * <TBD> Intended Purpose/Behavior of the class upon completion: 31 * Essentially this class automates a user toggling 'Airplane Mode' when WiFi "won't work". 32 * IF each available saved network has failed connecting more times than the FAILURE_THRESHOLD 33 * THEN Watchdog will restart Supplicant, wifi driver and return WifiStateMachine to InitialState. 34 * </TBD> 35 */ 36public class WifiLastResortWatchdog { 37 private static final String TAG = "WifiLastResortWatchdog"; 38 private static final boolean VDBG = false; 39 /** 40 * Cached WifiConfigurations of available networks seen within MAX_BSSID_AGE scan results 41 * Key:BSSID, Value:Counters of failure types 42 */ 43 private Map<String, AvailableNetworkFailureCount> mRecentAvailableNetworks = new HashMap<>(); 44 45 // Maximum number of scan results received since we last saw a BSSID. 46 // If it is not seen before this limit is reached, the network is culled 47 public static final int MAX_BSSID_AGE = 10; 48 49 /** 50 * Refreshes recentAvailableNetworks with the latest available networks 51 * Adds new networks, removes old ones that have timed out. Should be called after Wifi 52 * framework decides what networks it is potentially connecting to. 53 * @param availableNetworkFailureCounts ScanDetail & Config list of potential connection 54 * candidates 55 */ 56 public void updateAvailableNetworks( 57 List<Pair<ScanDetail, WifiConfiguration>> availableNetworkFailureCounts) { 58 // Add new networks to mRecentAvailableNetworks 59 if (availableNetworkFailureCounts != null) { 60 for (Pair<ScanDetail, WifiConfiguration> pair : availableNetworkFailureCounts) { 61 ScanResult scanResult = pair.first.getScanResult(); 62 if (scanResult == null) continue; 63 String key = scanResult.BSSID; 64 65 // Cache the scanResult & WifiConfig 66 AvailableNetworkFailureCount availableNetworkFailureCount = 67 mRecentAvailableNetworks.get(key); 68 if (availableNetworkFailureCount != null) { 69 // We've already cached this, refresh timeout count & config 70 availableNetworkFailureCount.config = pair.second; 71 } else { 72 // New network is available 73 availableNetworkFailureCount = new AvailableNetworkFailureCount(pair.second); 74 availableNetworkFailureCount.Ssid = pair.first.getSSID(); 75 } 76 // If we saw a network, set its Age to -1 here, next incrementation will set it to 0 77 availableNetworkFailureCount.age = -1; 78 mRecentAvailableNetworks.put(key, availableNetworkFailureCount); 79 } 80 } 81 82 // Iterate through available networks updating timeout counts & removing networks. 83 Iterator<Map.Entry<String, AvailableNetworkFailureCount>> it = 84 mRecentAvailableNetworks.entrySet().iterator(); 85 while (it.hasNext()) { 86 Map.Entry<String, AvailableNetworkFailureCount> entry = it.next(); 87 if (entry.getValue().age < MAX_BSSID_AGE - 1) { 88 entry.getValue().age++; 89 } else { 90 it.remove(); 91 } 92 } 93 if (VDBG) Log.v(TAG, toString()); 94 } 95 96 /** 97 * Gets the buffer of recently available networks 98 */ 99 Map<String, AvailableNetworkFailureCount> getRecentAvailableNetworks() { 100 return mRecentAvailableNetworks; 101 } 102 103 /** 104 * Prints all networks & counts within mRecentAvailableNetworks to string 105 */ 106 public String toString() { 107 StringBuilder sb = new StringBuilder(); 108 sb.append("WifiLastResortWatchdog: " + mRecentAvailableNetworks.size() + " networks..."); 109 for (Map.Entry<String, AvailableNetworkFailureCount> entry 110 : mRecentAvailableNetworks.entrySet()) { 111 sb.append("\n " + entry.getKey() + ": " + entry.getValue()); 112 } 113 return sb.toString(); 114 } 115 116 static class AvailableNetworkFailureCount { 117 /** 118 * WifiConfiguration associated with this network. Can be null for Ephemeral networks 119 */ 120 public WifiConfiguration config; 121 /** 122 * SSID of the network (from ScanDetail) 123 */ 124 public String Ssid = ""; 125 /** 126 * Number of times network has failed for this reason 127 */ 128 public int associationRejection = 0; 129 /** 130 * Number of times network has failed for this reason 131 */ 132 public int authenticationRejection = 0; 133 /** 134 * Number of times network has failed for this reason 135 */ 136 public int dhcpFailure = 0; 137 /** 138 * Number of scanResults since this network was last seen 139 */ 140 public int age = 0; 141 142 AvailableNetworkFailureCount(WifiConfiguration config) { 143 config = config; 144 } 145 146 void resetCounts() { 147 associationRejection = 0; 148 authenticationRejection = 0; 149 dhcpFailure = 0; 150 } 151 152 public String toString() { 153 return Ssid + ", HasEverConnected: " + ((config != null) 154 ? config.getNetworkSelectionStatus().getHasEverConnected() : false) 155 + ", Failures: {" 156 + "Assoc: " + associationRejection 157 + ", Auth: " + authenticationRejection 158 + ", Dhcp: " + dhcpFailure 159 + "}" 160 + ", Age: " + age; 161 } 162 } 163} 164