WifiAutoJoinController.java revision f22d23092ab37286a5ef9d257d5bb32c421d2669
1f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle/*
2f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Copyright (C) 2010 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;
23f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.wifi.WifiConfiguration;
24f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.wifi.ScanResult;
25f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.wifi.WifiManager;
26f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.net.wifi.WifiParser;
27f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
28f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.os.SystemClock;
29f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.util.Log;
30f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
31f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.Iterator;
32f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.HashMap;
33f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.List;
34f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.Date;
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 WifiTrafficPoller mWifiTrafficPoller;
48f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private WifiNative mWifiNative;
49f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
50f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private NetworkScoreManager scoreManager;
51f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private WifiNetworkScoreCache mNetworkScoreCache;
52f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
53f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
54f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final String TAG = "WifiAutoJoinController ";
55f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final boolean DBG = true;
56f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final boolean VDBG = false;
57f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final boolean mStaStaSupported = false;
58f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final int SCAN_RESULT_CACHE_SIZE = 80;
59f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
60f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
61f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private HashMap<String, ScanResult> scanResultCache =
62f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            new HashMap<String, ScanResult>();
63f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
64f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    WifiAutoJoinController(Context c, WifiStateMachine w, WifiConfigStore s,
65f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                           WifiTrafficPoller t, WifiNative n) {
66f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mContext = c;
67f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiStateMachine = w;
68f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiConfigStore = s;
69f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiTrafficPoller = t;
70f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiNative = n;
71f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mNetworkScoreCache = null;
72f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        scoreManager = (NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE);
73f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (scoreManager == null)
74f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("Registered scoreManager NULL " + " service " + Context.NETWORK_SCORE_SERVICE);
75f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        else
76f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("Registered scoreManager NOT NULL" + " service " + Context.NETWORK_SCORE_SERVICE);
77f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
78f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (scoreManager != null) {
79f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            // NETwork SCORE SERVICE doesnt seem to be working, so do nothing for now
80f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            mNetworkScoreCache = new WifiNetworkScoreCache();
81f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            scoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache);
82f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        } else {
83f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("No network score service: Couldnt register as a WiFi score Manager, type="
84f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + Integer.toString(NetworkKey.TYPE_WIFI)
85f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + " service " + Context.NETWORK_SCORE_SERVICE);
86f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            mNetworkScoreCache = null;
87f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
88f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
89f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
90f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    int mScanResultMaximumAge = 30000; /* milliseconds unit */
91f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
92f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* flush out scan results older than mScanResultMaximumAge */
93f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private void ageScanResultsOut(int delay) {
94f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (delay <= 0) {
95f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            delay = mScanResultMaximumAge; //something sane
96f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
97f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        Date now = new Date();
98f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        long milli = now.getTime();
99f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (VDBG) {
100f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("ageScanResultsOut delay " + Integer.valueOf(delay) + " size "
101f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + Integer.valueOf(scanResultCache.size()) + " now " + Long.valueOf(milli));
102f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
103f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
104f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        Iterator<HashMap.Entry<String,ScanResult>> iter = scanResultCache.entrySet().iterator();
105f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        while (iter.hasNext()) {
106f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            HashMap.Entry<String,ScanResult> entry = iter.next();
107f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            ScanResult result = entry.getValue();
108f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
109f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if ((result.seen + delay) < milli) {
110f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                iter.remove();
111f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
112f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
113f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
114f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
115f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* Check if this network is known to kepler and return its score */
116f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private int isScoredNetwork(ScanResult result) {
117f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (mNetworkScoreCache == null)
118f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return 0;
119f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return mNetworkScoreCache.getNetworkScore(result);
120f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
121f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
122f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
123f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void addToScanCache(List<ScanResult> scanList) {
124f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration associatedConfig;
125f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
126f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        for(ScanResult result: scanList) {
127f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            result.seen = System.currentTimeMillis();
128f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
129f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            ScanResult sr = scanResultCache.get(result.BSSID);
130f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (sr != null) {
131f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                // if there was a previous cache result for this BSSID, average the RSSI values
132f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
133f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int previous_rssi = sr.level;
134f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                long previously_seen_milli = sr.seen;
135f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
136f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                /* average RSSI with previously seen instances of this scan result */
137f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int avg_rssi = result.level;
138f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
139f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((previously_seen_milli > 0)
140f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        && (previously_seen_milli < mScanResultMaximumAge/2)) {
141f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
142f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    /*
143f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    *
144f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    * previously_seen_milli = 0 => RSSI = 0.5 * previous_seen_rssi + 0.5 * new_rssi
145f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    *
146f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    * If previously_seen_milli is 15+ seconds old:
147f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    *      previously_seen_milli = 15000 => RSSI = new_rssi
148f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    *
149f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    */
150f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
151f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    double alpha = 0.5 - (double)previously_seen_milli
152f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            / (double)mScanResultMaximumAge;
153f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
154f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    avg_rssi = (int)((double)avg_rssi * (1-alpha) + (double)previous_rssi * alpha);
155f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
156f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
157f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                result.level = avg_rssi;
158f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
159f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //remove the previous Scan Result
160f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                scanResultCache.remove(result.BSSID);
161f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
162f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
163f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            scanResultCache.put(result.BSSID, new ScanResult(result));
164f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
165f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            ScanResult srn = scanResultCache.get(result.BSSID);
166f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
167f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //add this BSSID to the scanResultCache of the relevant WifiConfiguration
168f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            associatedConfig = mWifiConfigStore.updateSavedNetworkHistory(result);
169f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
170f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //try to associate this BSSID to an existing Saved Wificonfiguration
171f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (associatedConfig == null) {
172f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                associatedConfig = mWifiConfigStore.associateWithConfiguration(result);
173f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (associatedConfig != null) {
174f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    if (VDBG) {
175f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        logDbg("addToScanCache save associated config "
176f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                + associatedConfig.SSID + " with " + associatedConfig.SSID);
177f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
178f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    mWifiStateMachine.sendMessage(WifiManager.SAVE_NETWORK, associatedConfig);
179f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
180f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
181f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
182f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
183f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
184f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void logDbg(String message) {
185f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        long now = SystemClock.elapsedRealtimeNanos();
186f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String ts = String.format("[%,d us] ", now/1000);
187f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        Log.e(TAG, ts + message   + " stack:"
188f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                + Thread.currentThread().getStackTrace()[2].getMethodName() +" - "
189f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                + Thread.currentThread().getStackTrace()[3].getMethodName() +" - "
190f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                + Thread.currentThread().getStackTrace()[4].getMethodName() +" - "
191f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                + Thread.currentThread().getStackTrace()[5].getMethodName());
192f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
193f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
194f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
195f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* called directly from WifiStateMachine  */
196f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void newSupplicantResults() {
197f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        List<ScanResult> scanList = mWifiStateMachine.syncGetScanResultsList();
198f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        addToScanCache(scanList);
199f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        ageScanResultsOut(mScanResultMaximumAge);
200f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (DBG)
201f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle           logDbg("newSupplicantResults size=" + Integer.valueOf(scanResultCache.size()) );
202f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
203f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        attemptAutoJoin();
204f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiConfigStore.writeKnownNetworkHistory();
205f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
206f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
207f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
208f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
209f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* not used at the moment
210f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * should be a call back from WifiScanner HAL ??
211f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * this function is not hooked and working yet, it will receive scan results from WifiScanners
212f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * with the list of IEs,then populate the capabilities by parsing the IEs and inject the scan
213f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * results as normal.
214f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
215f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void newHalScanResults() {
216f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        List<ScanResult> scanList = null;//mWifiScanner.syncGetScanResultsList();
217f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String akm = WifiParser.parse_akm(null, null);
218f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        logDbg(akm);
219f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        addToScanCache(scanList);
220f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        ageScanResultsOut(0);
221f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        attemptAutoJoin();
222f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiConfigStore.writeKnownNetworkHistory();
223f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
224f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
225f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* network link quality changed, called directly from WifiTrafficPoller,
226f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    or by listening to Link Quality intent */
227f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void linkQualitySignificantChange() {
228f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        attemptAutoJoin();
229f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
230f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
231f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /*
232f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * compare a WifiConfiguration against the current network, return a delta score
233f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * If not associated, and the candidate will always be better
234f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * For instance if the candidate is a home network versus an unknown public wifi,
235f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * the delta will be infinite, else compare Kepler scores etc…
236f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     ***/
237f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private int compareNetwork(WifiConfiguration candidate) {
238f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration currentNetwork = mWifiStateMachine.getCurrentWifiConfiguration();
239f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (currentNetwork == null)
240f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return 1000;
241f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
242f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (candidate.configKey(true).equals(currentNetwork.configKey(true))) {
243f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return -1;
244f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
245f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
246f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int order = compareWifiConfigurations(currentNetwork, candidate);
247f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
248f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (order > 0) {
249f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //ascending: currentNetwork < candidate
250f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return 10; //will try switch over to the candidate
251f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
252f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
253f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return 0;
254f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
255f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
256f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
257f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
258f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    public void updateSavedConfigurationsPriorities(int netId) {
259f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
260f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration selected = mWifiConfigStore.getWifiConfiguration(netId);
261f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (selected == null) {
262f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return;
263f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
264f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
265f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        // reenable autojoin for this network,
266f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        // since the user want to connect to this configuration
267f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        selected.autoJoinStatus = WifiConfiguration.AUTO_JOIN_ENABLED;
268f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
269f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (DBG) {
270f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (selected.connectChoices != null) {
271f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("updateSavedConfigurationsPriorities will update "
272f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(netId) + " now: "
273f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(selected.connectChoices.size()));
274f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
275f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("updateSavedConfigurationsPriorities will update "
276f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(netId));
277f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
278f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
279f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
280f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        List<WifiConfiguration> networks =  mWifiConfigStore.getRecentConfiguredNetworks(12000, true);
281f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (networks == null)
282f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return;
283f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
284f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        for (WifiConfiguration config: networks) {
285f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
286f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (DBG)
287f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("updateSavedConfigurationsPriorities got " + config.SSID);
288f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
289f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (selected.configKey(true).equals(config.configKey(true))) {
290f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
291f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
292f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
293f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //we were preferred over a recently seen config
294f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (selected.connectChoices == null) {
295f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                selected.connectChoices = new HashMap<String, Integer>();
296f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
297f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
298f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            int rssi = WifiConfiguration.INVALID_RSSI;
299f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.visibility != null) {
300f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                rssi = config.visibility.rssi5;
301f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (config.visibility.rssi24 > rssi)
302f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    rssi = config.visibility.rssi24;
303f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
304f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (rssi < -80) {
305f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
306f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
307f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
308f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //remember the user's choice:
309f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //add the recently seen config to the selected's choice
310f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("updateSavedConfigurationsPriorities add a choice " + selected.configKey(true)
311f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + " over " + config.configKey(true) + " RSSI " + Integer.toString(rssi));
312f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            selected.connectChoices.put(config.configKey(true), rssi);
313f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
314f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.connectChoices != null) {
315f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)
316f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("updateSavedConfigurationsPriorities try to remove "
317f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + selected.configKey(true) + " from " + config.configKey(true));
318f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
319f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //remove the selected from the recently seen config's array
320f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                config.connectChoices.remove(selected.configKey(true));
321f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
322f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            printChoices(config);
323f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
324f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
325f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (selected.connectChoices != null) {
326f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG) logDbg("updateSavedConfigurationsPriorities " + Integer.toString(netId)
327f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + " now: " + Integer.toString(selected.connectChoices.size()));
328f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
329f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
330f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        mWifiConfigStore.writeKnownNetworkHistory();
331f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
332f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
333f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void printChoices(WifiConfiguration config) {
334f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int num = 0;
335f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (config.connectChoices!= null) {
336f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            num = config.connectChoices.size();
337f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
338f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
339f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        logDbg("printChoices " + config.SSID + " num choices: " + Integer.toString(num));
340f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (config.connectChoices!= null) {
341f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            for (String key : config.connectChoices.keySet()) {
342f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("                 " + key);
343f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
344f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
345f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
346f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
347f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
348f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    boolean hasConnectChoice(WifiConfiguration source, WifiConfiguration target) {
349f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean found = false;
350f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (source == null)
351f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return false;
352f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (target == null)
353f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return false;
354f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
355f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (source.connectChoices != null) {
356f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if ( source.connectChoices.get(target.configKey(true)) != null) {
357f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                found = true;
358f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
359f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
360f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
361f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (source.linkedConfigurations != null) {
362f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            for (String key : source.linkedConfigurations.keySet()) {
363f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                WifiConfiguration config = mWifiConfigStore.getWifiConfiguration(key);
364f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (config != null) {
365f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    if (config.connectChoices != null) {
366f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        if (config.connectChoices.get(target.configKey(true)) != null) {
367f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
368f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        }
369f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
370f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
371f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
372f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
373f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return found;
374f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
375f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
376f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    int compareWifiConfigurationsRSSI(WifiConfiguration a, WifiConfiguration b) {
377f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int order = 0;
378f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int boost5 = 25;
379f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
380f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration.Visibility astatus = a.visibility;
381f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration.Visibility bstatus = b.visibility;
382f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (astatus == null || bstatus == null) {
383f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //error
384f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("compareWifiConfigurations NULL band status!");
385f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return 0;
386f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
387f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if ((astatus.rssi5 > -70) && (bstatus.rssi5 == -127)
388f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                && ((astatus.rssi5+boost5) > (bstatus.rssi24))) {
389f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //a is seen on 5GHz with good RSSI, greater rssi than b
390f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //a is of higher priority - descending
391f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            order = -1;
392f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        } else if ((bstatus.rssi5 > -70) && (astatus.rssi5 == -127)
393f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                && ((bstatus.rssi5+boost5) > (bstatus.rssi24))) {
394f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //b is seen on 5GHz with good RSSI, greater rssi than a
395f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //a is of lower priority - ascending
396f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            order = 1;
397f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
398f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return order;
399f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
400f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
401f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    int compareWifiConfigurations(WifiConfiguration a, WifiConfiguration b) {
402f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int order = 0;
403f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
404f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean linked = false;
405f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
406f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if ((a.linkedConfigurations != null) && (b.linkedConfigurations != null)) {
407f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if ((a.linkedConfigurations.get(b.configKey(true))!= null)
408f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    && (b.linkedConfigurations.get(a.configKey(true))!= null)) {
409f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                linked = true;
410f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
411f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
412f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
413f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (a.ephemeral && b.ephemeral == false) {
414f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG) {
415f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations ephemeral and prefers " + b.SSID
416f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + " over " + a.SSID);
417f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
418f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return 1; //b is of higher priority - ascending
419f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
420f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (b.ephemeral && a.ephemeral == false) {
421f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG) {
422f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations ephemeral and prefers " +a.SSID
423f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + " over " + b.SSID);
424f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
425f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return -1; //a is of higher priority - descending
426f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
427f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
428f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int boost5 = 25;
429f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (linked) {
430f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            // then we try prefer 5GHz, and try to ignore user's choice
431f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            WifiConfiguration.Visibility astatus = a.visibility;
432f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            WifiConfiguration.Visibility bstatus = b.visibility;
433f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (astatus == null || bstatus == null) {
434f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //error
435f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations NULL band status!");
436f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                return 0;
437f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
438f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
439f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG)  {
440f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations linked: " + Integer.toString(astatus.rssi5)
441f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + "," + Integer.toString(astatus.rssi24) + "   "
442f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(bstatus.rssi5) + ","
443f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(bstatus.rssi24));
444f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
445f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
446f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if ((astatus.rssi5 > -70) && (bstatus.rssi5 == -127)
447f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    && ((astatus.rssi5+boost5) > (bstatus.rssi24))) {
448f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //a is seen on 5GHz with good RSSI, greater rssi than b
449f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //a is of higher priority - descending
450f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    order = -10;
451f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
452f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG) {
453f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("compareWifiConfigurations linked and prefers " + a.SSID
454f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + " over " + b.SSID
455f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + " due to 5GHz RSSI " + Integer.toString(astatus.rssi5)
456f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + " over: 5=" + Integer.toString(bstatus.rssi5)
457f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + ", 2.4=" + Integer.toString(bstatus.rssi5));
458f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
459f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else if ((bstatus.rssi5 > -70) && (astatus.rssi5 == -127)
460f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    && ((bstatus.rssi5+boost5) > (bstatus.rssi24))) {
461f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //b is seen on 5GHz with good RSSI, greater rssi than a
462f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //a is of lower priority - ascending
463f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)   {
464f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("compareWifiConfigurations linked and prefers " + b.SSID
465f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + " over " + a.SSID + " due to 5GHz RSSI "
466f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + Integer.toString(astatus.rssi5) + " over: 5="
467f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + Integer.toString(bstatus.rssi5) + ", 2.4="
468f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + Integer.toString(bstatus.rssi5));
469f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
470f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                order = 10;
471f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
472f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
473f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        //assuming that the WifiConfiguration aren't part of the same "extended roam domain",
474f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        //then compare by user's choice.
475f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (hasConnectChoice(a, b)) {
476f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //a is of higher priority - descending
477f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            order = order -2;
478f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG)   {
479f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations prefers -2 " + a.SSID
480f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + " over " + b.SSID + " due to user choice order -> " + Integer.toString(order));
481f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
482f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
483f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
484f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (hasConnectChoice(b, a)) {
485f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //a is of lower priority - ascending
486f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            order = order + 2;
487f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG)   {
488f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("compareWifiConfigurations prefers +2 " + b.SSID + " over "
489f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + a.SSID + " due to user choice order ->" + Integer.toString(order));
490f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
491f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
492f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
493f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (order == 0) {
494f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //we don't know anything - pick the last seen i.e. K behavior
495f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //we should do this only for recently picked configurations
496f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (a.priority > b.priority) {
497f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //a is of higher priority - descending
498f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)   {
499f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("compareWifiConfigurations prefers -1 " + a.SSID + " over "
500f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + b.SSID + " due to priority");
501f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
502f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
503f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                order = -1;
504f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else if (a.priority < b.priority) {
505f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //a is of lower priority - ascending
506f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)  {
507f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("compareWifiConfigurations prefers +1 " + b.SSID + " over "
508f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + a.SSID + " due to priority");
509f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
510f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
511f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle              order = 1;
512f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
513f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //maybe just look at RSSI or band
514f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)  {
515f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("compareWifiConfigurations prefers +1 " + b.SSID + " over "
516f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + a.SSID + " due to nothing");
517f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
518f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
519f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                order = compareWifiConfigurationsRSSI(a, b); //compare RSSI
520f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
521f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
522f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
523f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String sorder = " == ";
524f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (order > 0)
525f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            sorder = " < ";
526f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (order < 0)
527f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            sorder = " > ";
528f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
529f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (VDBG)   {
530f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("compareWifiConfigurations Done: " + a.SSID + sorder
531f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + b.SSID + " order " + Integer.toString(order));
532f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
533f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
534f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return order;
535f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
536f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
537f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /* attemptAutoJoin function implement the core of the a network switching algorithm */
538f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    void attemptAutoJoin() {
539f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        WifiConfiguration candidate = null;
540f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
541f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        /* obtain the subset of recently seen networks */
542f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        List<WifiConfiguration> list = mWifiConfigStore.getRecentConfiguredNetworks(3000, true);
543f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (list == null) {
544f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (VDBG)  logDbg("attemptAutoJoin nothing");
545f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return;
546f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
547f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
548f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        /* find the currently connected network: ask the supplicant directly */
549f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String val = mWifiNative.status();
550f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String status[] = val.split("\\r?\\n");
551f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (VDBG) {
552f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            logDbg("attemptAutoJoin() status=" + val + " split="
553f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + Integer.toString(status.length));
554f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
555f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
556f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int currentNetId = -1;
557f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        for (String key : status) {
558f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (key.regionMatches(0, "id=", 0, 3)) {
559f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int idx = 3;
560f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                currentNetId = 0;
561f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                while (idx < key.length()) {
562f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    char c = key.charAt(idx);
563f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
564f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    if ((c >= 0x30) && (c <= 0x39)) {
565f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        currentNetId *= 10;
566f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        currentNetId += c - 0x30;
567f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        idx++;
568f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    } else {
569f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        break;
570f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
571f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
572f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
573f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
574f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        logDbg("attemptAutoJoin() num recent config " + Integer.toString(list.size())
575f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                +  " ---> currentId=" + Integer.toString(currentNetId));
576f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
577f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        /* select Best Network candidate from known WifiConfigurations */
578f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        for (WifiConfiguration config : list) {
579f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if ((config.status == WifiConfiguration.Status.DISABLED)
580f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    && (config.disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE)) {
581f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("attemptAutoJoin skip candidate due to auth failure "
582f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + config.SSID + " key " + config.configKey(true));
583f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
584f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
585f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.autoJoinStatus != WifiConfiguration.AUTO_JOIN_ENABLED) {
586f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("attemptAutoJoin skip candidate due to auto join status "
587f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + Integer.toString(config.autoJoinStatus) + " " + config.SSID + " key "
588f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + config.configKey(true));
589f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
590f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
591f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
592f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (config.networkId == currentNetId) {
593f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("attemptAutoJoin skip current candidate  " + Integer.toString(currentNetId)
594f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + " key " + config.configKey(true));
595f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                continue;
596f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
597f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
598f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (DBG) logDbg("attemptAutoJoin trying candidate id=" + config.networkId + " "
599f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + config.SSID + " key " + config.configKey(true));
600f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
601f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (candidate == null) {
602f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                candidate = config;
603f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            } else {
604f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG)  {
605f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("attemptAutoJoin will compare candidate  " + candidate.SSID
606f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            + " with " + config.SSID + " key " + config.configKey(true));
607f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
608f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
609f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int order = compareWifiConfigurations(candidate, config);
610f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
611f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (VDBG) {
612f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    logDbg("attemptAutoJoin did compare candidate " + Integer.toString(order));
613f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
614f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
615f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (order > 0) {
616f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //ascending : candidate < config
617f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    candidate = config;
618f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
619f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
620f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
621f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
622f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        /* now, go thru scan result to try finding a better Herrevad network */
623f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (mNetworkScoreCache != null) {
624f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            int rssi5 = WifiConfiguration.INVALID_RSSI;
625f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            int rssi24 = WifiConfiguration.INVALID_RSSI;
626f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            WifiConfiguration.Visibility visibility;
627f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (candidate != null) {
628f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                rssi5 = candidate.visibility.rssi5;
629f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                rssi24 = candidate.visibility.rssi24;
630f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
631f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
632f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //get current date
633f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            Date now = new Date();
634f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            long now_ms = now.getTime();
635f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
636f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (rssi5 < -60 && rssi24 < -70) {
637f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                for (ScanResult result : scanResultCache.values()) {
638f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    if ((now_ms - result.seen) < 3000) {
639f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        int score = mNetworkScoreCache.getNetworkScore(result);
640f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        if (score > 0) {
641f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            // try any arbitrary formula for now, adding apple and oranges,
642f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            // i.e. adding network score and "dBm over noise"
643f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                           if (result.frequency < 4000) {
644f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                if ((result.level + score) > (rssi24 -40)) {
645f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    // force it as open, TBD should we otherwise verify that this
646f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    // BSSID only supports open??
647f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    result.capabilities = "";
648f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
649f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    //switch to this scan result
650f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    candidate =
651f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                            mWifiConfigStore.wifiConfigurationFromScanResult(result);
652f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    candidate.ephemeral = true;
653f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                }
654f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                           } else {
655f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                if ((result.level + score) > (rssi5 -30)) {
656f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    // force it as open, TBD should we otherwise verify that this
657f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    // BSSID only supports open??
658f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    result.capabilities = "";
659f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
660f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    //switch to this scan result
661f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    candidate =
662f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                            mWifiConfigStore.wifiConfigurationFromScanResult(result);
663f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                    candidate.ephemeral = true;
664f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                }
665f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                           }
666f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        }
667f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
668f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
669f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
670f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
671f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
672f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (candidate != null) {
673f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle	    /* if candidate is found, check the state of the connection so as
674f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle	       to decide if we should be acting on this candidate and switching over */
675f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle           if (VDBG) {
676f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle               logDbg("attemptAutoJoin did find candidate " + candidate.SSID
677f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                       + " key " + candidate.configKey(true));
678f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle           }
679f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
680f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            int networkDelta = compareNetwork(candidate);
681f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (networkDelta > 0)
682f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                logDbg("attemptAutoJoin did find candidate " + candidate.SSID
683f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        + " for delta " + Integer.toString(networkDelta));
684f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
685f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            /* ASK traffic poller permission to switch:
686f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                for instance,
687f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if user is currently streaming voice traffic,
688f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                then don’t switch regardless of the delta */
689f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
690f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (mWifiTrafficPoller.shouldSwitchNetwork(networkDelta)) {
691f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (mStaStaSupported) {
692f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
693f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                } else {
694f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    if (DBG) {
695f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        logDbg("AutoJoin auto connect to netId "
696f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                + Integer.toString(candidate.networkId)
697f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                                + " SSID " + candidate.SSID);
698f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
699f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
700f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    mWifiStateMachine.sendMessage(WifiStateMachine.CMD_AUTO_CONNECT,
701f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            candidate.networkId);
702f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //mWifiConfigStore.enableNetworkWithoutBroadcast(candidate.networkId, true);
703f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
704f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //we would do the below only if we want to persist the new choice
705f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //mWifiConfigStore.selectNetwork(candidate.networkId);
706f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
707f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
708f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
709f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
710f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (VDBG) logDbg("Done attemptAutoJoin");
711f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
712f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle}
713f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
714