WifiAutoJoinController.java revision c290d8dff6172d5fde7b9dfd74d3a20785dab246
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 83f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiAutoJoinController(Context c, WifiStateMachine w, WifiConfigStore s, 84c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle WifiConnectionStatistics st, WifiNative n) { 85f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mContext = c; 86f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiStateMachine = w; 87f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore = s; 88f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiNative = n; 89f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mNetworkScoreCache = null; 90c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle mWifiConnectionStatistics = st; 9121bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle scoreManager = 9221bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle (NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE); 93f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (scoreManager == null) 94f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("Registered scoreManager NULL " + " service " + Context.NETWORK_SCORE_SERVICE); 95f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 96f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (scoreManager != null) { 97f13817203179f41620514718c8668ae7e418f8afJeff Davidson mNetworkScoreCache = new WifiNetworkScoreCache(mContext); 98f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); 99f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 100f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("No network score service: Couldnt register as a WiFi score Manager, type=" 101f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(NetworkKey.TYPE_WIFI) 102f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + " service " + Context.NETWORK_SCORE_SERVICE); 103f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mNetworkScoreCache = null; 104f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 105f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 106f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 107ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle void enableVerboseLogging(int verbose) { 108ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (verbose > 0 ) { 109abde872adced15dfb6781fb71959453d963326dbYuhao Zheng DBG = true; 110ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle VDBG = true; 111ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } else { 112abde872adced15dfb6781fb71959453d963326dbYuhao Zheng DBG = false; 113ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle VDBG = false; 114ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 115ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 116ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle 117931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 118931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Flush out scan results older than mScanResultMaximumAge 119ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * 120931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 121f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private void ageScanResultsOut(int delay) { 122f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (delay <= 0) { 123931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle delay = mScanResultMaximumAge; // Something sane 124f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 125b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle long milli = System.currentTimeMillis(); 126f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 127f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("ageScanResultsOut delay " + Integer.valueOf(delay) + " size " 128f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.valueOf(scanResultCache.size()) + " now " + Long.valueOf(milli)); 129f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 130f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 131f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle Iterator<HashMap.Entry<String,ScanResult>> iter = scanResultCache.entrySet().iterator(); 132f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle while (iter.hasNext()) { 133f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle HashMap.Entry<String,ScanResult> entry = iter.next(); 134f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ScanResult result = entry.getValue(); 135f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 136f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((result.seen + delay) < milli) { 137f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle iter.remove(); 138f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 139f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 140f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 141f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 142f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void addToScanCache(List<ScanResult> scanList) { 143f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration associatedConfig; 144f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1450c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle ArrayList<NetworkKey> unknownScanResults = new ArrayList<NetworkKey>(); 1460c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle 147c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle long nowMs = System.currentTimeMillis(); 148f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for(ScanResult result: scanList) { 1491fcf3c6d2b9ed65573e1e7c55fc5a30ebd364c4fYuhao Zheng if (result.SSID == null) continue; 150c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 151c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Make sure we record the last time we saw this result 152f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle result.seen = System.currentTimeMillis(); 153f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 154c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Fetch the previous instance for this result 155f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ScanResult sr = scanResultCache.get(result.BSSID); 156f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (sr != null) { 157931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If there was a previous cache result for this BSSID, average the RSSI values 158c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle result.averageRssi(sr.level, sr.seen, mScanResultMaximumAge); 159f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 160c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Remove the previous Scan Result - this is not necessary 161f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scanResultCache.remove(result.BSSID); 1620c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } else { 1630c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle if (!mNetworkScoreCache.isScoredNetwork(result)) { 16421bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle WifiKey wkey; 165931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Quoted SSIDs are the only one valid at this stage 16621bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle try { 16721bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle wkey = new WifiKey("\"" + result.SSID + "\"", result.BSSID); 16821bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle } catch (IllegalArgumentException e) { 16921bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle logDbg("AutoJoinController: received badly encoded SSID=[" + result.SSID + 17021bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle "] ->skipping this network"); 17121bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle wkey = null; 17221bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle } 17321bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle if (wkey != null) { 17421bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle NetworkKey nkey = new NetworkKey(wkey); 1752451dbcc4f9641df188326215b204b798eb70c46vandwalle //if we don't know this scan result then request a score from the scorer 17621bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle unknownScanResults.add(nkey); 17721bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle } 1780c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } 179f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 180f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 181f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle scanResultCache.put(result.BSSID, new ScanResult(result)); 182f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 183931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Add this BSSID to the scanResultCache of the relevant WifiConfiguration 184f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle associatedConfig = mWifiConfigStore.updateSavedNetworkHistory(result); 185f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 186931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Try to associate this BSSID to an existing Saved WifiConfiguration 187f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (associatedConfig == null) { 188c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // We couldn't associate the scan result to a saved configuration 189c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Hence it is untrusted 190c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle result.untrusted = true; 191f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle associatedConfig = mWifiConfigStore.associateWithConfiguration(result); 1921fcf3c6d2b9ed65573e1e7c55fc5a30ebd364c4fYuhao Zheng if (associatedConfig != null && associatedConfig.SSID != null) { 193f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 194f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("addToScanCache save associated config " 195f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + associatedConfig.SSID + " with " + associatedConfig.SSID); 196f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 197f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiStateMachine.sendMessage(WifiManager.SAVE_NETWORK, associatedConfig); 198f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 199f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 200f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 2010c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle 2020c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle if (unknownScanResults.size() != 0) { 2030c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle NetworkKey[] newKeys = 2040c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle unknownScanResults.toArray(new NetworkKey[unknownScanResults.size()]); 205931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Kick the score manager, we will get updated scores asynchronously 2060c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle scoreManager.requestScores(newKeys); 2070c8b99a3b78e458a5617cc449e2efe69c5bdd531vandwalle } 208f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 209f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 210f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void logDbg(String message) { 2110888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle logDbg(message, false); 212ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 213ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 214ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle void logDbg(String message, boolean stackTrace) { 215f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle long now = SystemClock.elapsedRealtimeNanos(); 2160888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle String ts = String.format("[%,d us] ", now / 1000); 217ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (stackTrace) { 218ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle Log.e(TAG, ts + message + " stack:" 219ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[2].getMethodName() + " - " 220ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[3].getMethodName() + " - " 221ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[4].getMethodName() + " - " 222ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + Thread.currentThread().getStackTrace()[5].getMethodName()); 223ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } else { 224ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle Log.e(TAG, ts + message); 225ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 226f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 227f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 228931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Called directly from WifiStateMachine 229f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void newSupplicantResults() { 230f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle List<ScanResult> scanList = mWifiStateMachine.syncGetScanResultsList(); 231f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle addToScanCache(scanList); 232f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ageScanResultsOut(mScanResultMaximumAge); 233f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (DBG) 234f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("newSupplicantResults size=" + Integer.valueOf(scanResultCache.size()) ); 235f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 236f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle attemptAutoJoin(); 237f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 238f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 239f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 240f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 241931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 242931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Not used at the moment 243f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * should be a call back from WifiScanner HAL ?? 244f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * this function is not hooked and working yet, it will receive scan results from WifiScanners 245f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * with the list of IEs,then populate the capabilities by parsing the IEs and inject the scan 246f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * results as normal. 247f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */ 248f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void newHalScanResults() { 249f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle List<ScanResult> scanList = null;//mWifiScanner.syncGetScanResultsList(); 250f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String akm = WifiParser.parse_akm(null, null); 251f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg(akm); 252f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle addToScanCache(scanList); 253f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle ageScanResultsOut(0); 254f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle attemptAutoJoin(); 255f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 256f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 257f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 258931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 259931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * network link quality changed, called directly from WifiTrafficPoller, 260931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * or by listening to Link Quality intent 261931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 262f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void linkQualitySignificantChange() { 263f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle attemptAutoJoin(); 264f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 265f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 266931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 267f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * compare a WifiConfiguration against the current network, return a delta score 268f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * If not associated, and the candidate will always be better 269f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * For instance if the candidate is a home network versus an unknown public wifi, 270f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * the delta will be infinite, else compare Kepler scores etc… 271b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle * Negatve return values from this functions are meaningless per se, just trying to 272b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle * keep them distinct for debug purpose (i.e. -1, -2 etc...) 273931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 274f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle private int compareNetwork(WifiConfiguration candidate) { 275b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (candidate == null) 276b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return -3; 277b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 278f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration currentNetwork = mWifiStateMachine.getCurrentWifiConfiguration(); 279b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (currentNetwork == null) { 280c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // Return any absurdly high score, if we are not connected there is no current 281c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // network to... 282b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return 1000; 283b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle } 284f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 285f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate.configKey(true).equals(currentNetwork.configKey(true))) { 286b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle return -2; 287f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 288f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 289c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurationsTop(currentNetwork, candidate); 290ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle return order; 291f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 292f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 293ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle /** 294ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * update the network history fields fo that configuration 295ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * - if userTriggered, we mark the configuration as "non selfAdded" since the user has seen it 296ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * and took over management 297ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * - if it is a "connect", remember which network were there at the point of the connect, so 298ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * as those networks get a relative lower score than the selected configuration 29962f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle * 300ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param netId 301ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param userTriggered : if the update come from WiFiManager 302ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle * @param connect : if the update includes a connect 303931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 30462f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle public void updateConfigurationHistory(int netId, boolean userTriggered, boolean connect) { 305f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration selected = mWifiConfigStore.getWifiConfiguration(netId); 306f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (selected == null) { 307c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory nid=" + netId + " no selected configuration!"); 308f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return; 309f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 310f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 311e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle if (selected.SSID == null) { 312c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory nid=" + netId + 313c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle " no SSID in selected configuration!"); 314e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle return; 315e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle } 316e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle 31762f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (userTriggered) { 318931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reenable autojoin for this network, 31962f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle // since the user want to connect to this configuration 32027355a942653264388e909a4276196ee63e57811vandwalle selected.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 32162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle selected.selfAdded = false; 32262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 323f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 324992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (DBG && userTriggered) { 325f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (selected.connectChoices != null) { 326ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will update " 327f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(netId) + " now: " 328992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(selected.connectChoices.size()) 329992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + " uid=" + Integer.toString(selected.creatorUid), true); 330f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 331ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will update " 332992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(netId) 333992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + " uid=" + Integer.toString(selected.creatorUid), true); 334f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 335f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 336f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 337ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (connect && userTriggered) { 338ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle boolean found = false; 3392451dbcc4f9641df188326215b204b798eb70c46vandwalle int choice = 0; 340c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int size = 0; 34162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle List<WifiConfiguration> networks = 34262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle mWifiConfigStore.getRecentConfiguredNetworks(12000, false); 343c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (networks != null) size = networks.size(); 344c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("updateConfigurationHistory found " + size + " networks"); 34562f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (networks != null) { 34662f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle for (WifiConfiguration config : networks) { 347992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (DBG) { 348992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle logDbg("updateConfigurationHistory got " + config.SSID + " nid=" 349992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle + Integer.toString(config.networkId)); 350992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle } 351f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 35262f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (selected.configKey(true).equals(config.configKey(true))) { 353ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle found = true; 35462f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle continue; 35562f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 356f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 3572451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare RSSI values so as to evaluate the strength of the user preference 3582451dbcc4f9641df188326215b204b798eb70c46vandwalle int order = compareWifiConfigurationsRSSI(config, selected, null); 3592451dbcc4f9641df188326215b204b798eb70c46vandwalle 3602451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order < -30) { 3612451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is worse than the visible configuration 3622451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence register a strong choice so as autojoin cannot override this 3632451dbcc4f9641df188326215b204b798eb70c46vandwalle // for instance, the user has select a network 3642451dbcc4f9641df188326215b204b798eb70c46vandwalle // with 1 bar over a network with 3 bars... 3652451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 60; 3662451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < -20) { 3672451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 50; 3682451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < -10) { 3692451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 40; 3702451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < 10) { 3712451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is about same or has a slightly better RSSI 3722451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence register a weaker choice, here a difference of at least +/-30 in 3732451dbcc4f9641df188326215b204b798eb70c46vandwalle // RSSI comparison triggered by autoJoin will override the choice 3742451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 30; 3752451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order <= 30) { 3762451dbcc4f9641df188326215b204b798eb70c46vandwalle // Selected configuration is better than the visible configuration 3772451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence we do not know if the user prefers this configuration strongly 3782451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 20; 3792451dbcc4f9641df188326215b204b798eb70c46vandwalle } else { 3802451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 10; 38162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 382f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 383931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // The selected configuration was preferred over a recently seen config 384931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // hence remember the user's choice: 385931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // add the recently seen config to the selected's connectChoices array 386ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 387ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (selected.connectChoices == null) { 388ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle selected.connectChoices = new HashMap<String, Integer>(); 389ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 390ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle 391ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory add a choice " + selected.configKey(true) 3920888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle + " over " + config.configKey(true) 3932451dbcc4f9641df188326215b204b798eb70c46vandwalle + " choice " + Integer.toString(choice)); 394cf5b8eb8a08c45bd4a82f1f4bb789c8a1b08744fvandwalle 3952451dbcc4f9641df188326215b204b798eb70c46vandwalle Integer currentChoice = selected.connectChoices.get(config.configKey(true)); 3962451dbcc4f9641df188326215b204b798eb70c46vandwalle if (currentChoice == null || currentChoice.intValue() < choice) { 3972451dbcc4f9641df188326215b204b798eb70c46vandwalle // Add the visible config to the selected's connect choice list 3982451dbcc4f9641df188326215b204b798eb70c46vandwalle selected.connectChoices.put(config.configKey(true), choice); 3992451dbcc4f9641df188326215b204b798eb70c46vandwalle } 400f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 40162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (config.connectChoices != null) { 402ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (VDBG) { 403ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory will remove " 40462f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle + selected.configKey(true) + " from " + config.configKey(true)); 405ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 406931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Remove the selected from the recently seen config's connectChoice list 40762f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle config.connectChoices.remove(selected.configKey(true)); 4080888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle 4090888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle if (selected.linkedConfigurations != null) { 410931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Remove the selected's linked configuration from the 411931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // recently seen config's connectChoice list 4120888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle for (String key : selected.linkedConfigurations.keySet()) { 4130888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle config.connectChoices.remove(key); 4140888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle } 4150888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle } 41662f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 417ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle } 418ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle if (found == false) { 4192451dbcc4f9641df188326215b204b798eb70c46vandwalle // We haven't found the configuration that the user just selected in our 4202451dbcc4f9641df188326215b204b798eb70c46vandwalle // scan cache. 4212451dbcc4f9641df188326215b204b798eb70c46vandwalle // In that case we will need a new scan before attempting to connect to this 4222451dbcc4f9641df188326215b204b798eb70c46vandwalle // configuration anyhow and thus we can process the scan results then. 423ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory try to connect to an old network!! : " 424ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle + selected.configKey()); 42562f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 426f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 42762f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (selected.connectChoices != null) { 42862f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle if (VDBG) 429ecd2b88214b5d214fd1f63a9560caff9058912ddvandwalle logDbg("updateConfigurationHistory " + Integer.toString(netId) 43062f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle + " now: " + Integer.toString(selected.connectChoices.size())); 43162f1d0ca8ea4466628f6ff179b1f20e1279fa7e0vandwalle } 432f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 433f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 434992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle 435931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // TODO: write only if something changed 436992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle if (userTriggered || connect) { 437992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle mWifiConfigStore.writeKnownNetworkHistory(); 438992ae00f25a9cc22cf5db3261bd7e72927069cf7vandwalle } 439f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 440f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 4412451dbcc4f9641df188326215b204b798eb70c46vandwalle int getConnectChoice(WifiConfiguration source, WifiConfiguration target) { 4422451dbcc4f9641df188326215b204b798eb70c46vandwalle Integer choice = null; 4432451dbcc4f9641df188326215b204b798eb70c46vandwalle if (source == null || target == null) { 4442451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 445f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 446f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 4472451dbcc4f9641df188326215b204b798eb70c46vandwalle if (source.connectChoices != null 4482451dbcc4f9641df188326215b204b798eb70c46vandwalle && source.connectChoices.containsKey(target.configKey(true))) { 4492451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = source.connectChoices.get(target.configKey(true)); 4502451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (source.linkedConfigurations != null) { 451f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (String key : source.linkedConfigurations.keySet()) { 452f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration config = mWifiConfigStore.getWifiConfiguration(key); 453f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config != null) { 454f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config.connectChoices != null) { 4552451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = config.connectChoices.get(target.configKey(true)); 456f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 457f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 458f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 4592451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4602451dbcc4f9641df188326215b204b798eb70c46vandwalle 4612451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice == null) { 4622451dbcc4f9641df188326215b204b798eb70c46vandwalle //We didn't find the connect choice 4632451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 4642451dbcc4f9641df188326215b204b798eb70c46vandwalle } else { 4652451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice.intValue() < 0) { 4662451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = 20; // Compatibility with older files 4672451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4682451dbcc4f9641df188326215b204b798eb70c46vandwalle return choice.intValue(); 4692451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4702451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4712451dbcc4f9641df188326215b204b798eb70c46vandwalle 4722451dbcc4f9641df188326215b204b798eb70c46vandwalle 4732451dbcc4f9641df188326215b204b798eb70c46vandwalle int getScoreFromVisibility(WifiConfiguration.Visibility visibility, int rssiBoost) { 4742451dbcc4f9641df188326215b204b798eb70c46vandwalle int rssiBoost5 = 0; 4752451dbcc4f9641df188326215b204b798eb70c46vandwalle int score = 0; 4764dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 4772451dbcc4f9641df188326215b204b798eb70c46vandwalle /** 4782451dbcc4f9641df188326215b204b798eb70c46vandwalle * Boost RSSI value of 5GHz bands iff the base value is better than threshold 4792451dbcc4f9641df188326215b204b798eb70c46vandwalle * This implements band preference where we prefer 5GHz if RSSI5 is good enough, whereas 4802451dbcc4f9641df188326215b204b798eb70c46vandwalle * we prefer 2.4GHz otherwise. 4812451dbcc4f9641df188326215b204b798eb70c46vandwalle * Note that 2.4GHz doesn't need a boost since at equal power the RSSI is typically 4822451dbcc4f9641df188326215b204b798eb70c46vandwalle * 6-10 dB higher 4832451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 4842451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((visibility.rssi5 + rssiBoost) > WifiConfiguration.A_BAND_PREFERENCE_RSSI_THRESHOLD) { 4852451dbcc4f9641df188326215b204b798eb70c46vandwalle rssiBoost5 = 25; 4862451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if ((visibility.rssi5 + rssiBoost) 4872451dbcc4f9641df188326215b204b798eb70c46vandwalle > WifiConfiguration.A_BAND_PREFERENCE_RSSI_THRESHOLD_LOW) { 4882451dbcc4f9641df188326215b204b798eb70c46vandwalle rssiBoost5 = 15; 4892451dbcc4f9641df188326215b204b798eb70c46vandwalle } 4902451dbcc4f9641df188326215b204b798eb70c46vandwalle 4912451dbcc4f9641df188326215b204b798eb70c46vandwalle // Select which band to use so as to score a 4922451dbcc4f9641df188326215b204b798eb70c46vandwalle if (visibility.rssi5 + rssiBoost5 > visibility.rssi24) { 4932451dbcc4f9641df188326215b204b798eb70c46vandwalle // Prefer a's 5GHz 4942451dbcc4f9641df188326215b204b798eb70c46vandwalle score = visibility.rssi5 + rssiBoost5 + rssiBoost; 4952451dbcc4f9641df188326215b204b798eb70c46vandwalle } else { 4962451dbcc4f9641df188326215b204b798eb70c46vandwalle // Prefer a's 2.4GHz 4972451dbcc4f9641df188326215b204b798eb70c46vandwalle score = visibility.rssi24 + rssiBoost; 498f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 4992451dbcc4f9641df188326215b204b798eb70c46vandwalle 5002451dbcc4f9641df188326215b204b798eb70c46vandwalle return score; 501f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 502f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 5032451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare WifiConfiguration by RSSI, and return a comparison value in the range [-50, +50] 5042451dbcc4f9641df188326215b204b798eb70c46vandwalle // The result represents "approximately" an RSSI difference measured in dBM 5052451dbcc4f9641df188326215b204b798eb70c46vandwalle // Adjusted with various parameters: 5062451dbcc4f9641df188326215b204b798eb70c46vandwalle // +) current network gets a +15 boost 5072451dbcc4f9641df188326215b204b798eb70c46vandwalle // +) 5GHz signal, if they are strong enough, get a +15 or +25 boost, representing the 5082451dbcc4f9641df188326215b204b798eb70c46vandwalle // fact that at short range we prefer 5GHz band as it is cleaner of interference and 5092451dbcc4f9641df188326215b204b798eb70c46vandwalle // provides for wider channels 5102451dbcc4f9641df188326215b204b798eb70c46vandwalle int compareWifiConfigurationsRSSI(WifiConfiguration a, WifiConfiguration b, 5112451dbcc4f9641df188326215b204b798eb70c46vandwalle String currentConfiguration) { 512f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int order = 0; 5132451dbcc4f9641df188326215b204b798eb70c46vandwalle 5142451dbcc4f9641df188326215b204b798eb70c46vandwalle // Boost used so as to favor current config 5152451dbcc4f9641df188326215b204b798eb70c46vandwalle int aRssiBoost = 0; 5162451dbcc4f9641df188326215b204b798eb70c46vandwalle int bRssiBoost = 0; 5172451dbcc4f9641df188326215b204b798eb70c46vandwalle 5182451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreA; 5192451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreB; 5202451dbcc4f9641df188326215b204b798eb70c46vandwalle 5212451dbcc4f9641df188326215b204b798eb70c46vandwalle // Retrieve the visibility 522f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility astatus = a.visibility; 523f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility bstatus = b.visibility; 524f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (astatus == null || bstatus == null) { 5252451dbcc4f9641df188326215b204b798eb70c46vandwalle // Error visibility wasn't set 526f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("compareWifiConfigurations NULL band status!"); 527f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return 0; 528f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5292451dbcc4f9641df188326215b204b798eb70c46vandwalle 5302451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply Hysteresis, boost RSSI of current configuration 5312451dbcc4f9641df188326215b204b798eb70c46vandwalle if (null != currentConfiguration) { 5322451dbcc4f9641df188326215b204b798eb70c46vandwalle if (a.configKey().equals(currentConfiguration)) { 533c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle aRssiBoost += 20; 5342451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (b.configKey().equals(currentConfiguration)) { 535c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle bRssiBoost += 20; 5362451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5372451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5382451dbcc4f9641df188326215b204b798eb70c46vandwalle 5392451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 5402451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurationsRSSI: " + a.configKey() 541c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " " + Integer.toString(astatus.rssi24) 542c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + "," + Integer.toString(astatus.rssi5) 5432451dbcc4f9641df188326215b204b798eb70c46vandwalle + " boost=" + Integer.toString(aRssiBoost) 544c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " " + b.configKey() + " " 545c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + Integer.toString(bstatus.rssi24) + "," 546c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + Integer.toString(bstatus.rssi5) 5472451dbcc4f9641df188326215b204b798eb70c46vandwalle + " boost=" + Integer.toString(bRssiBoost) 5482451dbcc4f9641df188326215b204b798eb70c46vandwalle ); 549f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 5502451dbcc4f9641df188326215b204b798eb70c46vandwalle 5512451dbcc4f9641df188326215b204b798eb70c46vandwalle scoreA = getScoreFromVisibility(astatus, aRssiBoost); 5522451dbcc4f9641df188326215b204b798eb70c46vandwalle scoreB = getScoreFromVisibility(bstatus, bRssiBoost); 5532451dbcc4f9641df188326215b204b798eb70c46vandwalle 5542451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare a and b 5552451dbcc4f9641df188326215b204b798eb70c46vandwalle // If a score is higher then a > b and the order is descending (negative) 5562451dbcc4f9641df188326215b204b798eb70c46vandwalle // If b score is higher then a < b and the order is ascending (positive) 5572451dbcc4f9641df188326215b204b798eb70c46vandwalle order = scoreB - scoreA; 5582451dbcc4f9641df188326215b204b798eb70c46vandwalle 5592451dbcc4f9641df188326215b204b798eb70c46vandwalle // Normalize the order to [-50, +50] 5602451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order > 50) order = 50; 5612451dbcc4f9641df188326215b204b798eb70c46vandwalle else if (order < -50) order = -50; 5622451dbcc4f9641df188326215b204b798eb70c46vandwalle 5632451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 5642451dbcc4f9641df188326215b204b798eb70c46vandwalle String prefer = " = "; 5652451dbcc4f9641df188326215b204b798eb70c46vandwalle if (order > 0) { 5662451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " < "; // Ascending 5672451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (order < 0) { 5682451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " > "; // Descending 5692451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5702451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurationsRSSI " + a.configKey() 5712451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + a.visibility.rssi24 5722451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.rssi5 5732451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + a.visibility.num24 5742451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.num5 + ")" 5752451dbcc4f9641df188326215b204b798eb70c46vandwalle + prefer + b.configKey() 5762451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + b.visibility.rssi24 5772451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.rssi5 5782451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + b.visibility.num24 5792451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.num5 + ")" 5802451dbcc4f9641df188326215b204b798eb70c46vandwalle + " -> " + order); 5812451dbcc4f9641df188326215b204b798eb70c46vandwalle } 5822451dbcc4f9641df188326215b204b798eb70c46vandwalle 583f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return order; 584f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 585f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 5864dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 5872451dbcc4f9641df188326215b204b798eb70c46vandwalle int compareWifiConfigurationsWithScorer(WifiConfiguration a, WifiConfiguration b) { 5882451dbcc4f9641df188326215b204b798eb70c46vandwalle 5892451dbcc4f9641df188326215b204b798eb70c46vandwalle int aRssiBoost = 0; 5902451dbcc4f9641df188326215b204b798eb70c46vandwalle int bRssiBoost = 0; 5912451dbcc4f9641df188326215b204b798eb70c46vandwalle 5922451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply Hysteresis : boost RSSI of current configuration before 5932451dbcc4f9641df188326215b204b798eb70c46vandwalle // looking up the score 5942451dbcc4f9641df188326215b204b798eb70c46vandwalle if (null != mCurrentConfigurationKey) { 5952451dbcc4f9641df188326215b204b798eb70c46vandwalle if (a.configKey().equals(mCurrentConfigurationKey)) { 596c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle aRssiBoost += 20; 5972451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if (b.configKey().equals(mCurrentConfigurationKey)) { 598c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle bRssiBoost += 20; 5992451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6002451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6012451dbcc4f9641df188326215b204b798eb70c46vandwalle int scoreA = getConfigNetworkScore(a, 3000, aRssiBoost); 602ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle int scoreB = getConfigNetworkScore(b, 3000, bRssiBoost); 6032451dbcc4f9641df188326215b204b798eb70c46vandwalle 6042451dbcc4f9641df188326215b204b798eb70c46vandwalle // Both configurations need to have a score for the scorer to be used 6052451dbcc4f9641df188326215b204b798eb70c46vandwalle // ...and the scores need to be different:-) 6062451dbcc4f9641df188326215b204b798eb70c46vandwalle if (scoreA == WifiNetworkScoreCache.INVALID_NETWORK_SCORE 6072451dbcc4f9641df188326215b204b798eb70c46vandwalle || scoreB == WifiNetworkScoreCache.INVALID_NETWORK_SCORE) { 6082451dbcc4f9641df188326215b204b798eb70c46vandwalle return 0; 6092451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6102451dbcc4f9641df188326215b204b798eb70c46vandwalle 6112451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 6122451dbcc4f9641df188326215b204b798eb70c46vandwalle String prefer = " = "; 6132451dbcc4f9641df188326215b204b798eb70c46vandwalle if (scoreA < scoreB) { 6142451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " < "; 6152451dbcc4f9641df188326215b204b798eb70c46vandwalle } if (scoreA > scoreB) { 6162451dbcc4f9641df188326215b204b798eb70c46vandwalle prefer = " > "; 6172451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6182451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurationsWithScorer " + a.configKey() 6192451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + a.visibility.rssi24 6202451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.rssi5 6212451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + a.visibility.num24 6222451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + a.visibility.num5 + ")" 6232451dbcc4f9641df188326215b204b798eb70c46vandwalle + prefer + b.configKey() 6242451dbcc4f9641df188326215b204b798eb70c46vandwalle + " rssi=(" + b.visibility.rssi24 6252451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.rssi5 6262451dbcc4f9641df188326215b204b798eb70c46vandwalle + ") num=(" + b.visibility.num24 6272451dbcc4f9641df188326215b204b798eb70c46vandwalle + "," + b.visibility.num5 + ")" 6282451dbcc4f9641df188326215b204b798eb70c46vandwalle + " -> " + Integer.toString(scoreB - scoreA)); 6292451dbcc4f9641df188326215b204b798eb70c46vandwalle } 630c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 6312451dbcc4f9641df188326215b204b798eb70c46vandwalle // If scoreA > scoreB, the comparison is descending hence the return value is negative 6322451dbcc4f9641df188326215b204b798eb70c46vandwalle return scoreB - scoreA; 6332451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6342451dbcc4f9641df188326215b204b798eb70c46vandwalle 635f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int compareWifiConfigurations(WifiConfiguration a, WifiConfiguration b) { 636f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int order = 0; 637117be607246604e875de62aa8cdd99700b77a2b4vandwalle String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration(); 638f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle boolean linked = false; 639f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 640453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle if ((a.linkedConfigurations != null) && (b.linkedConfigurations != null) 641453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle && (a.autoJoinStatus == WifiConfiguration.AUTO_JOIN_ENABLED) 642453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle && (b.autoJoinStatus == WifiConfiguration.AUTO_JOIN_ENABLED)) { 6432451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((a.linkedConfigurations.get(b.configKey(true)) != null) 6442451dbcc4f9641df188326215b204b798eb70c46vandwalle && (b.linkedConfigurations.get(a.configKey(true)) != null)) { 645f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle linked = true; 646f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 647f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 648f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 649f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (a.ephemeral && b.ephemeral == false) { 650f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 651453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("compareWifiConfigurations ephemeral and prefers " + b.configKey() 652453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + a.configKey()); 653f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 654931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle return 1; // b is of higher priority - ascending 655f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 656f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (b.ephemeral && a.ephemeral == false) { 657f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 6582451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurations ephemeral and prefers " + a.configKey() 659453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + b.configKey()); 660f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 661931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle return -1; // a is of higher priority - descending 662f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 663f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 6642451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply RSSI, in the range [-5, +5] 6652451dbcc4f9641df188326215b204b798eb70c46vandwalle // after band adjustment, +n difference roughly corresponds to +10xn dBm 6662451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + compareWifiConfigurationsRSSI(a, b, mCurrentConfigurationKey); 667f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 6682451dbcc4f9641df188326215b204b798eb70c46vandwalle // If the configurations are not linked, compare by user's choice, only a 6692451dbcc4f9641df188326215b204b798eb70c46vandwalle // very high RSSI difference can then override the choice 6702451dbcc4f9641df188326215b204b798eb70c46vandwalle if (!linked) { 6712451dbcc4f9641df188326215b204b798eb70c46vandwalle int choice; 672f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 6732451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = getConnectChoice(a, b); 6742451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice > 0) { 675931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of higher priority - descending 6762451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order - choice; 677f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 6782451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurations prefers " + a.configKey() 679453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + " over " + b.configKey() 6802451dbcc4f9641df188326215b204b798eb70c46vandwalle + " due to user choice order -> " + Integer.toString(order)); 681f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 6822451dbcc4f9641df188326215b204b798eb70c46vandwalle } 6832451dbcc4f9641df188326215b204b798eb70c46vandwalle 6842451dbcc4f9641df188326215b204b798eb70c46vandwalle choice = getConnectChoice(b, a); 6852451dbcc4f9641df188326215b204b798eb70c46vandwalle if (choice > 0) { 686931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of lower priority - ascending 6872451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + choice; 6884dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (VDBG) { 6892451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg("compareWifiConfigurations prefers " + b.configKey() + " over " 6902451dbcc4f9641df188326215b204b798eb70c46vandwalle + a.configKey() + " due to user choice order ->" 6912451dbcc4f9641df188326215b204b798eb70c46vandwalle + Integer.toString(order)); 692f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 693f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 694f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 695ede1310be531a84faa08f02c3fd243448dd936ddvandwalle 696f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (order == 0) { 697931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // We don't know anything - pick the last seen i.e. K behavior 698931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // we should do this only for recently picked configurations 699f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (a.priority > b.priority) { 700931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of higher priority - descending 7012451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 702453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("compareWifiConfigurations prefers -1 " + a.configKey() + " over " 703453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + b.configKey() + " due to priority"); 704f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 705f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 706f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle order = -1; 707f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else if (a.priority < b.priority) { 708931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // a is of lower priority - ascending 7092451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 710453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("compareWifiConfigurations prefers +1 " + b.configKey() + " over " 711453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + a.configKey() + " due to priority"); 712f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 7132451dbcc4f9641df188326215b204b798eb70c46vandwalle order = 1; 714f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 715f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 716f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 717f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String sorder = " == "; 718931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle if (order > 0) { 719f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle sorder = " < "; 720931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle } else if (order < 0) { 721f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle sorder = " > "; 722931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle } 723f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 7242451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 725453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("compareWifiConfigurations Done: " + a.configKey() + sorder 726453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + b.configKey() + " order " + Integer.toString(order)); 727f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 728f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 729f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return order; 730f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 731f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 732c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle boolean isBadCandidate(int rssi5, int rssi24) { 733c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle return (rssi5 < -80 && rssi24 < -90); 734c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 735c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 736c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int compareWifiConfigurationsTop(WifiConfiguration a, WifiConfiguration b) { 737c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int scorerOrder = compareWifiConfigurationsWithScorer(a, b); 738c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurations(a, b); 739c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 740c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle if (scorerOrder * order < 0) { 741c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // For debugging purpose, remember that an override happened 742c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // during that autojoin Attempt 743c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle didOverride = true; 744c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle a.numScorerOverride++; 745c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle b.numScorerOverride++; 746c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 747c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 748c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle if (scorerOrder != 0) { 749c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // If the scorer came up with a result then use the scorer's result, else use 750c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // the order provided by the base comparison function 751c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle order = scorerOrder; 752c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 753c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle return order; 754c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle } 755c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle 756c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle /** 757c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle * attemptRoam function implements the core of the same SSID switching algorithm 758c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle */ 759b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle ScanResult attemptRoam(WifiConfiguration current, int age) { 7604dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle ScanResult a = null; 761b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (current == null) { 762b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 763b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptRoam not associated"); 764b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 7654dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle return null; 7664dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 767b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (current.scanResultCache == null) { 768b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 769b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptRoam no scan cache"); 770b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 7714dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle return null; 7724dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 773b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle if (current.scanResultCache.size() > 6) { 774b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) { 775c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle logDbg("attemptRoam scan cache size " 776c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + current.scanResultCache.size() + " --> bail"); 777b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 778931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Implement same SSID roaming only for configurations 779c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle // that have less than 4 BSSIDs 7804dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle return null; 7814dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 782b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle String currentBSSID = mWifiStateMachine.getCurrentBSSID(); 783b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (currentBSSID == null) { 784b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 785b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptRoam currentBSSID unknown"); 786b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 787b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle return null; 788b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 789b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 790b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (current.bssidOwnerUid!= 0 && current.bssidOwnerUid != Process.WIFI_UID) { 791b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 792c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle logDbg("attemptRoam BSSID owner is " 793c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + Long.toString(current.bssidOwnerUid) + " -> bail"); 794b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 7954dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle return null; 7964dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 7974dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 798931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Determine which BSSID we want to associate to, taking account 799c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle // relative strength of 5 and 2.4 GHz BSSIDs 8002451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 8014dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle int bRssiBoost5 = 0; 8024dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle int aRssiBoost5 = 0; 8034dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle int bRssiBoost = 0; 8044dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle int aRssiBoost = 0; 805b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle for (ScanResult b : current.scanResultCache.values()) { 8064dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 807931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle if ((b.seen == 0) || (b.BSSID == null) 8082451dbcc4f9641df188326215b204b798eb70c46vandwalle || (nowMs - b.seen) > age ) { 8092451dbcc4f9641df188326215b204b798eb70c46vandwalle // TODO: do not apply blacklisting right now so as to leave this 8102451dbcc4f9641df188326215b204b798eb70c46vandwalle // bug as apparent 8112451dbcc4f9641df188326215b204b798eb70c46vandwalle // https://b2.corp.google.com/#/issues/16504012 8122451dbcc4f9641df188326215b204b798eb70c46vandwalle // || b.status != ScanResult.ENABLED) { 8134dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle continue; 8143a2a3d226881cce8a4e511302231d843b0def303vandwalle } 8154dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 816931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Pick first one 8174dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (a == null) { 8184dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle a = b; 8194dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle continue; 8204dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8214dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 8222451dbcc4f9641df188326215b204b798eb70c46vandwalle // Apply hysteresis: we favor the currentBSSID by giving it a boost 823b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (currentBSSID.equals(b.BSSID)) { 824931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reduce the benefit of hysteresis if RSSI <= -75 825c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.level <= WifiConfiguration.G_BAND_PREFERENCE_RSSI_THRESHOLD) { 826c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle bRssiBoost = +6; 827c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else { 828c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle bRssiBoost = +10; 829c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 8304dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 831b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (currentBSSID.equals(a.BSSID)) { 832c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (a.level <= WifiConfiguration.G_BAND_PREFERENCE_RSSI_THRESHOLD) { 833931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reduce the benefit of hysteresis if RSSI <= -75 834c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle aRssiBoost = +6; 835c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else { 836c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle aRssiBoost = +10; 837c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 8384dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8392451dbcc4f9641df188326215b204b798eb70c46vandwalle 8402451dbcc4f9641df188326215b204b798eb70c46vandwalle // Favor 5GHz: give a boost to 5GHz BSSIDs 8412451dbcc4f9641df188326215b204b798eb70c46vandwalle // Boost the BSSID if it is on 5GHz, above a threshold 8422451dbcc4f9641df188326215b204b798eb70c46vandwalle // But penalize it if it is on 5GHz and below threshold 843c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.is5GHz() && (b.level+bRssiBoost) 844c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle > WifiConfiguration.A_BAND_PREFERENCE_RSSI_THRESHOLD) { 8454dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle bRssiBoost5 = 25; 846c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else if (b.is5GHz() && (b.level+bRssiBoost) 847c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle < WifiConfiguration.G_BAND_PREFERENCE_RSSI_THRESHOLD) { 848c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle bRssiBoost5 = -10; 8494dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 850c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (a.is5GHz() && (a.level+aRssiBoost) 851c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle > WifiConfiguration.A_BAND_PREFERENCE_RSSI_THRESHOLD) { 8524dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle aRssiBoost5 = 25; 853c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } else if (a.is5GHz() && (a.level+aRssiBoost) 854c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle < WifiConfiguration.G_BAND_PREFERENCE_RSSI_THRESHOLD) { 855c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle aRssiBoost5 = -10; 8564dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8574dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 8584dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (VDBG) { 859c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle String comp = " < "; 860c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.level + bRssiBoost + bRssiBoost5 > a.level +aRssiBoost + aRssiBoost5) { 861c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle comp = " > "; 862c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 8634dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle logDbg("attemptRoam: " 864c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + b.BSSID + " rssi=" + b.level + " boost=" + Integer.toString(bRssiBoost) 865c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + "/" + Integer.toString(bRssiBoost5) + " freq=" + b.frequency + comp 866c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + a.BSSID + " rssi=" + a.level + " boost=" + Integer.toString(aRssiBoost) 867c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + "/" + Integer.toString(aRssiBoost5) + " freq=" + a.frequency); 868c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle } 869c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle 8702451dbcc4f9641df188326215b204b798eb70c46vandwalle // Compare the RSSIs after applying the hysteresis boost and the 5GHz 8712451dbcc4f9641df188326215b204b798eb70c46vandwalle // boost if applicable 872c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle if (b.level + bRssiBoost + bRssiBoost5 > a.level +aRssiBoost + aRssiBoost5) { 873931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // b is the better BSSID 874c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle a = b; 8754dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8764dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8773a2a3d226881cce8a4e511302231d843b0def303vandwalle if (a != null) { 8783a2a3d226881cce8a4e511302231d843b0def303vandwalle if (VDBG) { 8793a2a3d226881cce8a4e511302231d843b0def303vandwalle logDbg("attemptRoam: Found " 8803a2a3d226881cce8a4e511302231d843b0def303vandwalle + a.BSSID + " rssi=" + a.level + " freq=" + a.frequency 8813a2a3d226881cce8a4e511302231d843b0def303vandwalle + " Current: " + currentBSSID); 8823a2a3d226881cce8a4e511302231d843b0def303vandwalle } 8833a2a3d226881cce8a4e511302231d843b0def303vandwalle if (currentBSSID.equals(a.BSSID)) { 8843a2a3d226881cce8a4e511302231d843b0def303vandwalle return null; 8853a2a3d226881cce8a4e511302231d843b0def303vandwalle } 8864dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8873a2a3d226881cce8a4e511302231d843b0def303vandwalle return a; 8884dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 8894dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 890931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 8912451dbcc4f9641df188326215b204b798eb70c46vandwalle * getNetworkScore() 8922451dbcc4f9641df188326215b204b798eb70c46vandwalle * 8932451dbcc4f9641df188326215b204b798eb70c46vandwalle * if scorer is present, get the network score of a WifiConfiguration 8942451dbcc4f9641df188326215b204b798eb70c46vandwalle * 8952451dbcc4f9641df188326215b204b798eb70c46vandwalle * Note: this should be merge with setVisibility 8962451dbcc4f9641df188326215b204b798eb70c46vandwalle * 8972451dbcc4f9641df188326215b204b798eb70c46vandwalle * @param config 8982451dbcc4f9641df188326215b204b798eb70c46vandwalle * @return score 899c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle * @return score 9002451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 9012451dbcc4f9641df188326215b204b798eb70c46vandwalle int getConfigNetworkScore(WifiConfiguration config, int age, int rssiBoost) { 9022451dbcc4f9641df188326215b204b798eb70c46vandwalle 9032451dbcc4f9641df188326215b204b798eb70c46vandwalle int score = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; 9042451dbcc4f9641df188326215b204b798eb70c46vandwalle if (mNetworkScoreCache == null) { 9052451dbcc4f9641df188326215b204b798eb70c46vandwalle return score; 9062451dbcc4f9641df188326215b204b798eb70c46vandwalle } 9072451dbcc4f9641df188326215b204b798eb70c46vandwalle 9082451dbcc4f9641df188326215b204b798eb70c46vandwalle // Get current date 9092451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 9102451dbcc4f9641df188326215b204b798eb70c46vandwalle 9112451dbcc4f9641df188326215b204b798eb70c46vandwalle // Run thru all cached scan results 9122451dbcc4f9641df188326215b204b798eb70c46vandwalle for (ScanResult result : scanResultCache.values()) { 9132451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((nowMs - result.seen) < age) { 9142451dbcc4f9641df188326215b204b798eb70c46vandwalle int sc = mNetworkScoreCache.getNetworkScore(result, rssiBoost); 9152451dbcc4f9641df188326215b204b798eb70c46vandwalle if (sc > score) { 9162451dbcc4f9641df188326215b204b798eb70c46vandwalle score = sc; 9172451dbcc4f9641df188326215b204b798eb70c46vandwalle } 9182451dbcc4f9641df188326215b204b798eb70c46vandwalle } 9192451dbcc4f9641df188326215b204b798eb70c46vandwalle } 9202451dbcc4f9641df188326215b204b798eb70c46vandwalle return score; 9212451dbcc4f9641df188326215b204b798eb70c46vandwalle } 9222451dbcc4f9641df188326215b204b798eb70c46vandwalle 9232451dbcc4f9641df188326215b204b798eb70c46vandwalle /** 924931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * attemptAutoJoin() function implements the core of the a network switching algorithm 925931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 926f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle void attemptAutoJoin() { 927c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle didOverride = false; 928b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle int networkSwitchType = AUTO_JOIN_IDLE; 9294dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 9308c9088d11880553458f09377cc60d6eb7e66747bvandwalle String lastSelectedConfiguration = mWifiConfigStore.getLastSelectedConfiguration(); 9318c9088d11880553458f09377cc60d6eb7e66747bvandwalle 932931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reset the currentConfiguration Key, and set it only if WifiStateMachine and 933453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle // supplicant agree 934453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle mCurrentConfigurationKey = null; 935453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle WifiConfiguration currentConfiguration = mWifiStateMachine.getCurrentWifiConfiguration(); 936453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 937f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration candidate = null; 938f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 939931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Obtain the subset of recently seen networks 94027355a942653264388e909a4276196ee63e57811vandwalle List<WifiConfiguration> list = mWifiConfigStore.getRecentConfiguredNetworks(3000, false); 941f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (list == null) { 942f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) logDbg("attemptAutoJoin nothing"); 943f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle return; 944f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 945f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 946931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Find the currently connected network: ask the supplicant directly 947f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String val = mWifiNative.status(); 948f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle String status[] = val.split("\\r?\\n"); 949f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 950f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle logDbg("attemptAutoJoin() status=" + val + " split=" 951f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle + Integer.toString(status.length)); 952f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 953f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 954b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle int supplicantNetId = -1; 955f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (String key : status) { 956f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (key.regionMatches(0, "id=", 0, 3)) { 957f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int idx = 3; 958b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId = 0; 959f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle while (idx < key.length()) { 960f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle char c = key.charAt(idx); 961f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 962f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((c >= 0x30) && (c <= 0x39)) { 963b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId *= 10; 964b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle supplicantNetId += c - 0x30; 965f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle idx++; 966f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 967f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle break; 968f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 969f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 970f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 971f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 972ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 973ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle logDbg("attemptAutoJoin() num recent config " + Integer.toString(list.size()) 974b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + " ---> suppId=" + Integer.toString(supplicantNetId)); 975ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 976f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 977453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle if (currentConfiguration != null) { 9782451dbcc4f9641df188326215b204b798eb70c46vandwalle if (supplicantNetId != currentConfiguration.networkId 9792451dbcc4f9641df188326215b204b798eb70c46vandwalle //https://b.corp.google.com/issue?id=16484607 9802451dbcc4f9641df188326215b204b798eb70c46vandwalle //mark this confition as an error only if the mismatched networkId are valid 9812451dbcc4f9641df188326215b204b798eb70c46vandwalle && supplicantNetId != WifiConfiguration.INVALID_NETWORK_ID 9822451dbcc4f9641df188326215b204b798eb70c46vandwalle && currentConfiguration.networkId != WifiConfiguration.INVALID_NETWORK_ID) { 983453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("attemptAutoJoin() ERROR wpa_supplicant out of sync nid=" 984b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + Integer.toString(supplicantNetId) + " WifiStateMachine=" 985453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle + Integer.toString(currentConfiguration.networkId)); 986b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle mWifiStateMachine.disconnectCommand(); 987b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle return; 988453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } else { 989453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle mCurrentConfigurationKey = currentConfiguration.configKey(); 990453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } 991453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle } 992453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 993b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle int currentNetId = -1; 994b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (currentConfiguration != null) { 995931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If we are associated to a configuration, it will 996b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle // be compared thru the compareNetwork function 997b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle currentNetId = currentConfiguration.networkId; 998b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle } 999b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle 1000931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1001931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Run thru all visible configurations without looking at the one we 1002c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle * are currently associated to 10034dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle * select Best Network candidate from known WifiConfigurations 1004931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1005f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (WifiConfiguration config : list) { 1006f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if ((config.status == WifiConfiguration.Status.DISABLED) 1007f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle && (config.disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE)) { 1008ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1009b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("attemptAutoJoin skip candidate due to auth failure: " 1010ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + config.configKey(true)); 1011ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1012f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1013f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1014453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle 1015e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle if (config.SSID == null) { 1016b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle continue; 1017e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle } 1018e86c962bb99a8b126ed64ddcc6b112161549e26dvandwalle 101927355a942653264388e909a4276196ee63e57811vandwalle if (config.autoJoinStatus >= 102027355a942653264388e909a4276196ee63e57811vandwalle WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) { 1021931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Avoid networks disabled because of AUTH failure altogether 1022ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1023ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle logDbg("attemptAutoJoin skip candidate due to auto join status " 1024ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + Integer.toString(config.autoJoinStatus) + " key " 1025ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + config.configKey(true)); 1026ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1027f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1028f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1029f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1030931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Try to un-blacklist based on elapsed time 103127355a942653264388e909a4276196ee63e57811vandwalle if (config.blackListTimestamp > 0) { 103227355a942653264388e909a4276196ee63e57811vandwalle long now = System.currentTimeMillis(); 103327355a942653264388e909a4276196ee63e57811vandwalle if (now < config.blackListTimestamp) { 1034931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1035931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * looks like there was a change in the system clock since we black listed, and 1036931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * timestamp is not meaningful anymore, hence lose it. 1037931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * this event should be rare enough so that we still want to lose the black list 10382451dbcc4f9641df188326215b204b798eb70c46vandwalle */ 103927355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 104027355a942653264388e909a4276196ee63e57811vandwalle } else { 10414dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if ((now - config.blackListTimestamp) > loseBlackListHardMilli) { 1042931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Reenable it after 18 hours, i.e. next day 104327355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED); 10444dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } else if ((now - config.blackListTimestamp) > loseBlackListSoftMilli) { 1045931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Lose blacklisting due to bad link 104627355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 8); 104727355a942653264388e909a4276196ee63e57811vandwalle } 104827355a942653264388e909a4276196ee63e57811vandwalle } 104927355a942653264388e909a4276196ee63e57811vandwalle } 105027355a942653264388e909a4276196ee63e57811vandwalle 1051931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Try to unblacklist based on good visibility 105227355a942653264388e909a4276196ee63e57811vandwalle if (config.visibility.rssi5 < WifiConfiguration.UNBLACKLIST_THRESHOLD_5_SOFT 105327355a942653264388e909a4276196ee63e57811vandwalle && config.visibility.rssi24 < WifiConfiguration.UNBLACKLIST_THRESHOLD_24_SOFT) { 105427355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 1055c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("attemptAutoJoin do not unblacklist due to low visibility " 10564dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.autoJoinStatus 10574dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) 10584dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " rssi=(" + config.visibility.rssi24 10594dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.rssi5 10604dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 10614dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 106227355a942653264388e909a4276196ee63e57811vandwalle } 106327355a942653264388e909a4276196ee63e57811vandwalle } else if (config.visibility.rssi5 < WifiConfiguration.UNBLACKLIST_THRESHOLD_5_HARD 106427355a942653264388e909a4276196ee63e57811vandwalle && config.visibility.rssi24 < WifiConfiguration.UNBLACKLIST_THRESHOLD_24_HARD) { 1065931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // If the network is simply temporary disabled, don't allow reconnect until 1066931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // RSSI becomes good enough 106727355a942653264388e909a4276196ee63e57811vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 1); 106827355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 106927355a942653264388e909a4276196ee63e57811vandwalle logDbg("attemptAutoJoin good candidate seen, bumped soft -> status=" 107027355a942653264388e909a4276196ee63e57811vandwalle + config.autoJoinStatus 10714dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) + " rssi=(" 10724dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 10734dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 10744dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 107527355a942653264388e909a4276196ee63e57811vandwalle } 107627355a942653264388e909a4276196ee63e57811vandwalle } else { 1077c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle config.setAutoJoinStatus(config.autoJoinStatus - 3); 107827355a942653264388e909a4276196ee63e57811vandwalle if (DBG) { 107927355a942653264388e909a4276196ee63e57811vandwalle logDbg("attemptAutoJoin good candidate seen, bumped hard -> status=" 108027355a942653264388e909a4276196ee63e57811vandwalle + config.autoJoinStatus 10814dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) + " rssi=(" 10824dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 10834dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 10844dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 108527355a942653264388e909a4276196ee63e57811vandwalle } 108627355a942653264388e909a4276196ee63e57811vandwalle } 108727355a942653264388e909a4276196ee63e57811vandwalle 108827355a942653264388e909a4276196ee63e57811vandwalle if (config.autoJoinStatus >= 108927355a942653264388e909a4276196ee63e57811vandwalle WifiConfiguration.AUTO_JOIN_TEMPORARY_DISABLED) { 1090931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Network is blacklisted, skip 10914dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (DBG) { 10924dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle logDbg("attemptAutoJoin skip blacklisted -> status=" 10934dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.autoJoinStatus 10944dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) + " rssi=(" 10954dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + "," + config.visibility.rssi5 10964dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ") num=(" + config.visibility.num24 10974dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + "," + config.visibility.num5 + ")"); 10984dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 109927355a942653264388e909a4276196ee63e57811vandwalle continue; 110027355a942653264388e909a4276196ee63e57811vandwalle } 1101f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (config.networkId == currentNetId) { 1102ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 110321bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle logDbg("attemptAutoJoin skip current candidate " 110421bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle + Integer.toString(currentNetId) 1105ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle + " key " + config.configKey(true)); 1106ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1107f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle continue; 1108f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1109f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 111021bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle if (lastSelectedConfiguration == null || 111121bc54cb37a0085b1c909cb4d55ebb12a2facefbvandwalle !config.configKey().equals(lastSelectedConfiguration)) { 1112c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // Don't try to autojoin a network that is too far but 1113c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // If that configuration is a user's choice however, try anyway 11148c9088d11880553458f09377cc60d6eb7e66747bvandwalle if (config.visibility == null) { 11158c9088d11880553458f09377cc60d6eb7e66747bvandwalle continue; 11168c9088d11880553458f09377cc60d6eb7e66747bvandwalle } 111727355a942653264388e909a4276196ee63e57811vandwalle if (config.visibility.rssi5 < WifiConfiguration.INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 1118c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle && config.visibility.rssi24 1119c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle < WifiConfiguration.INITIAL_AUTO_JOIN_ATTEMPT_MIN_24) { 11204dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle if (DBG) { 1121ede507649471f1113e9e1919812115ca5a6bc0c8vandwalle logDbg("attemptAutoJoin skip due to low visibility -> status=" 11224dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.autoJoinStatus 11234dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " key " + config.configKey(true) + " rssi=" 11244dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.visibility.rssi24 + ", " + config.visibility.rssi5 11254dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " num=" + config.visibility.num24 11264dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + ", " + config.visibility.num5); 11274dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 11288c9088d11880553458f09377cc60d6eb7e66747bvandwalle continue; 11298c9088d11880553458f09377cc60d6eb7e66747bvandwalle } 11308c9088d11880553458f09377cc60d6eb7e66747bvandwalle } 11318c9088d11880553458f09377cc60d6eb7e66747bvandwalle 1132ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle if (DBG) { 1133c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle logDbg("attemptAutoJoin trying candidate id=" 1134c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + Integer.toString(config.networkId) + " " 11354dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + config.SSID + " key " + config.configKey(true) 11364dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " status=" + config.autoJoinStatus); 1137ed9938883ae2dade81c8be6cd6ceaef3febd5239vandwalle } 1138f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1139f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate == null) { 1140f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle candidate = config; 1141f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } else { 1142f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (VDBG) { 1143453aee50caf7e332e77ab3d995d7c87a958e4fd4vandwalle logDbg("attemptAutoJoin will compare candidate " + candidate.configKey() 11444dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle + " with " + config.configKey()); 1145f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1146c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle int order = compareWifiConfigurationsTop(candidate, config); 11472451dbcc4f9641df188326215b204b798eb70c46vandwalle 11482451dbcc4f9641df188326215b204b798eb70c46vandwalle // The lastSelectedConfiguration is the configuration the user has manually selected 1149c290d8dff6172d5fde7b9dfd74d3a20785dab246vandwalle // thru WifiPicker, or that a 3rd party app asked us to connect to via the 11502451dbcc4f9641df188326215b204b798eb70c46vandwalle // enableNetwork with disableOthers=true WifiManager API 11512451dbcc4f9641df188326215b204b798eb70c46vandwalle // As this is a direct user choice, we strongly prefer this configuration, 11522451dbcc4f9641df188326215b204b798eb70c46vandwalle // hence give +/-100 11532451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((lastSelectedConfiguration != null) 11542451dbcc4f9641df188326215b204b798eb70c46vandwalle && candidate.configKey().equals(lastSelectedConfiguration)) { 11552451dbcc4f9641df188326215b204b798eb70c46vandwalle // candidate is the last selected configuration, 11562451dbcc4f9641df188326215b204b798eb70c46vandwalle // so keep it above connect choices (+/-60) and 11572451dbcc4f9641df188326215b204b798eb70c46vandwalle // above RSSI/scorer based selection of linked configuration (+/- 50) 11582451dbcc4f9641df188326215b204b798eb70c46vandwalle // by reducing order by -100 11592451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order - 100; 11602451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 11612451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg(" prefers -100 " + candidate.configKey() 11622451dbcc4f9641df188326215b204b798eb70c46vandwalle + " over " + config.configKey() 11632451dbcc4f9641df188326215b204b798eb70c46vandwalle + " because it is the last selected -> " 11642451dbcc4f9641df188326215b204b798eb70c46vandwalle + Integer.toString(order)); 11652451dbcc4f9641df188326215b204b798eb70c46vandwalle } 11662451dbcc4f9641df188326215b204b798eb70c46vandwalle } else if ((lastSelectedConfiguration != null) 11672451dbcc4f9641df188326215b204b798eb70c46vandwalle && config.configKey().equals(lastSelectedConfiguration)) { 11682451dbcc4f9641df188326215b204b798eb70c46vandwalle // config is the last selected configuration, 11692451dbcc4f9641df188326215b204b798eb70c46vandwalle // so keep it above connect choices (+/-60) and 11702451dbcc4f9641df188326215b204b798eb70c46vandwalle // above RSSI/scorer based selection of linked configuration (+/- 50) 11712451dbcc4f9641df188326215b204b798eb70c46vandwalle // by increasing order by +100 11722451dbcc4f9641df188326215b204b798eb70c46vandwalle order = order + 100; 11732451dbcc4f9641df188326215b204b798eb70c46vandwalle if (VDBG) { 11742451dbcc4f9641df188326215b204b798eb70c46vandwalle logDbg(" prefers +100 " + config.configKey() 11752451dbcc4f9641df188326215b204b798eb70c46vandwalle + " over " + candidate.configKey() 11762451dbcc4f9641df188326215b204b798eb70c46vandwalle + " because it is the last selected -> " 11772451dbcc4f9641df188326215b204b798eb70c46vandwalle + Integer.toString(order)); 11782451dbcc4f9641df188326215b204b798eb70c46vandwalle } 11792451dbcc4f9641df188326215b204b798eb70c46vandwalle } 11802451dbcc4f9641df188326215b204b798eb70c46vandwalle 1181f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (order > 0) { 1182931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Ascending : candidate < config 1183f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle candidate = config; 1184f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1185f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1186f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1187f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1188c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Wait for VPN to be available on the system to make use of this code 11892451dbcc4f9641df188326215b204b798eb70c46vandwalle // Now, go thru scan result to try finding a better untrusted network 1190f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (mNetworkScoreCache != null) { 1191f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int rssi5 = WifiConfiguration.INVALID_RSSI; 1192f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle int rssi24 = WifiConfiguration.INVALID_RSSI; 1193f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle WifiConfiguration.Visibility visibility; 1194f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle if (candidate != null) { 1195f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle rssi5 = candidate.visibility.rssi5; 1196f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle rssi24 = candidate.visibility.rssi24; 1197f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1198f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1199931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Get current date 12002451dbcc4f9641df188326215b204b798eb70c46vandwalle long nowMs = System.currentTimeMillis(); 1201c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int currentScore = -10000; 1202c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // The untrusted network with highest score 1203c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle ScanResult untrustedCandidate = null; 12042451dbcc4f9641df188326215b204b798eb70c46vandwalle // Look for untrusted scored network only if the current candidate is bad 1205c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (isBadCandidate(rssi24, rssi5)) { 1206f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle for (ScanResult result : scanResultCache.values()) { 1207c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int rssiBoost = 0; 1208c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // We look only at untrusted networks with a valid SSID 1209c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // A trusted result would have been looked at thru it's Wificonfiguration 1210c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (TextUtils.isEmpty(result.SSID) || !result.untrusted) { 1211c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle continue; 1212c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 12132451dbcc4f9641df188326215b204b798eb70c46vandwalle if ((nowMs - result.seen) < 3000) { 1214c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Increment usage count for the network 1215c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle mWifiConnectionStatistics.incrementOrAddUntrusted(result.SSID, 0, 1); 1216c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle 1217c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (lastUntrustedBSSID != null 1218c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle && result.BSSID.equals(lastUntrustedBSSID)) { 1219c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Apply a large hysteresis to the untrusted network we are connected to 1220c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle rssiBoost = 25; 1221c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1222c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle int score = mNetworkScoreCache.getNetworkScore(result, rssiBoost); 1223c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (score != WifiNetworkScoreCache.INVALID_NETWORK_SCORE 1224c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle && score > currentScore) { 1225c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Highest score: Select this candidate 1226c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle currentScore = score; 1227c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle untrustedCandidate = result; 1228c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (VDBG) { 1229c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle logDbg("AutoJoinController: found untrusted candidate " 1230c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + result.SSID 1231c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " RSSI=" + result.level 1232c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " freq=" + result.frequency 1233c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle + " score=" + score); 1234c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1235f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1236f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1237f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1238f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1239c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (untrustedCandidate != null) { 1240c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle if (lastUntrustedBSSID == null 1241c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle || !untrustedCandidate.SSID.equals(lastUntrustedBSSID)) { 1242c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // We found a new candidate that we are going to connect to, then 1243c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // increase its connection count 1244c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle mWifiConnectionStatistics.incrementOrAddUntrusted(untrustedCandidate.SSID, 1, 0); 1245c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Remember which SSID we are connecting to 1246c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle lastUntrustedBSSID = untrustedCandidate.SSID; 1247c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1248c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1249c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle // Now we don't have VPN, and thus don't actually connect to the untrusted candidate 1250c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle untrustedCandidate = null; 1251c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle } 1252b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle 1253931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1254931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * If candidate is found, check the state of the connection so as 1255931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * to decide if we should be acting on this candidate and switching over 1256931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1257b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle int networkDelta = compareNetwork(candidate); 1258b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle if (DBG && candidate != null) { 1259b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle logDbg("attemptAutoJoin compare SSID candidate : delta=" 1260b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + Integer.toString(networkDelta) + " " 1261b57df70bdf17ba45ef4d18b11414cb24dcbe1fb9vandwalle + candidate.configKey() 1262c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle + " linked=" + (currentConfiguration != null 1263c6f06c628ee3583b60ff31a7da442e0ac7b26d97vandwalle && currentConfiguration.isLinked(candidate))); 1264b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 12654dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 1266931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle /** 1267931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * Ask WifiStateMachine permission to switch : 1268931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * if user is currently streaming voice traffic, 1269931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle * then we should not be allowed to switch regardless of the delta 1270931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle */ 1271b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (mWifiStateMachine.shouldSwitchNetwork(networkDelta)) { 1272b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (mStaStaSupported) { 1273b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("mStaStaSupported --> error do nothing now "); 1274b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } else { 1275b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (currentConfiguration != null && currentConfiguration.isLinked(candidate)) { 1276b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_EXTENDED_ROAMING; 1277b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } else { 1278b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_OUT_OF_NETWORK_ROAMING; 1279b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 1280b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 1281b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("AutoJoin auto connect with netId " 1282b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + Integer.toString(candidate.networkId) 1283b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " to " + candidate.configKey()); 1284b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 12852451dbcc4f9641df188326215b204b798eb70c46vandwalle if (didOverride) { 12862451dbcc4f9641df188326215b204b798eb70c46vandwalle candidate.numScorerOverrideAndSwitchedNetwork++; 12872451dbcc4f9641df188326215b204b798eb70c46vandwalle } 1288c298087de50ea56c31a4ade7ee1e83b313bb63c7vandwalle candidate.numAssociation++; 1289b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle mWifiStateMachine.sendMessage(WifiStateMachine.CMD_AUTO_CONNECT, 1290b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle candidate.networkId, networkSwitchType, candidate); 12914dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle } 1292b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 12934dc6f3a322806b25d50039614cde1b94fe91ab17vandwalle 1294b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (networkSwitchType == AUTO_JOIN_IDLE) { 1295931338d1533d1bd11ba0e5aebb4e4b7b2c8ab056vandwalle // Attempt same WifiConfiguration roaming 1296b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle ScanResult roamCandidate = attemptRoam(currentConfiguration, 3000); 1297b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (roamCandidate != null) { 1298b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (DBG) { 1299b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle logDbg("AutoJoin auto roam with netId " 1300b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + Integer.toString(currentConfiguration.networkId) 1301b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " " + currentConfiguration.configKey() + " to BSSID=" 1302b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + roamCandidate.BSSID + " freq=" + roamCandidate.frequency 1303b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle + " RSSI=" + roamCandidate.frequency); 1304b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle } 1305b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle networkSwitchType = AUTO_JOIN_ROAMING; 1306b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle mWifiStateMachine.sendMessage(WifiStateMachine.CMD_AUTO_ROAM, 1307b07da189850a4bfa268f8ab9be7867935eb2ecb5vandwalle currentConfiguration.networkId, 1, roamCandidate); 1308f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1309f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1310b97e66604f472f67c233bb8f8d9630bb36131e2cvandwalle if (VDBG) logDbg("Done attemptAutoJoin status=" + Integer.toString(networkSwitchType)); 1311f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle } 1312f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle} 1313f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle 1314