SupplicantWifiScannerImpl.java revision 2771787818003e53e8175036a3d09688c783f350
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 179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willspackage com.android.server.wifi; 189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.app.AlarmManager; 209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.content.Context; 219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.net.wifi.ScanResult; 229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.net.wifi.WifiScanner; 239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Handler; 249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Looper; 259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.Message; 269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.os.SystemClock; 279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport android.util.Log; 289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayDeque; 309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayList; 319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Arrays; 329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Collections; 339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.HashSet; 349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.List; 359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Set; 369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 37f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills/** 385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills * Implementation of the WifiScanner HAL API that uses wpa_supplicant to perform all scans 39f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills * @see com.android.server.wifi.WifiScannerImpl for more details on each method 40f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills */ 419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willspublic class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handler.Callback { 429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final String TAG = "SupplicantWifiScannerImpl"; 439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final boolean DBG = false; 449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int SCAN_BUFFER_CAPACITY = 10; 469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int MAX_APS_PER_SCAN = 32; 479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final int MAX_SCAN_BUCKETS = 16; 489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final String ACTION_SCAN_PERIOD = 509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills "com.android.server.util.SupplicantWifiScannerImpl.action.SCAN_PERIOD"; 519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final Context mContext; 539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final WifiNative mWifiNative; 549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final AlarmManager mAlarmManager; 559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final Handler mEventHandler; 569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private Object mSettingsLock = new Object(); 589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Next scan settings to apply when the previous scan completes 605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mPendingBackgroundScanSettings = null; 615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mPendingBackgroundScanEventHandler = null; 625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mPendingSingleScanSettings = null; 635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mPendingSingleScanEventHandler = null; 645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Active background scan settings/state 665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanSettings mBackgroundScanSettings = null; 675fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiNative.ScanEventHandler mBackgroundScanEventHandler = null; 685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mNextBackgroundScanPeriod = 0; 695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mNextBackgroundScanId = 0; 705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private boolean mBackgroundScanPeriodPending = false; 715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private boolean mBackgroundScanPaused = false; 725fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private ScanBuffer mBackgroundScanBuffer = new ScanBuffer(SCAN_BUFFER_CAPACITY); 735fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 745fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private WifiScanner.ScanData mLatestSingleScanResult = 755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills new WifiScanner.ScanData(0, 0, new ScanResult[0]); 765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 775fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Settings for the currently running scan, null if no scan active 789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private LastScanSettings mLastScanSettings = null; 799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Active hotlist settings 819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.HotlistEventHandler mHotlistHandler = null; 829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ChangeBuffer mHotlistChangeBuffer = new ChangeBuffer(); 839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 8441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills AlarmManager.OnAlarmListener mScanPeriodListener = new AlarmManager.OnAlarmListener() { 8541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills public void onAlarm() { 8641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills synchronized (mSettingsLock) { 8741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills handleScanPeriod(); 8841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 8941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 9041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills }; 9141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public SupplicantWifiScannerImpl(Context context, WifiNative wifiNative, Looper looper) { 939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mContext = context; 949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mWifiNative = wifiNative; 959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mEventHandler = new Handler(looper, this); 977d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills 987d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // We can't enable these until WifiStateMachine switches to using WifiScanner because 997d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // WifiMonitor only supports sending results to one listener 1007d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // TODO Enable these 1017d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // Also need to fix tests again when this is enabled 1027d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 1037d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // WifiMonitor.SCAN_FAILED_EVENT, mEventHandler); 1047d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 1057d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler); 1069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 1109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_cache_size = Integer.MAX_VALUE; 1119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_buckets = MAX_SCAN_BUCKETS; 1129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_ap_cache_per_scan = MAX_APS_PER_SCAN; 1139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_rssi_sample_size = 8; 1149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_reporting_threshold = SCAN_BUFFER_CAPACITY; 1159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_hotlist_bssids = 0; 1169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_significant_wifi_change_aps = 0; 1177d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills // TODO reenable once scan results handlers are enabled again 1187d2d8c27647676c51208e417afbb8dd6c6784b7cMitchell Wills return false; 1199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 122f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills public boolean startSingleScan(WifiNative.ScanSettings settings, 123f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills WifiNative.ScanEventHandler eventHandler) { 1245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (eventHandler == null || settings == null) { 1255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "Invalid arguments for startSingleScan: settings=" + settings 1265fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ",eventHandler=" + eventHandler); 1275fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return false; 1285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingSingleScanSettings != null 1305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings != null && mLastScanSettings.singleScanActive)) { 1315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "A single scan is already running"); 1325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return false; 1335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 1355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings = settings; 1365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler = eventHandler; 1375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 1385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return true; 1395fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 140f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills } 141f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills 142f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills @Override 143f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills public WifiScanner.ScanData getLatestSingleScanResults() { 1445fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return mLatestSingleScanResult; 145f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills } 146f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills 147f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills @Override 1489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean startBatchedScan(WifiNative.ScanSettings settings, 1499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.ScanEventHandler eventHandler) { 1505fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings == null || eventHandler == null) { 1515fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "Invalid arguments for startBatched: settings=" + settings 1525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ",eventHandler=" + eventHandler); 1539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.max_ap_per_scan < 0 || settings.max_ap_per_scan > MAX_APS_PER_SCAN) { 1579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.num_buckets < 0 || settings.num_buckets > MAX_SCAN_BUCKETS) { 1609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.report_threshold_num_scans < 0 1635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || settings.report_threshold_num_scans > SCAN_BUFFER_CAPACITY) { 1649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.report_threshold_percent < 0 || settings.report_threshold_percent > 100) { 1679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (settings.base_period_ms <= 0) { 1709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < settings.num_buckets; ++i) { 1739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.BucketSettings bucket = settings.buckets[i]; 1745fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bucket.period_ms % settings.base_period_ms != 0) { 1759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 1779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 1809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills stopBatchedScan(); 1815fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.d(TAG, "Starting scan num_buckets=" + settings.num_buckets + ", base_period=" 1825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + settings.base_period_ms + " ms"); 1835fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = settings; 1845fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = eventHandler; 1859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); // Try to start scan immediately 1869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 1879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void stopBatchedScan() { 1925fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 1935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Stopping scan"); 1945fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = null; 1955fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = null; 1965fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = null; 1975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = null; 1985fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = false; 1995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 2009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 2019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 2059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void pauseBatchedScan() { 2065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Pausing scan"); 2089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // if there isn't a pending scan then make the current scan pending 2095fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanSettings == null) { 2105fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = mBackgroundScanSettings; 2115fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = mBackgroundScanEventHandler; 2129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = null; 2145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = null; 2155fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 2165fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = true; 2179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 2199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiScanner.ScanData[] results = getLatestBatchedScanResults(/* flush = */ true); 2215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanEventHandler != null) { 2225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler.onScanPaused(results); 2235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 2289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void restartBatchedScan() { 2295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Restarting scan"); 2315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanEventHandler != null) { 2325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler.onScanRestarted(); 2335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPaused = false; 2359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); 2369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void unscheduleScansLocked() { 24041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mAlarmManager.cancel(mScanPeriodListener); 2419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLastScanSettings = null; // make sure that a running scan is marked as ended 2429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void handleScanPeriod() { 2455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2465fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = true; 2475fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 2485fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2495fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2505fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 2515fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private void processPendingScans() { 2525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 2539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLastScanSettings != null) { 2549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 2559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Set<Integer> freqs = new HashSet<>(); 2585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills LastScanSettings newScanSettings = new LastScanSettings(SystemClock.elapsedRealtime()); 2599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Update scan settings if there is a pending scan 2615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (!mBackgroundScanPaused) { 2625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingBackgroundScanSettings != null) { 2635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings = mPendingBackgroundScanSettings; 2645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler = mPendingBackgroundScanEventHandler; 2655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mNextBackgroundScanPeriod = 0; 2665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanSettings = null; 2675fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingBackgroundScanEventHandler = null; 2685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = true; 2695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanPeriodPending) { 2715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanSettings != null) { 2725fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills int reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; // default to no batch 2735fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills boolean haveBackgroundScanChannels = false; 2745fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int bucket_id = 0; bucket_id < mBackgroundScanSettings.num_buckets; 2755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills ++bucket_id) { 2765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.BucketSettings bucket = 2775fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings.buckets[bucket_id]; 2785fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mNextBackgroundScanPeriod % (bucket.period_ms 2795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills / mBackgroundScanSettings.base_period_ms) == 0) { 2805fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((bucket.report_events 2815fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0) { 2825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills reportEvents |= WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 2835fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2845fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((bucket.report_events 2855fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 2865fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills reportEvents |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 2875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2885fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // only no batch if all buckets specify it 2895fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((bucket.report_events 2905fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 2915fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills reportEvents &= ~WifiScanner.REPORT_EVENT_NO_BATCH; 2925fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 2935fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 2945fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bucket.band != WifiScanner.WIFI_BAND_UNSPECIFIED) { 2955fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiScanner.ChannelSpec[] channels = 2965fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiChannelHelper.getChannelsForBand(bucket.band); 2975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (WifiScanner.ChannelSpec channel : channels) { 2985fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills freqs.add(channel.frequency); 2995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills haveBackgroundScanChannels = true; 3005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3015fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 3025fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int channel_id = 0; channel_id < bucket.num_channels; 3035fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills ++channel_id) { 3045fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.ChannelSettings channel = 3055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills bucket.channels[channel_id]; 3065fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills freqs.add(channel.frequency); 3075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills haveBackgroundScanChannels = true; 3085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3095fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3125fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (haveBackgroundScanChannels) { 3135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills newScanSettings.setBackgroundScan(mNextBackgroundScanId++, 3145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings.max_ap_per_scan, reportEvents, 3155fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings.report_threshold_num_scans, 3165fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanSettings.report_threshold_percent); 3179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3195fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 3205fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mNextBackgroundScanPeriod++; 3215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanPeriodPending = false; 3225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mAlarmManager.set(AlarmManager.RTC_WAKEUP, 3235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills System.currentTimeMillis() + mBackgroundScanSettings.base_period_ms, 3245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills "SupplicantWifiScannerImpl Period", 3255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mScanPeriodListener, mEventHandler); 3269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3275fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 3295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mPendingSingleScanSettings != null) { 3305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills boolean reportFullResults = false; 3315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Set<Integer> singleScanFreqs = new HashSet<>(); 3325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < mPendingSingleScanSettings.num_buckets; ++i) { 3335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.BucketSettings bucketSettings = 3345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings.buckets[i]; 3355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((bucketSettings.report_events 3365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 3375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills reportFullResults = true; 3389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3395fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bucketSettings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) { 3405fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int j = 0; j < bucketSettings.num_channels; ++j) { 3415fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.ChannelSettings channel = bucketSettings.channels[j]; 3425fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanFreqs.add(channel.frequency); 3435fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3445fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 3455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiScanner.ChannelSpec[] channels = 3465fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiChannelHelper.getChannelsForBand(bucketSettings.band); 3475fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (WifiScanner.ChannelSpec channel : channels) { 3485fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanFreqs.add(channel.frequency); 3495fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills freqs.addAll(singleScanFreqs); 3535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills newScanSettings.setSingleScan(reportFullResults, singleScanFreqs, 3545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler); 3559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanSettings = null; 3575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mPendingSingleScanEventHandler = null; 3585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 3605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (freqs.size() > 0) { 3615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills boolean success = mWifiNative.scan( 3625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, freqs); 3635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (success) { 3645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // TODO handle scan timeout 3655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.d(TAG, "Starting wifi scan for " + freqs.size() + " freqs" 3665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ", background=" + newScanSettings.backgroundScanActive 3675fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ", single=" + newScanSettings.singleScanActive); 3685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings = newScanSettings; 3695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 3705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.w(TAG, "Failed starting wifi scan for " + freqs.size() + " freqs"); 3715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // TODO indicate failure for single and background scans 3725fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 3739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 3789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean handleMessage(Message msg) { 3799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills switch(msg.what) { 3809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_FAILED_EVENT: 381f2f6f79242454ff9161f5af772292fa0180436f8Mitchell Wills // TODO indicate failure to caller 3829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.w(TAG, "Scan failed"); 3839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized (mSettingsLock) { 3849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLastScanSettings = null; 3859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3865fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 3879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 3889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_RESULTS_EVENT: 3899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills pollLatestScanData(); 3905fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills processPendingScans(); 3919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 3929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills default: 3939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // ignore unknown event 3949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 3969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void pollLatestScanData() { 3995fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 4005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings == null) { 4019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // got a scan before we started scanning or after scan was canceled 4029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 4039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "Polling scan data for scan: " + mLastScanSettings.scanId); 4069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanDetail> nativeResults = mWifiNative.getScanResults(); 4075fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills List<ScanResult> singleScanResults = new ArrayList<>(); 4085fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills List<ScanResult> backgroundScanResults = new ArrayList<>(); 4099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < nativeResults.size(); ++i) { 4109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = nativeResults.get(i).getScanResult(); 4119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills long timestamp_ms = result.timestamp / 1000; // convert us -> ms 4129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (timestamp_ms > mLastScanSettings.startTime) { 4135fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.backgroundScanActive) { 4145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills backgroundScanResults.add(result); 4155fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4165fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.singleScanActive 4175fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills && mLastScanSettings.singleScanFreqs.contains(result.frequency)) { 4185fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanResults.add(result); 4195fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4205fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 4219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // was a cached result in wpa_supplicant 4229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 42441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 4255fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.backgroundScanActive) { 4265fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanEventHandler != null) { 4275fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents 4285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 4295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (ScanResult scanResult : backgroundScanResults) { 4305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler.onFullScanResult(scanResult); 4315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 43241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 43341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 43441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 4352771787818003e53e8175036a3d09688c783f350Mitchell Wills Collections.sort(backgroundScanResults, SCAN_RESULT_SORT_COMPARATOR); 4365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills ScanResult[] scanResultsArray = new ScanResult[Math.min(mLastScanSettings.maxAps, 4375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills backgroundScanResults.size())]; 4385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < scanResultsArray.length; ++i) { 4395fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills scanResultsArray[i] = backgroundScanResults.get(i); 4405fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4425fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 4435fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanBuffer.add(new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 4445fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills scanResultsArray)); 4455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4475fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mBackgroundScanEventHandler != null) { 4485fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((mLastScanSettings.reportEvents 4495fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0 4505fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings.reportEvents 4515fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0 4525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || (mLastScanSettings.reportEvents 4535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills == WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL 4545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills && (mBackgroundScanBuffer.size() 4555fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills >= (mBackgroundScanBuffer.capacity() 4565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills * mLastScanSettings.reportPercentThreshold 4575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills / 100) 4585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills || mBackgroundScanBuffer.size() 4595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills >= mLastScanSettings.reportNumScansThreshold))) { 4605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanEventHandler.onScanStatus(); 4615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mHotlistHandler != null) { 4655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills int event = mHotlistChangeBuffer.processScan(backgroundScanResults); 4665fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((event & ChangeBuffer.EVENT_FOUND) != 0) { 4675fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistHandler.onHotlistApFound( 4685fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_FOUND)); 4695fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4705fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if ((event & ChangeBuffer.EVENT_LOST) != 0) { 4715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistHandler.onHotlistApLost( 4725fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_LOST)); 4735fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4765fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 4775fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.singleScanActive 4785fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills && mLastScanSettings.singleScanEventHandler != null) { 4795fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (mLastScanSettings.reportSingleScanFullResults) { 4805fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (ScanResult scanResult : singleScanResults) { 4815fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings.singleScanEventHandler.onFullScanResult(scanResult); 4825fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 4839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4842771787818003e53e8175036a3d09688c783f350Mitchell Wills Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR); 4855fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLatestSingleScanResult = new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 4865fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanResults.toArray(new ScanResult[singleScanResults.size()])); 4875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings.singleScanEventHandler.onScanResultsAvailable(); 4889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4895fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 4905fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mLastScanSettings = null; 4919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 4969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush) { 4975fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 4985fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills WifiScanner.ScanData[] results = mBackgroundScanBuffer.get(); 49941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if (flush) { 5005fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBackgroundScanBuffer.clear(); 50141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 50241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills return results; 5039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 5079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean setHotlist(WifiScanner.HotlistSettings settings, 5089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.HotlistEventHandler eventHandler) { 5099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings == null || eventHandler == null) { 5109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 5119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5125fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 5139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = eventHandler; 5149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.setSettings(settings.bssidInfos, settings.apLostThreshold, 1); 5159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 5169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 5209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void resetHotlist() { 5215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills synchronized (mSettingsLock) { 5229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.clearSettings(); 5239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = null; 5249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class LastScanSettings { 5285fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public long startTime; 5295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 5305fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public LastScanSettings(long startTime) { 5315fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.startTime = startTime; 5325fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 5335fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 5345fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Background settings 5355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean backgroundScanActive = false; 5365fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int scanId; 5375fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int maxAps; 5385fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportEvents; 5395fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportNumScansThreshold; 5405fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int reportPercentThreshold; 5415fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 5425fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public void setBackgroundScan(int scanId, int maxAps, int reportEvents, 5439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportNumScansThreshold, int reportPercentThreshold) { 5445fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.backgroundScanActive = true; 5459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.scanId = scanId; 5469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.startTime = startTime; 5479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.maxAps = maxAps; 5489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportEvents = reportEvents; 5499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportNumScansThreshold = reportNumScansThreshold; 5509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportPercentThreshold = reportPercentThreshold; 5519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5525fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 5535fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills // Single scan settings 5545fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean singleScanActive = false; 5555fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public boolean reportSingleScanFullResults; 5565fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public Set<Integer> singleScanFreqs; 5575fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public WifiNative.ScanEventHandler singleScanEventHandler; 5585fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills 5595fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public void setSingleScan(boolean reportSingleScanFullResults, 5605fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Set<Integer> singleScanFreqs, WifiNative.ScanEventHandler singleScanEventHandler) { 5615fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills singleScanActive = true; 5625fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.reportSingleScanFullResults = reportSingleScanFullResults; 5635fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.singleScanFreqs = singleScanFreqs; 5645fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills this.singleScanEventHandler = singleScanEventHandler; 5655fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } 5669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ScanBuffer { 5709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final ArrayDeque<WifiScanner.ScanData> mBuffer; 5715fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private int mCapacity; 5729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanBuffer(int capacity) { 5745fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mCapacity = capacity; 5755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills mBuffer = new ArrayDeque<>(mCapacity); 5769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int size() { 5799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.size(); 5809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int capacity() { 5835fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return mCapacity; 5849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean isFull() { 5875fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return size() == mCapacity; 5889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void add(WifiScanner.ScanData scanData) { 5919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (isFull()) { 5929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.pollFirst(); 5939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.offerLast(scanData); 5959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clear() { 5989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.clear(); 5999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] get() { 6029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.toArray(new WifiScanner.ScanData[mBuffer.size()]); 6039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ChangeBuffer { 6079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_NONE = 0; 6089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_LOST = 1; 6099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_FOUND = 2; 6109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6115fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public static int STATE_FOUND = 0; 6129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiScanner.BssidInfo[] mBssidInfos = null; 6149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mApLostThreshold; 6159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mMinEvents; 6169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mLostCount = null; 6179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ScanResult[] mMostRecentResult = null; 6189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mPendingEvent = null; 6199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private boolean mFiredEvents = false; 6209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills private static ScanResult findResult(List<ScanResult> results, String bssid) { 6225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills for (int i = 0; i < results.size(); ++i) { 6235fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (bssid.equalsIgnoreCase(results.get(i).BSSID)) { 6245fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills return results.get(i); 6259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return null; 6289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void setSettings(WifiScanner.BssidInfo[] bssidInfos, int apLostThreshold, 6319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int minEvents) { 6329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBssidInfos = bssidInfos; 6339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (apLostThreshold <= 0) { 6349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = 1; 6355fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 6369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = apLostThreshold; 6379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMinEvents = minEvents; 6399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bssidInfos != null) { 6409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = new int[bssidInfos.length]; 6419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Arrays.fill(mLostCount, mApLostThreshold); // default to lost 6429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = new ScanResult[bssidInfos.length]; 6439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = new int[bssidInfos.length]; 6449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 6455fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 6469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = null; 6479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = null; 6489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = null; 6499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clearSettings() { 6539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills setSettings(null, 0, 0); 6549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 6579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Get the most recent scan results for APs that triggered the given event on the last call 6589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * to {@link #processScan}. 6599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 6609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanResult[] getLastResults(int event) { 6619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanResult> results = new ArrayList<>(); 6629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 6639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == event) { 6649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills results.add(mMostRecentResult[i]); 6659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return results.toArray(new ScanResult[results.size()]); 6689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 6719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Process the supplied scan results and determine if any events should be generated based 6729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * on the configured settings 6739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * @return The events that occurred 6749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 6755fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills public int processScan(List<ScanResult> scanResults) { 6769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mBssidInfos == null) { 6779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 6789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // clear events from last time 6819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mFiredEvents) { 6829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 6839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 6849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 6859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventCount = 0; 6899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventType = EVENT_NONE; 6909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 6919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = findResult(scanResults, mBssidInfos[i].bssid); 6929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int rssi = Integer.MIN_VALUE; 6939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (result != null) { 6949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult[i] = result; 6959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills rssi = result.level; 6969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 6979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 6989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (rssi < mBssidInfos[i].low) { 6999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] < mApLostThreshold) { 7009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i]++; 7019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 7029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 7039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_FOUND) { 7049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 7055fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 7069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_LOST; 7079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7105fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 7119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 7129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_LOST) { 7139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 7145fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills } else { 7159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_FOUND; 7169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i] = STATE_FOUND; 7199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { 7215fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills Log.d(TAG, "ChangeBuffer BSSID: " + mBssidInfos[i].bssid + "=" + mLostCount[i] 7225fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills + ", " + mPendingEvent[i] + ", rssi=" + rssi); 7239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] != EVENT_NONE) { 7259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ++eventCount; 7269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills eventType |= mPendingEvent[i]; 7279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7295fa6221c4e507cbc596b6de77d793ec08d690157Mitchell Wills if (DBG) Log.d(TAG, "ChangeBuffer events count=" + eventCount + ": " + eventType); 7309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (eventCount >= mMinEvents) { 7319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = true; 7329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return eventType; 7339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 7359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 7379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills} 738