WifiAutoJoinController.java revision 7b581f46f6c9bc6edf0edd287d47106712fb2144
1f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle/* 262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle * Copyright (C) 2014 The Android Open Source Project 3f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * 4f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Licensed under the Apache License, Version 2.0 (the "License"); 5f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * you may not use this file except in compliance with the License. 6f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * You may obtain a copy of the License at 7f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * 8f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * http://www.apache.org/licenses/LICENSE-2.0 9f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * 10f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Unless required by applicable law or agreed to in writing, software 11f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * distributed under the License is distributed on an "AS IS" BASIS, 12f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * See the License for the specific language governing permissions and 14f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * limitations under the License. 15f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */ 16f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 17f22d23092ab37286a5ef9d257d5bb32c421d2669vandwallepackage com.android.server.wifi; 18f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 19f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.content.Context; 20f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 21f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.NetworkKey; 22f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.NetworkScoreManager; 230c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalleimport android.net.WifiKey; 24c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalleimport android.net.wifi.*; 25f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 26f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.os.SystemClock; 27b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalleimport android.os.Process; 28c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalleimport android.text.TextUtils; 29f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.util.Log; 30f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 310c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalleimport java.util.ArrayList; 32f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.Iterator; 33f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.HashMap; 34f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.List; 35f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 36f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle/** 37f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * AutoJoin controller is responsible for WiFi Connect decision 38f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * 39f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * It runs in the thread context of WifiStateMachine 40f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * 41f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */ 42f22d23092ab37286a5ef9d257d5bb32c421d2669vandwallepublic class WifiAutoJoinController { 43f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 44f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private Context mContext; 45f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private WifiStateMachine mWifiStateMachine; 46f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private WifiConfigStore mWifiConfigStore; 47f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private WifiNative mWifiNative; 48f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 49f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private NetworkScoreManager scoreManager; 50f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private WifiNetworkScoreCache mNetworkScoreCache; 51f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 52f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private static final String TAG = "WifiAutoJoinController "; 53ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle private static boolean DBG = false; 54ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle private static boolean VDBG = false; 55f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private static final boolean mStaStaSupported = false; 56f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private static final int SCAN_RESULT_CACHE_SIZE = 80; 57f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 58c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle public static int mScanResultMaximumAge = 40000; /* milliseconds unit */ 59c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 60453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle private String mCurrentConfigurationKey = null; //used by autojoin 61f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 62f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private HashMap<String, ScanResult> scanResultCache = 63f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle new HashMap<String, ScanResult>(); 64f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 65c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle private WifiConnectionStatistics mWifiConnectionStatistics; 66c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 67c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle /* for debug purpose only : the untrusted SSID we would be connected to if we had VPN */ 68c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle String lastUntrustedBSSID = null; 69c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 70c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle /* For debug purpose only: if the scored override a score */ 71c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle boolean didOverride = false; 72c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 73931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Lose the non-auth failure blacklisting after 8 hours 744dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle private final static long loseBlackListHardMilli = 1000 * 60 * 60 * 8; 75931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Lose some temporary blacklisting after 30 minutes 764dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle private final static long loseBlackListSoftMilli = 1000 * 60 * 30; 7727355a942653264388e909a4276196ee63e57811vandwalle 78b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle public static final int AUTO_JOIN_IDLE = 0; 79b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle public static final int AUTO_JOIN_ROAMING = 1; 80b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle public static final int AUTO_JOIN_EXTENDED_ROAMING = 2; 81b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle public static final int AUTO_JOIN_OUT_OF_NETWORK_ROAMING = 3; 82b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 8397b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle public static final int HIGH_THRESHOLD_MODIFIER = 5; 8497b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle 85f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiAutoJoinController(Context c, WifiStateMachine w, WifiConfigStore s, 86c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle WifiConnectionStatistics st, WifiNative n) { 87f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mContext = c; 88f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiStateMachine = w; 89f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore = s; 90f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiNative = n; 91f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mNetworkScoreCache = null; 92c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle mWifiConnectionStatistics = st; 9321bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle scoreManager = 9421bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle (NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE); 95f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (scoreManager == null) 96f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("Registered scoreManager NULL " + " service " + Context.NETWORK_SCORE_SERVICE); 97f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 98f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (scoreManager != null) { 99f13817203179f41620514718c8668ae7e418f8afJeff Davidson mNetworkScoreCache = new WifiNetworkScoreCache(mContext); 100f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); 101f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 102f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("No network score service: Couldnt register as a WiFi score Manager, type=" 103f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(NetworkKey.TYPE_WIFI) 104f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + " service " + Context.NETWORK_SCORE_SERVICE); 105f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mNetworkScoreCache = null; 106f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 107f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 108f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 109ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle void enableVerboseLogging(int verbose) { 110ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (verbose > 0 ) { 111abde872adced15dfb6781fb71959453d963326dbYuhao Zheng DBG = true; 112ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle VDBG = true; 113ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } else { 114abde872adced15dfb6781fb71959453d963326dbYuhao Zheng DBG = false; 115ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle VDBG = false; 116ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 117ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 118ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle 119931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 120931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Flush out scan results older than mScanResultMaximumAge 121ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * 122931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 123f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private void ageScanResultsOut(int delay) { 124f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (delay <= 0) { 125931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle delay = mScanResultMaximumAge; // Something sane 126f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 127b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle long milli = System.currentTimeMillis(); 128f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 129f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("ageScanResultsOut delay " + Integer.valueOf(delay) + " size " 130f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.valueOf(scanResultCache.size()) + " now " + Long.valueOf(milli)); 131f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 132f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 133f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle Iterator<HashMap.Entry<String,ScanResult>> iter = scanResultCache.entrySet().iterator(); 134f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle while (iter.hasNext()) { 135f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle HashMap.Entry<String,ScanResult> entry = iter.next(); 136f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ScanResult result = entry.getValue(); 137f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 138f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((result.seen + delay) < milli) { 139f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle iter.remove(); 140f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 141f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 142f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 143f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 144be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle int addToScanCache(List<ScanResult> scanList) { 145be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle int numScanResultsKnown = 0; // Record number of scan results we knew about 146be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle WifiConfiguration associatedConfig = null; 1477b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle boolean didAssociate = false; 148f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1490c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle ArrayList<NetworkKey> unknownScanResults = new ArrayList<NetworkKey>(); 1500c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle 151c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle long nowMs = System.currentTimeMillis(); 152f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for(ScanResult result: scanList) { 1531fcf3c6d2b9ed65573e1e7c55fc5a30ebd364c4fYuhao Zheng if (result.SSID == null) continue; 154c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 155c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Make sure we record the last time we saw this result 156f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle result.seen = System.currentTimeMillis(); 157f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 158c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Fetch the previous instance for this result 159f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ScanResult sr = scanResultCache.get(result.BSSID); 160f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (sr != null) { 161931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If there was a previous cache result for this BSSID, average the RSSI values 162c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle result.averageRssi(sr.level, sr.seen, mScanResultMaximumAge); 163f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 164c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Remove the previous Scan Result - this is not necessary 165f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scanResultCache.remove(result.BSSID); 166e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } 167e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle 168e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle if (!mNetworkScoreCache.isScoredNetwork(result)) { 169e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle WifiKey wkey; 170e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle // Quoted SSIDs are the only one valid at this stage 171e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle try { 172e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle wkey = new WifiKey("\"" + result.SSID + "\"", result.BSSID); 173e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } catch (IllegalArgumentException e) { 174e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle logDbg("AutoJoinController: received badly encoded SSID=[" + result.SSID + 175e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle "] ->skipping this network"); 176e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle wkey = null; 177e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } 178e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle if (wkey != null) { 179e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle NetworkKey nkey = new NetworkKey(wkey); 180e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle //if we don't know this scan result then request a score from the scorer 181e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle unknownScanResults.add(nkey); 182e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } 183e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle if (VDBG) { 1847b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle String cap = ""; 1857b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle if (result.capabilities != null) 1867b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle cap = result.capabilities; 187e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle logDbg(result.SSID + " " + result.BSSID + " rssi=" 1887b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle + result.level + " cap " + cap + " is not scored"); 189e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } 1900c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } else { 191e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle if (VDBG) { 1927b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle String cap = ""; 1937b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle if (result.capabilities != null) 1947b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle cap = result.capabilities; 195e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle int score = mNetworkScoreCache.getNetworkScore(result); 196e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle logDbg(result.SSID + " " + result.BSSID + " rssi=" 1977b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle + result.level + " cap " + cap + " is scored : " + score); 1980c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } 199f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 200f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 201f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scanResultCache.put(result.BSSID, new ScanResult(result)); 202be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle // Add this BSSID to the scanResultCache of a Saved WifiConfiguration 2037b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle didAssociate = mWifiConfigStore.updateSavedNetworkHistory(result); 204f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 205be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle // If not successful, try to associate this BSSID to an existing Saved WifiConfiguration 2067b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle if (!didAssociate) { 207be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle // We couldn't associate the scan result to a Saved WifiConfiguration 208c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Hence it is untrusted 209c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle result.untrusted = true; 210f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle associatedConfig = mWifiConfigStore.associateWithConfiguration(result); 2111fcf3c6d2b9ed65573e1e7c55fc5a30ebd364c4fYuhao Zheng if (associatedConfig != null && associatedConfig.SSID != null) { 212f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 213f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("addToScanCache save associated config " 2147b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle + associatedConfig.SSID + " with " + result.SSID); 215f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 216be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle mWifiStateMachine.sendMessage( 217be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle WifiStateMachine.CMD_AUTO_SAVE_NETWORK, associatedConfig); 2187b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle didAssociate = true; 219f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 2200d616ef3bf635dff8722e064c0be842676390ed8vandwalle } else { 2210d616ef3bf635dff8722e064c0be842676390ed8vandwalle // If the scan result has been blacklisted fir 18 hours -> unblacklist 2220d616ef3bf635dff8722e064c0be842676390ed8vandwalle long now = System.currentTimeMillis(); 2230d616ef3bf635dff8722e064c0be842676390ed8vandwalle if ((now - result.blackListTimestamp) > loseBlackListHardMilli) { 2240d616ef3bf635dff8722e064c0be842676390ed8vandwalle result.setAutoJoinStatus(ScanResult.ENABLED); 2250d616ef3bf635dff8722e064c0be842676390ed8vandwalle } 226f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 2277b581f46f6c9bc6edf0edd287d47106712fb2144vandwalle if (didAssociate) { 228be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle numScanResultsKnown++; 229be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle } 230f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 2310c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle 2320c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle if (unknownScanResults.size() != 0) { 2330c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle NetworkKey[] newKeys = 2340c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle unknownScanResults.toArray(new NetworkKey[unknownScanResults.size()]); 235931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Kick the score manager, we will get updated scores asynchronously 2360c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle scoreManager.requestScores(newKeys); 2370c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } 238be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle return numScanResultsKnown; 239f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 240f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 241f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void logDbg(String message) { 2420888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle logDbg(message, false); 243ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 244ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 245ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle void logDbg(String message, boolean stackTrace) { 246f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle long now = SystemClock.elapsedRealtimeNanos(); 247ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (stackTrace) { 2482f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle Log.e(TAG, message + " stack:" 249ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[2].getMethodName() + " - " 250ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[3].getMethodName() + " - " 251ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[4].getMethodName() + " - " 252ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[5].getMethodName()); 253ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } else { 2542f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle Log.e(TAG, message); 255ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 256f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 257f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 258931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Called directly from WifiStateMachine 259be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle int newSupplicantResults(boolean doAutoJoin) { 260be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle int numScanResultsKnown; 261f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle List<ScanResult> scanList = mWifiStateMachine.syncGetScanResultsList(); 262be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle numScanResultsKnown = addToScanCache(scanList); 263f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ageScanResultsOut(mScanResultMaximumAge); 264be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle if (DBG) { 265be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle logDbg("newSupplicantResults size=" + Integer.valueOf(scanResultCache.size()) 2662f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle + " known=" + numScanResultsKnown + " " 2679f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle + doAutoJoin); 268be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle } 2697806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle if (doAutoJoin) { 2707806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle attemptAutoJoin(); 2717806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle } 272f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 273be3095ed758fca076b9ccb9fdae48f7f865c078avandwalle return numScanResultsKnown; 274f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 275f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 276f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 277931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 278931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Not used at the moment 279f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * should be a call back from WifiScanner HAL ?? 280f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * this function is not hooked and working yet, it will receive scan results from WifiScanners 281f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * with the list of IEs,then populate the capabilities by parsing the IEs and inject the scan 282f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * results as normal. 283f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */ 284f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void newHalScanResults() { 285f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle List<ScanResult> scanList = null;//mWifiScanner.syncGetScanResultsList(); 286f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String akm = WifiParser.parse_akm(null, null); 287f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg(akm); 288f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle addToScanCache(scanList); 289f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ageScanResultsOut(0); 290f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle attemptAutoJoin(); 291f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 292f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 293f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 294931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 295931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * network link quality changed, called directly from WifiTrafficPoller, 296931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * or by listening to Link Quality intent 297931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 298f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void linkQualitySignificantChange() { 299f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle attemptAutoJoin(); 300f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 301f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 302931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 303f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * compare a WifiConfiguration against the current network, return a delta score 304f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * If not associated, and the candidate will always be better 305f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * For instance if the candidate is a home network versus an unknown public wifi, 306f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * the delta will be infinite, else compare Kepler scores etc… 307b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle * Negatve return values from this functions are meaningless per se, just trying to 308b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle * keep them distinct for debug purpose (i.e. -1, -2 etc...) 309931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 310f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private int compareNetwork(WifiConfiguration candidate) { 311b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (candidate == null) 312b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return -3; 313b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 314f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration currentNetwork = mWifiStateMachine.getCurrentWifiConfiguration(); 315b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (currentNetwork == null) { 316c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // Return any absurdly high score, if we are not connected there is no current 317c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // network to... 318b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return 1000; 319b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle } 320f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 321f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate.configKey(true).equals(currentNetwork.configKey(true))) { 322b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return -2; 323f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 324f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 325b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle if (DBG) { 326b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg("compareNetwork will compare " + candidate.configKey() + " with current"); 327b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle } 328c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurationsTop(currentNetwork, candidate); 329ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle return order; 330f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 331f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 332ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle /** 333ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * update the network history fields fo that configuration 334ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * - if userTriggered, we mark the configuration as "non selfAdded" since the user has seen it 335ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * and took over management 336ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * - if it is a "connect", remember which network were there at the point of the connect, so 337ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * as those networks get a relative lower score than the selected configuration 33862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle * 339ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param netId 340ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param userTriggered : if the update come from WiFiManager 341ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param connect : if the update includes a connect 342931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 34362f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle public void updateConfigurationHistory(int netId, boolean userTriggered, boolean connect) { 344f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration selected = mWifiConfigStore.getWifiConfiguration(netId); 345f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (selected == null) { 346c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory nid=" + netId + " no selected configuration!"); 347f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return; 348f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 349f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 350e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle if (selected.SSID == null) { 351c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory nid=" + netId + 352c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle " no SSID in selected configuration!"); 353e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle return; 354e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle } 355e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle 35662f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (userTriggered) { 357931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reenable autojoin for this network, 35862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle // since the user want to connect to this configuration 35927355a942653264388e909a4276196ee63e57811vandwalle selected.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 36062f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle selected.selfAdded = false; 36162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 362f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 363992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (DBG && userTriggered) { 364f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (selected.connectChoices != null) { 365ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will update " 366f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(netId) + " now: " 367992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(selected.connectChoices.size()) 368992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + " uid=" + Integer.toString(selected.creatorUid), true); 369f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 370ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will update " 371992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(netId) 372992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + " uid=" + Integer.toString(selected.creatorUid), true); 373f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 374f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 375f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 376ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (connect && userTriggered) { 377ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle boolean found = false; 3782451dbcc4f9641df188326215b204b798eb70c46vandwalle int choice = 0; 379c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int size = 0; 3809f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle 3819f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle // Reset the triggered disabled count, because user wanted to connect to this 3829f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle // configuration, and we were not. 3839f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle selected.numUserTriggeredWifiDisableLowRSSI = 0; 3849f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle selected.numUserTriggeredWifiDisableBadRSSI = 0; 3859f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle selected.numUserTriggeredWifiDisableNotHighRSSI = 0; 3869f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle selected.numUserTriggeredJoinAttempts++; 3879f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle 38862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle List<WifiConfiguration> networks = 38962f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle mWifiConfigStore.getRecentConfiguredNetworks(12000, false); 390c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (networks != null) size = networks.size(); 391c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory found " + size + " networks"); 39262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (networks != null) { 39362f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle for (WifiConfiguration config : networks) { 394992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (DBG) { 395992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle logDbg("updateConfigurationHistory got " + config.SSID + " nid=" 396992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(config.networkId)); 397992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle } 398f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 39962f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (selected.configKey(true).equals(config.configKey(true))) { 400ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle found = true; 40162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle continue; 40262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 403f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 4042451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare RSSI values so as to evaluate the strength of the user preference 4052451dbcc4f9641df188326215b204b798eb70c46vandwalle int order = compareWifiConfigurationsRSSI(config, selected, null); 4062451dbcc4f9641df188326215b204b798eb70c46vandwalle 4072451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order < -30) { 4082451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is worse than the visible configuration 4092451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence register a strong choice so as autojoin cannot override this 4102451dbcc4f9641df188326215b204b798eb70c46vandwalle // for instance, the user has select a network 4112451dbcc4f9641df188326215b204b798eb70c46vandwalle // with 1 bar over a network with 3 bars... 4122451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 60; 4132451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < -20) { 4142451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 50; 4152451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < -10) { 4162451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 40; 4172f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle } else if (order < 20) { 4182451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is about same or has a slightly better RSSI 4192451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence register a weaker choice, here a difference of at least +/-30 in 4202451dbcc4f9641df188326215b204b798eb70c46vandwalle // RSSI comparison triggered by autoJoin will override the choice 4212451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 30; 4222f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle } else { 4232451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is better than the visible configuration 4242451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence we do not know if the user prefers this configuration strongly 4252451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 20; 42662f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 427f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 428931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // The selected configuration was preferred over a recently seen config 429931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // hence remember the user's choice: 430931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // add the recently seen config to the selected's connectChoices array 431ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 432ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (selected.connectChoices == null) { 433ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle selected.connectChoices = new HashMap<String, Integer>(); 434ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 435ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 436ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory add a choice " + selected.configKey(true) 4370888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle + " over " + config.configKey(true) 4382451dbcc4f9641df188326215b204b798eb70c46vandwalle + " choice " + Integer.toString(choice)); 439cf5b8eb8a08c45bd4a82f1f4bb789c8a1b08744fvandwalle 4402451dbcc4f9641df188326215b204b798eb70c46vandwalle Integer currentChoice = selected.connectChoices.get(config.configKey(true)); 4412f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (currentChoice != null) { 4422f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // User has made this choice multiple time in a row, so bump up a lot 4432f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle choice += currentChoice.intValue(); 4442451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4452f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // Add the visible config to the selected's connect choice list 4462f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle selected.connectChoices.put(config.configKey(true), choice); 447f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 44862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (config.connectChoices != null) { 449ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (VDBG) { 450ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will remove " 45162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle + selected.configKey(true) + " from " + config.configKey(true)); 452ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 453931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Remove the selected from the recently seen config's connectChoice list 45462f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle config.connectChoices.remove(selected.configKey(true)); 4550888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle 4560888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle if (selected.linkedConfigurations != null) { 457931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Remove the selected's linked configuration from the 458931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // recently seen config's connectChoice list 4590888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle for (String key : selected.linkedConfigurations.keySet()) { 4600888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle config.connectChoices.remove(key); 4610888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle } 4620888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle } 46362f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 464ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 465ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (found == false) { 4662451dbcc4f9641df188326215b204b798eb70c46vandwalle // We haven't found the configuration that the user just selected in our 4672451dbcc4f9641df188326215b204b798eb70c46vandwalle // scan cache. 4682451dbcc4f9641df188326215b204b798eb70c46vandwalle // In that case we will need a new scan before attempting to connect to this 4692451dbcc4f9641df188326215b204b798eb70c46vandwalle // configuration anyhow and thus we can process the scan results then. 470ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory try to connect to an old network!! : " 471ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + selected.configKey()); 47262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 473f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 47462f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (selected.connectChoices != null) { 47562f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (VDBG) 476ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory " + Integer.toString(netId) 47762f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle + " now: " + Integer.toString(selected.connectChoices.size())); 47862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 479f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 480f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 481992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle 482931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // TODO: write only if something changed 483992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (userTriggered || connect) { 484992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 485992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle } 486f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 487f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 4882451dbcc4f9641df188326215b204b798eb70c46vandwalle int getConnectChoice(WifiConfiguration source, WifiConfiguration target) { 4892451dbcc4f9641df188326215b204b798eb70c46vandwalle Integer choice = null; 4902451dbcc4f9641df188326215b204b798eb70c46vandwalle if (source == null || target == null) { 4912451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 492f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 493f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 4942451dbcc4f9641df188326215b204b798eb70c46vandwalle if (source.connectChoices != null 4952451dbcc4f9641df188326215b204b798eb70c46vandwalle && source.connectChoices.containsKey(target.configKey(true))) { 4962451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = source.connectChoices.get(target.configKey(true)); 4972451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (source.linkedConfigurations != null) { 498f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (String key : source.linkedConfigurations.keySet()) { 499f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration config = mWifiConfigStore.getWifiConfiguration(key); 500f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config != null) { 501f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config.connectChoices != null) { 5022451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = config.connectChoices.get(target.configKey(true)); 503f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 504f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 505f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5062451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5072451dbcc4f9641df188326215b204b798eb70c46vandwalle 5082451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice == null) { 5092451dbcc4f9641df188326215b204b798eb70c46vandwalle //We didn't find the connect choice 5102451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 5112451dbcc4f9641df188326215b204b798eb70c46vandwalle } else { 5122451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice.intValue() < 0) { 5132451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 20; // Compatibility with older files 5142451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5152451dbcc4f9641df188326215b204b798eb70c46vandwalle return choice.intValue(); 5162451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5172451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5182451dbcc4f9641df188326215b204b798eb70c46vandwalle 5192451dbcc4f9641df188326215b204b798eb70c46vandwalle 5209f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle int getScoreFromVisibility(WifiConfiguration.Visibility visibility, int rssiBoost, String dbg) { 5212451dbcc4f9641df188326215b204b798eb70c46vandwalle int rssiBoost5 = 0; 5222451dbcc4f9641df188326215b204b798eb70c46vandwalle int score = 0; 5234dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 5242451dbcc4f9641df188326215b204b798eb70c46vandwalle /** 5252451dbcc4f9641df188326215b204b798eb70c46vandwalle * Boost RSSI value of 5GHz bands iff the base value is better than threshold 5262451dbcc4f9641df188326215b204b798eb70c46vandwalle * This implements band preference where we prefer 5GHz if RSSI5 is good enough, whereas 5272451dbcc4f9641df188326215b204b798eb70c46vandwalle * we prefer 2.4GHz otherwise. 5282451dbcc4f9641df188326215b204b798eb70c46vandwalle * Note that 2.4GHz doesn't need a boost since at equal power the RSSI is typically 529e67ec726c07410073575473c0f50dc737629f5davandwalle * at least 6-10 dB higher 5302451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 5319f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle rssiBoost5 = rssiBoostFrom5GHzRssi(visibility.rssi5, dbg+"->"); 5322451dbcc4f9641df188326215b204b798eb70c46vandwalle 5332451dbcc4f9641df188326215b204b798eb70c46vandwalle // Select which band to use so as to score a 5342451dbcc4f9641df188326215b204b798eb70c46vandwalle if (visibility.rssi5 + rssiBoost5 > visibility.rssi24) { 5352451dbcc4f9641df188326215b204b798eb70c46vandwalle // Prefer a's 5GHz 5362451dbcc4f9641df188326215b204b798eb70c46vandwalle score = visibility.rssi5 + rssiBoost5 + rssiBoost; 5372451dbcc4f9641df188326215b204b798eb70c46vandwalle } else { 5382451dbcc4f9641df188326215b204b798eb70c46vandwalle // Prefer a's 2.4GHz 5392451dbcc4f9641df188326215b204b798eb70c46vandwalle score = visibility.rssi24 + rssiBoost; 540f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5412451dbcc4f9641df188326215b204b798eb70c46vandwalle 5422451dbcc4f9641df188326215b204b798eb70c46vandwalle return score; 543f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 544f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 5452451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare WifiConfiguration by RSSI, and return a comparison value in the range [-50, +50] 5462451dbcc4f9641df188326215b204b798eb70c46vandwalle // The result represents "approximately" an RSSI difference measured in dBM 5472451dbcc4f9641df188326215b204b798eb70c46vandwalle // Adjusted with various parameters: 5482451dbcc4f9641df188326215b204b798eb70c46vandwalle // +) current network gets a +15 boost 5492451dbcc4f9641df188326215b204b798eb70c46vandwalle // +) 5GHz signal, if they are strong enough, get a +15 or +25 boost, representing the 5502451dbcc4f9641df188326215b204b798eb70c46vandwalle // fact that at short range we prefer 5GHz band as it is cleaner of interference and 5512451dbcc4f9641df188326215b204b798eb70c46vandwalle // provides for wider channels 5522451dbcc4f9641df188326215b204b798eb70c46vandwalle int compareWifiConfigurationsRSSI(WifiConfiguration a, WifiConfiguration b, 5532451dbcc4f9641df188326215b204b798eb70c46vandwalle String currentConfiguration) { 554f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int order = 0; 5552451dbcc4f9641df188326215b204b798eb70c46vandwalle 5562451dbcc4f9641df188326215b204b798eb70c46vandwalle // Boost used so as to favor current config 5572451dbcc4f9641df188326215b204b798eb70c46vandwalle int aRssiBoost = 0; 5582451dbcc4f9641df188326215b204b798eb70c46vandwalle int bRssiBoost = 0; 5592451dbcc4f9641df188326215b204b798eb70c46vandwalle 5602451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreA; 5612451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreB; 5622451dbcc4f9641df188326215b204b798eb70c46vandwalle 5632451dbcc4f9641df188326215b204b798eb70c46vandwalle // Retrieve the visibility 564f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility astatus = a.visibility; 565f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility bstatus = b.visibility; 566f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (astatus == null || bstatus == null) { 5672451dbcc4f9641df188326215b204b798eb70c46vandwalle // Error visibility wasn't set 568b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations NULL band status!"); 569f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return 0; 570f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5712451dbcc4f9641df188326215b204b798eb70c46vandwalle 5722451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply Hysteresis, boost RSSI of current configuration 5732451dbcc4f9641df188326215b204b798eb70c46vandwalle if (null != currentConfiguration) { 5742451dbcc4f9641df188326215b204b798eb70c46vandwalle if (a.configKey().equals(currentConfiguration)) { 575b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle aRssiBoost = +10; 5762451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (b.configKey().equals(currentConfiguration)) { 577b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle bRssiBoost = +10; 5782451dbcc4f9641df188326215b204b798eb70c46vandwalle } 579b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle 580b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle 5812451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5822451dbcc4f9641df188326215b204b798eb70c46vandwalle 5832451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 584b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurationsRSSI: " + a.configKey() 585c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " " + Integer.toString(astatus.rssi24) 586c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + "," + Integer.toString(astatus.rssi5) 5872451dbcc4f9641df188326215b204b798eb70c46vandwalle + " boost=" + Integer.toString(aRssiBoost) 588c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " " + b.configKey() + " " 589c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + Integer.toString(bstatus.rssi24) + "," 590c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + Integer.toString(bstatus.rssi5) 5912451dbcc4f9641df188326215b204b798eb70c46vandwalle + " boost=" + Integer.toString(bRssiBoost) 5922451dbcc4f9641df188326215b204b798eb70c46vandwalle ); 593f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5942451dbcc4f9641df188326215b204b798eb70c46vandwalle 5959f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle scoreA = getScoreFromVisibility(astatus, aRssiBoost, a.configKey()); 5969f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle scoreB = getScoreFromVisibility(bstatus, bRssiBoost, b.configKey()); 5972451dbcc4f9641df188326215b204b798eb70c46vandwalle 5982451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare a and b 5992451dbcc4f9641df188326215b204b798eb70c46vandwalle // If a score is higher then a > b and the order is descending (negative) 6002451dbcc4f9641df188326215b204b798eb70c46vandwalle // If b score is higher then a < b and the order is ascending (positive) 6012451dbcc4f9641df188326215b204b798eb70c46vandwalle order = scoreB - scoreA; 6022451dbcc4f9641df188326215b204b798eb70c46vandwalle 6032451dbcc4f9641df188326215b204b798eb70c46vandwalle // Normalize the order to [-50, +50] 6042451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order > 50) order = 50; 6052451dbcc4f9641df188326215b204b798eb70c46vandwalle else if (order < -50) order = -50; 6062451dbcc4f9641df188326215b204b798eb70c46vandwalle 6072451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 6082451dbcc4f9641df188326215b204b798eb70c46vandwalle String prefer = " = "; 6092451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order > 0) { 6102451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " < "; // Ascending 6112451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < 0) { 6122451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " > "; // Descending 6132451dbcc4f9641df188326215b204b798eb70c46vandwalle } 614b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurationsRSSI " + a.configKey() 6152451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + a.visibility.rssi24 6162451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.rssi5 6172451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + a.visibility.num24 6182451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.num5 + ")" 619e67ec726c07410073575473c0f50dc737629f5davandwalle + " scorea=" + scoreA 6202451dbcc4f9641df188326215b204b798eb70c46vandwalle + prefer + b.configKey() 6212451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + b.visibility.rssi24 6222451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.rssi5 6232451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + b.visibility.num24 6242451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.num5 + ")" 625e67ec726c07410073575473c0f50dc737629f5davandwalle + " scoreb=" + scoreB 6262451dbcc4f9641df188326215b204b798eb70c46vandwalle + " -> " + order); 6272451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6282451dbcc4f9641df188326215b204b798eb70c46vandwalle 629f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return order; 630f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 631f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 6324dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 6332451dbcc4f9641df188326215b204b798eb70c46vandwalle int compareWifiConfigurationsWithScorer(WifiConfiguration a, WifiConfiguration b) { 6342451dbcc4f9641df188326215b204b798eb70c46vandwalle 6352451dbcc4f9641df188326215b204b798eb70c46vandwalle int aRssiBoost = 0; 6362451dbcc4f9641df188326215b204b798eb70c46vandwalle int bRssiBoost = 0; 6372451dbcc4f9641df188326215b204b798eb70c46vandwalle 6382451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply Hysteresis : boost RSSI of current configuration before 6392451dbcc4f9641df188326215b204b798eb70c46vandwalle // looking up the score 6402451dbcc4f9641df188326215b204b798eb70c46vandwalle if (null != mCurrentConfigurationKey) { 6412451dbcc4f9641df188326215b204b798eb70c46vandwalle if (a.configKey().equals(mCurrentConfigurationKey)) { 642c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle aRssiBoost += 20; 6432451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (b.configKey().equals(mCurrentConfigurationKey)) { 644c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle bRssiBoost += 20; 6452451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6462451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6472451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreA = getConfigNetworkScore(a, 3000, aRssiBoost); 648ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle int scoreB = getConfigNetworkScore(b, 3000, bRssiBoost); 6492451dbcc4f9641df188326215b204b798eb70c46vandwalle 6502451dbcc4f9641df188326215b204b798eb70c46vandwalle // Both configurations need to have a score for the scorer to be used 6512451dbcc4f9641df188326215b204b798eb70c46vandwalle // ...and the scores need to be different:-) 6522451dbcc4f9641df188326215b204b798eb70c46vandwalle if (scoreA == WifiNetworkScoreCache.INVALID_NETWORK_SCORE 6532451dbcc4f9641df188326215b204b798eb70c46vandwalle || scoreB == WifiNetworkScoreCache.INVALID_NETWORK_SCORE) { 654e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle if (VDBG) { 655b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurationsWithScorer no-scores: " 656e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle + a.configKey() 657e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle + " " 658e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle + b.configKey()); 659e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle } 6602451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 6612451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6622451dbcc4f9641df188326215b204b798eb70c46vandwalle 6632451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 6642451dbcc4f9641df188326215b204b798eb70c46vandwalle String prefer = " = "; 6652451dbcc4f9641df188326215b204b798eb70c46vandwalle if (scoreA < scoreB) { 6662451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " < "; 6672451dbcc4f9641df188326215b204b798eb70c46vandwalle } if (scoreA > scoreB) { 6682451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " > "; 6692451dbcc4f9641df188326215b204b798eb70c46vandwalle } 670b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurationsWithScorer " + a.configKey() 6712451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + a.visibility.rssi24 6722451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.rssi5 6732451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + a.visibility.num24 6742451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.num5 + ")" 675e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle + " sc=" + scoreA 6762451dbcc4f9641df188326215b204b798eb70c46vandwalle + prefer + b.configKey() 6772451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + b.visibility.rssi24 6782451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.rssi5 6792451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + b.visibility.num24 6802451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.num5 + ")" 681e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle + " sc=" + scoreB 6822451dbcc4f9641df188326215b204b798eb70c46vandwalle + " -> " + Integer.toString(scoreB - scoreA)); 6832451dbcc4f9641df188326215b204b798eb70c46vandwalle } 684c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 6852451dbcc4f9641df188326215b204b798eb70c46vandwalle // If scoreA > scoreB, the comparison is descending hence the return value is negative 6862451dbcc4f9641df188326215b204b798eb70c46vandwalle return scoreB - scoreA; 6872451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6882451dbcc4f9641df188326215b204b798eb70c46vandwalle 689f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int compareWifiConfigurations(WifiConfiguration a, WifiConfiguration b) { 690f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int order = 0; 691117be607246604e875de62aa8cdd99700b77a2b4vandwalle String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration(); 692f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle boolean linked = false; 693f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 694453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle if ((a.linkedConfigurations != null) && (b.linkedConfigurations != null) 695453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle && (a.autoJoinStatus == WifiConfiguration.AUTO_JOIN_ENABLED) 696453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle && (b.autoJoinStatus == WifiConfiguration.AUTO_JOIN_ENABLED)) { 6972451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((a.linkedConfigurations.get(b.configKey(true)) != null) 6982451dbcc4f9641df188326215b204b798eb70c46vandwalle && (b.linkedConfigurations.get(a.configKey(true)) != null)) { 699f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle linked = true; 700f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 701f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 702f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 703f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (a.ephemeral && b.ephemeral == false) { 704f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 705b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations ephemeral and prefers " + b.configKey() 706453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + a.configKey()); 707f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 708931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle return 1; // b is of higher priority - ascending 709f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 710f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (b.ephemeral && a.ephemeral == false) { 711f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 712b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations ephemeral and prefers " + a.configKey() 713453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + b.configKey()); 714f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 715931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle return -1; // a is of higher priority - descending 716f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 717f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 7182451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply RSSI, in the range [-5, +5] 7192451dbcc4f9641df188326215b204b798eb70c46vandwalle // after band adjustment, +n difference roughly corresponds to +10xn dBm 7202451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + compareWifiConfigurationsRSSI(a, b, mCurrentConfigurationKey); 721f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 7222451dbcc4f9641df188326215b204b798eb70c46vandwalle // If the configurations are not linked, compare by user's choice, only a 7232451dbcc4f9641df188326215b204b798eb70c46vandwalle // very high RSSI difference can then override the choice 7242451dbcc4f9641df188326215b204b798eb70c46vandwalle if (!linked) { 7252451dbcc4f9641df188326215b204b798eb70c46vandwalle int choice; 726f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 7272451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = getConnectChoice(a, b); 7282451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice > 0) { 729931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of higher priority - descending 7302451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order - choice; 731f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 732b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations prefers " + a.configKey() 733453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + b.configKey() 734b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " due to user choice of " + choice 735b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " order -> " + Integer.toString(order)); 736f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 7372451dbcc4f9641df188326215b204b798eb70c46vandwalle } 7382451dbcc4f9641df188326215b204b798eb70c46vandwalle 7392451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = getConnectChoice(b, a); 7402451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice > 0) { 741931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of lower priority - ascending 7422451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + choice; 7434dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (VDBG) { 744b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations prefers " + b.configKey() + " over " 745b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + a.configKey() + " due to user choice of " + choice 746b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " order ->" + Integer.toString(order)); 747f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 748f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 749f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 750ede1310be531a84faa08f02c3fd243448dd936ddvandwalle 751f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (order == 0) { 752931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // We don't know anything - pick the last seen i.e. K behavior 753931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // we should do this only for recently picked configurations 754f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (a.priority > b.priority) { 755931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of higher priority - descending 7562451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 757b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations prefers -1 " + a.configKey() + " over " 758453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + b.configKey() + " due to priority"); 759f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 760f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 761f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle order = -1; 762f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else if (a.priority < b.priority) { 763931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of lower priority - ascending 7642451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 765b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" compareWifiConfigurations prefers +1 " + b.configKey() + " over " 766453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + a.configKey() + " due to priority"); 767f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 7682451dbcc4f9641df188326215b204b798eb70c46vandwalle order = 1; 769f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 770f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 771f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 772f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String sorder = " == "; 773931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle if (order > 0) { 774f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle sorder = " < "; 775931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle } else if (order < 0) { 776f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle sorder = " > "; 777931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle } 778f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 7792451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 780b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg("compareWifiConfigurations: " + a.configKey() + sorder 781453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + b.configKey() + " order " + Integer.toString(order)); 782f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 783f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 784f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return order; 785f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 786f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 787c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle boolean isBadCandidate(int rssi5, int rssi24) { 788c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle return (rssi5 < -80 && rssi24 < -90); 789c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 790c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 791c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int compareWifiConfigurationsTop(WifiConfiguration a, WifiConfiguration b) { 792c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int scorerOrder = compareWifiConfigurationsWithScorer(a, b); 793c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurations(a, b); 794c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 795c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle if (scorerOrder * order < 0) { 796b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle if (VDBG) { 797b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" -> compareWifiConfigurationsTop: " + 798b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle "scorer override " + scorerOrder + " " + order); 799b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle } 800c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // For debugging purpose, remember that an override happened 801c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // during that autojoin Attempt 802c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle didOverride = true; 803c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle a.numScorerOverride++; 804c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle b.numScorerOverride++; 805c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 806c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 807c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle if (scorerOrder != 0) { 808c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // If the scorer came up with a result then use the scorer's result, else use 809c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // the order provided by the base comparison function 810c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle order = scorerOrder; 811c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 812c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle return order; 813c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 814c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 8159f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle public int rssiBoostFrom5GHzRssi(int rssi, String dbg) { 8160eebae7334d6129f7ca1344e4b20199794994358vandwalle if (!mWifiConfigStore.enable5GHzPreference) { 8170eebae7334d6129f7ca1344e4b20199794994358vandwalle return 0; 8180eebae7334d6129f7ca1344e4b20199794994358vandwalle } 819e67ec726c07410073575473c0f50dc737629f5davandwalle if (rssi 8200eebae7334d6129f7ca1344e4b20199794994358vandwalle > mWifiConfigStore.bandPreferenceBoostThreshold5) { 821e67ec726c07410073575473c0f50dc737629f5davandwalle // Boost by 2 dB for each point 822e67ec726c07410073575473c0f50dc737629f5davandwalle // Start boosting at -65 823e67ec726c07410073575473c0f50dc737629f5davandwalle // Boost by 20 if above -55 824e67ec726c07410073575473c0f50dc737629f5davandwalle // Boost by 40 if abore -45 8250eebae7334d6129f7ca1344e4b20199794994358vandwalle int boost = mWifiConfigStore.bandPreferenceBoostFactor5 8260eebae7334d6129f7ca1344e4b20199794994358vandwalle *(rssi - mWifiConfigStore.bandPreferenceBoostThreshold5); 827e67ec726c07410073575473c0f50dc737629f5davandwalle if (boost > 50) { 828e67ec726c07410073575473c0f50dc737629f5davandwalle // 50 dB boost is set so as to overcome the hysteresis of +20 plus a difference of 829e67ec726c07410073575473c0f50dc737629f5davandwalle // 25 dB between 2.4 and 5GHz band. This allows jumping from 2.4 to 5GHz 830e67ec726c07410073575473c0f50dc737629f5davandwalle // consistently 831e67ec726c07410073575473c0f50dc737629f5davandwalle boost = 50; 832e67ec726c07410073575473c0f50dc737629f5davandwalle } 8339f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle if (VDBG && dbg != null) { 834b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" " + dbg + ": rssi5 " + rssi + " boost " + boost); 8359f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle } 836e67ec726c07410073575473c0f50dc737629f5davandwalle return boost; 837e67ec726c07410073575473c0f50dc737629f5davandwalle } 838e67ec726c07410073575473c0f50dc737629f5davandwalle 839e67ec726c07410073575473c0f50dc737629f5davandwalle if (rssi 8400eebae7334d6129f7ca1344e4b20199794994358vandwalle < mWifiConfigStore.bandPreferencePenaltyThreshold5) { 8410eebae7334d6129f7ca1344e4b20199794994358vandwalle // penalize if < -75 8420eebae7334d6129f7ca1344e4b20199794994358vandwalle int boost = mWifiConfigStore.bandPreferencePenaltyFactor5 8430eebae7334d6129f7ca1344e4b20199794994358vandwalle *(rssi - mWifiConfigStore.bandPreferencePenaltyThreshold5); 8440eebae7334d6129f7ca1344e4b20199794994358vandwalle return boost; 845e67ec726c07410073575473c0f50dc737629f5davandwalle } 846e67ec726c07410073575473c0f50dc737629f5davandwalle return 0; 847e67ec726c07410073575473c0f50dc737629f5davandwalle } 848c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle /** 849e67ec726c07410073575473c0f50dc737629f5davandwalle * attemptRoam() function implements the core of the same SSID switching algorithm 850e67ec726c07410073575473c0f50dc737629f5davandwalle * 851e67ec726c07410073575473c0f50dc737629f5davandwalle * Run thru all recent scan result of a WifiConfiguration and select the 852e67ec726c07410073575473c0f50dc737629f5davandwalle * best one. 853c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle */ 854e67ec726c07410073575473c0f50dc737629f5davandwalle public ScanResult attemptRoam(ScanResult a, 855e67ec726c07410073575473c0f50dc737629f5davandwalle WifiConfiguration current, int age, String currentBSSID) { 856b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (current == null) { 857b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 858b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptRoam not associated"); 859b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 860e67ec726c07410073575473c0f50dc737629f5davandwalle return a; 8614dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 862b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (current.scanResultCache == null) { 863b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 864b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptRoam no scan cache"); 865b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 866e67ec726c07410073575473c0f50dc737629f5davandwalle return a; 8674dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 868b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle if (current.scanResultCache.size() > 6) { 869b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 870c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle logDbg("attemptRoam scan cache size " 871c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + current.scanResultCache.size() + " --> bail"); 872b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 873931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Implement same SSID roaming only for configurations 874c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle // that have less than 4 BSSIDs 875e67ec726c07410073575473c0f50dc737629f5davandwalle return a; 8764dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 877b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 8782f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (current.BSSID != null && !current.BSSID.equals("any")) { 879b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 8802f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle logDbg("attemptRoam() BSSID is set " 8812f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle + current.BSSID + " -> bail"); 882b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 883e67ec726c07410073575473c0f50dc737629f5davandwalle return a; 8844dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8854dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 886931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Determine which BSSID we want to associate to, taking account 887c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle // relative strength of 5 and 2.4 GHz BSSIDs 8882451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 8894dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 89097b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle for (ScanResult b : current.scanResultCache.values()) { 89197b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle int bRssiBoost5 = 0; 89297b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle int aRssiBoost5 = 0; 89397b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle int bRssiBoost = 0; 89497b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle int aRssiBoost = 0; 895931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle if ((b.seen == 0) || (b.BSSID == null) 8960d616ef3bf635dff8722e064c0be842676390ed8vandwalle || ((nowMs - b.seen) > age) 8970d616ef3bf635dff8722e064c0be842676390ed8vandwalle || b.autoJoinStatus != ScanResult.ENABLED) { 8984dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle continue; 8993a2a3d226881cce8a4e511302231d843b0def303vandwalle } 9004dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 901931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Pick first one 9024dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (a == null) { 9034dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle a = b; 9044dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle continue; 9054dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9064dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 9072451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply hysteresis: we favor the currentBSSID by giving it a boost 9087806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle if (currentBSSID != null && currentBSSID.equals(b.BSSID)) { 909931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reduce the benefit of hysteresis if RSSI <= -75 9100eebae7334d6129f7ca1344e4b20199794994358vandwalle if (b.level <= mWifiConfigStore.bandPreferencePenaltyThreshold5) { 9110eebae7334d6129f7ca1344e4b20199794994358vandwalle bRssiBoost = mWifiConfigStore.associatedHysteresisLow; 912c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else { 9130eebae7334d6129f7ca1344e4b20199794994358vandwalle bRssiBoost = mWifiConfigStore.associatedHysteresisHigh; 914c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 9154dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9167806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle if (currentBSSID != null && currentBSSID.equals(a.BSSID)) { 9170eebae7334d6129f7ca1344e4b20199794994358vandwalle if (a.level <= mWifiConfigStore.bandPreferencePenaltyThreshold5) { 918931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reduce the benefit of hysteresis if RSSI <= -75 9190eebae7334d6129f7ca1344e4b20199794994358vandwalle aRssiBoost = mWifiConfigStore.associatedHysteresisLow; 920c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else { 9210eebae7334d6129f7ca1344e4b20199794994358vandwalle aRssiBoost = mWifiConfigStore.associatedHysteresisHigh; 922c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 9234dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9242451dbcc4f9641df188326215b204b798eb70c46vandwalle 92597b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle // Favor 5GHz: give a boost to 5GHz BSSIDs, with a slightly progressive curve 9262451dbcc4f9641df188326215b204b798eb70c46vandwalle // Boost the BSSID if it is on 5GHz, above a threshold 9272451dbcc4f9641df188326215b204b798eb70c46vandwalle // But penalize it if it is on 5GHz and below threshold 92897b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle // 92997b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle // With he current threshold values, 5GHz network with RSSI above -55 93097b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle // Are given a boost of 30DB which is enough to overcome the current BSSID 93197b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle // hysteresis (+14) plus 2.4/5 GHz signal strength difference on most cases 9329f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle // 9339f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle // The "current BSSID" Boost must be added to the BSSID's level so as to introduce\ 9349f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle // soem amount of hysteresis 935e67ec726c07410073575473c0f50dc737629f5davandwalle if (b.is5GHz()) { 9369f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle bRssiBoost5 = rssiBoostFrom5GHzRssi(b.level + bRssiBoost, b.BSSID); 9374dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 938e67ec726c07410073575473c0f50dc737629f5davandwalle if (a.is5GHz()) { 9399f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle aRssiBoost5 = rssiBoostFrom5GHzRssi(a.level + aRssiBoost, a.BSSID); 9404dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9414dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 9424dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (VDBG) { 943c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle String comp = " < "; 944c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.level + bRssiBoost + bRssiBoost5 > a.level +aRssiBoost + aRssiBoost5) { 945c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle comp = " > "; 946c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 9474dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle logDbg("attemptRoam: " 948c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + b.BSSID + " rssi=" + b.level + " boost=" + Integer.toString(bRssiBoost) 94997b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle + "/" + Integer.toString(bRssiBoost5) + " freq=" + b.frequency 95097b9c4fef6e372d1f19b333c7a67ff27ef80baf0vandwalle + comp 951c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + a.BSSID + " rssi=" + a.level + " boost=" + Integer.toString(aRssiBoost) 952c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + "/" + Integer.toString(aRssiBoost5) + " freq=" + a.frequency); 953c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 954c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle 9552451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare the RSSIs after applying the hysteresis boost and the 5GHz 9562451dbcc4f9641df188326215b204b798eb70c46vandwalle // boost if applicable 957c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.level + bRssiBoost + bRssiBoost5 > a.level +aRssiBoost + aRssiBoost5) { 958931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // b is the better BSSID 959c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle a = b; 9604dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9614dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9623a2a3d226881cce8a4e511302231d843b0def303vandwalle if (a != null) { 9633a2a3d226881cce8a4e511302231d843b0def303vandwalle if (VDBG) { 9647806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle StringBuilder sb = new StringBuilder(); 965e67ec726c07410073575473c0f50dc737629f5davandwalle sb.append("attemptRoam: " + current.configKey() + 966e67ec726c07410073575473c0f50dc737629f5davandwalle " Found " + a.BSSID + " rssi=" + a.level + " freq=" + a.frequency); 9677806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle if (currentBSSID != null) { 9687806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle sb.append(" Current: " + currentBSSID); 9697806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle } 9707806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle sb.append("\n"); 9717806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle logDbg(sb.toString()); 9723a2a3d226881cce8a4e511302231d843b0def303vandwalle } 9734dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9743a2a3d226881cce8a4e511302231d843b0def303vandwalle return a; 9754dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 9764dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 977931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 9782451dbcc4f9641df188326215b204b798eb70c46vandwalle * getNetworkScore() 9792451dbcc4f9641df188326215b204b798eb70c46vandwalle * 9802451dbcc4f9641df188326215b204b798eb70c46vandwalle * if scorer is present, get the network score of a WifiConfiguration 9812451dbcc4f9641df188326215b204b798eb70c46vandwalle * 9822451dbcc4f9641df188326215b204b798eb70c46vandwalle * Note: this should be merge with setVisibility 9832451dbcc4f9641df188326215b204b798eb70c46vandwalle * 9842451dbcc4f9641df188326215b204b798eb70c46vandwalle * @param config 9852451dbcc4f9641df188326215b204b798eb70c46vandwalle * @return score 9862451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 9872451dbcc4f9641df188326215b204b798eb70c46vandwalle int getConfigNetworkScore(WifiConfiguration config, int age, int rssiBoost) { 9882451dbcc4f9641df188326215b204b798eb70c46vandwalle 9892451dbcc4f9641df188326215b204b798eb70c46vandwalle if (mNetworkScoreCache == null) { 990e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle if (VDBG) { 991b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" getConfigNetworkScore for " + config.configKey() 992e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle + " -> no scorer, hence no scores"); 993e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle } 9941db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle return WifiNetworkScoreCache.INVALID_NETWORK_SCORE; 9951db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle } 9961db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle if (config.scanResultCache == null) { 997e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle if (VDBG) { 998b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" getConfigNetworkScore for " + config.configKey() 999e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle + " -> no scan cache"); 1000e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle } 10011db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle return WifiNetworkScoreCache.INVALID_NETWORK_SCORE; 10022451dbcc4f9641df188326215b204b798eb70c46vandwalle } 10032451dbcc4f9641df188326215b204b798eb70c46vandwalle 10042451dbcc4f9641df188326215b204b798eb70c46vandwalle // Get current date 10052451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 10062451dbcc4f9641df188326215b204b798eb70c46vandwalle 10071db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle int startScore = -10000; 10081db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle 10092451dbcc4f9641df188326215b204b798eb70c46vandwalle // Run thru all cached scan results 10101db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle for (ScanResult result : config.scanResultCache.values()) { 10112451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((nowMs - result.seen) < age) { 10122451dbcc4f9641df188326215b204b798eb70c46vandwalle int sc = mNetworkScoreCache.getNetworkScore(result, rssiBoost); 10131db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle if (sc > startScore) { 10141db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle startScore = sc; 10152451dbcc4f9641df188326215b204b798eb70c46vandwalle } 10162451dbcc4f9641df188326215b204b798eb70c46vandwalle } 10172451dbcc4f9641df188326215b204b798eb70c46vandwalle } 10181db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle if (startScore == -10000) { 10191db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle startScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; 10201db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle } 1021e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle if (VDBG) { 1022e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle if (startScore == WifiNetworkScoreCache.INVALID_NETWORK_SCORE) { 1023b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" getConfigNetworkScore for " + config.configKey() 1024e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle + " -> no available score"); 1025e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle } else { 1026b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg(" getConfigNetworkScore for " + config.configKey() 1027e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle + " boost=" + Integer.toString(rssiBoost) 1028e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle + " score = " + Integer.toString(startScore)); 1029e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle } 1030e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle } 1031e6574ec7b6b2e7a678da7f77bdaaf31463852b2fvandwalle 10321db63db890fcb9051f402fdfd449eb0b80e2053cvandwalle return startScore; 10332451dbcc4f9641df188326215b204b798eb70c46vandwalle } 10342451dbcc4f9641df188326215b204b798eb70c46vandwalle 10352451dbcc4f9641df188326215b204b798eb70c46vandwalle /** 1036931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * attemptAutoJoin() function implements the core of the a network switching algorithm 1037931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1038f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void attemptAutoJoin() { 1039c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle didOverride = false; 1040b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle int networkSwitchType = AUTO_JOIN_IDLE; 10414dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 10428c9088d11880553458f09377cc60d6eb7e66747bvandwalle String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration(); 10438c9088d11880553458f09377cc60d6eb7e66747bvandwalle 1044931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reset the currentConfiguration Key, and set it only if WifiStateMachine and 1045453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle // supplicant agree 1046453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle mCurrentConfigurationKey = null; 1047453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle WifiConfiguration currentConfiguration = mWifiStateMachine.getCurrentWifiConfiguration(); 1048453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 1049f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration candidate = null; 1050f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1051931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Obtain the subset of recently seen networks 105227355a942653264388e909a4276196ee63e57811vandwalle List<WifiConfiguration> list = mWifiConfigStore.getRecentConfiguredNetworks(3000, false); 1053f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (list == null) { 10542f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (VDBG) logDbg("attemptAutoJoin nothing known=" + 10552f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle mWifiConfigStore.getconfiguredNetworkSize()); 1056f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return; 1057f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1058f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1059931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Find the currently connected network: ask the supplicant directly 106099d385e3b4d34841d6efcfd7cc9bf1d5ae25de14vandwalle String val = mWifiNative.status(true); 1061f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String status[] = val.split("\\r?\\n"); 1062f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 1063f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("attemptAutoJoin() status=" + val + " split=" 1064f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(status.length)); 1065f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1066f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1067b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle int supplicantNetId = -1; 1068f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (String key : status) { 1069f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (key.regionMatches(0, "id=", 0, 3)) { 1070f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int idx = 3; 1071b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId = 0; 1072f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle while (idx < key.length()) { 1073f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle char c = key.charAt(idx); 1074f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1075f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((c >= 0x30) && (c <= 0x39)) { 1076b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId *= 10; 1077b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId += c - 0x30; 1078f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle idx++; 1079f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 1080f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle break; 1081f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1082f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 108356d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle } else if (key.contains("wpa_state=ASSOCIATING") 108456d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle || key.contains("wpa_state=ASSOCIATED") 108556d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle || key.contains("wpa_state=FOUR_WAY_HANDSHAKE") 108656d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle || key.contains("wpa_state=GROUP_KEY_HANDSHAKE")) { 108756d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle if (DBG) { 108856d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle logDbg("attemptAutoJoin: bail out due to sup state " + key); 108956d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle } 109056d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // After WifiStateMachine ask the supplicant to associate or reconnect 109156d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // we might still obtain scan results from supplicant 109256d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // however the supplicant state in the mWifiInfo and supplicant state tracker 109356d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // are updated when we get the supplicant state change message which can be 109456d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // processed after the SCAN_RESULT message, so at this point the framework doesn't 109556d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // know that supplicant is ASSOCIATING. 109656d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // A good fix for this race condition would be for the WifiStateMachine to add 109756d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // a new transient state where it expects to get the supplicant message indicating 109856d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // that it started the association process and within which critical operations 109956d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // like autojoin should be deleted. 110056d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle 110156d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // This transient state would remove the need for the roam Wathchdog which 110256d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // basically does that. 110356d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle 110456d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // At the moment, we just query the supplicant state synchronously with the 110556d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // mWifiNative.status() command, which allow us to know that 110656d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // supplicant has started association process, even though we didnt yet get the 110756d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle // SUPPLICANT_STATE_CHANGE message. 110856d0178183460eed9afbd85e5c0d215e27d5f5bcvandwalle return; 1109f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1110f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1111ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 11127806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle String conf = ""; 1113b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle String last = ""; 11147806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle if (currentConfiguration != null) { 1115b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle conf = " curent=" + currentConfiguration.configKey(); 1116b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle } 1117b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle if (lastSelectedConfiguration != null) { 11182f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle last = " last=" + lastSelectedConfiguration; 11197806f8c800754da0f76d7a0c1a6a590381dac7a8vandwalle } 1120ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle logDbg("attemptAutoJoin() num recent config " + Integer.toString(list.size()) 1121b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + conf + last 1122b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " ---> suppNetId=" + Integer.toString(supplicantNetId)); 1123ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1124f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1125453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle if (currentConfiguration != null) { 11262451dbcc4f9641df188326215b204b798eb70c46vandwalle if (supplicantNetId != currentConfiguration.networkId 11272451dbcc4f9641df188326215b204b798eb70c46vandwalle //https://b.corp.google.com/issue?id=16484607 11282451dbcc4f9641df188326215b204b798eb70c46vandwalle //mark this confition as an error only if the mismatched networkId are valid 11292451dbcc4f9641df188326215b204b798eb70c46vandwalle && supplicantNetId != WifiConfiguration.INVALID_NETWORK_ID 11302451dbcc4f9641df188326215b204b798eb70c46vandwalle && currentConfiguration.networkId != WifiConfiguration.INVALID_NETWORK_ID) { 1131453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("attemptAutoJoin() ERROR wpa_supplicant out of sync nid=" 1132b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + Integer.toString(supplicantNetId) + " WifiStateMachine=" 1133453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + Integer.toString(currentConfiguration.networkId)); 1134b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle mWifiStateMachine.disconnectCommand(); 1135b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle return; 1136453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } else { 1137453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle mCurrentConfigurationKey = currentConfiguration.configKey(); 1138453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } 11398c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle } else { 11408c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle if (supplicantNetId != WifiConfiguration.INVALID_NETWORK_ID) { 11418c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle // Maybe in the process of associating, skip this attempt 11428c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle return; 11438c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle } 1144453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } 1145453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 1146b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle int currentNetId = -1; 1147b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (currentConfiguration != null) { 1148931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If we are associated to a configuration, it will 1149b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle // be compared thru the compareNetwork function 1150b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle currentNetId = currentConfiguration.networkId; 1151b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle } 1152b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle 1153931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1154931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Run thru all visible configurations without looking at the one we 1155c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle * are currently associated to 11564dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle * select Best Network candidate from known WifiConfigurations 1157931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1158f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (WifiConfiguration config : list) { 1159f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((config.status == WifiConfiguration.Status.DISABLED) 1160f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle && (config.disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE)) { 1161ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1162b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptAutoJoin skip candidate due to auth failure: " 1163ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + config.configKey(true)); 1164ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1165f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1166f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1167453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 1168e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle if (config.SSID == null) { 1169b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle continue; 1170e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle } 1171e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle 117227355a942653264388e909a4276196ee63e57811vandwalle if (config.autoJoinStatus >= 117327355a942653264388e909a4276196ee63e57811vandwalle WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) { 1174931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Avoid networks disabled because of AUTH failure altogether 1175ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1176ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle logDbg("attemptAutoJoin skip candidate due to auto join status " 1177ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + Integer.toString(config.autoJoinStatus) + " key " 1178ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + config.configKey(true)); 1179ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1180f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1181f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1182f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1183931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Try to un-blacklist based on elapsed time 118427355a942653264388e909a4276196ee63e57811vandwalle if (config.blackListTimestamp > 0) { 118527355a942653264388e909a4276196ee63e57811vandwalle long now = System.currentTimeMillis(); 118627355a942653264388e909a4276196ee63e57811vandwalle if (now < config.blackListTimestamp) { 1187931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1188931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * looks like there was a change in the system clock since we black listed, and 1189931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * timestamp is not meaningful anymore, hence lose it. 1190931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * this event should be rare enough so that we still want to lose the black list 11912451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 119227355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 119327355a942653264388e909a4276196ee63e57811vandwalle } else { 11944dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if ((now - config.blackListTimestamp) > loseBlackListHardMilli) { 1195931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reenable it after 18 hours, i.e. next day 119627355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 11974dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } else if ((now - config.blackListTimestamp) > loseBlackListSoftMilli) { 1198931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Lose blacklisting due to bad link 119927355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 8); 120027355a942653264388e909a4276196ee63e57811vandwalle } 120127355a942653264388e909a4276196ee63e57811vandwalle } 120227355a942653264388e909a4276196ee63e57811vandwalle } 120327355a942653264388e909a4276196ee63e57811vandwalle 1204931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Try to unblacklist based on good visibility 12058c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle if (config.visibility.rssi5 < mWifiConfigStore.thresholdUnblacklistThreshold5Soft 12068c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle && config.visibility.rssi24 12078c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle < mWifiConfigStore.thresholdUnblacklistThreshold24Soft) { 120827355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 1209c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("attemptAutoJoin do not unblacklist due to low visibility " 12104dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.autoJoinStatus 12114dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) 12124dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " rssi=(" + config.visibility.rssi24 12134dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.rssi5 12144dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 12154dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 121627355a942653264388e909a4276196ee63e57811vandwalle } 12178c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle } else if (config.visibility.rssi5 < mWifiConfigStore.thresholdUnblacklistThreshold5Hard 12188c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle && config.visibility.rssi24 12198c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle < mWifiConfigStore.thresholdUnblacklistThreshold24Hard) { 1220931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If the network is simply temporary disabled, don't allow reconnect until 1221931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // RSSI becomes good enough 122227355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 1); 122327355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 122427355a942653264388e909a4276196ee63e57811vandwalle logDbg("attemptAutoJoin good candidate seen, bumped soft -> status=" 122527355a942653264388e909a4276196ee63e57811vandwalle + config.autoJoinStatus 1226b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " " + config.configKey(true) + " rssi=(" 12274dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 12284dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 12294dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 123027355a942653264388e909a4276196ee63e57811vandwalle } 123127355a942653264388e909a4276196ee63e57811vandwalle } else { 1232c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 3); 123327355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 123427355a942653264388e909a4276196ee63e57811vandwalle logDbg("attemptAutoJoin good candidate seen, bumped hard -> status=" 123527355a942653264388e909a4276196ee63e57811vandwalle + config.autoJoinStatus 1236b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " " + config.configKey(true) + " rssi=(" 12374dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 12384dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 12394dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 124027355a942653264388e909a4276196ee63e57811vandwalle } 124127355a942653264388e909a4276196ee63e57811vandwalle } 124227355a942653264388e909a4276196ee63e57811vandwalle 124327355a942653264388e909a4276196ee63e57811vandwalle if (config.autoJoinStatus >= 124427355a942653264388e909a4276196ee63e57811vandwalle WifiConfiguration.AUTO_JOIN_TEMPORARY_DISABLED) { 1245931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Network is blacklisted, skip 12464dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (DBG) { 12474dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle logDbg("attemptAutoJoin skip blacklisted -> status=" 12484dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.autoJoinStatus 1249b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " " + config.configKey(true) + " rssi=(" 12504dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 12514dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 12524dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 12534dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 125427355a942653264388e909a4276196ee63e57811vandwalle continue; 125527355a942653264388e909a4276196ee63e57811vandwalle } 1256f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config.networkId == currentNetId) { 1257ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 125821bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle logDbg("attemptAutoJoin skip current candidate " 125921bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle + Integer.toString(currentNetId) 1260ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + " key " + config.configKey(true)); 1261ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1262f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1263f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1264f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 12650eebae7334d6129f7ca1344e4b20199794994358vandwalle boolean isLastSelected = false; 12660eebae7334d6129f7ca1344e4b20199794994358vandwalle if (lastSelectedConfiguration != null && 12670eebae7334d6129f7ca1344e4b20199794994358vandwalle config.configKey().equals(lastSelectedConfiguration)) { 12680eebae7334d6129f7ca1344e4b20199794994358vandwalle isLastSelected = true; 12690eebae7334d6129f7ca1344e4b20199794994358vandwalle } 12700eebae7334d6129f7ca1344e4b20199794994358vandwalle 12710eebae7334d6129f7ca1344e4b20199794994358vandwalle if (config.visibility == null) { 12720eebae7334d6129f7ca1344e4b20199794994358vandwalle continue; 12730eebae7334d6129f7ca1344e4b20199794994358vandwalle } 12740eebae7334d6129f7ca1344e4b20199794994358vandwalle int boost = config.autoJoinUseAggressiveJoinAttemptThreshold; 12750eebae7334d6129f7ca1344e4b20199794994358vandwalle if ((config.visibility.rssi5 + boost) 12760eebae7334d6129f7ca1344e4b20199794994358vandwalle < mWifiConfigStore.thresholdInitialAutoJoinAttemptMin5RSSI 12770eebae7334d6129f7ca1344e4b20199794994358vandwalle && (config.visibility.rssi24 + boost) 12780eebae7334d6129f7ca1344e4b20199794994358vandwalle < mWifiConfigStore.thresholdInitialAutoJoinAttemptMin24RSSI) { 12790eebae7334d6129f7ca1344e4b20199794994358vandwalle if (DBG) { 12800eebae7334d6129f7ca1344e4b20199794994358vandwalle logDbg("attemptAutoJoin skip due to low visibility -> status=" 12810eebae7334d6129f7ca1344e4b20199794994358vandwalle + config.autoJoinStatus 12820eebae7334d6129f7ca1344e4b20199794994358vandwalle + " key " + config.configKey(true) + " rssi=" 12830eebae7334d6129f7ca1344e4b20199794994358vandwalle + config.visibility.rssi24 + ", " + config.visibility.rssi5 12840eebae7334d6129f7ca1344e4b20199794994358vandwalle + " num=" + config.visibility.num24 12850eebae7334d6129f7ca1344e4b20199794994358vandwalle + ", " + config.visibility.num5); 12860eebae7334d6129f7ca1344e4b20199794994358vandwalle } 12870eebae7334d6129f7ca1344e4b20199794994358vandwalle 1288c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // Don't try to autojoin a network that is too far but 1289c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // If that configuration is a user's choice however, try anyway 12900eebae7334d6129f7ca1344e4b20199794994358vandwalle if (!isLastSelected) { 12910eebae7334d6129f7ca1344e4b20199794994358vandwalle config.autoJoinBailedDueToLowRssi = true; 12928c9088d11880553458f09377cc60d6eb7e66747bvandwalle continue; 12930eebae7334d6129f7ca1344e4b20199794994358vandwalle } else { 12940eebae7334d6129f7ca1344e4b20199794994358vandwalle // Next time, try to be a bit more aggressive in auto-joining 12950eebae7334d6129f7ca1344e4b20199794994358vandwalle if (config.autoJoinUseAggressiveJoinAttemptThreshold 12960eebae7334d6129f7ca1344e4b20199794994358vandwalle < WifiConfiguration.MAX_INITIAL_AUTO_JOIN_RSSI_BOOST) { 12970eebae7334d6129f7ca1344e4b20199794994358vandwalle config.autoJoinUseAggressiveJoinAttemptThreshold += 2; 12984dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 12998c9088d11880553458f09377cc60d6eb7e66747bvandwalle } 13000eebae7334d6129f7ca1344e4b20199794994358vandwalle } 13010eebae7334d6129f7ca1344e4b20199794994358vandwalle if (config.noInternetAccess && !isLastSelected) { 13020eebae7334d6129f7ca1344e4b20199794994358vandwalle // Avoid autojoining this network because last time we used it, it didn't 13030eebae7334d6129f7ca1344e4b20199794994358vandwalle // have internet access 13040eebae7334d6129f7ca1344e4b20199794994358vandwalle if (DBG) { 13050eebae7334d6129f7ca1344e4b20199794994358vandwalle logDbg("attemptAutoJoin skip candidate due to noInternetAccess flag " 13060eebae7334d6129f7ca1344e4b20199794994358vandwalle + config.configKey(true)); 13079f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle } 13080eebae7334d6129f7ca1344e4b20199794994358vandwalle continue; 13098c9088d11880553458f09377cc60d6eb7e66747bvandwalle } 13108c9088d11880553458f09377cc60d6eb7e66747bvandwalle 1311ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1312c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle logDbg("attemptAutoJoin trying candidate id=" 1313c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + Integer.toString(config.networkId) + " " 1314b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + config.configKey(true) 13154dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " status=" + config.autoJoinStatus); 1316ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1317f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1318f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate == null) { 1319f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle candidate = config; 1320f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 1321f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 1322453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("attemptAutoJoin will compare candidate " + candidate.configKey() 13234dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " with " + config.configKey()); 1324f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1325c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurationsTop(candidate, config); 13262451dbcc4f9641df188326215b204b798eb70c46vandwalle 13272451dbcc4f9641df188326215b204b798eb70c46vandwalle // The lastSelectedConfiguration is the configuration the user has manually selected 1328c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // thru WifiPicker, or that a 3rd party app asked us to connect to via the 13292451dbcc4f9641df188326215b204b798eb70c46vandwalle // enableNetwork with disableOthers=true WifiManager API 13302451dbcc4f9641df188326215b204b798eb70c46vandwalle // As this is a direct user choice, we strongly prefer this configuration, 13312451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence give +/-100 13322451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((lastSelectedConfiguration != null) 13332451dbcc4f9641df188326215b204b798eb70c46vandwalle && candidate.configKey().equals(lastSelectedConfiguration)) { 13342451dbcc4f9641df188326215b204b798eb70c46vandwalle // candidate is the last selected configuration, 13352451dbcc4f9641df188326215b204b798eb70c46vandwalle // so keep it above connect choices (+/-60) and 13362451dbcc4f9641df188326215b204b798eb70c46vandwalle // above RSSI/scorer based selection of linked configuration (+/- 50) 13372451dbcc4f9641df188326215b204b798eb70c46vandwalle // by reducing order by -100 13382451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order - 100; 13392451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 13402f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle logDbg(" ...and prefers -100 " + candidate.configKey() 13412451dbcc4f9641df188326215b204b798eb70c46vandwalle + " over " + config.configKey() 13422451dbcc4f9641df188326215b204b798eb70c46vandwalle + " because it is the last selected -> " 13432451dbcc4f9641df188326215b204b798eb70c46vandwalle + Integer.toString(order)); 13442451dbcc4f9641df188326215b204b798eb70c46vandwalle } 13452451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if ((lastSelectedConfiguration != null) 13462451dbcc4f9641df188326215b204b798eb70c46vandwalle && config.configKey().equals(lastSelectedConfiguration)) { 13472451dbcc4f9641df188326215b204b798eb70c46vandwalle // config is the last selected configuration, 13482451dbcc4f9641df188326215b204b798eb70c46vandwalle // so keep it above connect choices (+/-60) and 13492451dbcc4f9641df188326215b204b798eb70c46vandwalle // above RSSI/scorer based selection of linked configuration (+/- 50) 13502451dbcc4f9641df188326215b204b798eb70c46vandwalle // by increasing order by +100 13512451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + 100; 13522451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 13532f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle logDbg(" ...and prefers +100 " + config.configKey() 13542451dbcc4f9641df188326215b204b798eb70c46vandwalle + " over " + candidate.configKey() 13552451dbcc4f9641df188326215b204b798eb70c46vandwalle + " because it is the last selected -> " 13562451dbcc4f9641df188326215b204b798eb70c46vandwalle + Integer.toString(order)); 13572451dbcc4f9641df188326215b204b798eb70c46vandwalle } 13582451dbcc4f9641df188326215b204b798eb70c46vandwalle } 13592451dbcc4f9641df188326215b204b798eb70c46vandwalle 1360f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (order > 0) { 1361931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Ascending : candidate < config 1362f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle candidate = config; 1363f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1364f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1365f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1366f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1367c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Wait for VPN to be available on the system to make use of this code 13682451dbcc4f9641df188326215b204b798eb70c46vandwalle // Now, go thru scan result to try finding a better untrusted network 1369f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (mNetworkScoreCache != null) { 1370f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int rssi5 = WifiConfiguration.INVALID_RSSI; 1371f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int rssi24 = WifiConfiguration.INVALID_RSSI; 1372f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility visibility; 1373f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate != null) { 1374f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle rssi5 = candidate.visibility.rssi5; 1375f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle rssi24 = candidate.visibility.rssi24; 1376f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1377f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1378931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Get current date 13792451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 1380c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int currentScore = -10000; 1381c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // The untrusted network with highest score 1382c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle ScanResult untrustedCandidate = null; 13832451dbcc4f9641df188326215b204b798eb70c46vandwalle // Look for untrusted scored network only if the current candidate is bad 1384c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (isBadCandidate(rssi24, rssi5)) { 1385f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (ScanResult result : scanResultCache.values()) { 1386c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int rssiBoost = 0; 1387c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // We look only at untrusted networks with a valid SSID 1388c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // A trusted result would have been looked at thru it's Wificonfiguration 1389c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (TextUtils.isEmpty(result.SSID) || !result.untrusted) { 1390c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle continue; 1391c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 13922451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((nowMs - result.seen) < 3000) { 1393c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Increment usage count for the network 1394c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle mWifiConnectionStatistics.incrementOrAddUntrusted(result.SSID, 0, 1); 1395c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 1396c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (lastUntrustedBSSID != null 1397c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle && result.BSSID.equals(lastUntrustedBSSID)) { 1398c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Apply a large hysteresis to the untrusted network we are connected to 1399c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle rssiBoost = 25; 1400c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1401c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int score = mNetworkScoreCache.getNetworkScore(result, rssiBoost); 1402c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (score != WifiNetworkScoreCache.INVALID_NETWORK_SCORE 1403c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle && score > currentScore) { 1404c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Highest score: Select this candidate 1405c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle currentScore = score; 1406c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle untrustedCandidate = result; 1407c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (VDBG) { 1408c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("AutoJoinController: found untrusted candidate " 1409c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + result.SSID 1410c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " RSSI=" + result.level 1411c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " freq=" + result.frequency 1412c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " score=" + score); 1413c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1414f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1415f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1416f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1417f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1418c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (untrustedCandidate != null) { 1419c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (lastUntrustedBSSID == null 1420c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle || !untrustedCandidate.SSID.equals(lastUntrustedBSSID)) { 1421c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // We found a new candidate that we are going to connect to, then 1422c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // increase its connection count 14238c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle mWifiConnectionStatistics. 14248c0a54e9b0d3713cab52d06ad8fd7f3a1b6f73a8vandwalle incrementOrAddUntrusted(untrustedCandidate.SSID, 1, 0); 1425c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Remember which SSID we are connecting to 1426c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle lastUntrustedBSSID = untrustedCandidate.SSID; 1427c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1428c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1429c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Now we don't have VPN, and thus don't actually connect to the untrusted candidate 1430c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle untrustedCandidate = null; 1431c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1432b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 1433931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1434931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * If candidate is found, check the state of the connection so as 1435931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * to decide if we should be acting on this candidate and switching over 1436931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1437b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle int networkDelta = compareNetwork(candidate); 1438b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (DBG && candidate != null) { 1439b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle String doSwitch = ""; 1440b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle String current = ""; 1441b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle if (networkDelta < 0) { 1442b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle doSwitch = " -> not switching"; 1443b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle } 1444b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle if (currentConfiguration != null) { 14452f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle current = " with current " + currentConfiguration.configKey(); 1446b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle } 1447b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle logDbg("attemptAutoJoin networkSwitching candidate " 1448b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + candidate.configKey() 1449b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + current 1450c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + " linked=" + (currentConfiguration != null 1451b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle && currentConfiguration.isLinked(candidate)) 1452b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + " : delta=" 1453b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + Integer.toString(networkDelta) + " " 1454b664cfeab6f02e24376ea0a15beb83d142f0b14dvandwalle + doSwitch); 1455b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 14564dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 1457931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1458931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Ask WifiStateMachine permission to switch : 1459931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * if user is currently streaming voice traffic, 1460931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * then we should not be allowed to switch regardless of the delta 1461931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1462b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (mWifiStateMachine.shouldSwitchNetwork(networkDelta)) { 1463b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (mStaStaSupported) { 1464b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("mStaStaSupported --> error do nothing now "); 1465b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } else { 1466b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (currentConfiguration != null && currentConfiguration.isLinked(candidate)) { 1467b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_EXTENDED_ROAMING; 1468b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } else { 1469b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_OUT_OF_NETWORK_ROAMING; 1470b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 1471b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 1472b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("AutoJoin auto connect with netId " 1473b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + Integer.toString(candidate.networkId) 1474b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " to " + candidate.configKey()); 1475b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 14762451dbcc4f9641df188326215b204b798eb70c46vandwalle if (didOverride) { 14772451dbcc4f9641df188326215b204b798eb70c46vandwalle candidate.numScorerOverrideAndSwitchedNetwork++; 14782451dbcc4f9641df188326215b204b798eb70c46vandwalle } 1479c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle candidate.numAssociation++; 1480e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle mWifiConnectionStatistics.numAutoJoinAttempt++; 14819f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle 14822f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (candidate.BSSID == null || candidate.BSSID.equals("any")) { 14832f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // First step we selected the configuration we want to connect to 14842f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // Second step: Look for the best Scan result for this configuration 14852f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // TODO this algorithm should really be done in one step 14862f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle String currentBSSID = mWifiStateMachine.getCurrentBSSID(); 14872f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle ScanResult roamCandidate = attemptRoam(null, candidate, 3000, null); 14882f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (roamCandidate != null && currentBSSID != null 14892f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle && currentBSSID.equals(roamCandidate.BSSID)) { 14902f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // Sanity, we were already asociated to that candidate 14912f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle roamCandidate = null; 14922f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle } 14932f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (roamCandidate != null && roamCandidate.is5GHz()) { 14942f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // If the configuration hasn't a default BSSID selected, and the best 14952f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // candidate is 5GHZ, then select this candidate so as WifiStateMachine and 14962f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle // supplicant will pick it first 14972f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle candidate.autoJoinBSSID = roamCandidate.BSSID; 14982f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (VDBG) { 14992f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle logDbg("AutoJoinController: lock to 5GHz " 15002f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle + candidate.autoJoinBSSID 15012f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle + " RSSI=" + roamCandidate.level 15022f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle + " freq=" + roamCandidate.frequency); 15032f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle } 1504448c9536a302c58a79e271b1721c08b8882f800evandwalle } else { 1505448c9536a302c58a79e271b1721c08b8882f800evandwalle // We couldnt find a roam candidate 1506448c9536a302c58a79e271b1721c08b8882f800evandwalle candidate.autoJoinBSSID = "any"; 15079f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle } 15089f3349fa2cd39d690d1e2b7c3b71ced412e24f2cvandwalle } 1509448c9536a302c58a79e271b1721c08b8882f800evandwalle mWifiStateMachine.sendMessage(WifiStateMachine.CMD_AUTO_CONNECT, 1510448c9536a302c58a79e271b1721c08b8882f800evandwalle candidate.networkId, networkSwitchType, candidate); 15114dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 1512b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 15134dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 1514b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (networkSwitchType == AUTO_JOIN_IDLE) { 1515e67ec726c07410073575473c0f50dc737629f5davandwalle String currentBSSID = mWifiStateMachine.getCurrentBSSID(); 1516931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Attempt same WifiConfiguration roaming 1517e67ec726c07410073575473c0f50dc737629f5davandwalle ScanResult roamCandidate = attemptRoam(null, currentConfiguration, 3000, 1518e67ec726c07410073575473c0f50dc737629f5davandwalle currentBSSID); 1519e67ec726c07410073575473c0f50dc737629f5davandwalle /** 1520e67ec726c07410073575473c0f50dc737629f5davandwalle * TODO: (post L initial release) 1521e67ec726c07410073575473c0f50dc737629f5davandwalle * consider handling linked configurations roaming (i.e. extended Roaming) 1522e67ec726c07410073575473c0f50dc737629f5davandwalle * thru the attemptRoam function which makes use of the RSSI roaming threshold. 1523e67ec726c07410073575473c0f50dc737629f5davandwalle * At the moment, extended roaming is only handled thru the attemptAutoJoin() 1524e67ec726c07410073575473c0f50dc737629f5davandwalle * function which compare configurations. 1525e67ec726c07410073575473c0f50dc737629f5davandwalle * 1526e67ec726c07410073575473c0f50dc737629f5davandwalle * The advantage of making use of attemptRoam function is that this function 1527e67ec726c07410073575473c0f50dc737629f5davandwalle * will looks at all the BSSID of each configurations, instead of only looking 1528e67ec726c07410073575473c0f50dc737629f5davandwalle * at WifiConfiguration.visibility which keeps trackonly of the RSSI/band of the 1529e67ec726c07410073575473c0f50dc737629f5davandwalle * two highest BSSIDs. 1530e67ec726c07410073575473c0f50dc737629f5davandwalle */ 1531e67ec726c07410073575473c0f50dc737629f5davandwalle // Attempt linked WifiConfiguration roaming 1532e67ec726c07410073575473c0f50dc737629f5davandwalle /* if (currentConfiguration != null 1533e67ec726c07410073575473c0f50dc737629f5davandwalle && currentConfiguration.linkedConfigurations != null) { 1534e67ec726c07410073575473c0f50dc737629f5davandwalle for (String key : currentConfiguration.linkedConfigurations.keySet()) { 1535e67ec726c07410073575473c0f50dc737629f5davandwalle WifiConfiguration link = mWifiConfigStore.getWifiConfiguration(key); 1536e67ec726c07410073575473c0f50dc737629f5davandwalle if (link != null) { 1537e67ec726c07410073575473c0f50dc737629f5davandwalle roamCandidate = attemptRoam(roamCandidate, link, 3000, 1538e67ec726c07410073575473c0f50dc737629f5davandwalle currentBSSID); 1539e67ec726c07410073575473c0f50dc737629f5davandwalle } 1540e67ec726c07410073575473c0f50dc737629f5davandwalle } 1541e67ec726c07410073575473c0f50dc737629f5davandwalle }*/ 1542e67ec726c07410073575473c0f50dc737629f5davandwalle if (roamCandidate != null && currentBSSID != null 1543e67ec726c07410073575473c0f50dc737629f5davandwalle && currentBSSID.equals(roamCandidate.BSSID)) { 1544e67ec726c07410073575473c0f50dc737629f5davandwalle roamCandidate = null; 1545e67ec726c07410073575473c0f50dc737629f5davandwalle } 15462f2cf21662275a0e93d7d7a6ad3d98b4c596dcf0vandwalle if (roamCandidate != null && mWifiStateMachine.shouldSwitchNetwork(999)) { 1547b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 1548b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("AutoJoin auto roam with netId " 1549b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + Integer.toString(currentConfiguration.networkId) 1550b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " " + currentConfiguration.configKey() + " to BSSID=" 1551b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + roamCandidate.BSSID + " freq=" + roamCandidate.frequency 1552b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " RSSI=" + roamCandidate.frequency); 1553b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 1554b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_ROAMING; 1555e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle mWifiConnectionStatistics.numAutoRoamAttempt++; 1556e8c89583e489d451880471b7cc7659bd9fa802f4vandwalle 1557b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle mWifiStateMachine.sendMessage(WifiStateMachine.CMD_AUTO_ROAM, 1558b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle currentConfiguration.networkId, 1, roamCandidate); 1559f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1560f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1561b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) logDbg("Done attemptAutoJoin status=" + Integer.toString(networkSwitchType)); 1562f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1563f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle} 1564f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1565