SupplicantWifiScannerImpl.java revision 41e38d84f562e12198f7db0d45f633712cae6cba
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 com.android.server.wifi.WifiMonitor; 309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport com.android.server.wifi.WifiNative; 319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayDeque; 339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.ArrayList; 349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Arrays; 359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Collections; 369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Comparator; 379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.HashSet; 389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.List; 399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Willsimport java.util.Set; 409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell 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 609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.ScanSettings mPendingScanSettings = null; 619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.ScanEventHandler mPendingScanEventHandler = null; 629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Active scan settings 649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.ScanSettings mScanSettings = null; 659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.ScanEventHandler mScanEventHandler = null; 669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mNextScanPeriod = 0; 679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mNextScanId = 0; 689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private LastScanSettings mLastScanSettings = null; 699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ScanBuffer mScanBuffer = new ScanBuffer(SCAN_BUFFER_CAPACITY); 709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Active hotlist settings 729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiNative.HotlistEventHandler mHotlistHandler = null; 739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ChangeBuffer mHotlistChangeBuffer = new ChangeBuffer(); 749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 7541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills AlarmManager.OnAlarmListener mScanPeriodListener = new AlarmManager.OnAlarmListener() { 7641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills public void onAlarm() { 7741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills // in case we never got the results of the previous scan 7841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills // make sure we start a new scan 7941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills synchronized (mSettingsLock) { 8041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if (mLastScanSettings != null) { 8141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills Log.w(TAG, 8241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills "Did not get a scan results/failure event from previous scan"); 8341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mLastScanSettings = null; 8441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 8541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills handleScanPeriod(); 8641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 8741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 8841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills }; 8941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public SupplicantWifiScannerImpl(Context context, WifiNative wifiNative, Looper looper) { 919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mContext = context; 929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mWifiNative = wifiNative; 939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mEventHandler = new Handler(looper, this); 969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiMonitor.SCAN_FAILED_EVENT, mEventHandler); 989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(), 999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler); 1009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 1049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_cache_size = Integer.MAX_VALUE; 1059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_buckets = MAX_SCAN_BUCKETS; 1069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_ap_cache_per_scan = MAX_APS_PER_SCAN; 1079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_rssi_sample_size = 8; 1089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_scan_reporting_threshold = SCAN_BUFFER_CAPACITY; 1099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_hotlist_bssids = 0; 1109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills capabilities.max_significant_wifi_change_aps = 0; 1119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 1129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean startBatchedScan(WifiNative.ScanSettings settings, 1169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.ScanEventHandler eventHandler) { 1179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings == null || eventHandler == null) 1189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings.max_ap_per_scan < 0 || settings.max_ap_per_scan > MAX_APS_PER_SCAN) 1219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings.num_buckets < 0 || settings.num_buckets > MAX_SCAN_BUCKETS) 1239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings.report_threshold_num_scans < 0 || 1259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills settings.report_threshold_num_scans > SCAN_BUFFER_CAPACITY) 1269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings.report_threshold_percent < 0 || settings.report_threshold_percent > 100) 1289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings.base_period_ms <= 0) 1309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < settings.num_buckets; ++i) { 1329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.BucketSettings bucket = settings.buckets[i]; 1339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bucket.period_ms % settings.base_period_ms != 0) 1349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 1359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 1389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills stopBatchedScan(); 1399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.d(TAG, "Starting scan num_buckets=" + settings.num_buckets + ", base_period=" + 1409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills settings.base_period_ms + " ms"); 1419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanSettings = settings; 1429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler = eventHandler; 1439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); // Try to start scan immediately 1449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 1459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void stopBatchedScan() { 1509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 1519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) {Log.d(TAG, "Stopping scan"); } 1529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanSettings = null; 1539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanEventHandler = null; 1549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanSettings = null; 1559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler = null; 1569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 1579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void pauseBatchedScan() { 1629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 1639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { Log.d(TAG, "Pausing scan"); } 1649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // if there isn't a pending scan then make the current scan pending 1659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingScanSettings == null) { 1669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanSettings = mScanSettings; 1679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler = mScanEventHandler; 1689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanSettings = null; 1709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanEventHandler = null; 1719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills unscheduleScansLocked(); 1739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiScanner.ScanData[] results = getLatestBatchedScanResults(/* flush = */ true); 1759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingScanEventHandler != null) 1769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler.onScanPaused(results); 1779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 1819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void restartBatchedScan() { 1829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 1839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { Log.d(TAG, "Restarting scan"); } 1849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingScanEventHandler != null) 1859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler.onScanRestarted(); 1869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills handleScanPeriod(); 1879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void unscheduleScansLocked() { 19141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mAlarmManager.cancel(mScanPeriodListener); 1929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLastScanSettings = null; // make sure that a running scan is marked as ended 1939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 1949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 1959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void handleScanPeriod() { 1969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 1979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLastScanSettings != null) { 1989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 1999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // Update scan settings if there is a pending scan 2029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingScanSettings != null) { 2039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanSettings = mPendingScanSettings; 2049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanEventHandler = mPendingScanEventHandler; 2059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mNextScanPeriod = 0; 2069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanSettings = null; 2079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingScanEventHandler = null; 2089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mScanSettings != null && mScanSettings.num_buckets > 0) { 2119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Set<Integer> freqs = new HashSet<>(); 2129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportEvents = WifiScanner.REPORT_EVENT_NO_BATCH; // default to no batch 2139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int bucket_id = 0; bucket_id < mScanSettings.num_buckets; ++bucket_id) { 2149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.BucketSettings bucket = mScanSettings.buckets[bucket_id]; 2159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mNextScanPeriod % (bucket.period_ms / mScanSettings.base_period_ms) == 0) { 2169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((bucket.report_events & WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) 2179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills != 0) { 2189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills reportEvents |= WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; 2199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((bucket.report_events & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) 2219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills != 0) { 2229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills reportEvents |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 2239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // only no batch if all buckets specify it 2259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((bucket.report_events & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 2269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills reportEvents &= ~WifiScanner.REPORT_EVENT_NO_BATCH; 2279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bucket.band != WifiScanner.WIFI_BAND_UNSPECIFIED) { 23041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills WifiScanner.ChannelSpec[] channels = 23141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills WifiChannelHelper.getChannelsForBand(bucket.band); 23241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills for (WifiScanner.ChannelSpec channel : channels) { 23341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills freqs.add(channel.frequency); 2349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 2379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int channel_id = 0; channel_id < bucket.num_channels; 2389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ++channel_id) { 2399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.ChannelSettings channel = bucket.channels[channel_id]; 2409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills freqs.add(channel.frequency); 2419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (freqs.size() > 0) { 2469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills boolean success = mWifiNative.scan( 2479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, freqs); 2489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (success) { 2499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.d(TAG, "Starting wifi scan " + mNextScanId + " for " + freqs.size() + 2509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills " freqs"); 2519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLastScanSettings = new LastScanSettings(mNextScanId++, 2529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills SystemClock.elapsedRealtime(), mScanSettings.max_ap_per_scan, 2539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills reportEvents, mScanSettings.report_threshold_num_scans, 2549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanSettings.report_threshold_percent); 2559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 2579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.w(TAG, "Failed starting wifi scan for " + freqs.size() + " freqs"); 2589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mNextScanPeriod++; 2629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mAlarmManager.set(AlarmManager.RTC_WAKEUP, 2639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills System.currentTimeMillis() + mScanSettings.base_period_ms, 26441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills "SupplicantWifiScannerImpl Period", 26541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mScanPeriodListener, mEventHandler); 2669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 2719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean handleMessage(Message msg) { 2729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills switch(msg.what) { 2739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_FAILED_EVENT: 2749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.w(TAG, "Scan failed"); 2759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized (mSettingsLock) { 2769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLastScanSettings = null; 2779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 2799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills case WifiMonitor.SCAN_RESULTS_EVENT: 2809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills pollLatestScanData(); 2819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills break; 2829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills default: 2839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // ignore unknown event 2849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 2869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 2889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static final Comparator<ScanResult> SCAN_RESULT_RSSI_COMPARATOR = 2899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills new Comparator<ScanResult>() { 2909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int compare(ScanResult r1, ScanResult r2) { 2919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return r2.level - r1.level; 2929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 2939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills }; 2949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private void pollLatestScanData() { 2959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 2969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLastScanSettings == null || mScanSettings == null) { 2979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // got a scan before we started scanning or after scan was canceled 2989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return; 2999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { Log.d(TAG, "Polling scan data for scan: " + mLastScanSettings.scanId); } 3029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanDetail> nativeResults = mWifiNative.getScanResults(); 3039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills List<ScanResult> scanResults = new ArrayList<>(); 3049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < nativeResults.size(); ++i) { 3059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = nativeResults.get(i).getScanResult(); 3069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills long timestamp_ms = result.timestamp / 1000; // convert us -> ms 3079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (timestamp_ms > mLastScanSettings.startTime) { 3089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills scanResults.add(result); 3099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 3119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // was a cached result in wpa_supplicant 3129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 31441e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 31541e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if (mScanEventHandler != null) { 31641e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if ((mLastScanSettings.reportEvents & 31741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) { 31841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills for (ScanResult scanResult : scanResults) { 31941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mScanEventHandler.onFullScanResult(scanResult); 32041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 32141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 32241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 32341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills 3249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Collections.sort(scanResults, SCAN_RESULT_RSSI_COMPARATOR); 3259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult[] scanResultsArray = 3269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills new ScanResult[Math.min(mLastScanSettings.maxAps, scanResults.size())]; 3279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < scanResultsArray.length; ++i) { 3289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills scanResultsArray[i] = scanResults.get(i); 3299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((mLastScanSettings.reportEvents & WifiScanner.REPORT_EVENT_NO_BATCH) == 0) { 33241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mScanBuffer.add(new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 33341e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills scanResultsArray)); 3349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mScanEventHandler != null) { 3379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((mLastScanSettings.reportEvents & 3389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0 || 3399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills (mLastScanSettings.reportEvents & 3409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN) != 0 || 3419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills (mLastScanSettings.reportEvents == WifiScanner.REPORT_EVENT_AFTER_BUFFER_FULL 3429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills && (mScanBuffer.size() >= 3439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills (mScanBuffer.capacity() * mLastScanSettings.reportPercentThreshold 3449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills / 100) || 3459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanBuffer.size() >= mLastScanSettings.reportNumScansThreshold)) ) { 3469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mScanEventHandler.onScanStatus(); 3479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mHotlistHandler != null) { 3519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int event = mHotlistChangeBuffer.processScan(scanResultsArray); 3529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((event & ChangeBuffer.EVENT_FOUND) != 0) { 3539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler.onHotlistApFound( 3549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_FOUND)); 3559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if ((event & ChangeBuffer.EVENT_LOST) != 0) { 3579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler.onHotlistApLost( 3589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.getLastResults(ChangeBuffer.EVENT_LOST)); 3599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 3669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] getLatestBatchedScanResults(boolean flush) { 36741e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills synchronized(mSettingsLock) { 36841e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills WifiScanner.ScanData[] results = mScanBuffer.get(); 36941e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills if (flush) { 37041e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills mScanBuffer.clear(); 37141e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills } 37241e38d84f562e12198f7db0d45f633712cae6cbaMitchell Wills return results; 3739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 3779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean setHotlist(WifiScanner.HotlistSettings settings, 3789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills WifiNative.HotlistEventHandler eventHandler) { 3799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (settings == null || eventHandler == null) { 3809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return false; 3819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 3839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = eventHandler; 3849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.setSettings(settings.bssidInfos, settings.apLostThreshold, 1); 3859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return true; 3869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills @Override 3909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void resetHotlist() { 3919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills synchronized(mSettingsLock) { 3929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistChangeBuffer.clearSettings(); 3939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mHotlistHandler = null; 3949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 3969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 3979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class LastScanSettings { 3989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int scanId; 3999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills long startTime; 4009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int maxAps; 4019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportEvents; 4029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportNumScansThreshold; 4039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportPercentThreshold; 4049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public LastScanSettings(int scanId, long startTime, int maxAps, int reportEvents, 4069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int reportNumScansThreshold, int reportPercentThreshold) { 4079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.scanId = scanId; 4089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.startTime = startTime; 4099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.maxAps = maxAps; 4109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportEvents = reportEvents; 4119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportNumScansThreshold = reportNumScansThreshold; 4129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.reportPercentThreshold = reportPercentThreshold; 4139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ScanBuffer { 4189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private final ArrayDeque<WifiScanner.ScanData> mBuffer; 4199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int capacity; 4209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanBuffer(int capacity) { 4229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer = new ArrayDeque<>(capacity); 4239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills this.capacity = capacity; 4249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int size() { 4279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.size(); 4289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int capacity() { 4319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return capacity; 4329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public boolean isFull() { 4359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return size() == capacity; 4369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void add(WifiScanner.ScanData scanData) { 4399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (isFull()) { 4409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.pollFirst(); 4419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.offerLast(scanData); 4439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clear() { 4469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBuffer.clear(); 4479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public WifiScanner.ScanData[] get() { 4509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return mBuffer.toArray(new WifiScanner.ScanData[mBuffer.size()]); 4519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static class ChangeBuffer { 4559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_NONE = 0; 4569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_LOST = 1; 4579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public static int EVENT_FOUND = 2; 4589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static int STATE_FOUND = 0; 4609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private WifiScanner.BssidInfo[] mBssidInfos = null; 4629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mApLostThreshold; 4639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int mMinEvents; 4649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mLostCount = null; 4659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private ScanResult[] mMostRecentResult = null; 4669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private int[] mPendingEvent = null; 4679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private boolean mFiredEvents = false; 4689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills private static ScanResult findResult(ScanResult[] results, String bssid) { 4709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < results.length; ++i) { 4719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bssid.equalsIgnoreCase(results[i].BSSID)) { 4729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return results[i]; 4739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return null; 4769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 4789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void setSettings(WifiScanner.BssidInfo[] bssidInfos, int apLostThreshold, 4799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int minEvents) { 4809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mBssidInfos = bssidInfos; 4819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (apLostThreshold <= 0) { 4829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = 1; 4839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 4859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mApLostThreshold = apLostThreshold; 4869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMinEvents = minEvents; 4889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (bssidInfos != null) { 4899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = new int[bssidInfos.length]; 4909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Arrays.fill(mLostCount, mApLostThreshold); // default to lost 4919ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = new ScanResult[bssidInfos.length]; 4929ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = new int[bssidInfos.length]; 4939ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 4949ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 4959ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 4969ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount = null; 4979ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult = null; 4989ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent = null; 4999ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5009ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5019ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5029ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public void clearSettings() { 5039ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills setSettings(null, 0, 0); 5049ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5059ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5069ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 5079ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Get the most recent scan results for APs that triggered the given event on the last call 5089ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * to {@link #processScan}. 5099ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 5109ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public ScanResult[] getLastResults(int event) { 5119ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ArrayList<ScanResult> results = new ArrayList<>(); 5129ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 5139ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == event) { 5149ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills results.add(mMostRecentResult[i]); 5159ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5169ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5179ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return results.toArray(new ScanResult[results.size()]); 5189ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5199ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5209ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills /** 5219ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * Process the supplied scan results and determine if any events should be generated based 5229ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * on the configured settings 5239ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills * @return The events that occurred 5249ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills */ 5259ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills public int processScan(ScanResult[] scanResults) { 5269ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mBssidInfos == null) { 5279ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 5289ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5299ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5309ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills // clear events from last time 5319ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mFiredEvents) { 5329ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = false; 5339ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 5349ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 5359ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5369ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5379ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5389ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventCount = 0; 5399ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int eventType = EVENT_NONE; 5409ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills for (int i = 0; i < mLostCount.length; ++i) { 5419ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ScanResult result = findResult(scanResults, mBssidInfos[i].bssid); 5429ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills int rssi = Integer.MIN_VALUE; 5439ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (result != null) { 5449ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mMostRecentResult[i] = result; 5459ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills rssi = result.level; 5469ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5479ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5489ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (rssi < mBssidInfos[i].low) { 5499ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] < mApLostThreshold) { 5509ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i]++; 5519ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills 5529ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 5539ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_FOUND) { 5549ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 5559ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5569ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 5579ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_LOST; 5589ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5599ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5609ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5619ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5629ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 5639ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mLostCount[i] >= mApLostThreshold) { 5649ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] == EVENT_LOST) { 5659ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_NONE; 5669ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5679ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills else { 5689ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mPendingEvent[i] = EVENT_FOUND; 5699ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5709ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5719ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mLostCount[i] = STATE_FOUND; 5729ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5739ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { 5749ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills Log.d(TAG, "ChangeBuffer BSSID: " + mBssidInfos[i].bssid + "=" + mLostCount[i] + 5759ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ", " + mPendingEvent[i] + ", rssi=" + rssi); 5769ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5779ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (mPendingEvent[i] != EVENT_NONE) { 5789ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills ++eventCount; 5799ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills eventType |= mPendingEvent[i]; 5809ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5819ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5829ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (DBG) { Log.d(TAG, "ChangeBuffer events count=" + eventCount + ": " + eventType); } 5839ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills if (eventCount >= mMinEvents) { 5849ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills mFiredEvents = true; 5859ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return eventType; 5869ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5879ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills return EVENT_NONE; 5889ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5899ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills } 5909ec71f6499e0e3d6f52310a41ff4a59d2fa4f8b2Mitchell Wills} 591