WifiConnectivityManager.java revision 3d09b9117df33608a43c1fbe0135123e2de9aea2
184d962ec8f487f824214744498bba505a6db0c59Randy Pan/* 284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Copyright (C) 2016 The Android Open Source Project 384d962ec8f487f824214744498bba505a6db0c59Randy Pan * 484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Licensed under the Apache License, Version 2.0 (the "License"); 584d962ec8f487f824214744498bba505a6db0c59Randy Pan * you may not use this file except in compliance with the License. 684d962ec8f487f824214744498bba505a6db0c59Randy Pan * You may obtain a copy of the License at 784d962ec8f487f824214744498bba505a6db0c59Randy Pan * 884d962ec8f487f824214744498bba505a6db0c59Randy Pan * http://www.apache.org/licenses/LICENSE-2.0 984d962ec8f487f824214744498bba505a6db0c59Randy Pan * 1084d962ec8f487f824214744498bba505a6db0c59Randy Pan * Unless required by applicable law or agreed to in writing, software 1184d962ec8f487f824214744498bba505a6db0c59Randy Pan * distributed under the License is distributed on an "AS IS" BASIS, 1284d962ec8f487f824214744498bba505a6db0c59Randy Pan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1384d962ec8f487f824214744498bba505a6db0c59Randy Pan * See the License for the specific language governing permissions and 1484d962ec8f487f824214744498bba505a6db0c59Randy Pan * limitations under the License. 1584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 1684d962ec8f487f824214744498bba505a6db0c59Randy Pan 1784d962ec8f487f824214744498bba505a6db0c59Randy Panpackage com.android.server.wifi; 1884d962ec8f487f824214744498bba505a6db0c59Randy Pan 1948444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Willsimport static com.android.server.wifi.WifiStateMachine.WIFI_WORK_SOURCE; 2048444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills 2184d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.app.ActivityManager; 2284d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.app.AlarmManager; 2384d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.content.Context; 2484d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.ScanResult; 25eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Panimport android.net.wifi.SupplicantState; 2684d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiConfiguration; 2784d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiInfo; 2884d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiManager; 2984d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner; 3084d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.PnoSettings; 3184d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.ScanSettings; 32c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Panimport android.os.Handler; 33c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Panimport android.os.Looper; 3484d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.util.LocalLog; 3584d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.util.Log; 3684d962ec8f487f824214744498bba505a6db0c59Randy Pan 3784d962ec8f487f824214744498bba505a6db0c59Randy Panimport com.android.internal.R; 383d09b9117df33608a43c1fbe0135123e2de9aea2Randy Panimport com.android.internal.annotations.VisibleForTesting; 3984d962ec8f487f824214744498bba505a6db0c59Randy Panimport com.android.server.wifi.util.ScanDetailUtil; 4084d962ec8f487f824214744498bba505a6db0c59Randy Pan 4184d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.io.FileDescriptor; 4284d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.io.PrintWriter; 4384d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.ArrayList; 444f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Piusimport java.util.Iterator; 454f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Piusimport java.util.LinkedList; 4684d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.List; 4784d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.Set; 4884d962ec8f487f824214744498bba505a6db0c59Randy Pan 4984d962ec8f487f824214744498bba505a6db0c59Randy Pan/** 5084d962ec8f487f824214744498bba505a6db0c59Randy Pan * This class manages all the connectivity related scanning activities. 5184d962ec8f487f824214744498bba505a6db0c59Randy Pan * 5284d962ec8f487f824214744498bba505a6db0c59Randy Pan * When the screen is turned on or off, WiFi is connected or disconnected, 5384d962ec8f487f824214744498bba505a6db0c59Randy Pan * or on-demand, a scan is initiatiated and the scan results are passed 5484d962ec8f487f824214744498bba505a6db0c59Randy Pan * to QNS for it to make a recommendation on which network to connect to. 5584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 5684d962ec8f487f824214744498bba505a6db0c59Randy Panpublic class WifiConnectivityManager { 5784d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final String TAG = "WifiConnectivityManager"; 5884d962ec8f487f824214744498bba505a6db0c59Randy Pan 5984d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan interval in milli-seconds. This is the scan 6084d962ec8f487f824214744498bba505a6db0c59Randy Pan // performed when screen is on. 614f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int PERIODIC_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds 6284d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO scan interval in milli-seconds. This is the scan 6379e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // performed when screen is off and disconnected. 644f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int DISCONNECTED_PNO_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds 6579e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // PNO scan interval in milli-seconds. This is the scan 6679e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // performed when screen is off and connected. 674f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int CONNECTED_PNO_SCAN_INTERVAL_MS = 160 * 1000; // 160 seconds 683d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // When a network is found by PNO scan but gets rejected by QNS due to its 693d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // low RSSI value, scan will be reschduled in an exponential back off manner. 703d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private static final int LOW_RSSI_NETWORK_RETRY_START_DELAY_MS = 20 * 1000; // 20 seconds 713d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private static final int LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS = 80 * 1000; // 80 seconds 7284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Maximum number of retries when starting a scan failed 7384d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final int MAX_SCAN_RESTART_ALLOWED = 5; 7484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Number of milli-seconds to delay before retry starting 7584d962ec8f487f824214744498bba505a6db0c59Randy Pan // a previously failed scan 764f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int RESTART_SCAN_DELAY_MS = 2 * 1000; // 2 seconds 7784d962ec8f487f824214744498bba505a6db0c59Randy Pan // When in disconnected mode, a watchdog timer will be fired 7884d962ec8f487f824214744498bba505a6db0c59Randy Pan // every WATCHDOG_INTERVAL_MS to start a single scan. This is 7984d962ec8f487f824214744498bba505a6db0c59Randy Pan // to prevent caveat from things like PNO scan. 804f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int WATCHDOG_INTERVAL_MS = 20 * 60 * 1000; // 20 minutes 814f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // This is the time interval for the connection attempt rate calculation. Connection attempt 824f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // timestamps beyond this interval is evicted from the list. 83fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public static final int MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS = 4 * 60 * 1000; // 4 mins 844f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // Max number of connection attempts in the above time interval. 85fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public static final int MAX_CONNECTION_ATTEMPTS_RATE = 6; 8684d962ec8f487f824214744498bba505a6db0c59Randy Pan 8784d962ec8f487f824214744498bba505a6db0c59Randy Pan // WifiStateMachine has a bunch of states. From the 8884d962ec8f487f824214744498bba505a6db0c59Randy Pan // WifiConnectivityManager's perspective it only cares 8984d962ec8f487f824214744498bba505a6db0c59Randy Pan // if it is in Connected state, Disconnected state or in 9084d962ec8f487f824214744498bba505a6db0c59Randy Pan // transition between these two states. 9184d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_UNKNOWN = 0; 9284d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_CONNECTED = 1; 9384d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_DISCONNECTED = 2; 9484d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_TRANSITIONING = 3; 9584d962ec8f487f824214744498bba505a6db0c59Randy Pan 9679e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // Due to b/28020168, timer based single scan will be scheduled every 9779e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // PERIODIC_SCAN_INTERVAL_MS to provide periodic scan. 987ce0f144104c68da40c196c16f73e2d0bcc50cc7Roshan Pius private static final boolean ENABLE_BACKGROUND_SCAN = false; 9979e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // Flag to turn on connected PNO, when needed 1007ce0f144104c68da40c196c16f73e2d0bcc50cc7Roshan Pius private static final boolean ENABLE_CONNECTED_PNO_SCAN = false; 10179e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius 10284d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiStateMachine mStateMachine; 10384d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiScanner mScanner; 10484d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiConfigManager mConfigManager; 10584d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiInfo mWifiInfo; 10684d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiQualifiedNetworkSelector mQualifiedNetworkSelector; 10709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne private final WifiLastResortWatchdog mWifiLastResortWatchdog; 108fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final AlarmManager mAlarmManager; 109c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan private final Handler mEventHandler; 110fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final Clock mClock; 111fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final LocalLog mLocalLog = 112fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 1024 : 16384); 1134f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private final LinkedList<Long> mConnectionAttemptTimeStamps; 114fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 11584d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mDbg = false; 11684d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mWifiEnabled = false; 117466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan private boolean mWifiConnectivityManagerEnabled = true; 11884d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mForceSelectNetwork = false; 11984d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mScreenOn = false; 12084d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mWifiState = WIFI_STATE_UNKNOWN; 12184d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mUntrustedConnectionAllowed = false; 12284d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mScanRestartCount = 0; 12384d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSingleScanRestartCount = 0; 124d54ddacc42d9cd929d40b1df391895293bacafe2Roshan Pius private int mTotalConnectivityAttemptsRateLimited = 0; 12584d962ec8f487f824214744498bba505a6db0c59Randy Pan 12684d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO settings 12784d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mMin5GHzRssi; 12884d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mMin24GHzRssi; 12984d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mInitialScoreMax; 13084d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mCurrentConnectionBonus; 13184d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSameNetworkBonus; 13284d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSecureBonus; 13384d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mBand5GHzBonus; 13484d962ec8f487f824214744498bba505a6db0c59Randy Pan 13584d962ec8f487f824214744498bba505a6db0c59Randy Pan // A helper to log debugging information in the local log buffer, which can 13684d962ec8f487f824214744498bba505a6db0c59Randy Pan // be retrieved in bugreport. 13784d962ec8f487f824214744498bba505a6db0c59Randy Pan private void localLog(String log) { 13884d962ec8f487f824214744498bba505a6db0c59Randy Pan mLocalLog.log(log); 13984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 14084d962ec8f487f824214744498bba505a6db0c59Randy Pan 14184d962ec8f487f824214744498bba505a6db0c59Randy Pan // A periodic/PNO scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times 14284d962ec8f487f824214744498bba505a6db0c59Randy Pan // if the start scan command failed. An timer is used here to make it a deferred retry. 14384d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mRestartScanListener = 14484d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 14584d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 14684d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(mForceSelectNetwork); 14784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 14884d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 14984d962ec8f487f824214744498bba505a6db0c59Randy Pan 15084d962ec8f487f824214744498bba505a6db0c59Randy Pan // A single scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times 15184d962ec8f487f824214744498bba505a6db0c59Randy Pan // if the start scan command failed. An timer is used here to make it a deferred retry. 15284d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mRestartSingleScanListener = 15384d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 15484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 15584d962ec8f487f824214744498bba505a6db0c59Randy Pan startSingleScan(); 15684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 15784d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 15884d962ec8f487f824214744498bba505a6db0c59Randy Pan 15984d962ec8f487f824214744498bba505a6db0c59Randy Pan // As a watchdog mechanism, a single scan will be scheduled every WATCHDOG_INTERVAL_MS 16084d962ec8f487f824214744498bba505a6db0c59Randy Pan // if it is in the WIFI_STATE_DISCONNECTED state. 16184d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mWatchdogListener = 16284d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 16384d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 16484d962ec8f487f824214744498bba505a6db0c59Randy Pan watchdogHandler(); 16584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 16684d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 16784d962ec8f487f824214744498bba505a6db0c59Randy Pan 16884d962ec8f487f824214744498bba505a6db0c59Randy Pan // Due to b/28020168, timer based single scan will be scheduled every 16984d962ec8f487f824214744498bba505a6db0c59Randy Pan // PERIODIC_SCAN_INTERVAL_MS to provide periodic scan. 17084d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mPeriodicScanTimerListener = 17184d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 17284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 17384d962ec8f487f824214744498bba505a6db0c59Randy Pan periodicScanTimerHandler(); 17484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 17584d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 17684d962ec8f487f824214744498bba505a6db0c59Randy Pan 17709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne /** 17809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener. 17909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * Executes selection of potential network candidates, initiation of connection attempt to that 18009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * network. 1813d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * 1823d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * @return true - if a candidate is selected by QNS 1833d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * false - if no candidate is selected by QNS 18409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne */ 1853d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) { 18609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne localLog(listenerName + " onResults: start QNS"); 18709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiConfiguration candidate = 18809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mQualifiedNetworkSelector.selectQualifiedNetwork(mForceSelectNetwork, 18909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mUntrustedConnectionAllowed, scanDetails, 19009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isLinkDebouncing(), mStateMachine.isConnected(), 19109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isDisconnected(), 19209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isSupplicantTransientState()); 19309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiLastResortWatchdog.updateAvailableNetworks( 19409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mQualifiedNetworkSelector.getFilteredScanDetails()); 19509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne if (candidate != null) { 19609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne localLog(listenerName + ": QNS candidate-" + candidate.SSID); 19709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne connectToNetwork(candidate); 1983d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return true; 1993d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } else { 2003d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return false; 20109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne } 20209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne } 20309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne 20484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan results listener. A periodic scan is initiated when 20584d962ec8f487f824214744498bba505a6db0c59Randy Pan // screen is on. 20684d962ec8f487f824214744498bba505a6db0c59Randy Pan private class PeriodicScanListener implements WifiScanner.ScanListener { 20784d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 20884d962ec8f487f824214744498bba505a6db0c59Randy Pan 20984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 21084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 21184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 21284d962ec8f487f824214744498bba505a6db0c59Randy Pan 21384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 21484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 21584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onSuccess"); 21684d962ec8f487f824214744498bba505a6db0c59Randy Pan 21784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 21884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 21984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 22084d962ec8f487f824214744498bba505a6db0c59Randy Pan 22184d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 22284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 22384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "PeriodicScanListener onFailure:" 22484d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 22584d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 22684d962ec8f487f824214744498bba505a6db0c59Randy Pan 22784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 22884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 2293d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(RESTART_SCAN_DELAY_MS); 23084d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 23184d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 23284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start periodic scan for " 23384d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 23484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 23584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 23684d962ec8f487f824214744498bba505a6db0c59Randy Pan 23784d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 23884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 23984d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onPeriodChanged: " 24084d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 24184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 24284d962ec8f487f824214744498bba505a6db0c59Randy Pan 24384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 24484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 24509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne handleScanResults(mScanDetails, "PeriodicScanListener"); 24684d962ec8f487f824214744498bba505a6db0c59Randy Pan clearScanDetails(); 24784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 24884d962ec8f487f824214744498bba505a6db0c59Randy Pan 24984d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 25084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 25184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mDbg) { 25284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onFullResult: " 25384d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.SSID + " capabilities " 25484d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.capabilities); 25584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 25684d962ec8f487f824214744498bba505a6db0c59Randy Pan 25784d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(fullScanResult)); 25884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 25984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 26084d962ec8f487f824214744498bba505a6db0c59Randy Pan 26184d962ec8f487f824214744498bba505a6db0c59Randy Pan private final PeriodicScanListener mPeriodicScanListener = new PeriodicScanListener(); 26284d962ec8f487f824214744498bba505a6db0c59Randy Pan 26384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Single scan results listener. A single scan is initiated when 26484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disconnected/ConnectedPNO scan found a valid network and woke up 26584d962ec8f487f824214744498bba505a6db0c59Randy Pan // the system, or by the watchdog timer. 26684d962ec8f487f824214744498bba505a6db0c59Randy Pan private class SingleScanListener implements WifiScanner.ScanListener { 26784d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 26884d962ec8f487f824214744498bba505a6db0c59Randy Pan 26984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 27084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 27184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 27284d962ec8f487f824214744498bba505a6db0c59Randy Pan 27384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 27484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 27584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onSuccess"); 27684d962ec8f487f824214744498bba505a6db0c59Randy Pan 27784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 27884d962ec8f487f824214744498bba505a6db0c59Randy Pan mSingleScanRestartCount = 0; 27984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 28084d962ec8f487f824214744498bba505a6db0c59Randy Pan 28184d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 28284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 28384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "SingleScanListener onFailure:" 28484d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 28584d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 28684d962ec8f487f824214744498bba505a6db0c59Randy Pan 28784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 28884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mSingleScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 28984d962ec8f487f824214744498bba505a6db0c59Randy Pan scheduleDelayedSingleScan(); 29084d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 29184d962ec8f487f824214744498bba505a6db0c59Randy Pan mSingleScanRestartCount = 0; 29284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start single scan for " 29384d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 29484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 29584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 29684d962ec8f487f824214744498bba505a6db0c59Randy Pan 29784d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 29884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 29984d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onPeriodChanged: " 30084d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 30184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 30284d962ec8f487f824214744498bba505a6db0c59Randy Pan 30384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 30484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 30509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne handleScanResults(mScanDetails, "SingleScanListener"); 306224198c8ba46f362a5df6d25f1b60e56f442b58bRoshan Pius clearScanDetails(); 30784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 30884d962ec8f487f824214744498bba505a6db0c59Randy Pan 30984d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 31084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 31184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mDbg) { 31284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onFullResult: " 31384d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.SSID + " capabilities " 31484d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.capabilities); 31584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 31684d962ec8f487f824214744498bba505a6db0c59Randy Pan 31784d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(fullScanResult)); 31884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 31984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 32084d962ec8f487f824214744498bba505a6db0c59Randy Pan 32184d962ec8f487f824214744498bba505a6db0c59Randy Pan // re-enable this when b/27695292 is fixed 32284d962ec8f487f824214744498bba505a6db0c59Randy Pan // private final SingleScanListener mSingleScanListener = new SingleScanListener(); 32384d962ec8f487f824214744498bba505a6db0c59Randy Pan 32484d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO scan results listener for both disconected and connected PNO scanning. 32584d962ec8f487f824214744498bba505a6db0c59Randy Pan // A PNO scan is initiated when screen is off. 32684d962ec8f487f824214744498bba505a6db0c59Randy Pan private class PnoScanListener implements WifiScanner.PnoScanListener { 32784d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 3283d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private int mLowRssiNetworkRetryDelay = 3293d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; 33084d962ec8f487f824214744498bba505a6db0c59Randy Pan 33184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 33284d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 33384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 33484d962ec8f487f824214744498bba505a6db0c59Randy Pan 3353d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Reset to the start value when either a non-PNO scan is started or 3363d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // QNS selects a candidate from the PNO scan results. 3373d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan public void resetLowRssiNetworkRetryDelay() { 3383d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; 3393d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 3403d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 3413d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan @VisibleForTesting 3423d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan public int getLowRssiNetworkRetryDelay() { 3433d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return mLowRssiNetworkRetryDelay; 3443d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 3453d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 34684d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 34784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 34884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener onSuccess"); 34984d962ec8f487f824214744498bba505a6db0c59Randy Pan 35084d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 35184d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 35284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 35384d962ec8f487f824214744498bba505a6db0c59Randy Pan 35484d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 35584d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 35684d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "PnoScanListener onFailure:" 35784d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 35884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 35984d962ec8f487f824214744498bba505a6db0c59Randy Pan 36084d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 36184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 3623d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(RESTART_SCAN_DELAY_MS); 36384d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 36484d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 36584d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start PNO scan for " 36684d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 36784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 36884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 36984d962ec8f487f824214744498bba505a6db0c59Randy Pan 37084d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 37184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 37284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener onPeriodChanged: " 37384d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 37484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 37584d962ec8f487f824214744498bba505a6db0c59Randy Pan 37684d962ec8f487f824214744498bba505a6db0c59Randy Pan // Currently the PNO scan results doesn't include IE, 37784d962ec8f487f824214744498bba505a6db0c59Randy Pan // which contains information required by QNS. Ignore them 37884d962ec8f487f824214744498bba505a6db0c59Randy Pan // for now. 37984d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 38084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 38184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 38284d962ec8f487f824214744498bba505a6db0c59Randy Pan 38384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 38484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 38584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 38684d962ec8f487f824214744498bba505a6db0c59Randy Pan 38784d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 38884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPnoNetworkFound(ScanResult[] results) { 38984d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener: onPnoNetworkFound: results len = " + results.length); 39084d962ec8f487f824214744498bba505a6db0c59Randy Pan 39184d962ec8f487f824214744498bba505a6db0c59Randy Pan for (ScanResult result: results) { 39284d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(result)); 39384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 3943d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 3953d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan boolean wasConnectAttempted; 3963d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan wasConnectAttempted = handleScanResults(mScanDetails, "PnoScanListener"); 397224198c8ba46f362a5df6d25f1b60e56f442b58bRoshan Pius clearScanDetails(); 3983d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 3993d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan if (!wasConnectAttempted) { 4003d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // The scan results were rejected by QNS due to low RSSI values 4013d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan if (mLowRssiNetworkRetryDelay > LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS) { 4023d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS; 4033d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 4043d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(mLowRssiNetworkRetryDelay); 4053d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4063d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set up the delay value for next retry. 4073d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay *= 2; 4083d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } else { 4093d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan resetLowRssiNetworkRetryDelay(); 4103d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 41184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 41284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 41384d962ec8f487f824214744498bba505a6db0c59Randy Pan 41484d962ec8f487f824214744498bba505a6db0c59Randy Pan private final PnoScanListener mPnoScanListener = new PnoScanListener(); 41584d962ec8f487f824214744498bba505a6db0c59Randy Pan 41684d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 41784d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiConnectivityManager constructor 41884d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 41984d962ec8f487f824214744498bba505a6db0c59Randy Pan public WifiConnectivityManager(Context context, WifiStateMachine stateMachine, 42084d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiScanner scanner, WifiConfigManager configManager, WifiInfo wifiInfo, 42109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiQualifiedNetworkSelector qualifiedNetworkSelector, 422c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan WifiInjector wifiInjector, Looper looper) { 42384d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine = stateMachine; 42484d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner = scanner; 42584d962ec8f487f824214744498bba505a6db0c59Randy Pan mConfigManager = configManager; 42684d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiInfo = wifiInfo; 427fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mQualifiedNetworkSelector = qualifiedNetworkSelector; 42809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiLastResortWatchdog = wifiInjector.getWifiLastResortWatchdog(); 429fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 430c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mEventHandler = new Handler(looper); 431fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mClock = wifiInjector.getClock(); 4324f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius mConnectionAttemptTimeStamps = new LinkedList<>(); 43384d962ec8f487f824214744498bba505a6db0c59Randy Pan 43484d962ec8f487f824214744498bba505a6db0c59Randy Pan mMin5GHzRssi = WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI; 43584d962ec8f487f824214744498bba505a6db0c59Randy Pan mMin24GHzRssi = WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI; 43684d962ec8f487f824214744498bba505a6db0c59Randy Pan mBand5GHzBonus = WifiQualifiedNetworkSelector.BAND_AWARD_5GHz; 43773a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan mCurrentConnectionBonus = mConfigManager.mCurrentNetworkBoost.get(); 43884d962ec8f487f824214744498bba505a6db0c59Randy Pan mSameNetworkBonus = context.getResources().getInteger( 43984d962ec8f487f824214744498bba505a6db0c59Randy Pan R.integer.config_wifi_framework_SAME_BSSID_AWARD); 44084d962ec8f487f824214744498bba505a6db0c59Randy Pan mSecureBonus = context.getResources().getInteger( 44184d962ec8f487f824214744498bba505a6db0c59Randy Pan R.integer.config_wifi_framework_SECURITY_AWARD); 44273a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan mInitialScoreMax = (mConfigManager.mThresholdSaturatedRssi24.get() 44384d962ec8f487f824214744498bba505a6db0c59Randy Pan + WifiQualifiedNetworkSelector.RSSI_SCORE_OFFSET) 44484d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiQualifiedNetworkSelector.RSSI_SCORE_SLOPE; 44584d962ec8f487f824214744498bba505a6db0c59Randy Pan 44684d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "PNO settings:" + " min5GHzRssi " + mMin5GHzRssi 44784d962ec8f487f824214744498bba505a6db0c59Randy Pan + " min24GHzRssi " + mMin24GHzRssi 44884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " currentConnectionBonus " + mCurrentConnectionBonus 44984d962ec8f487f824214744498bba505a6db0c59Randy Pan + " sameNetworkBonus " + mSameNetworkBonus 45084d962ec8f487f824214744498bba505a6db0c59Randy Pan + " secureNetworkBonus " + mSecureBonus 45184d962ec8f487f824214744498bba505a6db0c59Randy Pan + " initialScoreMax " + mInitialScoreMax); 45284d962ec8f487f824214744498bba505a6db0c59Randy Pan 45384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "ConnectivityScanManager initialized "); 45484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 45584d962ec8f487f824214744498bba505a6db0c59Randy Pan 45684d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 4574f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * This checks the connection attempt rate and recommends whether the connection attempt 4584f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * should be skipped or not. This attempts to rate limit the rate of connections to 4594f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * prevent us from flapping between networks and draining battery rapidly. 4604f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 4614f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private boolean shouldSkipConnectionAttempt(Long currentTimeMillis) { 4624f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius Iterator<Long> attemptIter = mConnectionAttemptTimeStamps.iterator(); 4634f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // First evict old entries from the queue. 464c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan while (attemptIter.hasNext()) { 4654f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius Long connectionAttemptTimeMillis = attemptIter.next(); 466c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan if ((currentTimeMillis - connectionAttemptTimeMillis) 467c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan > MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS) { 4684f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius attemptIter.remove(); 4694f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } else { 4704f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // This list is sorted by timestamps, so we can skip any more checks 4714f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius break; 4724f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 4734f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 4744f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // If we've reached the max connection attempt rate, skip this connection attempt 4754f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius return (mConnectionAttemptTimeStamps.size() >= MAX_CONNECTION_ATTEMPTS_RATE); 4764f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 4774f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 4784f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 4794f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * Add the current connection attempt timestamp to our queue of connection attempts. 4804f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 4814f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private void noteConnectionAttempt(Long currentTimeMillis) { 4824f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius mConnectionAttemptTimeStamps.addLast(currentTimeMillis); 4834f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 4844f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 4854f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 4864f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * This is used to clear the connection attempt rate limiter. This is done when the user 4874f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * explicitly tries to connect to a specified network. 4884f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 4894f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private void clearConnectionAttemptTimeStamps() { 4904f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius mConnectionAttemptTimeStamps.clear(); 4914f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 4924f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 4934f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 49484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Attempt to connect to a network candidate. 49584d962ec8f487f824214744498bba505a6db0c59Randy Pan * 49684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Based on the currently connected network, this menthod determines whether we should 49784d962ec8f487f824214744498bba505a6db0c59Randy Pan * connect or roam to the network candidate recommended by QNS. 49884d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 49984d962ec8f487f824214744498bba505a6db0c59Randy Pan private void connectToNetwork(WifiConfiguration candidate) { 50084d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); 50184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (scanResultCandidate == null) { 50284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "connectToNetwork: bad candidate - " + candidate 50384d962ec8f487f824214744498bba505a6db0c59Randy Pan + " scanResult: " + scanResultCandidate); 50484d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 50584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 50684d962ec8f487f824214744498bba505a6db0c59Randy Pan 50784d962ec8f487f824214744498bba505a6db0c59Randy Pan String targetBssid = scanResultCandidate.BSSID; 50884d962ec8f487f824214744498bba505a6db0c59Randy Pan String targetAssociationId = candidate.SSID + " : " + targetBssid; 509eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan if (targetBssid != null && targetBssid.equals(mWifiInfo.getBSSID()) 510eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan && SupplicantState.isConnecting(mWifiInfo.getSupplicantState())) { 511eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan localLog("connectToNetwork: Either already connected " 512eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan + "or is connecting to " + targetAssociationId); 51384d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 51484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 51584d962ec8f487f824214744498bba505a6db0c59Randy Pan 516fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius Long currentTimeMillis = mClock.currentTimeMillis(); 5174f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius if (!mScreenOn && shouldSkipConnectionAttempt(currentTimeMillis)) { 5184f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius localLog("connectToNetwork: Too many connection attempts. Skipping this attempt!"); 519d54ddacc42d9cd929d40b1df391895293bacafe2Roshan Pius mTotalConnectivityAttemptsRateLimited++; 5204f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius return; 5214f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5224f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius noteConnectionAttempt(currentTimeMillis); 5234f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 52484d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConfiguration currentConnectedNetwork = mConfigManager 52584d962ec8f487f824214744498bba505a6db0c59Randy Pan .getWifiConfiguration(mWifiInfo.getNetworkId()); 52684d962ec8f487f824214744498bba505a6db0c59Randy Pan String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : 52784d962ec8f487f824214744498bba505a6db0c59Randy Pan (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); 52884d962ec8f487f824214744498bba505a6db0c59Randy Pan 52984d962ec8f487f824214744498bba505a6db0c59Randy Pan if (currentConnectedNetwork != null 53084d962ec8f487f824214744498bba505a6db0c59Randy Pan && (currentConnectedNetwork.networkId == candidate.networkId 53184d962ec8f487f824214744498bba505a6db0c59Randy Pan || currentConnectedNetwork.isLinked(candidate))) { 53284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("connectToNetwork: Roaming from " + currentAssociationId + " to " 53384d962ec8f487f824214744498bba505a6db0c59Randy Pan + targetAssociationId); 53484d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine.autoRoamToNetwork(candidate.networkId, scanResultCandidate); 53584d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 53684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("connectToNetwork: Reconnect from " + currentAssociationId + " to " 53784d962ec8f487f824214744498bba505a6db0c59Randy Pan + targetAssociationId); 53884d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine.autoConnectToNetwork(candidate.networkId, scanResultCandidate.BSSID); 53984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 54084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 54184d962ec8f487f824214744498bba505a6db0c59Randy Pan 54284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Helper for selecting the band for connectivity scan 54384d962ec8f487f824214744498bba505a6db0c59Randy Pan private int getScanBand() { 54484d962ec8f487f824214744498bba505a6db0c59Randy Pan int freqBand = mStateMachine.getFrequencyBand(); 54584d962ec8f487f824214744498bba505a6db0c59Randy Pan if (freqBand == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) { 54684d962ec8f487f824214744498bba505a6db0c59Randy Pan return WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS; 54784d962ec8f487f824214744498bba505a6db0c59Randy Pan } else if (freqBand == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) { 54884d962ec8f487f824214744498bba505a6db0c59Randy Pan return WifiScanner.WIFI_BAND_24_GHZ; 54984d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 55084d962ec8f487f824214744498bba505a6db0c59Randy Pan return WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 55184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 55284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 55384d962ec8f487f824214744498bba505a6db0c59Randy Pan 55484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Watchdog timer handler 55584d962ec8f487f824214744498bba505a6db0c59Randy Pan private void watchdogHandler() { 55684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("watchdogHandler"); 55784d962ec8f487f824214744498bba505a6db0c59Randy Pan 55884d962ec8f487f824214744498bba505a6db0c59Randy Pan // Schedule the next timer and start a single scan if we are in disconnected state. 55984d962ec8f487f824214744498bba505a6db0c59Randy Pan // Otherwise, the watchdog timer will be scheduled when entering disconnected 56084d962ec8f487f824214744498bba505a6db0c59Randy Pan // state. 56184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_DISCONNECTED) { 56284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "start a single scan from watchdogHandler"); 56384d962ec8f487f824214744498bba505a6db0c59Randy Pan 56484d962ec8f487f824214744498bba505a6db0c59Randy Pan scheduleWatchdogTimer(); 56584d962ec8f487f824214744498bba505a6db0c59Randy Pan startSingleScan(); 56684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 56784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 56884d962ec8f487f824214744498bba505a6db0c59Randy Pan 56984d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan timer handler 57084d962ec8f487f824214744498bba505a6db0c59Randy Pan private void periodicScanTimerHandler() { 57184d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("periodicScanTimerHandler"); 57284d962ec8f487f824214744498bba505a6db0c59Randy Pan 57384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Schedule the next timer and start a single scan if screen is on. 57484d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScreenOn) { 57584d962ec8f487f824214744498bba505a6db0c59Randy Pan schedulePeriodicScanTimer(); 57684d962ec8f487f824214744498bba505a6db0c59Randy Pan startSingleScan(); 57784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 57884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 57984d962ec8f487f824214744498bba505a6db0c59Randy Pan 5803d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Start a single scan 58184d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startSingleScan() { 582466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) { 58384d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 58484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 58584d962ec8f487f824214744498bba505a6db0c59Randy Pan 5863d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mPnoScanListener.resetLowRssiNetworkRetryDelay(); 5873d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 58884d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings settings = new ScanSettings(); 58984d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.band = getScanBand(); 59084d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT 59184d962ec8f487f824214744498bba505a6db0c59Randy Pan | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 59284d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.numBssidsPerScan = 0; 59384d962ec8f487f824214744498bba505a6db0c59Randy Pan 59484d962ec8f487f824214744498bba505a6db0c59Randy Pan //Retrieve the list of hidden networkId's to scan for. 59584d962ec8f487f824214744498bba505a6db0c59Randy Pan Set<Integer> hiddenNetworkIds = mConfigManager.getHiddenConfiguredNetworkIds(); 59684d962ec8f487f824214744498bba505a6db0c59Randy Pan if (hiddenNetworkIds != null && hiddenNetworkIds.size() > 0) { 59784d962ec8f487f824214744498bba505a6db0c59Randy Pan int i = 0; 59884d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.hiddenNetworkIds = new int[hiddenNetworkIds.size()]; 59984d962ec8f487f824214744498bba505a6db0c59Randy Pan for (Integer netId : hiddenNetworkIds) { 60084d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.hiddenNetworkIds[i++] = netId; 60184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 60284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 60384d962ec8f487f824214744498bba505a6db0c59Randy Pan 60484d962ec8f487f824214744498bba505a6db0c59Randy Pan // re-enable this when b/27695292 is fixed 60584d962ec8f487f824214744498bba505a6db0c59Randy Pan // mSingleScanListener.clearScanDetails(); 60648444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills // mScanner.startScan(settings, mSingleScanListener, WIFI_WORK_SOURCE); 60784d962ec8f487f824214744498bba505a6db0c59Randy Pan SingleScanListener singleScanListener = new SingleScanListener(); 60848444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills mScanner.startScan(settings, singleScanListener, WIFI_WORK_SOURCE); 60984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 61084d962ec8f487f824214744498bba505a6db0c59Randy Pan 61184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a periodic scan when screen is on 61284d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startPeriodicScan() { 6133d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mPnoScanListener.resetLowRssiNetworkRetryDelay(); 6143d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 61584d962ec8f487f824214744498bba505a6db0c59Randy Pan // Due to b/28020168, timer based single scan will be scheduled every 61684d962ec8f487f824214744498bba505a6db0c59Randy Pan // PERIODIC_SCAN_INTERVAL_MS to provide periodic scan. 61779e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_BACKGROUND_SCAN) { 61884d962ec8f487f824214744498bba505a6db0c59Randy Pan startSingleScan(); 61984d962ec8f487f824214744498bba505a6db0c59Randy Pan schedulePeriodicScanTimer(); 62084d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 62184d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings settings = new ScanSettings(); 62284d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.band = getScanBand(); 62384d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT 62484d962ec8f487f824214744498bba505a6db0c59Randy Pan | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 62584d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.numBssidsPerScan = 0; 62684d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.periodInMs = PERIODIC_SCAN_INTERVAL_MS; 62784d962ec8f487f824214744498bba505a6db0c59Randy Pan 62884d962ec8f487f824214744498bba505a6db0c59Randy Pan mPeriodicScanListener.clearScanDetails(); 62948444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills mScanner.startBackgroundScan(settings, mPeriodicScanListener, WIFI_WORK_SOURCE); 63084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 63184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 63284d962ec8f487f824214744498bba505a6db0c59Randy Pan 63384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a DisconnectedPNO scan when screen is off and Wifi is disconnected 63484d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startDisconnectedPnoScan() { 63584d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize PNO settings 63684d962ec8f487f824214744498bba505a6db0c59Randy Pan PnoSettings pnoSettings = new PnoSettings(); 63784d962ec8f487f824214744498bba505a6db0c59Randy Pan ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = 638329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius mConfigManager.retrieveDisconnectedPnoNetworkList(); 63984d962ec8f487f824214744498bba505a6db0c59Randy Pan int listSize = pnoNetworkList.size(); 64084d962ec8f487f824214744498bba505a6db0c59Randy Pan 64184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (listSize == 0) { 64284d962ec8f487f824214744498bba505a6db0c59Randy Pan // No saved network 64384d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("No saved network for starting disconnected PNO."); 64484d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 64584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 64684d962ec8f487f824214744498bba505a6db0c59Randy Pan 64784d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize]; 64884d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList); 64984d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min5GHzRssi = mMin5GHzRssi; 65084d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min24GHzRssi = mMin24GHzRssi; 65184d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.initialScoreMax = mInitialScoreMax; 65284d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.currentConnectionBonus = mCurrentConnectionBonus; 65384d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.sameNetworkBonus = mSameNetworkBonus; 65484d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.secureBonus = mSecureBonus; 65584d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.band5GHzBonus = mBand5GHzBonus; 65684d962ec8f487f824214744498bba505a6db0c59Randy Pan 65784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize scan settings 65884d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings scanSettings = new ScanSettings(); 65984d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.band = getScanBand(); 66084d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; 66184d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.numBssidsPerScan = 0; 66279e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius scanSettings.periodInMs = DISCONNECTED_PNO_SCAN_INTERVAL_MS; 66384d962ec8f487f824214744498bba505a6db0c59Randy Pan // TODO: enable exponential back off scan later to further save energy 66484d962ec8f487f824214744498bba505a6db0c59Randy Pan // scanSettings.maxPeriodInMs = 8 * scanSettings.periodInMs; 66584d962ec8f487f824214744498bba505a6db0c59Randy Pan 66684d962ec8f487f824214744498bba505a6db0c59Randy Pan mPnoScanListener.clearScanDetails(); 66784d962ec8f487f824214744498bba505a6db0c59Randy Pan 66884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener); 66984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 67084d962ec8f487f824214744498bba505a6db0c59Randy Pan 67184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a ConnectedPNO scan when screen is off and Wifi is connected 67284d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startConnectedPnoScan() { 67384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disable ConnectedPNO for now due to b/28020168 67479e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_CONNECTED_PNO_SCAN) { 67584d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 67684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 67784d962ec8f487f824214744498bba505a6db0c59Randy Pan 67884d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize PNO settings 67984d962ec8f487f824214744498bba505a6db0c59Randy Pan PnoSettings pnoSettings = new PnoSettings(); 68084d962ec8f487f824214744498bba505a6db0c59Randy Pan ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = 68184d962ec8f487f824214744498bba505a6db0c59Randy Pan mConfigManager.retrieveConnectedPnoNetworkList(); 68284d962ec8f487f824214744498bba505a6db0c59Randy Pan int listSize = pnoNetworkList.size(); 68384d962ec8f487f824214744498bba505a6db0c59Randy Pan 68484d962ec8f487f824214744498bba505a6db0c59Randy Pan if (listSize == 0) { 68584d962ec8f487f824214744498bba505a6db0c59Randy Pan // No saved network 68684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("No saved network for starting connected PNO."); 68784d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 68884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 68984d962ec8f487f824214744498bba505a6db0c59Randy Pan 69084d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize]; 69184d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList); 69284d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min5GHzRssi = mMin5GHzRssi; 69384d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min24GHzRssi = mMin24GHzRssi; 69484d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.initialScoreMax = mInitialScoreMax; 69584d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.currentConnectionBonus = mCurrentConnectionBonus; 69684d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.sameNetworkBonus = mSameNetworkBonus; 69784d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.secureBonus = mSecureBonus; 69884d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.band5GHzBonus = mBand5GHzBonus; 69984d962ec8f487f824214744498bba505a6db0c59Randy Pan 70084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize scan settings 70184d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings scanSettings = new ScanSettings(); 70284d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.band = getScanBand(); 70384d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; 70484d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.numBssidsPerScan = 0; 70579e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius scanSettings.periodInMs = CONNECTED_PNO_SCAN_INTERVAL_MS; 70684d962ec8f487f824214744498bba505a6db0c59Randy Pan // TODO: enable exponential back off scan later to further save energy 70784d962ec8f487f824214744498bba505a6db0c59Randy Pan // scanSettings.maxPeriodInMs = 8 * scanSettings.periodInMs; 70884d962ec8f487f824214744498bba505a6db0c59Randy Pan 70984d962ec8f487f824214744498bba505a6db0c59Randy Pan mPnoScanListener.clearScanDetails(); 71084d962ec8f487f824214744498bba505a6db0c59Randy Pan 71184d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.startConnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener); 71284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 71384d962ec8f487f824214744498bba505a6db0c59Randy Pan 71484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up watchdog timer 71584d962ec8f487f824214744498bba505a6db0c59Randy Pan private void scheduleWatchdogTimer() { 71684d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "scheduleWatchdogTimer"); 71784d962ec8f487f824214744498bba505a6db0c59Randy Pan 71884d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.set(AlarmManager.RTC_WAKEUP, 719fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mClock.currentTimeMillis() + WATCHDOG_INTERVAL_MS, 72084d962ec8f487f824214744498bba505a6db0c59Randy Pan "WifiConnectivityManager Schedule Watchdog Timer", 721c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mWatchdogListener, mEventHandler); 72284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 72384d962ec8f487f824214744498bba505a6db0c59Randy Pan 72484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up periodic scan timer 72584d962ec8f487f824214744498bba505a6db0c59Randy Pan private void schedulePeriodicScanTimer() { 72684d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.set(AlarmManager.RTC_WAKEUP, 727fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mClock.currentTimeMillis() + PERIODIC_SCAN_INTERVAL_MS, 72884d962ec8f487f824214744498bba505a6db0c59Randy Pan "WifiConnectivityManager Schedule Periodic Scan Timer", 729c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mPeriodicScanTimerListener, mEventHandler); 73084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 73184d962ec8f487f824214744498bba505a6db0c59Randy Pan 73284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up timer to start a delayed single scan after RESTART_SCAN_DELAY_MS 73384d962ec8f487f824214744498bba505a6db0c59Randy Pan private void scheduleDelayedSingleScan() { 73484d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("scheduleDelayedSingleScan"); 73584d962ec8f487f824214744498bba505a6db0c59Randy Pan 73684d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.set(AlarmManager.RTC_WAKEUP, 737fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mClock.currentTimeMillis() + RESTART_SCAN_DELAY_MS, 73884d962ec8f487f824214744498bba505a6db0c59Randy Pan "WifiConnectivityManager Restart Single Scan", 739c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mRestartSingleScanListener, mEventHandler); 74084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 74184d962ec8f487f824214744498bba505a6db0c59Randy Pan 7423d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set up timer to start a delayed scan after msFromNow milli-seconds 7433d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private void scheduleDelayedConnectivityScan(int msFromNow) { 74484d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("scheduleDelayedConnectivityScan"); 74584d962ec8f487f824214744498bba505a6db0c59Randy Pan 74684d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.set(AlarmManager.RTC_WAKEUP, 7473d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mClock.currentTimeMillis() + msFromNow, 74884d962ec8f487f824214744498bba505a6db0c59Randy Pan "WifiConnectivityManager Restart Scan", 749c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mRestartScanListener, mEventHandler); 75084d962ec8f487f824214744498bba505a6db0c59Randy Pan 75184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 75284d962ec8f487f824214744498bba505a6db0c59Randy Pan 75384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a connectivity scan. The scan method is chosen according to 75484d962ec8f487f824214744498bba505a6db0c59Randy Pan // the current screen state and WiFi state. 75584d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startConnectivityScan(boolean forceSelectNetwork) { 75684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("startConnectivityScan: screenOn=" + mScreenOn 75784d962ec8f487f824214744498bba505a6db0c59Randy Pan + " wifiState=" + mWifiState 75884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " forceSelectNetwork=" + forceSelectNetwork 759466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + " wifiEnabled=" + mWifiEnabled 760466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + " wifiConnectivityManagerEnabled=" 761466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + mWifiConnectivityManagerEnabled); 76284d962ec8f487f824214744498bba505a6db0c59Randy Pan 763466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) { 76484d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 76584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 76684d962ec8f487f824214744498bba505a6db0c59Randy Pan 76784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Always stop outstanding connecivity scan if there is any 76884d962ec8f487f824214744498bba505a6db0c59Randy Pan stopConnectivityScan(); 76984d962ec8f487f824214744498bba505a6db0c59Randy Pan 77084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Don't start a connectivity scan while Wifi is in the transition 77184d962ec8f487f824214744498bba505a6db0c59Randy Pan // between connected and disconnected states. 77284d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) { 77384d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 77484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 77584d962ec8f487f824214744498bba505a6db0c59Randy Pan 77684d962ec8f487f824214744498bba505a6db0c59Randy Pan mForceSelectNetwork = forceSelectNetwork; 77784d962ec8f487f824214744498bba505a6db0c59Randy Pan 77884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScreenOn) { 77984d962ec8f487f824214744498bba505a6db0c59Randy Pan startPeriodicScan(); 78084d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { // screenOff 78184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_CONNECTED) { 78284d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectedPnoScan(); 78384d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 78484d962ec8f487f824214744498bba505a6db0c59Randy Pan startDisconnectedPnoScan(); 78584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 78684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 78784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 78884d962ec8f487f824214744498bba505a6db0c59Randy Pan 78984d962ec8f487f824214744498bba505a6db0c59Randy Pan // Stop connectivity scan if there is any. 79084d962ec8f487f824214744498bba505a6db0c59Randy Pan private void stopConnectivityScan() { 79184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Due to b/28020168, timer based single scan will be scheduled every 79284d962ec8f487f824214744498bba505a6db0c59Randy Pan // PERIODIC_SCAN_INTERVAL_MS to provide periodic scan. 79379e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_BACKGROUND_SCAN) { 79484d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.cancel(mPeriodicScanTimerListener); 79584d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 79684d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.stopBackgroundScan(mPeriodicScanListener); 79784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 798f37079e3d8f4aca3242a971cbaef732fe1b75bdeRoshan Pius mScanner.stopPnoScan(mPnoScanListener); 79984d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 80084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 80184d962ec8f487f824214744498bba505a6db0c59Randy Pan 80284d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 80384d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for screen state (on/off) changes 80484d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 80584d962ec8f487f824214744498bba505a6db0c59Randy Pan public void handleScreenStateChanged(boolean screenOn) { 80684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("handleScreenStateChanged: screenOn=" + screenOn); 80784d962ec8f487f824214744498bba505a6db0c59Randy Pan 80884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScreenOn = screenOn; 80984d962ec8f487f824214744498bba505a6db0c59Randy Pan 81084d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 81184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 81284d962ec8f487f824214744498bba505a6db0c59Randy Pan 81384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 81484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for WiFi state (connected/disconnected) changes 81584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 81684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void handleConnectionStateChanged(int state) { 81784d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("handleConnectionStateChanged: state=" + state); 81884d962ec8f487f824214744498bba505a6db0c59Randy Pan 81984d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiState = state; 82084d962ec8f487f824214744498bba505a6db0c59Randy Pan 82184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Kick off the watchdog timer if entering disconnected state 82284d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_DISCONNECTED) { 82384d962ec8f487f824214744498bba505a6db0c59Randy Pan scheduleWatchdogTimer(); 82484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 82584d962ec8f487f824214744498bba505a6db0c59Randy Pan 82684d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 82784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 82884d962ec8f487f824214744498bba505a6db0c59Randy Pan 82984d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 83084d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler when user toggles whether untrusted connection is allowed 83184d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 83284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setUntrustedConnectionAllowed(boolean allowed) { 83384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "setUntrustedConnectionAllowed: allowed=" + allowed); 83484d962ec8f487f824214744498bba505a6db0c59Randy Pan 83584d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mUntrustedConnectionAllowed != allowed) { 83684d962ec8f487f824214744498bba505a6db0c59Randy Pan mUntrustedConnectionAllowed = allowed; 83784d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 83884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 83984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 84084d962ec8f487f824214744498bba505a6db0c59Randy Pan 84184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 84284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler when user specifies a particular network to connect to 84384d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 84484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void connectToUserSelectNetwork(int netId, boolean persistent) { 84584d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "connectToUserSelectNetwork: netId=" + netId 84684d962ec8f487f824214744498bba505a6db0c59Randy Pan + " persist=" + persistent); 84784d962ec8f487f824214744498bba505a6db0c59Randy Pan 84884d962ec8f487f824214744498bba505a6db0c59Randy Pan mQualifiedNetworkSelector.userSelectNetwork(netId, persistent); 84984d962ec8f487f824214744498bba505a6db0c59Randy Pan 8504f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius clearConnectionAttemptTimeStamps(); 8514f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 85284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initiate a scan which will trigger the connection to the user selected 85384d962ec8f487f824214744498bba505a6db0c59Randy Pan // network when scan result is available. 85484d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(true); 85584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 85684d962ec8f487f824214744498bba505a6db0c59Randy Pan 85784d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 85884d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for on-demand connectivity scan 85984d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 86084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void forceConnectivityScan() { 86184d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "forceConnectivityScan"); 86284d962ec8f487f824214744498bba505a6db0c59Randy Pan 86384d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 86484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 86584d962ec8f487f824214744498bba505a6db0c59Randy Pan 86684d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 86784d962ec8f487f824214744498bba505a6db0c59Randy Pan * Track whether a BSSID should be enabled or disabled for QNS 86884d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 86984d962ec8f487f824214744498bba505a6db0c59Randy Pan public boolean trackBssid(String bssid, boolean enable) { 87084d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "trackBssid: " + (enable ? "enable " : "disable ") + bssid); 87184d962ec8f487f824214744498bba505a6db0c59Randy Pan 87284d962ec8f487f824214744498bba505a6db0c59Randy Pan boolean ret = mQualifiedNetworkSelector 87384d962ec8f487f824214744498bba505a6db0c59Randy Pan .enableBssidForQualityNetworkSelection(bssid, enable); 87484d962ec8f487f824214744498bba505a6db0c59Randy Pan 87584d962ec8f487f824214744498bba505a6db0c59Randy Pan if (ret && !enable) { 87684d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disabling a BSSID can happen when the AP candidate to connect to has 87784d962ec8f487f824214744498bba505a6db0c59Randy Pan // no capacity for new stations. We start another scan immediately so that QNS 87884d962ec8f487f824214744498bba505a6db0c59Randy Pan // can give us another candidate to connect to. 87984d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 88084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 88184d962ec8f487f824214744498bba505a6db0c59Randy Pan 88284d962ec8f487f824214744498bba505a6db0c59Randy Pan return ret; 88384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 88484d962ec8f487f824214744498bba505a6db0c59Randy Pan 88584d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 88684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Set band preference when doing scan and making connection 88784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 88884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setUserPreferredBand(int band) { 88984d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "User band preference: " + band); 89084d962ec8f487f824214744498bba505a6db0c59Randy Pan 89184d962ec8f487f824214744498bba505a6db0c59Randy Pan mQualifiedNetworkSelector.setUserPreferredBand(band); 89284d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectivityScan(false); 89384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 89484d962ec8f487f824214744498bba505a6db0c59Randy Pan 89584d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 89684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Inform WiFi is enabled for connection or not 89784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 89884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setWifiEnabled(boolean enable) { 89984d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "Set WiFi " + (enable ? "enabled" : "disabled")); 90084d962ec8f487f824214744498bba505a6db0c59Randy Pan 90184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiEnabled = enable; 90284d962ec8f487f824214744498bba505a6db0c59Randy Pan 90384d962ec8f487f824214744498bba505a6db0c59Randy Pan if (!mWifiEnabled) { 90484d962ec8f487f824214744498bba505a6db0c59Randy Pan stopConnectivityScan(); 90584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 90684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 90784d962ec8f487f824214744498bba505a6db0c59Randy Pan 90884d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 909466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan * Turn on/off the WifiConnectivityMangager at runtime 910466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan */ 911466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan public void enable(boolean enable) { 912466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan Log.i(TAG, "Set WiFiConnectivityManager " + (enable ? "enabled" : "disabled")); 913466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 914466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan mWifiConnectivityManagerEnabled = enable; 915466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 916466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiConnectivityManagerEnabled) { 917466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan stopConnectivityScan(); 918466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan } 919466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan } 920466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 921466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan /** 92284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Enable/disable verbose logging 92384d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 92484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void enableVerboseLogging(int verbose) { 92584d962ec8f487f824214744498bba505a6db0c59Randy Pan mDbg = verbose > 0; 92684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 92784d962ec8f487f824214744498bba505a6db0c59Randy Pan 92884d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 92984d962ec8f487f824214744498bba505a6db0c59Randy Pan * Dump the local log buffer 93084d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 93184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 93284d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("Dump of WifiConnectivityManager"); 93384d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("WifiConnectivityManager - Log Begin ----"); 9343d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan pw.println("WifiConnectivityManager - Number of connectivity attempts rate limited: " 9353d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan + mTotalConnectivityAttemptsRateLimited); 93684d962ec8f487f824214744498bba505a6db0c59Randy Pan mLocalLog.dump(fd, pw, args); 93784d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("WifiConnectivityManager - Log End ----"); 93884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 9393d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 9403d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan @VisibleForTesting 9413d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan int getLowRssiNetworkRetryDelay() { 9423d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return mPnoScanListener.getLowRssiNetworkRetryDelay(); 9433d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 94484d962ec8f487f824214744498bba505a6db0c59Randy Pan} 945