19ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills/* 29ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Copyright (C) 2015 The Android Open Source Project 39ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * 49ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Licensed under the Apache License, Version 2.0 (the "License"); 59ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * you may not use this file except in compliance with the License. 69ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * You may obtain a copy of the License at 79ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * 89ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * http://www.apache.org/licenses/LICENSE-2.0 99ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * 109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Unless required by applicable law or agreed to in writing, software 119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * distributed under the License is distributed on an "AS IS" BASIS, 129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * See the License for the specific language governing permissions and 149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * limitations under the License. 159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 17a8367288377cbaed6371256ca837b7aa22280706Mitchell Willspackage com.android.server.wifi.scanner; 189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.app.AlarmManager; 209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.content.Context; 219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.net.wifi.ScanResult; 229153bd67d51b305ffdd61355e0748e3c332c2cafRoshan Piusimport android.net.wifi.WifiConfiguration; 239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.net.wifi.WifiScanner; 249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Handler; 259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Looper; 269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Message; 279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.util.Log; 289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2962bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Piusimport com.android.internal.R; 30ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Piusimport com.android.server.wifi.Clock; 31a8367288377cbaed6371256ca837b7aa22280706Mitchell Willsimport com.android.server.wifi.ScanDetail; 32a8367288377cbaed6371256ca837b7aa22280706Mitchell Willsimport com.android.server.wifi.WifiMonitor; 33a8367288377cbaed6371256ca837b7aa22280706Mitchell Willsimport com.android.server.wifi.WifiNative; 347e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Willsimport com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; 357e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills 369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayDeque; 379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayList; 389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Arrays; 399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Collections; 40d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Piusimport java.util.HashSet; 419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.List; 429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Set; 439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 44f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills/** 455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills * Implementation of the WifiScanner HAL API that uses wpa_supplicant to perform all scans 46a8367288377cbaed6371256ca837b7aa22280706Mitchell Wills * @see com.android.server.wifi.scanner.WifiScannerImpl for more details on each method. 47f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills */ 489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willspublic class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handler.Callback { 499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final String TAG = "SupplicantWifiScannerImpl"; 509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final boolean DBG = false; 519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 529d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills public static final String BACKGROUND_PERIOD_ALARM_TAG = TAG + " Background Scan Period"; 539d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills public static final String TIMEOUT_ALARM_TAG = TAG + " Scan Timeout"; 54362fad8eddd674d7cf19ffcc1fec38d2d2ee2f53Roshan Pius // Max number of networks that can be specified to wpa_supplicant per scan request 55362fad8eddd674d7cf19ffcc1fec38d2d2ee2f53Roshan Pius public static final int MAX_HIDDEN_NETWORK_IDS_PER_SCAN = 16; 569d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills 579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int SCAN_BUFFER_CAPACITY = 10; 589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int MAX_APS_PER_SCAN = 32; 599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int MAX_SCAN_BUCKETS = 16; 609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final String ACTION_SCAN_PERIOD = 629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills "com.android.server.util.SupplicantWifiScannerImpl.action.SCAN_PERIOD"; 639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final Context mContext; 659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final WifiNative mWifiNative; 669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final AlarmManager mAlarmManager; 679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final Handler mEventHandler; 687e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills private final ChannelHelper mChannelHelper; 69ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius private final Clock mClock; 709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private Object mSettingsLock = new Object(); 729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Next scan settings to apply when the previous scan completes 745fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mPendingBackgroundScanSettings = null; 755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mPendingBackgroundScanEventHandler = null; 765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mPendingSingleScanSettings = null; 775fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mPendingSingleScanEventHandler = null; 785fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Active background scan settings/state 805fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mBackgroundScanSettings = null; 815fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mBackgroundScanEventHandler = null; 825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mNextBackgroundScanPeriod = 0; 835fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mNextBackgroundScanId = 0; 845fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private boolean mBackgroundScanPeriodPending = false; 855fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private boolean mBackgroundScanPaused = false; 865fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private ScanBuffer mBackgroundScanBuffer = new ScanBuffer(SCAN_BUFFER_CAPACITY); 875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 885fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiScanner.ScanData mLatestSingleScanResult = 895fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills new WifiScanner.ScanData(0, 0, new ScanResult[0]); 905fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 915fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Settings for the currently running scan, null if no scan active 929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private LastScanSettings mLastScanSettings = null; 939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Active hotlist settings 959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.HotlistEventHandler mHotlistHandler = null; 969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ChangeBuffer mHotlistChangeBuffer = new ChangeBuffer(); 979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 989153bd67d51b305ffdd61355e0748e3c332c2cafRoshan Pius // Pno related info. 99063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius private WifiNative.PnoSettings mPnoSettings = null; 1009153bd67d51b305ffdd61355e0748e3c332c2cafRoshan Pius private WifiNative.PnoEventHandler mPnoEventHandler; 10162bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius private final boolean mHwPnoScanSupported; 102e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final HwPnoDebouncer mHwPnoDebouncer; 103e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final HwPnoDebouncer.Listener mHwPnoDebouncerListener = new HwPnoDebouncer.Listener() { 104e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public void onPnoScanFailed() { 105e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius Log.e(TAG, "Pno scan failure received"); 106e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius reportPnoScanFailure(); 107e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 108e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius }; 1099153bd67d51b305ffdd61355e0748e3c332c2cafRoshan Pius 1109d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills /** 1119d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills * Duration to wait before timing out a scan. 1129d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills * 1139d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills * The expected behavior is that the hardware will return a failed scan if it does not 1149d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills * complete, but timeout just in case it does not. 1159d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills */ 116a85fc1b07490d3ff194a98fe7389f6697ace5801Roshan Pius private static final long SCAN_TIMEOUT_MS = 15000; 1179d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills 11841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills AlarmManager.OnAlarmListener mScanPeriodListener = new AlarmManager.OnAlarmListener() { 11941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills public void onAlarm() { 12041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills synchronized (mSettingsLock) { 12141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills handleScanPeriod(); 12241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 12341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 12441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills }; 12541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 1269d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills AlarmManager.OnAlarmListener mScanTimeoutListener = new AlarmManager.OnAlarmListener() { 1279d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills public void onAlarm() { 1289d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills synchronized (mSettingsLock) { 1299d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills handleScanTimeout(); 1309d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 1319d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 1329d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills }; 1339d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills 1342332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius public SupplicantWifiScannerImpl(Context context, WifiNative wifiNative, 135ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius ChannelHelper channelHelper, Looper looper, Clock clock) { 1369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mContext = context; 1379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mWifiNative = wifiNative; 1382332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius mChannelHelper = channelHelper; 1399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 1409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mEventHandler = new Handler(looper, this); 141ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock = clock; 142ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mHwPnoDebouncer = new HwPnoDebouncer(mWifiNative, mAlarmManager, mEventHandler, mClock); 1437d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills 14462bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius // Check if the device supports HW PNO scans. 14562bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius mHwPnoScanSupported = mContext.getResources().getBoolean( 14662bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius R.bool.config_wifi_background_scan_support); 14762bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius 1488adb4e72f58e3e25918f33e0b2687e6acc14c47dMitchell Wills WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 1498adb4e72f58e3e25918f33e0b2687e6acc14c47dMitchell Wills WifiMonitor.SCAN_FAILED_EVENT, mEventHandler); 1508adb4e72f58e3e25918f33e0b2687e6acc14c47dMitchell Wills WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 1518adb4e72f58e3e25918f33e0b2687e6acc14c47dMitchell Wills WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler); 1529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 154ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius public SupplicantWifiScannerImpl(Context context, WifiNative wifiNative, Looper looper, 155ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius Clock clock) { 1562332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius // TODO figure out how to get channel information from supplicant 157ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius this(context, wifiNative, new NoBandChannelHelper(), looper, clock); 1582332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 1592332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 1609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1611e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills public void cleanup() { 1621e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills synchronized (mSettingsLock) { 1631e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills mPendingSingleScanSettings = null; 1641e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills mPendingSingleScanEventHandler = null; 16562bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius stopHwPnoScan(); 1661e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills stopBatchedScan(); 1671e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills resetHotlist(); 1681e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills untrackSignificantWifiChange(); 1691e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills mLastScanSettings = null; // finally clear any active scan 1701e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills } 1711e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills } 1721e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills 1731e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills @Override 1749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 1759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_cache_size = Integer.MAX_VALUE; 1769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_buckets = MAX_SCAN_BUCKETS; 1779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_ap_cache_per_scan = MAX_APS_PER_SCAN; 1789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_rssi_sample_size = 8; 1799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_reporting_threshold = SCAN_BUFFER_CAPACITY; 1809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_hotlist_bssids = 0; 1819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_significant_wifi_change_aps = 0; 1825ed43368643dab64c83bfb15e14ab59d63645c6fMitchell Wills return true; 1839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1867e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills public ChannelHelper getChannelHelper() { 1877e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills return mChannelHelper; 1887e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills } 1897e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills 1907e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills @Override 191f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills public boolean startSingleScan(WifiNative.ScanSettings settings, 192f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills WifiNative.ScanEventHandler eventHandler) { 1935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (eventHandler == null || settings == null) { 1945fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "Invalid arguments for startSingleScan: settings=" + settings 1955fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ",eventHandler=" + eventHandler); 1965fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return false; 1975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1985fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingSingleScanSettings != null 1995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings != null && mLastScanSettings.singleScanActive)) { 2005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "A single scan is already running"); 2015fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return false; 2025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings = settings; 2055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler = eventHandler; 2065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 2075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return true; 2085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 209f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills } 210f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills 211f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills @Override 212f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills public WifiScanner.ScanData getLatestSingleScanResults() { 2135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return mLatestSingleScanResult; 214f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills } 215f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills 216f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills @Override 2179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean startBatchedScan(WifiNative.ScanSettings settings, 2189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.ScanEventHandler eventHandler) { 2195fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings == null || eventHandler == null) { 2205fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "Invalid arguments for startBatched: settings=" + settings 2215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ",eventHandler=" + eventHandler); 2229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.max_ap_per_scan < 0 || settings.max_ap_per_scan > MAX_APS_PER_SCAN) { 2269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2275fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.num_buckets < 0 || settings.num_buckets > MAX_SCAN_BUCKETS) { 2299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.report_threshold_num_scans < 0 2325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || settings.report_threshold_num_scans > SCAN_BUFFER_CAPACITY) { 2339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.report_threshold_percent < 0 || settings.report_threshold_percent > 100) { 2369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.base_period_ms <= 0) { 2399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2405fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < settings.num_buckets; ++i) { 2429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.BucketSettings bucket = settings.buckets[i]; 2435fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bucket.period_ms % settings.base_period_ms != 0) { 2449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 2455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2485fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills stopBatchedScan(); 2505cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills if (DBG) { 2515cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills Log.d(TAG, "Starting scan num_buckets=" + settings.num_buckets + ", base_period=" 2525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + settings.base_period_ms + " ms"); 2535cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills } 2545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = settings; 2555fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = eventHandler; 2569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); // Try to start scan immediately 2579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 2589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 2629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void stopBatchedScan() { 2635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Stopping scan"); 2655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = null; 2665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = null; 2675fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = null; 2685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = null; 2695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = false; 2705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 2719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 2729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2731e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills processPendingScans(); 2749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 2779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void pauseBatchedScan() { 2785fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Pausing scan"); 2809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // if there isn't a pending scan then make the current scan pending 2815fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanSettings == null) { 2825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = mBackgroundScanSettings; 2835fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = mBackgroundScanEventHandler; 2849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2855fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = null; 2865fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = null; 2875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 2885fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = true; 2899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 2919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiScanner.ScanData[] results = getLatestBatchedScanResults(/* flush = */ true); 2935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanEventHandler != null) { 2945fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler.onScanPaused(results); 2955fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2971e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills processPendingScans(); 2989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 3019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void restartBatchedScan() { 3025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 3035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Restarting scan"); 3045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanEventHandler != null) { 3055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler.onScanRestarted(); 3065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = false; 3089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); 3099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void unscheduleScansLocked() { 31341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mAlarmManager.cancel(mScanPeriodListener); 3141e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills if (mLastScanSettings != null) { 3151e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills mLastScanSettings.backgroundScanActive = false; 3161e806a7aac77f6f65ba299329e1fc452e0148b8dMitchell Wills } 3179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void handleScanPeriod() { 3205fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 3215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = true; 3225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 3235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 3269d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills private void handleScanTimeout() { 3279d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills Log.e(TAG, "Timed out waiting for scan result from supplicant"); 3289d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills reportScanFailure(); 3299d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills processPendingScans(); 3309d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 3319d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills 3321bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius private boolean isDifferentPnoScanSettings(LastScanSettings newScanSettings) { 3331bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius return (mLastScanSettings == null || !Arrays.equals( 3341bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius newScanSettings.pnoNetworkList, mLastScanSettings.pnoNetworkList)); 3351bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius } 3361bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius 3375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private void processPendingScans() { 3385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 33962bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius // Wait for the active scan result to come back to reschedule other scans, 34062bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius // unless if HW pno scan is running. Hw PNO scans are paused it if there 34162bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius // are other pending scans, 34262bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius if (mLastScanSettings != null && !mLastScanSettings.hwPnoScanActive) { 3439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 3449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3467e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills ChannelCollection allFreqs = mChannelHelper.createChannelCollection(); 347d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius Set<Integer> hiddenNetworkIdSet = new HashSet<Integer>(); 34863539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills final LastScanSettings newScanSettings = 349ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius new LastScanSettings(mClock.elapsedRealtime()); 3509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3515fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Update scan settings if there is a pending scan 3525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (!mBackgroundScanPaused) { 3535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanSettings != null) { 3545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = mPendingBackgroundScanSettings; 3555fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = mPendingBackgroundScanEventHandler; 3565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mNextBackgroundScanPeriod = 0; 3575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = null; 3585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = null; 3595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = true; 3605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3610d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if (mBackgroundScanPeriodPending && mBackgroundScanSettings != null) { 3620d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal int reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; // default to no batch 3630d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal for (int bucket_id = 0; bucket_id < mBackgroundScanSettings.num_buckets; 3640d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal ++bucket_id) { 3650d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal WifiNative.BucketSettings bucket = 3660d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal mBackgroundScanSettings.buckets[bucket_id]; 3670d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if (mNextBackgroundScanPeriod % (bucket.period_ms 3680d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal / mBackgroundScanSettings.base_period_ms) == 0) { 3690d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if ((bucket.report_events 3700d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0) { 3710d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal reportEvents |= WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 3729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3730d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if ((bucket.report_events 3740d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 3750d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal reportEvents |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 3760d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal } 3770d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal // only no batch if all buckets specify it 3780d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if ((bucket.report_events 3790d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 3800d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal reportEvents &= ~WifiScanner.REPORT_EVENT_NO_BATCH; 3810d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal } 3820d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal 3830d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal allFreqs.addChannels(bucket); 3849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3850d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal } 3860d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if (!allFreqs.isEmpty()) { 3870d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal newScanSettings.setBackgroundScan(mNextBackgroundScanId++, 3880d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal mBackgroundScanSettings.max_ap_per_scan, reportEvents, 3890d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal mBackgroundScanSettings.report_threshold_num_scans, 3900d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal mBackgroundScanSettings.report_threshold_percent); 3910d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal } 39262bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius 3930d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal int[] hiddenNetworkIds = mBackgroundScanSettings.hiddenNetworkIds; 3940d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal if (hiddenNetworkIds != null) { 3950d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal int numHiddenNetworkIds = Math.min(hiddenNetworkIds.length, 3960d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal MAX_HIDDEN_NETWORK_IDS_PER_SCAN); 3970d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal for (int i = 0; i < numHiddenNetworkIds; i++) { 3980d0a4c339b3950ad6d882e89223dc21a89ef3953John Eckerdal hiddenNetworkIdSet.add(hiddenNetworkIds[i]); 399d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius } 4009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4015fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 4025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mNextBackgroundScanPeriod++; 4035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 404ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 405ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + mBackgroundScanSettings.base_period_ms, 4069d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills BACKGROUND_PERIOD_ALARM_TAG, mScanPeriodListener, mEventHandler); 4079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4095fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 4105fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingSingleScanSettings != null) { 4115fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills boolean reportFullResults = false; 4127e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills ChannelCollection singleScanFreqs = mChannelHelper.createChannelCollection(); 4135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < mPendingSingleScanSettings.num_buckets; ++i) { 4145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.BucketSettings bucketSettings = 4155fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings.buckets[i]; 4165fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((bucketSettings.report_events 4175fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 4185fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills reportFullResults = true; 4199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4207e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills singleScanFreqs.addChannels(bucketSettings); 4217e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills allFreqs.addChannels(bucketSettings); 4229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills newScanSettings.setSingleScan(reportFullResults, singleScanFreqs, 4245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler); 425d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius int[] hiddenNetworkIds = mPendingSingleScanSettings.hiddenNetworkIds; 426d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius if (hiddenNetworkIds != null) { 427362fad8eddd674d7cf19ffcc1fec38d2d2ee2f53Roshan Pius int numHiddenNetworkIds = Math.min(hiddenNetworkIds.length, 428362fad8eddd674d7cf19ffcc1fec38d2d2ee2f53Roshan Pius MAX_HIDDEN_NETWORK_IDS_PER_SCAN); 429362fad8eddd674d7cf19ffcc1fec38d2d2ee2f53Roshan Pius for (int i = 0; i < numHiddenNetworkIds; i++) { 430d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius hiddenNetworkIdSet.add(hiddenNetworkIds[i]); 431d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius } 432d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius } 4335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings = null; 4345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler = null; 4355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 43762bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius if ((newScanSettings.backgroundScanActive || newScanSettings.singleScanActive) 43862bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius && !allFreqs.isEmpty()) { 43962bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius pauseHwPnoScan(); 4407e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills Set<Integer> freqs = allFreqs.getSupplicantScanFreqs(); 441d74ff28cdb01d3f711e0b0f0e99e51fdb221eaf2Roshan Pius boolean success = mWifiNative.scan(freqs, hiddenNetworkIdSet); 4425fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (success) { 4435fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // TODO handle scan timeout 4445cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills if (DBG) { 4455cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills Log.d(TAG, "Starting wifi scan for freqs=" + freqs 4465cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills + ", background=" + newScanSettings.backgroundScanActive 4475cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills + ", single=" + newScanSettings.singleScanActive); 4485cdc80d103ebd2935693a8d855162d55bed2821cMitchell Wills } 4495fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings = newScanSettings; 450ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 451ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + SCAN_TIMEOUT_MS, 4529d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler); 4535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 45463539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills Log.e(TAG, "Failed to start scan, freqs=" + freqs); 45563539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills // indicate scan failure async 45663539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills mEventHandler.post(new Runnable() { 45763539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills public void run() { 45863539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills if (newScanSettings.singleScanEventHandler != null) { 45963539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills newScanSettings.singleScanEventHandler 46063539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills .onScanStatus(WifiNative.WIFI_SCAN_FAILED); 46163539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills } 46263539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills } 46363539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills }); 4649d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills // TODO(b/27769665) background scans should be failed too if scans fail enough 4655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 466dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius } else if (isHwPnoScanRequired()) { 4671bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius newScanSettings.setHwPnoScan(mPnoSettings.networkList, mPnoEventHandler); 4681bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius boolean status; 4691bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius // If the PNO network list has changed from the previous request, ensure that 4701bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius // we bypass the debounce logic and restart PNO scan. 4711bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius if (isDifferentPnoScanSettings(newScanSettings)) { 4721bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius status = restartHwPnoScan(); 4731bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius } else { 4741bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius status = startHwPnoScan(); 4751bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius } 4761bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius if (status) { 477063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mLastScanSettings = newScanSettings; 478063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } else { 479063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius Log.e(TAG, "Failed to start PNO scan"); 480063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius // indicate scan failure async 481063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mEventHandler.post(new Runnable() { 482063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius public void run() { 483063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius if (mPnoEventHandler != null) { 484063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mPnoEventHandler.onPnoScanFailed(); 485063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 486063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius // Clean up PNO state, we don't want to continue PNO scanning. 487063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mPnoSettings = null; 488063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mPnoEventHandler = null; 489063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 490063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius }); 491063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 4929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 4979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean handleMessage(Message msg) { 4989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills switch(msg.what) { 4999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_FAILED_EVENT: 5009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.w(TAG, "Scan failed"); 5019d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills mAlarmManager.cancel(mScanTimeoutListener); 5029d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills reportScanFailure(); 5035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 5049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 5059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_RESULTS_EVENT: 5069d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills mAlarmManager.cancel(mScanTimeoutListener); 5079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills pollLatestScanData(); 5085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 5099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 5109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills default: 5119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // ignore unknown event 5129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 5149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5169d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills private void reportScanFailure() { 5179d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills synchronized (mSettingsLock) { 5189d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills if (mLastScanSettings != null) { 5199d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills if (mLastScanSettings.singleScanEventHandler != null) { 5209d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills mLastScanSettings.singleScanEventHandler 5219d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills .onScanStatus(WifiNative.WIFI_SCAN_FAILED); 5229d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 5239d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills // TODO(b/27769665) background scans should be failed too if scans fail enough 5249d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills mLastScanSettings = null; 5259d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 5269d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 5279d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills } 5289d0c558cab7c80a572a32ae70d501df15367fd5fMitchell Wills 529e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private void reportPnoScanFailure() { 530e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius synchronized (mSettingsLock) { 531e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (mLastScanSettings != null && mLastScanSettings.hwPnoScanActive) { 532e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (mLastScanSettings.pnoScanEventHandler != null) { 533e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mLastScanSettings.pnoScanEventHandler.onPnoScanFailed(); 534e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 535e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius // Clean up PNO state, we don't want to continue PNO scanning. 536e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mPnoSettings = null; 537e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mPnoEventHandler = null; 538e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mLastScanSettings = null; 539e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 540e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 541e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 542e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 5439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void pollLatestScanData() { 5445fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 5455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings == null) { 5469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // got a scan before we started scanning or after scan was canceled 5479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 5489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5505fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Polling scan data for scan: " + mLastScanSettings.scanId); 5519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanDetail> nativeResults = mWifiNative.getScanResults(); 5525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills List<ScanResult> singleScanResults = new ArrayList<>(); 5535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills List<ScanResult> backgroundScanResults = new ArrayList<>(); 55462bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius List<ScanResult> hwPnoScanResults = new ArrayList<>(); 5559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < nativeResults.size(); ++i) { 5569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = nativeResults.get(i).getScanResult(); 5579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills long timestamp_ms = result.timestamp / 1000; // convert us -> ms 5589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (timestamp_ms > mLastScanSettings.startTime) { 5595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.backgroundScanActive) { 5605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills backgroundScanResults.add(result); 5615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 5625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.singleScanActive 5637e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills && mLastScanSettings.singleScanFreqs.containsChannel( 5647e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills result.frequency)) { 5655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanResults.add(result); 5665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 56762bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius if (mLastScanSettings.hwPnoScanActive) { 56862bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius hwPnoScanResults.add(result); 569063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 5705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 5719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // was a cached result in wpa_supplicant 5729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 57441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 5755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.backgroundScanActive) { 5765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanEventHandler != null) { 5775fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents 5785fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 5795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (ScanResult scanResult : backgroundScanResults) { 580c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills // TODO(b/27506257): Fill in correct bucketsScanned value 581c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills mBackgroundScanEventHandler.onFullScanResult(scanResult, 0); 5825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 58341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 58441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 58541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 5862771787818003e53e8175036a3d09688c783f350Mitchell Wills Collections.sort(backgroundScanResults, SCAN_RESULT_SORT_COMPARATOR); 5875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills ScanResult[] scanResultsArray = new ScanResult[Math.min(mLastScanSettings.maxAps, 5885fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills backgroundScanResults.size())]; 5895fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < scanResultsArray.length; ++i) { 5905fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills scanResultsArray[i] = backgroundScanResults.get(i); 5915fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 5929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 594c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills // TODO(b/27506257): Fill in correct bucketsScanned value 5955fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanBuffer.add(new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 5965fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills scanResultsArray)); 5975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 5989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanEventHandler != null) { 6005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents 6015fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0 6025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings.reportEvents 6035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0 6045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings.reportEvents 6055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills == WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL 6065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills && (mBackgroundScanBuffer.size() 6075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills >= (mBackgroundScanBuffer.capacity() 6085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills * mLastScanSettings.reportPercentThreshold 6095fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills / 100) 6105fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || mBackgroundScanBuffer.size() 6115fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills >= mLastScanSettings.reportNumScansThreshold))) { 61263539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills mBackgroundScanEventHandler 61363539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 6145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 6159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6175fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mHotlistHandler != null) { 6185fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills int event = mHotlistChangeBuffer.processScan(backgroundScanResults); 6195fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((event & ChangeBuffer.EVENT_FOUND) != 0) { 6205fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistHandler.onHotlistApFound( 6215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_FOUND)); 6225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 6235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((event & ChangeBuffer.EVENT_LOST) != 0) { 6245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistHandler.onHotlistApLost( 6255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_LOST)); 6265fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 6279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 6295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 6305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.singleScanActive 6315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills && mLastScanSettings.singleScanEventHandler != null) { 6325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.reportSingleScanFullResults) { 6335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (ScanResult scanResult : singleScanResults) { 634c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills // ignore buckets scanned since there is only one bucket for a single scan 635c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills mLastScanSettings.singleScanEventHandler.onFullScanResult(scanResult, 636c9e6069eb941d282af213dc20b171877db6b567bMitchell Wills /* bucketsScanned */ 0); 6375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 6389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6392771787818003e53e8175036a3d09688c783f350Mitchell Wills Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR); 6404e1f32efceee1db37bfb1e2624b434dbfb055686Mitchell Wills mLatestSingleScanResult = new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 0, 6414e1f32efceee1db37bfb1e2624b434dbfb055686Mitchell Wills mLastScanSettings.singleScanFreqs.isAllChannels(), 6425fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanResults.toArray(new ScanResult[singleScanResults.size()])); 64363539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills mLastScanSettings.singleScanEventHandler 64463539f1283899fbbf83ab90757961b4be51d5034Mitchell Wills .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 6459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6465fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 64762bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius if (mLastScanSettings.hwPnoScanActive 648063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius && mLastScanSettings.pnoScanEventHandler != null) { 64962bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius ScanResult[] pnoScanResultsArray = new ScanResult[hwPnoScanResults.size()]; 650063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius for (int i = 0; i < pnoScanResultsArray.length; ++i) { 65162bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius pnoScanResultsArray[i] = hwPnoScanResults.get(i); 652063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 653063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius mLastScanSettings.pnoScanEventHandler.onPnoNetworkFound(pnoScanResultsArray); 654063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius } 655063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius 6565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings = null; 6579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 6629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush) { 6635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 6645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiScanner.ScanData[] results = mBackgroundScanBuffer.get(); 66541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if (flush) { 6665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanBuffer.clear(); 66741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 66841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills return results; 6699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6722332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius private boolean setNetworkPriorities(WifiNative.PnoNetwork[] networkList) { 6732332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius if (networkList != null) { 6742332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius if (DBG) Log.i(TAG, "Enable network and Set priorities for PNO."); 6752332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius for (WifiNative.PnoNetwork network : networkList) { 6762332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius if (!mWifiNative.setNetworkVariable(network.networkId, 6772332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius WifiConfiguration.priorityVarName, 6782332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius Integer.toString(network.priority))) { 6792332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius Log.e(TAG, "Set priority failed for: " + network.networkId); 6802332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return false; 6812332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 68262bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius if (!mWifiNative.enableNetworkWithoutConnect(network.networkId)) { 6832332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius Log.e(TAG, "Enable network failed for: " + network.networkId); 6842332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return false; 6852332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6862332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6872332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6882332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return true; 6892332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6902332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 69162bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius private boolean startHwPnoScan() { 692e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return mHwPnoDebouncer.startPnoScan(mHwPnoDebouncerListener); 6932332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6942332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 695e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private void stopHwPnoScan() { 696e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mHwPnoDebouncer.stopPnoScan(); 6972332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 6982332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 699e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private void pauseHwPnoScan() { 700e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mHwPnoDebouncer.forceStopPnoScan(); 7012332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7022332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 7031bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius private boolean restartHwPnoScan() { 7041bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius mHwPnoDebouncer.forceStopPnoScan(); 7051bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius return mHwPnoDebouncer.startPnoScan(mHwPnoDebouncerListener); 7061bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius } 7071bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius 708dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius /** 709dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius * Hw Pno Scan is required only for disconnected PNO when the device supports it. 710dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius * @param isConnectedPno Whether this is connected PNO vs disconnected PNO. 711dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius * @return true if HW PNO scan is required, false otherwise. 712dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius */ 713dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius private boolean isHwPnoScanRequired(boolean isConnectedPno) { 714dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius return (!isConnectedPno & mHwPnoScanSupported); 715dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius } 716dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius 717dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius private boolean isHwPnoScanRequired() { 718dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius if (mPnoSettings == null) return false; 719dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius return isHwPnoScanRequired(mPnoSettings.isConnected); 720dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius } 721dcd877d6c143db557884993ea437e2a432cb0ba3Roshan Pius 7222332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius @Override 7236c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius public boolean setHwPnoList(WifiNative.PnoSettings settings, 7242332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius WifiNative.PnoEventHandler eventHandler) { 7252332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius synchronized (mSettingsLock) { 7262332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius if (mPnoSettings != null) { 7272332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius Log.w(TAG, "Already running a PNO scan"); 7282332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return false; 7292332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7302332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius mPnoEventHandler = eventHandler; 7312332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius mPnoSettings = settings; 7326c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius if (!setNetworkPriorities(settings.networkList)) return false; 7336c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius // For supplicant based PNO, we start the scan immediately when we set pno list. 7346c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius processPendingScans(); 7352332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return true; 7362332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7372332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7382332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 7392332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius @Override 740476172f2eef83ff367fae4344eda8129ea9d16f7Roshan Pius public boolean resetHwPnoList() { 7412332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius synchronized (mSettingsLock) { 7422332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius if (mPnoSettings == null) { 7432332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius Log.w(TAG, "No PNO scan running"); 7442332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius return false; 7452332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7462332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius mPnoEventHandler = null; 7472332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius mPnoSettings = null; 7486c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius // For supplicant based PNO, we stop the scan immediately when we reset pno list. 749e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius stopHwPnoScan(); 750e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return true; 7512332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7522332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7532332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 7542332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius @Override 7556c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius public boolean isHwPnoSupported(boolean isConnectedPno) { 7566c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius // Hw Pno Scan is supported only for disconnected PNO when the device supports it. 7576c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius return isHwPnoScanRequired(isConnectedPno); 7586c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius } 7596c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius 7606c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius @Override 7616c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius public boolean shouldScheduleBackgroundScanForHwPno() { 7626c5018cef1eb7acbcfa7fc6c9b7c018bab7ba7baRoshan Pius return false; 7632332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius } 7642332e9ea1b691fa0ea3a340feec159f2040aa6caRoshan Pius 7659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 7669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean setHotlist(WifiScanner.HotlistSettings settings, 7679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.HotlistEventHandler eventHandler) { 7689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings == null || eventHandler == null) { 7699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 7709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 7729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = eventHandler; 7739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.setSettings(settings.bssidInfos, settings.apLostThreshold, 1); 7749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 7759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 7789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 7799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void resetHotlist() { 7805fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 7819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.clearSettings(); 7829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = null; 7839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 78694bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills /* 78794bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills * Significant Wifi Change API is not implemented 78894bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills */ 78994bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills @Override 79094bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills public boolean trackSignificantWifiChange(WifiScanner.WifiChangeSettings settings, 79194bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills WifiNative.SignificantWifiChangeEventHandler handler) { 79294bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills return false; 79394bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills } 79494bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills @Override 79594bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills public void untrackSignificantWifiChange() {} 79694bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills 79794bd575cb4766ed0dfbaad0fc7719a9e9e85a260Mitchell Wills 7989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class LastScanSettings { 7995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public long startTime; 8005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 8015fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public LastScanSettings(long startTime) { 8025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.startTime = startTime; 8035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 8045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 8055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Background settings 8065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean backgroundScanActive = false; 8075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int scanId; 8085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int maxAps; 8095fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportEvents; 8105fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportNumScansThreshold; 8115fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportPercentThreshold; 8125fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 8135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public void setBackgroundScan(int scanId, int maxAps, int reportEvents, 8149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportNumScansThreshold, int reportPercentThreshold) { 8155fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.backgroundScanActive = true; 8169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.scanId = scanId; 8179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.maxAps = maxAps; 8189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportEvents = reportEvents; 8199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportNumScansThreshold = reportNumScansThreshold; 8209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportPercentThreshold = reportPercentThreshold; 8219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 8235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Single scan settings 8245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean singleScanActive = false; 8255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean reportSingleScanFullResults; 8267e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills public ChannelCollection singleScanFreqs; 8275fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public WifiNative.ScanEventHandler singleScanEventHandler; 8285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 8295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public void setSingleScan(boolean reportSingleScanFullResults, 8307e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills ChannelCollection singleScanFreqs, 8317e3e85327ca82a83de84b4750e793f2e3d1b3bfcMitchell Wills WifiNative.ScanEventHandler singleScanEventHandler) { 8325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanActive = true; 8335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.reportSingleScanFullResults = reportSingleScanFullResults; 8345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.singleScanFreqs = singleScanFreqs; 8355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.singleScanEventHandler = singleScanEventHandler; 8365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 837063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius 83862bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius public boolean hwPnoScanActive = false; 8391bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius public WifiNative.PnoNetwork[] pnoNetworkList; 840063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius public WifiNative.PnoEventHandler pnoScanEventHandler; 841063cfc7e3eef78fcbda24a66f0c473828b39c854Roshan Pius 8421bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius public void setHwPnoScan( 8431bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius WifiNative.PnoNetwork[] pnoNetworkList, 8441bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius WifiNative.PnoEventHandler pnoScanEventHandler) { 84562bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius hwPnoScanActive = true; 8461bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius this.pnoNetworkList = pnoNetworkList; 84762bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius this.pnoScanEventHandler = pnoScanEventHandler; 84862bc101940ae1f5e60c4d8861a149b900dbf5e5cRoshan Pius } 8499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ScanBuffer { 8539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final ArrayDeque<WifiScanner.ScanData> mBuffer; 8545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mCapacity; 8559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanBuffer(int capacity) { 8575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mCapacity = capacity; 8585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBuffer = new ArrayDeque<>(mCapacity); 8599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int size() { 8629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.size(); 8639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int capacity() { 8665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return mCapacity; 8679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean isFull() { 8705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return size() == mCapacity; 8719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void add(WifiScanner.ScanData scanData) { 8749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (isFull()) { 8759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.pollFirst(); 8769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.offerLast(scanData); 8789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clear() { 8819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.clear(); 8829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] get() { 8859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.toArray(new WifiScanner.ScanData[mBuffer.size()]); 8869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 8889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ChangeBuffer { 8909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_NONE = 0; 8919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_LOST = 1; 8929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_FOUND = 2; 8939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8945fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public static int STATE_FOUND = 0; 8959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiScanner.BssidInfo[] mBssidInfos = null; 8979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mApLostThreshold; 8989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mMinEvents; 8999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mLostCount = null; 9009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ScanResult[] mMostRecentResult = null; 9019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mPendingEvent = null; 9029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private boolean mFiredEvents = false; 9039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private static ScanResult findResult(List<ScanResult> results, String bssid) { 9055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < results.size(); ++i) { 9065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bssid.equalsIgnoreCase(results.get(i).BSSID)) { 9075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return results.get(i); 9089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return null; 9119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void setSettings(WifiScanner.BssidInfo[] bssidInfos, int apLostThreshold, 9149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int minEvents) { 9159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBssidInfos = bssidInfos; 9169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (apLostThreshold <= 0) { 9179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = 1; 9185fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 9199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = apLostThreshold; 9209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMinEvents = minEvents; 9229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bssidInfos != null) { 9239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = new int[bssidInfos.length]; 9249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Arrays.fill(mLostCount, mApLostThreshold); // default to lost 9259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = new ScanResult[bssidInfos.length]; 9269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = new int[bssidInfos.length]; 9279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 9285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 9299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = null; 9309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = null; 9319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = null; 9329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clearSettings() { 9369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills setSettings(null, 0, 0); 9379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 9409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Get the most recent scan results for APs that triggered the given event on the last call 9419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * to {@link #processScan}. 9429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 9439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanResult[] getLastResults(int event) { 9449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanResult> results = new ArrayList<>(); 9459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 9469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == event) { 9479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills results.add(mMostRecentResult[i]); 9489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return results.toArray(new ScanResult[results.size()]); 9519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 9549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Process the supplied scan results and determine if any events should be generated based 9559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * on the configured settings 9569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * @return The events that occurred 9579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 9585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int processScan(List<ScanResult> scanResults) { 9599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mBssidInfos == null) { 9609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 9619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // clear events from last time 9649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mFiredEvents) { 9659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 9669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 9679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 9689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventCount = 0; 9729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventType = EVENT_NONE; 9739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 9749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = findResult(scanResults, mBssidInfos[i].bssid); 9759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int rssi = Integer.MIN_VALUE; 9769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (result != null) { 9779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult[i] = result; 9789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills rssi = result.level; 9799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (rssi < mBssidInfos[i].low) { 9829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] < mApLostThreshold) { 9839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i]++; 9849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 9859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 9869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_FOUND) { 9879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 9885fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 9899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_LOST; 9909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 9935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 9949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 9959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_LOST) { 9969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 9975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 9989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_FOUND; 9999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i] = STATE_FOUND; 10029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { 10045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.d(TAG, "ChangeBuffer BSSID: " + mBssidInfos[i].bssid + "=" + mLostCount[i] 10055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ", " + mPendingEvent[i] + ", rssi=" + rssi); 10069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] != EVENT_NONE) { 10089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ++eventCount; 10099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills eventType |= mPendingEvent[i]; 10109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10125fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "ChangeBuffer events count=" + eventCount + ": " + eventType); 10139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (eventCount >= mMinEvents) { 10149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = true; 10159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return eventType; 10169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 10189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 10199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1020e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1021e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1022e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * HW PNO Debouncer is used to debounce PNO requests. This guards against toggling the PNO 1023e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * state too often which is not handled very well by some drivers. 1024e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Note: This is not thread safe! 1025e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1026e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public static class HwPnoDebouncer { 1027e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public static final String PNO_DEBOUNCER_ALARM_TAG = TAG + "Pno Monitor"; 1028e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private static final int MINIMUM_PNO_GAP_MS = 5 * 1000; 1029e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1030e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final WifiNative mWifiNative; 1031e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final AlarmManager mAlarmManager; 1032e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final Handler mEventHandler; 1033ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius private final Clock mClock; 1034e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private long mLastPnoChangeTimeStamp = -1L; 1035e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private boolean mExpectedPnoState = false; 1036e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private boolean mCurrentPnoState = false;; 1037e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private boolean mWaitForTimer = false; 1038e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private Listener mListener; 1039e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1040e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1041e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Interface used to indicate PNO scan notifications. 1042e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1043e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public interface Listener { 1044e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1045e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Used to indicate a delayed PNO scan request failure. 1046e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1047e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius void onPnoScanFailed(); 1048e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1049e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1050e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public HwPnoDebouncer(WifiNative wifiNative, AlarmManager alarmManager, 1051ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius Handler eventHandler, Clock clock) { 1052e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mWifiNative = wifiNative; 1053e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mAlarmManager = alarmManager; 1054e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mEventHandler = eventHandler; 1055ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock = clock; 1056e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1057e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1058e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1059e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Enable/Disable PNO state in wpa_supplicant 1060e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * @param enable boolean indicating whether PNO is being enabled or disabled. 1061e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1062e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private boolean updatePnoState(boolean enable) { 1063e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (mCurrentPnoState == enable) { 1064e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (DBG) Log.d(TAG, "PNO state is already " + enable); 1065e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return true; 1066e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1067ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mLastPnoChangeTimeStamp = mClock.elapsedRealtime(); 1068e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (mWifiNative.setPnoScan(enable)) { 1069ab3adbcced14ec2ae5cf8f8a75f2ef9c9224f2a3Roshan Pius Log.d(TAG, "Changed PNO state from " + mCurrentPnoState + " to " + enable); 1070e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mCurrentPnoState = enable; 1071e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return true; 1072e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } else { 1073e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius Log.e(TAG, "PNO state change to " + enable + " failed"); 1074e483fd4a3151e59b3d0a596572b4d9f035fa8424Roshan Pius mCurrentPnoState = false; 1075e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return false; 1076e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1077e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1078e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1079e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private final AlarmManager.OnAlarmListener mAlarmListener = 1080e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius new AlarmManager.OnAlarmListener() { 1081e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public void onAlarm() { 1082e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (DBG) Log.d(TAG, "PNO timer expired, expected state " + mExpectedPnoState); 1083e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (!updatePnoState(mExpectedPnoState)) { 1084e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (mListener != null) { 1085e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mListener.onPnoScanFailed(); 1086e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1087e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1088e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mWaitForTimer = false; 1089e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1090e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius }; 1091e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1092e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1093e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Enable/Disable PNO state. This method will debounce PNO scan requests. 1094e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * @param enable boolean indicating whether PNO is being enabled or disabled. 1095e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1096e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius private boolean setPnoState(boolean enable) { 1097e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius boolean isSuccess = true; 1098e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mExpectedPnoState = enable; 1099e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (!mWaitForTimer) { 1100ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius long timeDifference = mClock.elapsedRealtime() - mLastPnoChangeTimeStamp; 1101e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (timeDifference >= MINIMUM_PNO_GAP_MS) { 1102e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius isSuccess = updatePnoState(enable); 1103e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } else { 1104e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius long alarmTimeout = MINIMUM_PNO_GAP_MS - timeDifference; 1105e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius Log.d(TAG, "Start PNO timer with delay " + alarmTimeout); 1106ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1107ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius mClock.elapsedRealtime() + alarmTimeout, PNO_DEBOUNCER_ALARM_TAG, 1108e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mAlarmListener, mEventHandler); 1109e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mWaitForTimer = true; 1110e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1111e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1112e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return isSuccess; 1113e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1114e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1115e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1116e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Start PNO scan 1117e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1118e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public boolean startPnoScan(Listener listener) { 1119e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (DBG) Log.d(TAG, "Starting PNO scan"); 1120e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mListener = listener; 1121e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (!setPnoState(true)) { 1122e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mListener = null; 1123e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return false; 1124e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1125e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius return true; 1126e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1127e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1128e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1129e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Stop PNO scan 1130e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1131e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public void stopPnoScan() { 1132e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius if (DBG) Log.d(TAG, "Stopping PNO scan"); 1133e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius setPnoState(false); 1134e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius mListener = null; 1135e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1136e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius 1137e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius /** 1138e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * Force stop PNO scanning. This method will bypass the debounce logic and stop PNO 1139e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius * scan immediately. 1140e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius */ 1141e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius public void forceStopPnoScan() { 11421bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius if (DBG) Log.d(TAG, "Force stopping Pno scan"); 11431bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius // Cancel the debounce timer and stop PNO scan. 11441bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius if (mWaitForTimer) { 11451bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius mAlarmManager.cancel(mAlarmListener); 11461bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius mWaitForTimer = false; 1147e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 11481bf983a4211f547593a60523e43112ecdb5c8997Roshan Pius updatePnoState(false); 1149e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 1150e7ba2963bedf426a1d8ba09ab535260ef364512bRoshan Pius } 11519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills} 1152