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; 44ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Panimport java.util.HashSet; 454f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Piusimport java.util.Iterator; 464f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Piusimport java.util.LinkedList; 4784d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.List; 4884d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.Set; 4984d962ec8f487f824214744498bba505a6db0c59Randy Pan 5084d962ec8f487f824214744498bba505a6db0c59Randy Pan/** 5184d962ec8f487f824214744498bba505a6db0c59Randy Pan * This class manages all the connectivity related scanning activities. 5284d962ec8f487f824214744498bba505a6db0c59Randy Pan * 5384d962ec8f487f824214744498bba505a6db0c59Randy Pan * When the screen is turned on or off, WiFi is connected or disconnected, 5484d962ec8f487f824214744498bba505a6db0c59Randy Pan * or on-demand, a scan is initiatiated and the scan results are passed 5584d962ec8f487f824214744498bba505a6db0c59Randy Pan * to QNS for it to make a recommendation on which network to connect to. 5684d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 5784d962ec8f487f824214744498bba505a6db0c59Randy Panpublic class WifiConnectivityManager { 581d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public static final String WATCHDOG_TIMER_TAG = 591d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius "WifiConnectivityManager Schedule Watchdog Timer"; 601d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public static final String PERIODIC_SCAN_TIMER_TAG = 611d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius "WifiConnectivityManager Schedule Periodic Scan Timer"; 621d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public static final String RESTART_SINGLE_SCAN_TIMER_TAG = 631d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius "WifiConnectivityManager Restart Single Scan"; 641d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public static final String RESTART_CONNECTIVITY_SCAN_TIMER_TAG = 651d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius "WifiConnectivityManager Restart Scan"; 6684d962ec8f487f824214744498bba505a6db0c59Randy Pan 671d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius private static final String TAG = "WifiConnectivityManager"; 68016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private static final long RESET_TIME_STAMP = Long.MIN_VALUE; 69016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Constants to indicate whether a scan should start immediately or 70016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // it should comply to the minimum scan interval rule. 71016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private static final boolean SCAN_IMMEDIATELY = true; 72016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private static final boolean SCAN_ON_SCHEDULE = false; 7384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan interval in milli-seconds. This is the scan 7484d962ec8f487f824214744498bba505a6db0c59Randy Pan // performed when screen is on. 75b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan @VisibleForTesting 76b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan public static final int PERIODIC_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds 77ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // When screen is on and WiFi traffic is heavy, exponential backoff 78ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // connectivity scans are scheduled. This constant defines the maximum 79ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // scan interval in this scenario. 80b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan @VisibleForTesting 81b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan public static final int MAX_PERIODIC_SCAN_INTERVAL_MS = 160 * 1000; // 160 seconds 8284d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO scan interval in milli-seconds. This is the scan 8379e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // performed when screen is off and disconnected. 844f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int DISCONNECTED_PNO_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds 8579e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // PNO scan interval in milli-seconds. This is the scan 8679e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // performed when screen is off and connected. 874f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int CONNECTED_PNO_SCAN_INTERVAL_MS = 160 * 1000; // 160 seconds 883d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // When a network is found by PNO scan but gets rejected by QNS due to its 893d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // low RSSI value, scan will be reschduled in an exponential back off manner. 903d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private static final int LOW_RSSI_NETWORK_RETRY_START_DELAY_MS = 20 * 1000; // 20 seconds 913d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private static final int LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS = 80 * 1000; // 80 seconds 9284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Maximum number of retries when starting a scan failed 9384d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final int MAX_SCAN_RESTART_ALLOWED = 5; 9484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Number of milli-seconds to delay before retry starting 9584d962ec8f487f824214744498bba505a6db0c59Randy Pan // a previously failed scan 964f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int RESTART_SCAN_DELAY_MS = 2 * 1000; // 2 seconds 9784d962ec8f487f824214744498bba505a6db0c59Randy Pan // When in disconnected mode, a watchdog timer will be fired 9884d962ec8f487f824214744498bba505a6db0c59Randy Pan // every WATCHDOG_INTERVAL_MS to start a single scan. This is 9984d962ec8f487f824214744498bba505a6db0c59Randy Pan // to prevent caveat from things like PNO scan. 1004f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private static final int WATCHDOG_INTERVAL_MS = 20 * 60 * 1000; // 20 minutes 101ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Restricted channel list age out value. 102ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private static final int CHANNEL_LIST_AGE_MS = 60 * 60 * 1000; // 1 hour 1034f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // This is the time interval for the connection attempt rate calculation. Connection attempt 1044f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // timestamps beyond this interval is evicted from the list. 105fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public static final int MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS = 4 * 60 * 1000; // 4 mins 1064f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // Max number of connection attempts in the above time interval. 107fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public static final int MAX_CONNECTION_ATTEMPTS_RATE = 6; 10884d962ec8f487f824214744498bba505a6db0c59Randy Pan 10984d962ec8f487f824214744498bba505a6db0c59Randy Pan // WifiStateMachine has a bunch of states. From the 11084d962ec8f487f824214744498bba505a6db0c59Randy Pan // WifiConnectivityManager's perspective it only cares 11184d962ec8f487f824214744498bba505a6db0c59Randy Pan // if it is in Connected state, Disconnected state or in 11284d962ec8f487f824214744498bba505a6db0c59Randy Pan // transition between these two states. 11384d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_UNKNOWN = 0; 11484d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_CONNECTED = 1; 11584d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_DISCONNECTED = 2; 11684d962ec8f487f824214744498bba505a6db0c59Randy Pan public static final int WIFI_STATE_TRANSITIONING = 3; 11784d962ec8f487f824214744498bba505a6db0c59Randy Pan 118ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Due to b/28020168, timer based single scan will be scheduled 119ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // to provide periodic scan in an exponential backoff fashion. 1207ce0f144104c68da40c196c16f73e2d0bcc50cc7Roshan Pius private static final boolean ENABLE_BACKGROUND_SCAN = false; 12179e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius // Flag to turn on connected PNO, when needed 1227ce0f144104c68da40c196c16f73e2d0bcc50cc7Roshan Pius private static final boolean ENABLE_CONNECTED_PNO_SCAN = false; 12379e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius 12484d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiStateMachine mStateMachine; 12584d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiScanner mScanner; 12684d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiConfigManager mConfigManager; 12784d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiInfo mWifiInfo; 12884d962ec8f487f824214744498bba505a6db0c59Randy Pan private final WifiQualifiedNetworkSelector mQualifiedNetworkSelector; 12909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne private final WifiLastResortWatchdog mWifiLastResortWatchdog; 130bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius private final WifiMetrics mWifiMetrics; 131fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final AlarmManager mAlarmManager; 132c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan private final Handler mEventHandler; 133fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final Clock mClock; 134fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private final LocalLog mLocalLog = 13515941215e85f924765f00779e9b5daff9ed6f118Randy Pan new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 256 : 1024); 1364f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private final LinkedList<Long> mConnectionAttemptTimeStamps; 137fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 13884d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mDbg = false; 13984d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mWifiEnabled = false; 140466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan private boolean mWifiConnectivityManagerEnabled = true; 14184d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mScreenOn = false; 14284d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mWifiState = WIFI_STATE_UNKNOWN; 14384d962ec8f487f824214744498bba505a6db0c59Randy Pan private boolean mUntrustedConnectionAllowed = false; 14484d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mScanRestartCount = 0; 14584d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSingleScanRestartCount = 0; 146d54ddacc42d9cd929d40b1df391895293bacafe2Roshan Pius private int mTotalConnectivityAttemptsRateLimited = 0; 14750abba06efa7834b5309df561375e4a2e2df630dRandy Pan private String mLastConnectionAttemptBssid = null; 148ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private int mPeriodicSingleScanInterval = PERIODIC_SCAN_INTERVAL_MS; 149016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private long mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP; 15084d962ec8f487f824214744498bba505a6db0c59Randy Pan 15184d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO settings 15284d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mMin5GHzRssi; 15384d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mMin24GHzRssi; 15484d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mInitialScoreMax; 15584d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mCurrentConnectionBonus; 15684d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSameNetworkBonus; 15784d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mSecureBonus; 15884d962ec8f487f824214744498bba505a6db0c59Randy Pan private int mBand5GHzBonus; 15984d962ec8f487f824214744498bba505a6db0c59Randy Pan 16084d962ec8f487f824214744498bba505a6db0c59Randy Pan // A helper to log debugging information in the local log buffer, which can 16184d962ec8f487f824214744498bba505a6db0c59Randy Pan // be retrieved in bugreport. 16284d962ec8f487f824214744498bba505a6db0c59Randy Pan private void localLog(String log) { 16384d962ec8f487f824214744498bba505a6db0c59Randy Pan mLocalLog.log(log); 16484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 16584d962ec8f487f824214744498bba505a6db0c59Randy Pan 16684d962ec8f487f824214744498bba505a6db0c59Randy Pan // A periodic/PNO scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times 16784d962ec8f487f824214744498bba505a6db0c59Randy Pan // if the start scan command failed. An timer is used here to make it a deferred retry. 16884d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mRestartScanListener = 16984d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 17084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 171016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_IMMEDIATELY); 17284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 17384d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 17484d962ec8f487f824214744498bba505a6db0c59Randy Pan 17584d962ec8f487f824214744498bba505a6db0c59Randy Pan // A single scan will be rescheduled up to MAX_SCAN_RESTART_ALLOWED times 17684d962ec8f487f824214744498bba505a6db0c59Randy Pan // if the start scan command failed. An timer is used here to make it a deferred retry. 177bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius private class RestartSingleScanListener implements AlarmManager.OnAlarmListener { 178bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius private final boolean mIsWatchdogTriggered; 179ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private final boolean mIsFullBandScan; 180bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius 181304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan RestartSingleScanListener(boolean isWatchdogTriggered, boolean isFullBandScan) { 182bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mIsWatchdogTriggered = isWatchdogTriggered; 183ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan mIsFullBandScan = isFullBandScan; 184bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 185bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius 186bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius @Override 187bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius public void onAlarm() { 188304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan startSingleScan(mIsWatchdogTriggered, mIsFullBandScan); 189bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 190bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 19184d962ec8f487f824214744498bba505a6db0c59Randy Pan 19284d962ec8f487f824214744498bba505a6db0c59Randy Pan // As a watchdog mechanism, a single scan will be scheduled every WATCHDOG_INTERVAL_MS 19384d962ec8f487f824214744498bba505a6db0c59Randy Pan // if it is in the WIFI_STATE_DISCONNECTED state. 19484d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mWatchdogListener = 19584d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 19684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 19784d962ec8f487f824214744498bba505a6db0c59Randy Pan watchdogHandler(); 19884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 19984d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 20084d962ec8f487f824214744498bba505a6db0c59Randy Pan 201ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Due to b/28020168, timer based single scan will be scheduled 202ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // to provide periodic scan in an exponential backoff fashion. 20384d962ec8f487f824214744498bba505a6db0c59Randy Pan private final AlarmManager.OnAlarmListener mPeriodicScanTimerListener = 20484d962ec8f487f824214744498bba505a6db0c59Randy Pan new AlarmManager.OnAlarmListener() { 20584d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onAlarm() { 20684d962ec8f487f824214744498bba505a6db0c59Randy Pan periodicScanTimerHandler(); 20784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 20884d962ec8f487f824214744498bba505a6db0c59Randy Pan }; 20984d962ec8f487f824214744498bba505a6db0c59Randy Pan 21009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne /** 21109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * Handles 'onResult' callbacks for the Periodic, Single & Pno ScanListener. 21209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * Executes selection of potential network candidates, initiation of connection attempt to that 21309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne * network. 2143d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * 2153d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * @return true - if a candidate is selected by QNS 2163d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * false - if no candidate is selected by QNS 21709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne */ 2183d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private boolean handleScanResults(List<ScanDetail> scanDetails, String listenerName) { 21909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne localLog(listenerName + " onResults: start QNS"); 22009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiConfiguration candidate = 221016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan mQualifiedNetworkSelector.selectQualifiedNetwork(false, 22209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mUntrustedConnectionAllowed, scanDetails, 22309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isLinkDebouncing(), mStateMachine.isConnected(), 22409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isDisconnected(), 22509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mStateMachine.isSupplicantTransientState()); 22609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiLastResortWatchdog.updateAvailableNetworks( 22709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mQualifiedNetworkSelector.getFilteredScanDetails()); 22809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne if (candidate != null) { 22909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne localLog(listenerName + ": QNS candidate-" + candidate.SSID); 23009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne connectToNetwork(candidate); 2313d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return true; 2323d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } else { 2333d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return false; 23409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne } 23509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne } 23609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne 23784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan results listener. A periodic scan is initiated when 23884d962ec8f487f824214744498bba505a6db0c59Randy Pan // screen is on. 23984d962ec8f487f824214744498bba505a6db0c59Randy Pan private class PeriodicScanListener implements WifiScanner.ScanListener { 24084d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 24184d962ec8f487f824214744498bba505a6db0c59Randy Pan 24284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 24384d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 24484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 24584d962ec8f487f824214744498bba505a6db0c59Randy Pan 24684d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 24784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 24884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onSuccess"); 24984d962ec8f487f824214744498bba505a6db0c59Randy Pan 25084d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 25184d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 25284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 25384d962ec8f487f824214744498bba505a6db0c59Randy Pan 25484d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 25584d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 25684d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "PeriodicScanListener onFailure:" 25784d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 25884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 25984d962ec8f487f824214744498bba505a6db0c59Randy Pan 26084d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 26184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 2623d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(RESTART_SCAN_DELAY_MS); 26384d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 26484d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 26584d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start periodic scan for " 26684d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 26784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 26884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 26984d962ec8f487f824214744498bba505a6db0c59Randy Pan 27084d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 27184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 27284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onPeriodChanged: " 27384d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 27484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 27584d962ec8f487f824214744498bba505a6db0c59Randy Pan 27684d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 27784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 27809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne handleScanResults(mScanDetails, "PeriodicScanListener"); 27984d962ec8f487f824214744498bba505a6db0c59Randy Pan clearScanDetails(); 28084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 28184d962ec8f487f824214744498bba505a6db0c59Randy Pan 28284d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 28384d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 28484d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mDbg) { 28584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PeriodicScanListener onFullResult: " 28684d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.SSID + " capabilities " 28784d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.capabilities); 28884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 28984d962ec8f487f824214744498bba505a6db0c59Randy Pan 29084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(fullScanResult)); 29184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 29284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 29384d962ec8f487f824214744498bba505a6db0c59Randy Pan 29484d962ec8f487f824214744498bba505a6db0c59Randy Pan private final PeriodicScanListener mPeriodicScanListener = new PeriodicScanListener(); 29584d962ec8f487f824214744498bba505a6db0c59Randy Pan 29684d962ec8f487f824214744498bba505a6db0c59Randy Pan // Single scan results listener. A single scan is initiated when 29784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disconnected/ConnectedPNO scan found a valid network and woke up 29884d962ec8f487f824214744498bba505a6db0c59Randy Pan // the system, or by the watchdog timer. 29984d962ec8f487f824214744498bba505a6db0c59Randy Pan private class SingleScanListener implements WifiScanner.ScanListener { 30084d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 301bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius private final boolean mIsWatchdogTriggered; 302ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private final boolean mIsFullBandScan; 303bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius 304304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan SingleScanListener(boolean isWatchdogTriggered, boolean isFullBandScan) { 305bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mIsWatchdogTriggered = isWatchdogTriggered; 306ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan mIsFullBandScan = isFullBandScan; 307bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 30884d962ec8f487f824214744498bba505a6db0c59Randy Pan 30984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 31084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 31184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 31284d962ec8f487f824214744498bba505a6db0c59Randy Pan 31384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 31484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 31584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onSuccess"); 31684d962ec8f487f824214744498bba505a6db0c59Randy Pan 31784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 31884d962ec8f487f824214744498bba505a6db0c59Randy Pan mSingleScanRestartCount = 0; 31984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 32084d962ec8f487f824214744498bba505a6db0c59Randy Pan 32184d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 32284d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 32384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "SingleScanListener onFailure:" 32484d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 32584d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 32684d962ec8f487f824214744498bba505a6db0c59Randy Pan 32784d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 32884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mSingleScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 329304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan scheduleDelayedSingleScan(mIsWatchdogTriggered, mIsFullBandScan); 33084d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 33184d962ec8f487f824214744498bba505a6db0c59Randy Pan mSingleScanRestartCount = 0; 33284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start single scan for " 33384d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 33484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 33584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 33684d962ec8f487f824214744498bba505a6db0c59Randy Pan 33784d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 33884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 33984d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onPeriodChanged: " 34084d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 34184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 34284d962ec8f487f824214744498bba505a6db0c59Randy Pan 34384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 34484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 345bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius boolean wasConnectAttempted = handleScanResults(mScanDetails, "SingleScanListener"); 346224198c8ba46f362a5df6d25f1b60e56f442b58bRoshan Pius clearScanDetails(); 347bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius // update metrics if this was a watchdog triggered single scan 348bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius if (mIsWatchdogTriggered) { 349bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius if (wasConnectAttempted) { 350bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius if (mScreenOn) { 351bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mWifiMetrics.incrementNumConnectivityWatchdogBackgroundBad(); 352bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } else { 353bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mWifiMetrics.incrementNumConnectivityWatchdogPnoBad(); 354bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 355bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } else { 356bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius if (mScreenOn) { 357bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mWifiMetrics.incrementNumConnectivityWatchdogBackgroundGood(); 358bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } else { 359bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mWifiMetrics.incrementNumConnectivityWatchdogPnoGood(); 360bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 361bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 362bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius } 36384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 36484d962ec8f487f824214744498bba505a6db0c59Randy Pan 36584d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 36684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 36784d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mDbg) { 36884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("SingleScanListener onFullResult: " 36984d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.SSID + " capabilities " 37084d962ec8f487f824214744498bba505a6db0c59Randy Pan + fullScanResult.capabilities); 37184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 37284d962ec8f487f824214744498bba505a6db0c59Randy Pan 37384d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(fullScanResult)); 37484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 37584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 37684d962ec8f487f824214744498bba505a6db0c59Randy Pan 37784d962ec8f487f824214744498bba505a6db0c59Randy Pan // re-enable this when b/27695292 is fixed 37884d962ec8f487f824214744498bba505a6db0c59Randy Pan // private final SingleScanListener mSingleScanListener = new SingleScanListener(); 37984d962ec8f487f824214744498bba505a6db0c59Randy Pan 38084d962ec8f487f824214744498bba505a6db0c59Randy Pan // PNO scan results listener for both disconected and connected PNO scanning. 38184d962ec8f487f824214744498bba505a6db0c59Randy Pan // A PNO scan is initiated when screen is off. 38284d962ec8f487f824214744498bba505a6db0c59Randy Pan private class PnoScanListener implements WifiScanner.PnoScanListener { 38384d962ec8f487f824214744498bba505a6db0c59Randy Pan private List<ScanDetail> mScanDetails = new ArrayList<ScanDetail>(); 3843d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private int mLowRssiNetworkRetryDelay = 3853d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; 38684d962ec8f487f824214744498bba505a6db0c59Randy Pan 38784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void clearScanDetails() { 38884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.clear(); 38984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 39084d962ec8f487f824214744498bba505a6db0c59Randy Pan 3913d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Reset to the start value when either a non-PNO scan is started or 3923d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // QNS selects a candidate from the PNO scan results. 3933d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan public void resetLowRssiNetworkRetryDelay() { 3943d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_START_DELAY_MS; 3953d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 3963d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 3973d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan @VisibleForTesting 3983d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan public int getLowRssiNetworkRetryDelay() { 3993d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return mLowRssiNetworkRetryDelay; 4003d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 4013d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 40284d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 40384d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onSuccess() { 40484d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener onSuccess"); 40584d962ec8f487f824214744498bba505a6db0c59Randy Pan 40684d962ec8f487f824214744498bba505a6db0c59Randy Pan // reset the count 40784d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 40884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 40984d962ec8f487f824214744498bba505a6db0c59Randy Pan 41084d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 41184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFailure(int reason, String description) { 41284d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "PnoScanListener onFailure:" 41384d962ec8f487f824214744498bba505a6db0c59Randy Pan + " reason: " + reason 41484d962ec8f487f824214744498bba505a6db0c59Randy Pan + " description: " + description); 41584d962ec8f487f824214744498bba505a6db0c59Randy Pan 41684d962ec8f487f824214744498bba505a6db0c59Randy Pan // reschedule the scan 41784d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScanRestartCount++ < MAX_SCAN_RESTART_ALLOWED) { 4183d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(RESTART_SCAN_DELAY_MS); 41984d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 42084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 42184d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "Failed to successfully start PNO scan for " 42284d962ec8f487f824214744498bba505a6db0c59Randy Pan + MAX_SCAN_RESTART_ALLOWED + " times"); 42384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 42484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 42584d962ec8f487f824214744498bba505a6db0c59Randy Pan 42684d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 42784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPeriodChanged(int periodInMs) { 42884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener onPeriodChanged: " 42984d962ec8f487f824214744498bba505a6db0c59Randy Pan + "actual scan period " + periodInMs + "ms"); 43084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 43184d962ec8f487f824214744498bba505a6db0c59Randy Pan 43284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Currently the PNO scan results doesn't include IE, 43384d962ec8f487f824214744498bba505a6db0c59Randy Pan // which contains information required by QNS. Ignore them 43484d962ec8f487f824214744498bba505a6db0c59Randy Pan // for now. 43584d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 43684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onResults(WifiScanner.ScanData[] results) { 43784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 43884d962ec8f487f824214744498bba505a6db0c59Randy Pan 43984d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 44084d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onFullResult(ScanResult fullScanResult) { 44184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 44284d962ec8f487f824214744498bba505a6db0c59Randy Pan 44384d962ec8f487f824214744498bba505a6db0c59Randy Pan @Override 44484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void onPnoNetworkFound(ScanResult[] results) { 44584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("PnoScanListener: onPnoNetworkFound: results len = " + results.length); 44684d962ec8f487f824214744498bba505a6db0c59Randy Pan 44784d962ec8f487f824214744498bba505a6db0c59Randy Pan for (ScanResult result: results) { 44884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanDetails.add(ScanDetailUtil.toScanDetail(result)); 44984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 4503d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4513d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan boolean wasConnectAttempted; 4523d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan wasConnectAttempted = handleScanResults(mScanDetails, "PnoScanListener"); 453224198c8ba46f362a5df6d25f1b60e56f442b58bRoshan Pius clearScanDetails(); 4543d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4553d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan if (!wasConnectAttempted) { 4563d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // The scan results were rejected by QNS due to low RSSI values 4573d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan if (mLowRssiNetworkRetryDelay > LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS) { 4583d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay = LOW_RSSI_NETWORK_RETRY_MAX_DELAY_MS; 4593d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 4603d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan scheduleDelayedConnectivityScan(mLowRssiNetworkRetryDelay); 4613d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4623d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set up the delay value for next retry. 4633d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mLowRssiNetworkRetryDelay *= 2; 4643d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } else { 4653d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan resetLowRssiNetworkRetryDelay(); 4663d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 46784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 46884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 46984d962ec8f487f824214744498bba505a6db0c59Randy Pan 47084d962ec8f487f824214744498bba505a6db0c59Randy Pan private final PnoScanListener mPnoScanListener = new PnoScanListener(); 47184d962ec8f487f824214744498bba505a6db0c59Randy Pan 47284d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 47384d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiConnectivityManager constructor 47484d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 47584d962ec8f487f824214744498bba505a6db0c59Randy Pan public WifiConnectivityManager(Context context, WifiStateMachine stateMachine, 47684d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiScanner scanner, WifiConfigManager configManager, WifiInfo wifiInfo, 47709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiQualifiedNetworkSelector qualifiedNetworkSelector, 478c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan WifiInjector wifiInjector, Looper looper) { 47984d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine = stateMachine; 48084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner = scanner; 48184d962ec8f487f824214744498bba505a6db0c59Randy Pan mConfigManager = configManager; 48284d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiInfo = wifiInfo; 483fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mQualifiedNetworkSelector = qualifiedNetworkSelector; 48409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiLastResortWatchdog = wifiInjector.getWifiLastResortWatchdog(); 485bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius mWifiMetrics = wifiInjector.getWifiMetrics(); 486fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 487c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mEventHandler = new Handler(looper); 488fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mClock = wifiInjector.getClock(); 4894f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius mConnectionAttemptTimeStamps = new LinkedList<>(); 49084d962ec8f487f824214744498bba505a6db0c59Randy Pan 49184d962ec8f487f824214744498bba505a6db0c59Randy Pan mMin5GHzRssi = WifiQualifiedNetworkSelector.MINIMUM_5G_ACCEPT_RSSI; 49284d962ec8f487f824214744498bba505a6db0c59Randy Pan mMin24GHzRssi = WifiQualifiedNetworkSelector.MINIMUM_2G_ACCEPT_RSSI; 49384d962ec8f487f824214744498bba505a6db0c59Randy Pan mBand5GHzBonus = WifiQualifiedNetworkSelector.BAND_AWARD_5GHz; 49473a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan mCurrentConnectionBonus = mConfigManager.mCurrentNetworkBoost.get(); 49584d962ec8f487f824214744498bba505a6db0c59Randy Pan mSameNetworkBonus = context.getResources().getInteger( 49684d962ec8f487f824214744498bba505a6db0c59Randy Pan R.integer.config_wifi_framework_SAME_BSSID_AWARD); 49784d962ec8f487f824214744498bba505a6db0c59Randy Pan mSecureBonus = context.getResources().getInteger( 49884d962ec8f487f824214744498bba505a6db0c59Randy Pan R.integer.config_wifi_framework_SECURITY_AWARD); 49973a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan mInitialScoreMax = (mConfigManager.mThresholdSaturatedRssi24.get() 50084d962ec8f487f824214744498bba505a6db0c59Randy Pan + WifiQualifiedNetworkSelector.RSSI_SCORE_OFFSET) 50184d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiQualifiedNetworkSelector.RSSI_SCORE_SLOPE; 50284d962ec8f487f824214744498bba505a6db0c59Randy Pan 50384d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "PNO settings:" + " min5GHzRssi " + mMin5GHzRssi 50484d962ec8f487f824214744498bba505a6db0c59Randy Pan + " min24GHzRssi " + mMin24GHzRssi 50584d962ec8f487f824214744498bba505a6db0c59Randy Pan + " currentConnectionBonus " + mCurrentConnectionBonus 50684d962ec8f487f824214744498bba505a6db0c59Randy Pan + " sameNetworkBonus " + mSameNetworkBonus 50784d962ec8f487f824214744498bba505a6db0c59Randy Pan + " secureNetworkBonus " + mSecureBonus 50884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " initialScoreMax " + mInitialScoreMax); 50984d962ec8f487f824214744498bba505a6db0c59Randy Pan 51084d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "ConnectivityScanManager initialized "); 51184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 51284d962ec8f487f824214744498bba505a6db0c59Randy Pan 51384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 5144f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * This checks the connection attempt rate and recommends whether the connection attempt 5154f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * should be skipped or not. This attempts to rate limit the rate of connections to 5164f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * prevent us from flapping between networks and draining battery rapidly. 5174f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 518ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius private boolean shouldSkipConnectionAttempt(Long timeMillis) { 5194f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius Iterator<Long> attemptIter = mConnectionAttemptTimeStamps.iterator(); 5204f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // First evict old entries from the queue. 521c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan while (attemptIter.hasNext()) { 5224f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius Long connectionAttemptTimeMillis = attemptIter.next(); 523ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius if ((timeMillis - connectionAttemptTimeMillis) 524c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan > MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS) { 5254f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius attemptIter.remove(); 5264f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } else { 5274f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // This list is sorted by timestamps, so we can skip any more checks 5284f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius break; 5294f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5304f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5314f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius // If we've reached the max connection attempt rate, skip this connection attempt 5324f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius return (mConnectionAttemptTimeStamps.size() >= MAX_CONNECTION_ATTEMPTS_RATE); 5334f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5344f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 5354f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 5364f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * Add the current connection attempt timestamp to our queue of connection attempts. 5374f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 538ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius private void noteConnectionAttempt(Long timeMillis) { 539ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mConnectionAttemptTimeStamps.addLast(timeMillis); 5404f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5414f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 5424f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 5434f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * This is used to clear the connection attempt rate limiter. This is done when the user 5444f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius * explicitly tries to connect to a specified network. 5454f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius */ 5464f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius private void clearConnectionAttemptTimeStamps() { 5474f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius mConnectionAttemptTimeStamps.clear(); 5484f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 5494f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 5504f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius /** 55184d962ec8f487f824214744498bba505a6db0c59Randy Pan * Attempt to connect to a network candidate. 55284d962ec8f487f824214744498bba505a6db0c59Randy Pan * 55384d962ec8f487f824214744498bba505a6db0c59Randy Pan * Based on the currently connected network, this menthod determines whether we should 55484d962ec8f487f824214744498bba505a6db0c59Randy Pan * connect or roam to the network candidate recommended by QNS. 55584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 55684d962ec8f487f824214744498bba505a6db0c59Randy Pan private void connectToNetwork(WifiConfiguration candidate) { 55784d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate(); 55884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (scanResultCandidate == null) { 55984d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.e(TAG, "connectToNetwork: bad candidate - " + candidate 56084d962ec8f487f824214744498bba505a6db0c59Randy Pan + " scanResult: " + scanResultCandidate); 56184d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 56284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 56384d962ec8f487f824214744498bba505a6db0c59Randy Pan 56484d962ec8f487f824214744498bba505a6db0c59Randy Pan String targetBssid = scanResultCandidate.BSSID; 56584d962ec8f487f824214744498bba505a6db0c59Randy Pan String targetAssociationId = candidate.SSID + " : " + targetBssid; 56650abba06efa7834b5309df561375e4a2e2df630dRandy Pan 56750abba06efa7834b5309df561375e4a2e2df630dRandy Pan // Check if we are already connected or in the process of connecting to the target 56850abba06efa7834b5309df561375e4a2e2df630dRandy Pan // BSSID. mWifiInfo.mBSSID tracks the currently connected BSSID. This is checked just 56950abba06efa7834b5309df561375e4a2e2df630dRandy Pan // in case the firmware automatically roamed to a BSSID different from what QNS 57050abba06efa7834b5309df561375e4a2e2df630dRandy Pan // selected. 57150abba06efa7834b5309df561375e4a2e2df630dRandy Pan if (targetBssid != null 57250abba06efa7834b5309df561375e4a2e2df630dRandy Pan && (targetBssid.equals(mLastConnectionAttemptBssid) 57350abba06efa7834b5309df561375e4a2e2df630dRandy Pan || targetBssid.equals(mWifiInfo.getBSSID())) 57450abba06efa7834b5309df561375e4a2e2df630dRandy Pan && SupplicantState.isConnecting(mWifiInfo.getSupplicantState())) { 575eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan localLog("connectToNetwork: Either already connected " 576eeb1a3c3cb4c09f925496000392d63b2b28301f7Randy Pan + "or is connecting to " + targetAssociationId); 57784d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 57884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 57984d962ec8f487f824214744498bba505a6db0c59Randy Pan 580ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius Long elapsedTimeMillis = mClock.elapsedRealtime(); 581ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius if (!mScreenOn && shouldSkipConnectionAttempt(elapsedTimeMillis)) { 5824f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius localLog("connectToNetwork: Too many connection attempts. Skipping this attempt!"); 583d54ddacc42d9cd929d40b1df391895293bacafe2Roshan Pius mTotalConnectivityAttemptsRateLimited++; 5844f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius return; 5854f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius } 586ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius noteConnectionAttempt(elapsedTimeMillis); 5874f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius 58850abba06efa7834b5309df561375e4a2e2df630dRandy Pan mLastConnectionAttemptBssid = targetBssid; 58950abba06efa7834b5309df561375e4a2e2df630dRandy Pan 59084d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConfiguration currentConnectedNetwork = mConfigManager 59184d962ec8f487f824214744498bba505a6db0c59Randy Pan .getWifiConfiguration(mWifiInfo.getNetworkId()); 59284d962ec8f487f824214744498bba505a6db0c59Randy Pan String currentAssociationId = (currentConnectedNetwork == null) ? "Disconnected" : 59384d962ec8f487f824214744498bba505a6db0c59Randy Pan (mWifiInfo.getSSID() + " : " + mWifiInfo.getBSSID()); 59484d962ec8f487f824214744498bba505a6db0c59Randy Pan 59584d962ec8f487f824214744498bba505a6db0c59Randy Pan if (currentConnectedNetwork != null 59684d962ec8f487f824214744498bba505a6db0c59Randy Pan && (currentConnectedNetwork.networkId == candidate.networkId 59784d962ec8f487f824214744498bba505a6db0c59Randy Pan || currentConnectedNetwork.isLinked(candidate))) { 59884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("connectToNetwork: Roaming from " + currentAssociationId + " to " 59984d962ec8f487f824214744498bba505a6db0c59Randy Pan + targetAssociationId); 60084d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine.autoRoamToNetwork(candidate.networkId, scanResultCandidate); 60184d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 60284d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("connectToNetwork: Reconnect from " + currentAssociationId + " to " 60384d962ec8f487f824214744498bba505a6db0c59Randy Pan + targetAssociationId); 60484d962ec8f487f824214744498bba505a6db0c59Randy Pan mStateMachine.autoConnectToNetwork(candidate.networkId, scanResultCandidate.BSSID); 60584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 60684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 60784d962ec8f487f824214744498bba505a6db0c59Randy Pan 60884d962ec8f487f824214744498bba505a6db0c59Randy Pan // Helper for selecting the band for connectivity scan 60984d962ec8f487f824214744498bba505a6db0c59Randy Pan private int getScanBand() { 610ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan return getScanBand(true); 611ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 612ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 613ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private int getScanBand(boolean isFullBandScan) { 614ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (isFullBandScan) { 615ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan int freqBand = mStateMachine.getFrequencyBand(); 616ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (freqBand == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) { 617ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan return WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS; 618ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } else if (freqBand == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) { 619ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan return WifiScanner.WIFI_BAND_24_GHZ; 620ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } else { 621ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan return WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 622ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 623ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } else { 624ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Use channel list instead. 625ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan return WifiScanner.WIFI_BAND_UNSPECIFIED; 626ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 627ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 628ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 629fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Helper for setting the channels for connectivity scan when band is unspecified. Returns 630fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // false if we can't retrieve the info. 631fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius private boolean setScanChannels(ScanSettings settings) { 632ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan WifiConfiguration config = mStateMachine.getCurrentWifiConfiguration(); 633ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 634ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (config == null) { 635fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius return false; 636ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 637ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 638304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan HashSet<Integer> freqs = mConfigManager.makeChannelList(config, CHANNEL_LIST_AGE_MS); 639ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 640ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (freqs != null && freqs.size() != 0) { 641ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan int index = 0; 642ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan settings.channels = new WifiScanner.ChannelSpec[freqs.size()]; 643ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan for (Integer freq : freqs) { 644ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan settings.channels[index++] = new WifiScanner.ChannelSpec(freq); 645ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 646fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius return true; 64784d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 648fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius localLog("No scan channels for " + config.configKey() + ". Perform full band scan"); 649fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius return false; 65084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 65184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 65284d962ec8f487f824214744498bba505a6db0c59Randy Pan 65384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Watchdog timer handler 65484d962ec8f487f824214744498bba505a6db0c59Randy Pan private void watchdogHandler() { 65584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("watchdogHandler"); 65684d962ec8f487f824214744498bba505a6db0c59Randy Pan 65784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Schedule the next timer and start a single scan if we are in disconnected state. 65884d962ec8f487f824214744498bba505a6db0c59Randy Pan // Otherwise, the watchdog timer will be scheduled when entering disconnected 65984d962ec8f487f824214744498bba505a6db0c59Randy Pan // state. 66084d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_DISCONNECTED) { 66184d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "start a single scan from watchdogHandler"); 66284d962ec8f487f824214744498bba505a6db0c59Randy Pan 66384d962ec8f487f824214744498bba505a6db0c59Randy Pan scheduleWatchdogTimer(); 664304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan startSingleScan(true, true); 665ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 666ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 667ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 668ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Start a single scan and set up the interval for next single scan. 669ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private void startPeriodicSingleScan() { 670c2963eb07660a06592c60224279685166390217dRandy Pan long currentTimeStamp = mClock.elapsedRealtime(); 671c2963eb07660a06592c60224279685166390217dRandy Pan 672016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan if (mLastPeriodicSingleScanTimeStamp != RESET_TIME_STAMP) { 673c2963eb07660a06592c60224279685166390217dRandy Pan long msSinceLastScan = currentTimeStamp - mLastPeriodicSingleScanTimeStamp; 674c2963eb07660a06592c60224279685166390217dRandy Pan if (msSinceLastScan < PERIODIC_SCAN_INTERVAL_MS) { 675c2963eb07660a06592c60224279685166390217dRandy Pan localLog("Last periodic single scan started " + msSinceLastScan 676c2963eb07660a06592c60224279685166390217dRandy Pan + "ms ago, defer this new scan request."); 677c2963eb07660a06592c60224279685166390217dRandy Pan schedulePeriodicScanTimer(PERIODIC_SCAN_INTERVAL_MS - (int) msSinceLastScan); 678c2963eb07660a06592c60224279685166390217dRandy Pan return; 679c2963eb07660a06592c60224279685166390217dRandy Pan } 680c2963eb07660a06592c60224279685166390217dRandy Pan } 681c2963eb07660a06592c60224279685166390217dRandy Pan 682ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan boolean isFullBandScan = true; 683ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 684ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // If the WiFi traffic is heavy, only partial scan is initiated. 685ee9329dc901d59b8ae1e39edac99bd9d91306d2fRandy Pan if (mWifiState == WIFI_STATE_CONNECTED 686ee9329dc901d59b8ae1e39edac99bd9d91306d2fRandy Pan && (mWifiInfo.txSuccessRate 687ee9329dc901d59b8ae1e39edac99bd9d91306d2fRandy Pan > mConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS 688ee9329dc901d59b8ae1e39edac99bd9d91306d2fRandy Pan || mWifiInfo.rxSuccessRate 689ee9329dc901d59b8ae1e39edac99bd9d91306d2fRandy Pan > mConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS)) { 69046604d0d8d27c9dbdf986032de6e906e331f80ceRandy Pan localLog("No full band scan due to heavy traffic, txSuccessRate=" 69146604d0d8d27c9dbdf986032de6e906e331f80ceRandy Pan + mWifiInfo.txSuccessRate + " rxSuccessRate=" 69246604d0d8d27c9dbdf986032de6e906e331f80ceRandy Pan + mWifiInfo.rxSuccessRate); 693ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan isFullBandScan = false; 694ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 695ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 696c2963eb07660a06592c60224279685166390217dRandy Pan mLastPeriodicSingleScanTimeStamp = currentTimeStamp; 697304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan startSingleScan(false, isFullBandScan); 698ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan schedulePeriodicScanTimer(mPeriodicSingleScanInterval); 699ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan 700ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Set up the next scan interval in an exponential backoff fashion. 701ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan mPeriodicSingleScanInterval *= 2; 702ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (mPeriodicSingleScanInterval > MAX_PERIODIC_SCAN_INTERVAL_MS) { 703ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan mPeriodicSingleScanInterval = MAX_PERIODIC_SCAN_INTERVAL_MS; 70484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 70584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 70684d962ec8f487f824214744498bba505a6db0c59Randy Pan 707016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Reset the last periodic single scan time stamp so that the next periodic single 708016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // scan can start immediately. 709016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private void resetLastPeriodicSingleScanTimeStamp() { 710016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP; 711016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan } 712016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 71384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Periodic scan timer handler 71484d962ec8f487f824214744498bba505a6db0c59Randy Pan private void periodicScanTimerHandler() { 71584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("periodicScanTimerHandler"); 71684d962ec8f487f824214744498bba505a6db0c59Randy Pan 71784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Schedule the next timer and start a single scan if screen is on. 71884d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScreenOn) { 719ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan startPeriodicSingleScan(); 72084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 72184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 72284d962ec8f487f824214744498bba505a6db0c59Randy Pan 7233d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Start a single scan 724304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan private void startSingleScan(boolean isWatchdogTriggered, boolean isFullBandScan) { 725466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) { 72684d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 72784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 72884d962ec8f487f824214744498bba505a6db0c59Randy Pan 7293d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mPnoScanListener.resetLowRssiNetworkRetryDelay(); 7303d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 73184d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings settings = new ScanSettings(); 732ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan if (!isFullBandScan) { 733fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius if (!setScanChannels(settings)) { 734fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius isFullBandScan = true; 735fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius } 736ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan } 737fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius settings.band = getScanBand(isFullBandScan); 73884d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT 73984d962ec8f487f824214744498bba505a6db0c59Randy Pan | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 74084d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.numBssidsPerScan = 0; 74184d962ec8f487f824214744498bba505a6db0c59Randy Pan 74284d962ec8f487f824214744498bba505a6db0c59Randy Pan //Retrieve the list of hidden networkId's to scan for. 74384d962ec8f487f824214744498bba505a6db0c59Randy Pan Set<Integer> hiddenNetworkIds = mConfigManager.getHiddenConfiguredNetworkIds(); 74484d962ec8f487f824214744498bba505a6db0c59Randy Pan if (hiddenNetworkIds != null && hiddenNetworkIds.size() > 0) { 74584d962ec8f487f824214744498bba505a6db0c59Randy Pan int i = 0; 74684d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.hiddenNetworkIds = new int[hiddenNetworkIds.size()]; 74784d962ec8f487f824214744498bba505a6db0c59Randy Pan for (Integer netId : hiddenNetworkIds) { 74884d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.hiddenNetworkIds[i++] = netId; 74984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 75084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 75184d962ec8f487f824214744498bba505a6db0c59Randy Pan 75284d962ec8f487f824214744498bba505a6db0c59Randy Pan // re-enable this when b/27695292 is fixed 75384d962ec8f487f824214744498bba505a6db0c59Randy Pan // mSingleScanListener.clearScanDetails(); 75448444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills // mScanner.startScan(settings, mSingleScanListener, WIFI_WORK_SOURCE); 755ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan SingleScanListener singleScanListener = 756304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan new SingleScanListener(isWatchdogTriggered, isFullBandScan); 75748444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills mScanner.startScan(settings, singleScanListener, WIFI_WORK_SOURCE); 75884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 75984d962ec8f487f824214744498bba505a6db0c59Randy Pan 76084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a periodic scan when screen is on 761016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private void startPeriodicScan(boolean scanImmediately) { 7623d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mPnoScanListener.resetLowRssiNetworkRetryDelay(); 7633d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 764ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Due to b/28020168, timer based single scan will be scheduled 765ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // to provide periodic scan in an exponential backoff fashion. 76679e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_BACKGROUND_SCAN) { 767016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan if (scanImmediately) { 768016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan resetLastPeriodicSingleScanTimeStamp(); 769016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan } 770ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan mPeriodicSingleScanInterval = PERIODIC_SCAN_INTERVAL_MS; 771ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan startPeriodicSingleScan(); 77284d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 77384d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings settings = new ScanSettings(); 77484d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.band = getScanBand(); 77584d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT 77684d962ec8f487f824214744498bba505a6db0c59Randy Pan | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 77784d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.numBssidsPerScan = 0; 77884d962ec8f487f824214744498bba505a6db0c59Randy Pan settings.periodInMs = PERIODIC_SCAN_INTERVAL_MS; 77984d962ec8f487f824214744498bba505a6db0c59Randy Pan 78084d962ec8f487f824214744498bba505a6db0c59Randy Pan mPeriodicScanListener.clearScanDetails(); 78148444cb4214a48a3a0bf4bbb93945c2aa68c9980Mitchell Wills mScanner.startBackgroundScan(settings, mPeriodicScanListener, WIFI_WORK_SOURCE); 78284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 78384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 78484d962ec8f487f824214744498bba505a6db0c59Randy Pan 78584d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a DisconnectedPNO scan when screen is off and Wifi is disconnected 78684d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startDisconnectedPnoScan() { 78784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize PNO settings 78884d962ec8f487f824214744498bba505a6db0c59Randy Pan PnoSettings pnoSettings = new PnoSettings(); 78984d962ec8f487f824214744498bba505a6db0c59Randy Pan ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = 790329b3a9a9bc32d14649e91c15876ea7f95f148d1Roshan Pius mConfigManager.retrieveDisconnectedPnoNetworkList(); 79184d962ec8f487f824214744498bba505a6db0c59Randy Pan int listSize = pnoNetworkList.size(); 79284d962ec8f487f824214744498bba505a6db0c59Randy Pan 79384d962ec8f487f824214744498bba505a6db0c59Randy Pan if (listSize == 0) { 79484d962ec8f487f824214744498bba505a6db0c59Randy Pan // No saved network 79584d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("No saved network for starting disconnected PNO."); 79684d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 79784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 79884d962ec8f487f824214744498bba505a6db0c59Randy Pan 79984d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize]; 80084d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList); 80184d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min5GHzRssi = mMin5GHzRssi; 80284d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min24GHzRssi = mMin24GHzRssi; 80384d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.initialScoreMax = mInitialScoreMax; 80484d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.currentConnectionBonus = mCurrentConnectionBonus; 80584d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.sameNetworkBonus = mSameNetworkBonus; 80684d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.secureBonus = mSecureBonus; 80784d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.band5GHzBonus = mBand5GHzBonus; 80884d962ec8f487f824214744498bba505a6db0c59Randy Pan 80984d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize scan settings 81084d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings scanSettings = new ScanSettings(); 81184d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.band = getScanBand(); 81284d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; 81384d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.numBssidsPerScan = 0; 81479e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius scanSettings.periodInMs = DISCONNECTED_PNO_SCAN_INTERVAL_MS; 81584d962ec8f487f824214744498bba505a6db0c59Randy Pan // TODO: enable exponential back off scan later to further save energy 81684d962ec8f487f824214744498bba505a6db0c59Randy Pan // scanSettings.maxPeriodInMs = 8 * scanSettings.periodInMs; 81784d962ec8f487f824214744498bba505a6db0c59Randy Pan 81884d962ec8f487f824214744498bba505a6db0c59Randy Pan mPnoScanListener.clearScanDetails(); 81984d962ec8f487f824214744498bba505a6db0c59Randy Pan 82084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener); 82184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 82284d962ec8f487f824214744498bba505a6db0c59Randy Pan 82384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a ConnectedPNO scan when screen is off and Wifi is connected 82484d962ec8f487f824214744498bba505a6db0c59Randy Pan private void startConnectedPnoScan() { 82584d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disable ConnectedPNO for now due to b/28020168 82679e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_CONNECTED_PNO_SCAN) { 82784d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 82884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 82984d962ec8f487f824214744498bba505a6db0c59Randy Pan 83084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize PNO settings 83184d962ec8f487f824214744498bba505a6db0c59Randy Pan PnoSettings pnoSettings = new PnoSettings(); 83284d962ec8f487f824214744498bba505a6db0c59Randy Pan ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = 83384d962ec8f487f824214744498bba505a6db0c59Randy Pan mConfigManager.retrieveConnectedPnoNetworkList(); 83484d962ec8f487f824214744498bba505a6db0c59Randy Pan int listSize = pnoNetworkList.size(); 83584d962ec8f487f824214744498bba505a6db0c59Randy Pan 83684d962ec8f487f824214744498bba505a6db0c59Randy Pan if (listSize == 0) { 83784d962ec8f487f824214744498bba505a6db0c59Randy Pan // No saved network 83884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("No saved network for starting connected PNO."); 83984d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 84084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 84184d962ec8f487f824214744498bba505a6db0c59Randy Pan 84284d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = new PnoSettings.PnoNetwork[listSize]; 84384d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.networkList = pnoNetworkList.toArray(pnoSettings.networkList); 84484d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min5GHzRssi = mMin5GHzRssi; 84584d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.min24GHzRssi = mMin24GHzRssi; 84684d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.initialScoreMax = mInitialScoreMax; 84784d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.currentConnectionBonus = mCurrentConnectionBonus; 84884d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.sameNetworkBonus = mSameNetworkBonus; 84984d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.secureBonus = mSecureBonus; 85084d962ec8f487f824214744498bba505a6db0c59Randy Pan pnoSettings.band5GHzBonus = mBand5GHzBonus; 85184d962ec8f487f824214744498bba505a6db0c59Randy Pan 85284d962ec8f487f824214744498bba505a6db0c59Randy Pan // Initialize scan settings 85384d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanSettings scanSettings = new ScanSettings(); 85484d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.band = getScanBand(); 85584d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; 85684d962ec8f487f824214744498bba505a6db0c59Randy Pan scanSettings.numBssidsPerScan = 0; 85779e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius scanSettings.periodInMs = CONNECTED_PNO_SCAN_INTERVAL_MS; 85884d962ec8f487f824214744498bba505a6db0c59Randy Pan // TODO: enable exponential back off scan later to further save energy 85984d962ec8f487f824214744498bba505a6db0c59Randy Pan // scanSettings.maxPeriodInMs = 8 * scanSettings.periodInMs; 86084d962ec8f487f824214744498bba505a6db0c59Randy Pan 86184d962ec8f487f824214744498bba505a6db0c59Randy Pan mPnoScanListener.clearScanDetails(); 86284d962ec8f487f824214744498bba505a6db0c59Randy Pan 86384d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.startConnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener); 86484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 86584d962ec8f487f824214744498bba505a6db0c59Randy Pan 86684d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up watchdog timer 86784d962ec8f487f824214744498bba505a6db0c59Randy Pan private void scheduleWatchdogTimer() { 86884d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "scheduleWatchdogTimer"); 86984d962ec8f487f824214744498bba505a6db0c59Randy Pan 870ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 871ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + WATCHDOG_INTERVAL_MS, 8721d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius WATCHDOG_TIMER_TAG, 873c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mWatchdogListener, mEventHandler); 87484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 87584d962ec8f487f824214744498bba505a6db0c59Randy Pan 87684d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up periodic scan timer 877ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan private void schedulePeriodicScanTimer(int intervalMs) { 878ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 879ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + intervalMs, 8801d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius PERIODIC_SCAN_TIMER_TAG, 881c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mPeriodicScanTimerListener, mEventHandler); 88284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 88384d962ec8f487f824214744498bba505a6db0c59Randy Pan 88484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set up timer to start a delayed single scan after RESTART_SCAN_DELAY_MS 885304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan private void scheduleDelayedSingleScan(boolean isWatchdogTriggered, boolean isFullBandScan) { 88684d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("scheduleDelayedSingleScan"); 88784d962ec8f487f824214744498bba505a6db0c59Randy Pan 888bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius RestartSingleScanListener restartSingleScanListener = 889304d3451b9245f7c7bb5e81465561f0eb63b2473Randy Pan new RestartSingleScanListener(isWatchdogTriggered, isFullBandScan); 890ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 891ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + RESTART_SCAN_DELAY_MS, 8921d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius RESTART_SINGLE_SCAN_TIMER_TAG, 893bacd0dca59fbba9f650a421a3d3b0dc5fa2eb606Roshan Pius restartSingleScanListener, mEventHandler); 89484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 89584d962ec8f487f824214744498bba505a6db0c59Randy Pan 8963d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set up timer to start a delayed scan after msFromNow milli-seconds 8973d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan private void scheduleDelayedConnectivityScan(int msFromNow) { 89884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("scheduleDelayedConnectivityScan"); 89984d962ec8f487f824214744498bba505a6db0c59Randy Pan 900ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 901ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + msFromNow, 9021d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius RESTART_CONNECTIVITY_SCAN_TIMER_TAG, 903c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mRestartScanListener, mEventHandler); 90484d962ec8f487f824214744498bba505a6db0c59Randy Pan 90584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 90684d962ec8f487f824214744498bba505a6db0c59Randy Pan 90784d962ec8f487f824214744498bba505a6db0c59Randy Pan // Start a connectivity scan. The scan method is chosen according to 90884d962ec8f487f824214744498bba505a6db0c59Randy Pan // the current screen state and WiFi state. 909016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan private void startConnectivityScan(boolean scanImmediately) { 91084d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("startConnectivityScan: screenOn=" + mScreenOn 91184d962ec8f487f824214744498bba505a6db0c59Randy Pan + " wifiState=" + mWifiState 912016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan + " scanImmediately=" + scanImmediately 913466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + " wifiEnabled=" + mWifiEnabled 914466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + " wifiConnectivityManagerEnabled=" 915466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan + mWifiConnectivityManagerEnabled); 91684d962ec8f487f824214744498bba505a6db0c59Randy Pan 917466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) { 91884d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 91984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 92084d962ec8f487f824214744498bba505a6db0c59Randy Pan 92184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Always stop outstanding connecivity scan if there is any 92284d962ec8f487f824214744498bba505a6db0c59Randy Pan stopConnectivityScan(); 92384d962ec8f487f824214744498bba505a6db0c59Randy Pan 92484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Don't start a connectivity scan while Wifi is in the transition 92584d962ec8f487f824214744498bba505a6db0c59Randy Pan // between connected and disconnected states. 92684d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) { 92784d962ec8f487f824214744498bba505a6db0c59Randy Pan return; 92884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 92984d962ec8f487f824214744498bba505a6db0c59Randy Pan 93084d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mScreenOn) { 931016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startPeriodicScan(scanImmediately); 93284d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { // screenOff 93384d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_CONNECTED) { 93484d962ec8f487f824214744498bba505a6db0c59Randy Pan startConnectedPnoScan(); 93584d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 93684d962ec8f487f824214744498bba505a6db0c59Randy Pan startDisconnectedPnoScan(); 93784d962ec8f487f824214744498bba505a6db0c59Randy Pan } 93884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 93984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 94084d962ec8f487f824214744498bba505a6db0c59Randy Pan 94184d962ec8f487f824214744498bba505a6db0c59Randy Pan // Stop connectivity scan if there is any. 94284d962ec8f487f824214744498bba505a6db0c59Randy Pan private void stopConnectivityScan() { 943ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // Due to b/28020168, timer based single scan will be scheduled 944ae9e0ef3efdd579fab8d89b5c653f4069e7ac883Randy Pan // to provide periodic scan in an exponential backoff fashion. 94579e3bf8db6b566a5b3c7065cdd43f87f07e73747Roshan Pius if (!ENABLE_BACKGROUND_SCAN) { 94684d962ec8f487f824214744498bba505a6db0c59Randy Pan mAlarmManager.cancel(mPeriodicScanTimerListener); 94784d962ec8f487f824214744498bba505a6db0c59Randy Pan } else { 94884d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanner.stopBackgroundScan(mPeriodicScanListener); 94984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 950f37079e3d8f4aca3242a971cbaef732fe1b75bdeRoshan Pius mScanner.stopPnoScan(mPnoScanListener); 95184d962ec8f487f824214744498bba505a6db0c59Randy Pan mScanRestartCount = 0; 95284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 95384d962ec8f487f824214744498bba505a6db0c59Randy Pan 95484d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 95584d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for screen state (on/off) changes 95684d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 95784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void handleScreenStateChanged(boolean screenOn) { 95884d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("handleScreenStateChanged: screenOn=" + screenOn); 95984d962ec8f487f824214744498bba505a6db0c59Randy Pan 96084d962ec8f487f824214744498bba505a6db0c59Randy Pan mScreenOn = screenOn; 96184d962ec8f487f824214744498bba505a6db0c59Randy Pan 962016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_ON_SCHEDULE); 96384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 96484d962ec8f487f824214744498bba505a6db0c59Randy Pan 96584d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 96684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for WiFi state (connected/disconnected) changes 96784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 96884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void handleConnectionStateChanged(int state) { 96984d962ec8f487f824214744498bba505a6db0c59Randy Pan localLog("handleConnectionStateChanged: state=" + state); 97084d962ec8f487f824214744498bba505a6db0c59Randy Pan 97184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiState = state; 97284d962ec8f487f824214744498bba505a6db0c59Randy Pan 97384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Kick off the watchdog timer if entering disconnected state 97484d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mWifiState == WIFI_STATE_DISCONNECTED) { 97584d962ec8f487f824214744498bba505a6db0c59Randy Pan scheduleWatchdogTimer(); 97684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 97784d962ec8f487f824214744498bba505a6db0c59Randy Pan 978016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_ON_SCHEDULE); 97984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 98084d962ec8f487f824214744498bba505a6db0c59Randy Pan 98184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 98284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler when user toggles whether untrusted connection is allowed 98384d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 98484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setUntrustedConnectionAllowed(boolean allowed) { 98584d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "setUntrustedConnectionAllowed: allowed=" + allowed); 98684d962ec8f487f824214744498bba505a6db0c59Randy Pan 98784d962ec8f487f824214744498bba505a6db0c59Randy Pan if (mUntrustedConnectionAllowed != allowed) { 98884d962ec8f487f824214744498bba505a6db0c59Randy Pan mUntrustedConnectionAllowed = allowed; 989016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_IMMEDIATELY); 99084d962ec8f487f824214744498bba505a6db0c59Randy Pan } 99184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 99284d962ec8f487f824214744498bba505a6db0c59Randy Pan 99384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 99484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler when user specifies a particular network to connect to 99584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 99684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void connectToUserSelectNetwork(int netId, boolean persistent) { 99784d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "connectToUserSelectNetwork: netId=" + netId 99884d962ec8f487f824214744498bba505a6db0c59Randy Pan + " persist=" + persistent); 99984d962ec8f487f824214744498bba505a6db0c59Randy Pan 100084d962ec8f487f824214744498bba505a6db0c59Randy Pan mQualifiedNetworkSelector.userSelectNetwork(netId, persistent); 100184d962ec8f487f824214744498bba505a6db0c59Randy Pan 10024f5054647a2f4cac54a78d6e3bf3efa0727b488aRoshan Pius clearConnectionAttemptTimeStamps(); 100384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 100484d962ec8f487f824214744498bba505a6db0c59Randy Pan 100584d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 100684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Handler for on-demand connectivity scan 100784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 100884d962ec8f487f824214744498bba505a6db0c59Randy Pan public void forceConnectivityScan() { 100984d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "forceConnectivityScan"); 101084d962ec8f487f824214744498bba505a6db0c59Randy Pan 1011016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_IMMEDIATELY); 101284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 101384d962ec8f487f824214744498bba505a6db0c59Randy Pan 101484d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 101584d962ec8f487f824214744498bba505a6db0c59Randy Pan * Track whether a BSSID should be enabled or disabled for QNS 101684d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 101784d962ec8f487f824214744498bba505a6db0c59Randy Pan public boolean trackBssid(String bssid, boolean enable) { 101884d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "trackBssid: " + (enable ? "enable " : "disable ") + bssid); 101984d962ec8f487f824214744498bba505a6db0c59Randy Pan 102084d962ec8f487f824214744498bba505a6db0c59Randy Pan boolean ret = mQualifiedNetworkSelector 102184d962ec8f487f824214744498bba505a6db0c59Randy Pan .enableBssidForQualityNetworkSelection(bssid, enable); 102284d962ec8f487f824214744498bba505a6db0c59Randy Pan 102384d962ec8f487f824214744498bba505a6db0c59Randy Pan if (ret && !enable) { 102484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Disabling a BSSID can happen when the AP candidate to connect to has 102584d962ec8f487f824214744498bba505a6db0c59Randy Pan // no capacity for new stations. We start another scan immediately so that QNS 102684d962ec8f487f824214744498bba505a6db0c59Randy Pan // can give us another candidate to connect to. 1027016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_IMMEDIATELY); 102884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 102984d962ec8f487f824214744498bba505a6db0c59Randy Pan 103084d962ec8f487f824214744498bba505a6db0c59Randy Pan return ret; 103184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 103284d962ec8f487f824214744498bba505a6db0c59Randy Pan 103384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 103484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Set band preference when doing scan and making connection 103584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 103684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setUserPreferredBand(int band) { 103784d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "User band preference: " + band); 103884d962ec8f487f824214744498bba505a6db0c59Randy Pan 103984d962ec8f487f824214744498bba505a6db0c59Randy Pan mQualifiedNetworkSelector.setUserPreferredBand(band); 1040016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan startConnectivityScan(SCAN_IMMEDIATELY); 104184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 104284d962ec8f487f824214744498bba505a6db0c59Randy Pan 104384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 104484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Inform WiFi is enabled for connection or not 104584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 104684d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setWifiEnabled(boolean enable) { 104784d962ec8f487f824214744498bba505a6db0c59Randy Pan Log.i(TAG, "Set WiFi " + (enable ? "enabled" : "disabled")); 104884d962ec8f487f824214744498bba505a6db0c59Randy Pan 104984d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiEnabled = enable; 105084d962ec8f487f824214744498bba505a6db0c59Randy Pan 105184d962ec8f487f824214744498bba505a6db0c59Randy Pan if (!mWifiEnabled) { 105284d962ec8f487f824214744498bba505a6db0c59Randy Pan stopConnectivityScan(); 1053016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan resetLastPeriodicSingleScanTimeStamp(); 105484d962ec8f487f824214744498bba505a6db0c59Randy Pan } 105584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 105684d962ec8f487f824214744498bba505a6db0c59Randy Pan 105784d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 1058466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan * Turn on/off the WifiConnectivityMangager at runtime 1059466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan */ 1060466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan public void enable(boolean enable) { 1061466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan Log.i(TAG, "Set WiFiConnectivityManager " + (enable ? "enabled" : "disabled")); 1062466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 1063466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan mWifiConnectivityManagerEnabled = enable; 1064466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 1065466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan if (!mWifiConnectivityManagerEnabled) { 1066466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan stopConnectivityScan(); 1067016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan resetLastPeriodicSingleScanTimeStamp(); 1068466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan } 1069466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan } 1070466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan 1071466158a6669d51541ce6c5c4e04a71dad36cdb4eRandy Pan /** 107284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Enable/disable verbose logging 107384d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 107484d962ec8f487f824214744498bba505a6db0c59Randy Pan public void enableVerboseLogging(int verbose) { 107584d962ec8f487f824214744498bba505a6db0c59Randy Pan mDbg = verbose > 0; 107684d962ec8f487f824214744498bba505a6db0c59Randy Pan } 107784d962ec8f487f824214744498bba505a6db0c59Randy Pan 107884d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 107984d962ec8f487f824214744498bba505a6db0c59Randy Pan * Dump the local log buffer 108084d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 108184d962ec8f487f824214744498bba505a6db0c59Randy Pan public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 108284d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("Dump of WifiConnectivityManager"); 108384d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("WifiConnectivityManager - Log Begin ----"); 108450abba06efa7834b5309df561375e4a2e2df630dRandy Pan pw.println("WifiConnectivityManager - Number of connectivity attempts rate limited: " 108550abba06efa7834b5309df561375e4a2e2df630dRandy Pan + mTotalConnectivityAttemptsRateLimited); 108684d962ec8f487f824214744498bba505a6db0c59Randy Pan mLocalLog.dump(fd, pw, args); 108784d962ec8f487f824214744498bba505a6db0c59Randy Pan pw.println("WifiConnectivityManager - Log End ----"); 108884d962ec8f487f824214744498bba505a6db0c59Randy Pan } 10893d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 10903d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan @VisibleForTesting 10913d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan int getLowRssiNetworkRetryDelay() { 10923d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan return mPnoScanListener.getLowRssiNetworkRetryDelay(); 10933d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 1094016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 1095016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan @VisibleForTesting 1096016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan long getLastPeriodicSingleScanTimeStamp() { 1097016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan return mLastPeriodicSingleScanTimeStamp; 1098016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan } 109984d962ec8f487f824214744498bba505a6db0c59Randy Pan} 1100