diff options
author | Quang Luong <qal@google.com> | 2019-10-18 17:01:36 -0700 |
---|---|---|
committer | Quang Luong <qal@google.com> | 2019-10-29 15:24:40 -0700 |
commit | 1824c4a65f417262013219d01a69a8a9034cd862 (patch) | |
tree | 3d1bd53da009d40208dd705da3a38503ebefda29 /libs | |
parent | c5862c2fd835b6217480d625a9c9309b727aba7e (diff) |
Split WifiTracker2 into separate classes for each Settings fragment
The original WifiTracker2 was intended to be monolithic and cover every
surface of WifiSettings. But since the same WifiTracker2 instance can't
be transfered to different fragments, it would be more maintainable and
efficient to have separate classes handle each fragment, which require
a similar scanning functionality but for different purposes.
Test: atest WifiPickerTrackerTest
Bug: 70983952
Change-Id: Ib0642b0973fce37a3a74d07c7f768bdaf165670e
Diffstat (limited to 'libs')
-rw-r--r-- | libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java | 301 | ||||
-rw-r--r-- | libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java | 7 | ||||
-rw-r--r-- | libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java | 379 | ||||
-rw-r--r-- | libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiTracker2.java | 504 | ||||
-rw-r--r-- | libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java (renamed from libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiTracker2Test.java) | 78 |
5 files changed, 723 insertions, 546 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java new file mode 100644 index 000000000..bfa61b3df --- /dev/null +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wifitrackerlib; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkScoreManager; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.AnyThread; +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.WorkerThread; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; + +import java.time.Clock; + +/** + * Abstract base for WifiTracker functionality. + * + * This class provides the basic functions of issuing scans, receiving Wi-Fi related broadcasts, and + * keeping track of the Wi-Fi state. + * + * Subclasses are expected to provide their own API to clients and implement the abstract broadcast + * handling methods here to populate the data returned by their API. + * + * This class runs on two threads: + * + * The main thread + * - Processes lifecycle events (onStart, onStop) + * - Runs listener callbacks + * + * The worker thread + * - Drives the periodic scan requests + * - Handles the system broadcasts to update the API return values + * - Notifies the listener for updates to the API return values + * + * To keep synchronization simple, this means that the vast majority of work is done within the + * worker thread. Synchronized blocks are only to be used for data returned by the API updated by + * the worker thread and consumed by the main thread. +*/ + +public abstract class BaseWifiTracker implements LifecycleObserver { + private final String mTag; + + private static boolean sVerboseLogging; + + public static boolean isVerboseLoggingEnabled() { + return BaseWifiTracker.sVerboseLogging; + } + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + /** + * TODO (b/70983952): Add the rest of the broadcast handling. + * WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); + * WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); + * WifiManager.NETWORK_STATE_CHANGED_ACTION); + * WifiManager.RSSI_CHANGED_ACTION); + */ + @Override + @WorkerThread + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (isVerboseLoggingEnabled()) { + Log.v(mTag, "Received broadcast: " + action); + } + + if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { + if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { + mScanner.start(); + } else { + mScanner.stop(); + } + notifyOnWifiStateChanged(); + handleWifiStateChangedAction(); + } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) { + handleScanResultsAvailableAction(intent); + } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)) { + handleConfiguredNetworksChangedAction(intent); + } + } + }; + private final BaseWifiTracker.Scanner mScanner; + private final BaseWifiTrackerCallback mListener; + + protected final Context mContext; + protected final WifiManager mWifiManager; + protected final ConnectivityManager mConnectivityManager; + protected final NetworkScoreManager mNetworkScoreManager; + protected final Handler mMainHandler; + protected final Handler mWorkerHandler; + protected final long mMaxScanAgeMillis; + protected final long mScanIntervalMillis; + protected final ScanResultUpdater mScanResultUpdater; + + /** + * Constructor for BaseWifiTracker. + * + * @param lifecycle Lifecycle this is tied to for lifecycle callbacks. + * @param context Context for registering broadcast receiver and for resource strings. + * @param wifiManager Provides all Wi-Fi info. + * @param connectivityManager Provides network info. + * @param networkScoreManager Provides network scores for network badging. + * @param mainHandler Handler for processing listener callbacks. + * @param workerHandler Handler for processing all broadcasts and running the Scanner. + * @param clock Clock used for evaluating the age of scans + * @param maxScanAgeMillis Max age for tracked WifiEntries. + * @param scanIntervalMillis Interval between initiating scans. + */ + BaseWifiTracker(@NonNull Lifecycle lifecycle, @NonNull Context context, + @NonNull WifiManager wifiManager, + @NonNull ConnectivityManager connectivityManager, + @NonNull NetworkScoreManager networkScoreManager, + @NonNull Handler mainHandler, + @NonNull Handler workerHandler, + @NonNull Clock clock, + long maxScanAgeMillis, + long scanIntervalMillis, + BaseWifiTrackerCallback listener, + String tag) { + lifecycle.addObserver(this); + mContext = context; + mWifiManager = wifiManager; + mConnectivityManager = connectivityManager; + mNetworkScoreManager = networkScoreManager; + mMainHandler = mainHandler; + mWorkerHandler = workerHandler; + mMaxScanAgeMillis = maxScanAgeMillis; + mScanIntervalMillis = scanIntervalMillis; + mListener = listener; + mTag = tag; + + mScanResultUpdater = new ScanResultUpdater(clock, + maxScanAgeMillis + scanIntervalMillis); + mScanner = new BaseWifiTracker.Scanner(workerHandler.getLooper()); + sVerboseLogging = mWifiManager.getVerboseLoggingLevel() > 0; + } + + /** + * Registers the broadcast receiver and network callbacks and starts the scanning mechanism. + */ + @OnLifecycleEvent(Lifecycle.Event.ON_START) + @MainThread + public void onStart() { + // TODO (b/70983952): Register score cache and receivers for network callbacks. + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); + mContext.registerReceiver(mBroadcastReceiver, filter, + /* broadcastPermission */ null, mWorkerHandler); + if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { + mScanner.start(); + } else { + mScanner.stop(); + } + mWorkerHandler.post(this::handleOnStart); + } + + /** + * Unregisters the broadcast receiver, network callbacks, and pauses the scanning mechanism. + */ + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + @MainThread + public void onStop() { + // TODO (b/70983952): Unregister score cache and receivers for network callbacks. + mScanner.stop(); + mContext.unregisterReceiver(mBroadcastReceiver); + } + + /** + * Returns the state of Wi-Fi as one of the following values. + * + * <li>{@link WifiManager#WIFI_STATE_DISABLED}</li> + * <li>{@link WifiManager#WIFI_STATE_ENABLED}</li> + * <li>{@link WifiManager#WIFI_STATE_DISABLING}</li> + * <li>{@link WifiManager#WIFI_STATE_ENABLING}</li> + * <li>{@link WifiManager#WIFI_STATE_UNKNOWN}</li> + */ + @AnyThread + public int getWifiState() { + return mWifiManager.getWifiState(); + } + + /** + * Method to run on the worker thread when onStart is invoked. + * Data that can be updated immediately after onStart should be populated here. + */ + @WorkerThread + protected abstract void handleOnStart(); + + /** + * Handle receiving the WifiManager.WIFI_STATE_CHANGED_ACTION broadcast + */ + @WorkerThread + protected abstract void handleWifiStateChangedAction(); + + /** + * Handle receiving the WifiManager.SCAN_RESULTS_AVAILABLE_ACTION broadcast + */ + @WorkerThread + protected abstract void handleScanResultsAvailableAction(@NonNull Intent intent); + + /** + * Handle receiving the WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION broadcast + */ + @WorkerThread + protected abstract void handleConfiguredNetworksChangedAction(@NonNull Intent intent); + + /** + * Scanner to handle starting scans every SCAN_INTERVAL_MILLIS + */ + private class Scanner extends Handler { + private static final int SCAN_RETRY_TIMES = 3; + + private int mRetry = 0; + + private Scanner(Looper looper) { + super(looper); + } + + @AnyThread + private void start() { + if (isVerboseLoggingEnabled()) { + Log.v(mTag, "Scanner start"); + } + post(this::postScan); + } + + @AnyThread + private void stop() { + if (isVerboseLoggingEnabled()) { + Log.v(mTag, "Scanner stop"); + } + mRetry = 0; + removeCallbacksAndMessages(null); + } + + @WorkerThread + private void postScan() { + if (mWifiManager.startScan()) { + mRetry = 0; + } else if (++mRetry >= SCAN_RETRY_TIMES) { + // TODO(b/70983952): See if toast is needed here + if (isVerboseLoggingEnabled()) { + Log.v(mTag, "Scanner failed to start scan " + mRetry + " times!"); + } + mRetry = 0; + return; + } + postDelayed(this::postScan, mScanIntervalMillis); + } + } + + /** + * Posts onWifiStateChanged callback on the main thread. + */ + @WorkerThread + private void notifyOnWifiStateChanged() { + if (mListener != null) { + mMainHandler.post(mListener::onWifiStateChanged); + } + } + + /** + * Base callback handling Wi-Fi state changes + * + * Subclasses should extend this for their own needs. + */ + protected interface BaseWifiTrackerCallback { + /** + * Called when the state of Wi-Fi has changed. The new value can be read through + * {@link #getWifiState()} + */ + @MainThread + void onWifiStateChanged(); + } +} diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java index c3b762633..94fbdf278 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java @@ -30,10 +30,11 @@ import java.lang.annotation.RetentionPolicy; import java.util.List; /** - * Abstract base class for an entry representing a Wi-Fi network in a Wi-Fi picker. + * Abstract base class for an entry representing a Wi-Fi network in a Wi-Fi picker/settings. * - * Clients implementing a Wi-Fi picker should receive WifiEntry objects from WifiTracker2, and rely - * on the given API for all user-displayable information and actions on the represented network. + * Clients implementing a Wi-Fi picker/settings should receive WifiEntry objects from classes + * implementing BaseWifiTracker, and rely on the given API for all user-displayable information and + * actions on the represented network. */ public abstract class WifiEntry implements Comparable<WifiEntry> { @Retention(RetentionPolicy.SOURCE) diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java new file mode 100644 index 000000000..e6c17a4cb --- /dev/null +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wifitrackerlib; + +import static androidx.core.util.Preconditions.checkNotNull; + +import static com.android.wifitrackerlib.StandardWifiEntry.wifiConfigToStandardWifiEntryKey; +import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; + +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkScoreManager; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.AnyThread; +import androidx.annotation.GuardedBy; +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.WorkerThread; +import androidx.lifecycle.Lifecycle; + +import java.time.Clock; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Wi-Fi tracker that provides all Wi-Fi related data to the Wi-Fi picker page. + * + * These include + * - The connected WifiEntry + * - List of all visible WifiEntries + * - Number of saved networks + * - Number of saved subscriptions + */ +public class WifiPickerTracker extends BaseWifiTracker { + + private static final String TAG = "WifiPickerTracker"; + + private final WifiPickerTrackerCallback mListener; + + // Lock object for data returned by the public API + private final Object mLock = new Object(); + // List representing return value of the getWifiEntries() API + @GuardedBy("mLock") private final List<WifiEntry> mWifiEntries = new ArrayList<>(); + // Cache containing visible StandardWifiEntries. Must be accessed only by the worker thread. + private final Map<String, StandardWifiEntry> mStandardWifiEntryCache = new HashMap<>(); + + private int mNumSavedNetworks = 0; + + /** + * Constructor for WifiPickerTracker. + * + * @param lifecycle Lifecycle this is tied to for lifecycle callbacks. + * @param context Context for registering broadcast receiver and for resource strings. + * @param wifiManager Provides all Wi-Fi info. + * @param connectivityManager Provides network info. + * @param networkScoreManager Provides network scores for network badging. + * @param mainHandler Handler for processing listener callbacks. + * @param workerHandler Handler for processing all broadcasts and running the Scanner. + * @param clock Clock used for evaluating the age of scans + * @param maxScanAgeMillis Max age for tracked WifiEntries. + * @param scanIntervalMillis Interval between initiating scans. + * @param listener WifiTrackerCallback listening on changes to WifiPickerTracker data. + */ + public WifiPickerTracker(@NonNull Lifecycle lifecycle, @NonNull Context context, + @NonNull WifiManager wifiManager, + @NonNull ConnectivityManager connectivityManager, + @NonNull NetworkScoreManager networkScoreManager, + @NonNull Handler mainHandler, + @NonNull Handler workerHandler, + @NonNull Clock clock, + long maxScanAgeMillis, + long scanIntervalMillis, + @Nullable WifiPickerTrackerCallback listener) { + super(lifecycle, context, wifiManager, connectivityManager, networkScoreManager, + mainHandler, workerHandler, clock, maxScanAgeMillis, scanIntervalMillis, listener, + TAG); + mListener = listener; + } + + /** + * Returns the WifiEntry representing the current connection. + */ + @AnyThread + public @Nullable WifiEntry getConnectedWifiEntry() { + // TODO (b/70983952): Fill in this method. + return null; + } + + /** + * Returns a list of in-range WifiEntries. + * + * The currently connected entry is omitted and may be accessed through + * {@link #getConnectedWifiEntry()} + */ + @AnyThread + public @NonNull List<WifiEntry> getWifiEntries() { + synchronized (mLock) { + return new ArrayList<>(mWifiEntries); + } + } + + /** + * Returns the number of saved networks. + */ + @AnyThread + public int getNumSavedNetworks() { + return mNumSavedNetworks; + } + + /** + * Returns the number of saved subscriptions. + */ + @AnyThread + public int getNumSavedSubscriptions() { + //TODO(b/70983952): Use a cached value for this and update dynamically instead of calling + // this expensive method every time. + return mWifiManager.getPasspointConfigurations().size(); + } + + @WorkerThread + @Override + protected void handleOnStart() { + mScanResultUpdater.update(mWifiManager.getScanResults()); + conditionallyUpdateScanResults(true /* lastScanSucceeded */); + updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); + updateWifiEntries(); + } + + @WorkerThread + @Override + protected void handleWifiStateChangedAction() { + conditionallyUpdateScanResults(true /* lastScanSucceeded */); + updateWifiEntries(); + } + + @WorkerThread + @Override + protected void handleScanResultsAvailableAction(@NonNull Intent intent) { + checkNotNull(intent, "Intent cannot be null!"); + conditionallyUpdateScanResults( + intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, true)); + updateWifiEntries(); + } + + @WorkerThread + @Override + protected void handleConfiguredNetworksChangedAction(@NonNull Intent intent) { + checkNotNull(intent, "Intent cannot be null!"); + + final WifiConfiguration config = + (WifiConfiguration) intent.getExtra(WifiManager.EXTRA_WIFI_CONFIGURATION); + if (config != null) { + updateStandardWifiEntryConfig( + config, (Integer) intent.getExtra(WifiManager.EXTRA_CHANGE_REASON)); + } else { + updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); + } + updateWifiEntries(); + } + + /** + * Update the list returned by getWifiEntries() with the current states of the entry caches. + */ + @WorkerThread + private void updateWifiEntries() { + synchronized (mLock) { + mWifiEntries.clear(); + mWifiEntries.addAll(mStandardWifiEntryCache.values().stream().filter( + entry -> entry.getLevel() != WIFI_LEVEL_UNREACHABLE).collect(toList())); + // mWifiEntries.addAll(mPasspointWifiEntryCache); + // mWifiEntries.addAll(mCarrierWifiEntryCache); + // mWifiEntries.addAll(mSuggestionWifiEntryCache); + Collections.sort(mWifiEntries); + if (isVerboseLoggingEnabled()) { + Log.v(TAG, "Updated WifiEntries: " + Arrays.toString(mWifiEntries.toArray())); + } + } + notifyOnWifiEntriesChanged(); + } + + /** + * Updates or removes scan results for the corresponding StandardWifiEntries. + * New entries will be created for scan results without an existing entry. + * Unreachable entries will be removed. + * + * @param scanResults List of valid scan results to convey as StandardWifiEntries + */ + @WorkerThread + private void updateStandardWifiEntryScans(@NonNull List<ScanResult> scanResults) { + checkNotNull(scanResults, "Scan Result list should not be null!"); + + // Group scans by StandardWifiEntry key + final Map<String, List<ScanResult>> scanResultsByKey = scanResults.stream() + .filter(scanResult -> !TextUtils.isEmpty(scanResult.SSID)) + .collect(groupingBy(StandardWifiEntry::scanResultToStandardWifiEntryKey)); + + // Iterate through current entries and update each entry's scan results + mStandardWifiEntryCache.entrySet().removeIf(e -> { + final String key = e.getKey(); + final StandardWifiEntry entry = e.getValue(); + // Update scan results if available, or set to null. + entry.updateScanResultInfo(scanResultsByKey.remove(key)); + // Entry is now unreachable, remove it. + return entry.getLevel() == WIFI_LEVEL_UNREACHABLE; + }); + + // Create new StandardWifiEntry objects for each leftover group of scan results. + for (Map.Entry<String, List<ScanResult>> e: scanResultsByKey.entrySet()) { + mStandardWifiEntryCache.put(e.getKey(), + new StandardWifiEntry(mMainHandler, e.getValue())); + } + + updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); + } + + /** + * Conditionally updates the WifiEntry scan results based on the current wifi state and + * whether the last scan succeeded or not. + */ + @WorkerThread + private void conditionallyUpdateScanResults(boolean lastScanSucceeded) { + if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) { + updateStandardWifiEntryScans(Collections.emptyList()); + return; + } + + long scanAgeWindow = mMaxScanAgeMillis; + if (lastScanSucceeded) { + // Scan succeeded, cache new scans + mScanResultUpdater.update(mWifiManager.getScanResults()); + } else { + // Scan failed, increase scan age window to prevent WifiEntry list from + // clearing prematurely. + scanAgeWindow += mScanIntervalMillis; + } + updateStandardWifiEntryScans(mScanResultUpdater.getScanResults(scanAgeWindow)); + } + + /** + * Updates a single WifiConfiguration for the corresponding StandardWifiEntry if it exists. + * + * @param config WifiConfiguration to update + * @param changeReason WifiManager.CHANGE_REASON_ADDED, WifiManager.CHANGE_REASON_REMOVED, or + * WifiManager.CHANGE_REASON_CONFIG_CHANGE + */ + @WorkerThread + private void updateStandardWifiEntryConfig(@NonNull WifiConfiguration config, + int changeReason) { + checkNotNull(config, "Config should not be null!"); + + final String key = wifiConfigToStandardWifiEntryKey(config); + final StandardWifiEntry entry = mStandardWifiEntryCache.get(key); + + if (entry != null) { + if (changeReason == WifiManager.CHANGE_REASON_REMOVED) { + mNumSavedNetworks--; + entry.updateConfig(null); + } else { // CHANGE_REASON_ADDED || CHANGE_REASON_CONFIG_CHANGE + if (changeReason == WifiManager.CHANGE_REASON_ADDED) mNumSavedNetworks++; + entry.updateConfig(config); + } + } + } + + /** + * Updates all saved WifiConfigurations for the corresponding StandardWifiEntries if they exist. + * + * @param configs List of saved WifiConfigurations + */ + @WorkerThread + private void updateStandardWifiEntryConfigs(@NonNull List<WifiConfiguration> configs) { + checkNotNull(configs, "Config list should not be null!"); + mNumSavedNetworks = configs.size(); + + // Group configs by StandardWifiEntry key + final Map<String, WifiConfiguration> wifiConfigsByKey = + configs.stream().collect(Collectors.toMap( + StandardWifiEntry::wifiConfigToStandardWifiEntryKey, + Function.identity())); + + // Iterate through current entries and update each entry's config + mStandardWifiEntryCache.entrySet().forEach((entry) -> { + final StandardWifiEntry wifiEntry = entry.getValue(); + final String key = wifiEntry.getKey(); + wifiEntry.updateConfig(wifiConfigsByKey.get(key)); + }); + } + + /** + * Posts onWifiEntryChanged callback on the main thread. + */ + @WorkerThread + private void notifyOnWifiEntriesChanged() { + if (mListener != null) { + mMainHandler.post(mListener::onWifiEntriesChanged); + } + } + + /** + * Posts onNumSavedNetworksChanged callback on the main thread. + */ + @WorkerThread + private void notifyOnNumSavedNetworksChanged() { + if (mListener != null) { + mMainHandler.post(mListener::onNumSavedNetworksChanged); + } + } + + /** + * Posts onNumSavedSubscriptionsChanged callback on the main thread. + */ + @WorkerThread + private void notifyOnNumSavedSubscriptionsChanged() { + if (mListener != null) { + mMainHandler.post(mListener::onNumSavedSubscriptionsChanged); + } + } + + /** + * Listener for changes to the list of visible WifiEntries as well as the number of saved + * networks and subscriptions. + * + * These callbacks must be run on the MainThread. + */ + public interface WifiPickerTrackerCallback extends BaseWifiTracker.BaseWifiTrackerCallback { + /** + * Called when there are changes to + * {@link #getConnectedWifiEntry()} + * {@link #getWifiEntries()} + */ + @MainThread + void onWifiEntriesChanged(); + + /** + * Called when there are changes to + * {@link #getNumSavedNetworks()} + */ + @MainThread + void onNumSavedNetworksChanged(); + + /** + * Called when there are changes to + * {@link #getNumSavedSubscriptions()} + */ + @MainThread + void onNumSavedSubscriptionsChanged(); + } +} diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiTracker2.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiTracker2.java deleted file mode 100644 index 3feab63d6..000000000 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiTracker2.java +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wifitrackerlib; - -import static androidx.core.util.Preconditions.checkNotNull; - -import static com.android.wifitrackerlib.StandardWifiEntry.wifiConfigToStandardWifiEntryKey; -import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE; - -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toList; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkScoreManager; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.AnyThread; -import androidx.annotation.GuardedBy; -import androidx.annotation.MainThread; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; -import androidx.lifecycle.Lifecycle; -import androidx.lifecycle.LifecycleObserver; -import androidx.lifecycle.OnLifecycleEvent; - -import java.time.Clock; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * Keeps track of the state of Wi-Fi and supplies {@link WifiEntry} for use in Wi-Fi picker lists. - * - * Clients should use WifiTracker2/WifiEntry for all information regarding Wi-Fi. - * - * This class runs on two threads: - * - * The main thread processes lifecycle events (onStart, onStop), as well as listener callbacks since - * these directly manipulate the UI. - * - * The worker thread is responsible for driving the periodic scan requests and updating internal - * data in reaction to system broadcasts. After a data update, the listener is notified on the main - * thread. - * - * To keep synchronization simple, this means that the vast majority of work is done within the - * worker thread. Synchronized blocks should then be used for updating/accessing only data that is - * consumed by the client listener. - */ -public class WifiTracker2 implements LifecycleObserver { - - private static final String TAG = "WifiTracker2"; - - public static boolean sVerboseLogging; - - private static boolean isVerboseLoggingEnabled() { - return WifiTracker2.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE); - } - - private final Context mContext; - private final WifiManager mWifiManager; - private final ConnectivityManager mConnectivityManager; - private final NetworkScoreManager mNetworkScoreManager; - private final Handler mMainHandler; - private final Handler mWorkerHandler; - private final long mMaxScanAgeMillis; - private final long mScanIntervalMillis; - private final WifiTrackerCallback mListener; - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - /** - * TODO (b/70983952): Add the rest of the broadcast handling. - * WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); - * WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); - * WifiManager.NETWORK_STATE_CHANGED_ACTION); - * WifiManager.RSSI_CHANGED_ACTION); - */ - @Override - @WorkerThread - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - - if (isVerboseLoggingEnabled()) { - Log.v(TAG, "Received broadcast: " + action); - } - - if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { - if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { - mScanner.start(); - } else { - mScanner.stop(); - } - notifyOnWifiStateChanged(); - } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) { - if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, true)) { - // Scan succeeded, update scans aged to mMaxScanAgeMillis - mScanResultUpdater.update(mWifiManager.getScanResults()); - updateStandardWifiEntryScans(mScanResultUpdater.getScanResults( - mMaxScanAgeMillis)); - } else { - // Scan failed, keep results from previous scan to prevent WifiEntry list from - // clearing prematurely. - updateStandardWifiEntryScans(mScanResultUpdater.getScanResults( - mMaxScanAgeMillis + mScanIntervalMillis)); - } - updateWifiEntries(); - } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)) { - final WifiConfiguration config = - (WifiConfiguration) intent.getExtra(WifiManager.EXTRA_WIFI_CONFIGURATION); - if (config != null) { - updateStandardWifiEntryConfig( - config, (Integer) intent.getExtra(WifiManager.EXTRA_CHANGE_REASON)); - } else { - updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); - } - updateWifiEntries(); - } - } - }; - private final ScanResultUpdater mScanResultUpdater; - private final Scanner mScanner; - - // Lock object for data returned by the public API - private final Object mLock = new Object(); - - // List representing return value of the getWifiEntries() API - @GuardedBy("mLock") private final List<WifiEntry> mWifiEntries = new ArrayList<>(); - - // Cache containing StandardWifiEntries for visible networks and saved networks - // Must be accessed only by the worker thread. - private final Map<String, StandardWifiEntry> mStandardWifiEntryCache = new HashMap<>(); - - /** - * Constructor for WifiTracker2. - * - * @param lifecycle Lifecycle this is tied to for lifecycle callbacks. - * @param context Context to retrieve WifiManager and resource strings. - * @param wifiManager Provides all Wi-Fi info. - * @param connectivityManager Provides network info. - * @param networkScoreManager Provides network scores for network badging. - * @param mainHandler Handler for processing listener callbacks. - * @param workerHandler Handler for processing all broadcasts and running the Scanner. - * @param clock Clock used for evaluating the age of scans - * @param maxScanAgeMillis Max age for tracked WifiEntries. - * @param scanIntervalMillis Interval between initiating scans. - * @param listener WifiTrackerCallback listening on changes to WifiTracker2 data. - */ - public WifiTracker2(@NonNull Lifecycle lifecycle, @NonNull Context context, - @NonNull WifiManager wifiManager, - @NonNull ConnectivityManager connectivityManager, - @NonNull NetworkScoreManager networkScoreManager, - @NonNull Handler mainHandler, - @NonNull Handler workerHandler, - @NonNull Clock clock, - long maxScanAgeMillis, - long scanIntervalMillis, - @Nullable WifiTrackerCallback listener) { - lifecycle.addObserver(this); - mContext = context; - mWifiManager = wifiManager; - mConnectivityManager = connectivityManager; - mNetworkScoreManager = networkScoreManager; - mMainHandler = mainHandler; - mWorkerHandler = workerHandler; - mMaxScanAgeMillis = maxScanAgeMillis; - mScanIntervalMillis = scanIntervalMillis; - mListener = listener; - - mScanResultUpdater = new ScanResultUpdater(clock, - maxScanAgeMillis + scanIntervalMillis); - mScanner = new Scanner(workerHandler.getLooper()); - - sVerboseLogging = mWifiManager.getVerboseLoggingLevel() > 0; - } - - /** - * Registers the broadcast receiver and network callbacks and starts the scanning mechanism. - */ - @OnLifecycleEvent(Lifecycle.Event.ON_START) - @MainThread - public void onStart() { - // TODO (b/70983952): Register score cache and receivers for network callbacks. - IntentFilter filter = new IntentFilter(); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - mContext.registerReceiver(mBroadcastReceiver, filter, - /* broadcastPermission */ null, mWorkerHandler); - - // Populate data now so we don't have to wait for the next broadcast. - mWorkerHandler.post(() -> { - if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { - mScanner.start(); - } else { - mScanner.stop(); - } - notifyOnWifiStateChanged(); - - mScanResultUpdater.update(mWifiManager.getScanResults()); - updateStandardWifiEntryScans(mScanResultUpdater.getScanResults(mMaxScanAgeMillis)); - updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); - updateWifiEntries(); - }); - } - - /** - * Unregisters the broadcast receiver, network callbacks, and pauses the scanning mechanism. - */ - @OnLifecycleEvent(Lifecycle.Event.ON_STOP) - @MainThread - public void onStop() { - // TODO (b/70983952): Unregister score cache and receivers for network callbacks. - mScanner.stop(); - mContext.unregisterReceiver(mBroadcastReceiver); - } - - /** - * Returns the state of Wi-Fi as one of the following values. - * - * <li>{@link WifiManager#WIFI_STATE_DISABLED}</li> - * <li>{@link WifiManager#WIFI_STATE_ENABLED}</li> - * <li>{@link WifiManager#WIFI_STATE_DISABLING}</li> - * <li>{@link WifiManager#WIFI_STATE_ENABLING}</li> - * <li>{@link WifiManager#WIFI_STATE_UNKNOWN}</li> - */ - @AnyThread - public int getWifiState() { - return mWifiManager.getWifiState(); - } - - /** - * Returns the WifiEntry representing the current connection. - */ - @AnyThread - public @Nullable WifiEntry getConnectedWifiEntry() { - // TODO (b/70983952): Fill in this method. - return null; - } - - /** - * Returns a list of in-range WifiEntries. - * - * The currently connected entry is omitted and may be accessed through - * {@link #getConnectedWifiEntry()} - */ - @AnyThread - public @NonNull List<WifiEntry> getWifiEntries() { - synchronized (mLock) { - return new ArrayList<>(mWifiEntries); - } - } - - /** - * Returns a list of WifiEntries representing saved networks. - */ - @AnyThread - public @NonNull List<WifiEntry> getSavedWifiEntries() { - // TODO (b/70983952): Fill in this method. - return new ArrayList<>(); - } - - /** - * Returns a list of WifiEntries representing network subscriptions. - */ - @AnyThread - public @NonNull List<WifiEntry> getSubscriptionEntries() { - // TODO (b/70983952): Fill in this method. - return new ArrayList<>(); - } - - /** - * Update the list returned by getWifiEntries() with the current states of the entry caches. - */ - @WorkerThread - private void updateWifiEntries() { - synchronized (mLock) { - mWifiEntries.clear(); - mWifiEntries.addAll(mStandardWifiEntryCache.values().stream().filter( - entry -> entry.getLevel() != WIFI_LEVEL_UNREACHABLE).collect(toList())); - // mWifiEntries.addAll(mPasspointWifiEntryCache); - // mWifiEntries.addAll(mCarrierWifiEntryCache); - // mWifiEntries.addAll(mSuggestionWifiEntryCache); - Collections.sort(mWifiEntries); - if (isVerboseLoggingEnabled()) { - Log.v(TAG, "Updated WifiEntries: " + Arrays.toString(mWifiEntries.toArray())); - } - } - notifyOnWifiEntriesChanged(); - } - - /** - * Updates or removes a single WifiConfiguration for the corresponding StandardWifiEntry. - * A new entry will be created for configs without an existing entry. - * Unsaved and unreachable entries will be removed. - * - * @param config WifiConfiguration to update - * @param changeReason WifiManager.CHANGE_REASON_ADDED, WifiManager.CHANGE_REASON_REMOVED, or - * WifiManager.CHANGE_REASON_CONFIG_CHANGE - */ - @WorkerThread - private void updateStandardWifiEntryConfig(WifiConfiguration config, int changeReason) { - checkNotNull(config, "Config should not be null!"); - - final String key = wifiConfigToStandardWifiEntryKey(config); - final StandardWifiEntry entry = mStandardWifiEntryCache.get(key); - - if (entry != null) { - if (changeReason == WifiManager.CHANGE_REASON_REMOVED) { - entry.updateConfig(null); - // Remove unsaved, unreachable entry from cache - if (entry.getLevel() == WIFI_LEVEL_UNREACHABLE) mStandardWifiEntryCache.remove(key); - } else { // CHANGE_REASON_ADDED || CHANGE_REASON_CONFIG_CHANGE - entry.updateConfig(config); - } - } else { - if (changeReason != WifiManager.CHANGE_REASON_REMOVED) { - mStandardWifiEntryCache.put(key, new StandardWifiEntry(mMainHandler, config)); - } - } - } - - /** - * Updates or removes all saved WifiConfigurations for the corresponding StandardWifiEntries. - * New entries will be created for configs without an existing entry. - * Unsaved and unreachable entries will be removed. - * - * @param configs List of saved WifiConfigurations - */ - @WorkerThread - private void updateStandardWifiEntryConfigs(@NonNull List<WifiConfiguration> configs) { - checkNotNull(configs, "Config list should not be null!"); - - // Group configs by StandardWifiEntry key - final Map<String, WifiConfiguration> wifiConfigsByKey = - configs.stream().collect(Collectors.toMap( - StandardWifiEntry::wifiConfigToStandardWifiEntryKey, - Function.identity())); - - // Iterate through current entries and update each entry's config - mStandardWifiEntryCache.entrySet().removeIf(e -> { - final String key = e.getKey(); - final StandardWifiEntry entry = e.getValue(); - // Update the config if available, or set to null. - entry.updateConfig(wifiConfigsByKey.remove(key)); - // Entry is not saved and is unreachable, remove it. - return !entry.isSaved() && entry.getLevel() == WIFI_LEVEL_UNREACHABLE; - }); - - // Create new StandardWifiEntry objects for each leftover config - for (Map.Entry<String, WifiConfiguration> e: wifiConfigsByKey.entrySet()) { - mStandardWifiEntryCache.put(e.getKey(), - new StandardWifiEntry(mMainHandler, e.getValue())); - } - } - - /** - * Updates or removes scan results for the corresponding StandardWifiEntries. - * New entries will be created for scan results without an existing entry. - * Unsaved and unreachable entries will be removed. - * - * @param scanResults List of valid scan results to convey as StandardWifiEntries - */ - @WorkerThread - private void updateStandardWifiEntryScans(@NonNull List<ScanResult> scanResults) { - checkNotNull(scanResults, "Scan Result list should not be null!"); - - // Group scans by StandardWifiEntry key - final Map<String, List<ScanResult>> scanResultsByKey = scanResults.stream() - .filter(scanResult -> !TextUtils.isEmpty(scanResult.SSID)) - .collect(groupingBy(StandardWifiEntry::scanResultToStandardWifiEntryKey)); - - // Iterate through current entries and update each entry's scan results - mStandardWifiEntryCache.entrySet().removeIf(e -> { - final String key = e.getKey(); - final StandardWifiEntry entry = e.getValue(); - // Update scan results if available, or set to null. - entry.updateScanResultInfo(scanResultsByKey.remove(key)); - // Entry is not saved and is unreachable, remove it. - return !entry.isSaved() && entry.getLevel() == WIFI_LEVEL_UNREACHABLE; - }); - - // Create new StandardWifiEntry objects for each leftover group of scan results. - for (Map.Entry<String, List<ScanResult>> e: scanResultsByKey.entrySet()) { - mStandardWifiEntryCache.put(e.getKey(), - new StandardWifiEntry(mMainHandler, e.getValue())); - } - } - - /** - * Posts onWifiEntryChanged callback on the main thread. - */ - @WorkerThread - private void notifyOnWifiEntriesChanged() { - if (mListener != null) { - mMainHandler.post(mListener::onWifiEntriesChanged); - } - } - - /** - * Posts onWifiStateChanged callback on the main thread. - */ - @WorkerThread - private void notifyOnWifiStateChanged() { - if (mListener != null) { - mMainHandler.post(mListener::onWifiStateChanged); - } - } - - /** - * Scanner to handle starting scans every SCAN_INTERVAL_MILLIS - */ - private class Scanner extends Handler { - private static final int SCAN_RETRY_TIMES = 3; - - private int mRetry = 0; - - private Scanner(Looper looper) { - super(looper); - } - - @AnyThread - private void start() { - if (isVerboseLoggingEnabled()) { - Log.v(TAG, "Scanner start"); - } - post(this::postScan); - } - - @AnyThread - private void stop() { - if (isVerboseLoggingEnabled()) { - Log.v(TAG, "Scanner stop"); - } - mRetry = 0; - removeCallbacksAndMessages(null); - } - - @WorkerThread - private void postScan() { - if (mWifiManager.startScan()) { - mRetry = 0; - } else if (++mRetry >= SCAN_RETRY_TIMES) { - // TODO(b/70983952): See if toast is needed here - if (isVerboseLoggingEnabled()) { - Log.v(TAG, "Scanner failed to start scan " + mRetry + " times!"); - } - mRetry = 0; - return; - } - postDelayed(this::postScan, mScanIntervalMillis); - } - } - - /** - * Listener for changes to the Wi-Fi state or lists of WifiEntries. - * - * These callbacks must be run on the MainThread. - * - * TODO (b/70983952): Investigate need for callbacks for saved/subscription entry updates. - */ - public interface WifiTrackerCallback { - /** - * Called when there are changes to - * {@link #getConnectedWifiEntry()} - * {@link #getWifiEntries()} - */ - @MainThread - void onWifiEntriesChanged(); - - /** - * Called when the state of Wi-Fi has changed. The new value can be read through - * {@link #getWifiState()} - */ - @MainThread - void onWifiStateChanged(); - } -} diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiTracker2Test.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java index f7dc5cc30..4e5104851 100644 --- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiTracker2Test.java +++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java @@ -50,7 +50,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -public class WifiTracker2Test { +public class WifiPickerTrackerTest { private static final long START_MILLIS = 123_456_789; @@ -63,17 +63,17 @@ public class WifiTracker2Test { @Mock private ConnectivityManager mMockConnectivityManager; @Mock private NetworkScoreManager mMockNetworkScoreManager; @Mock private Clock mMockClock; - @Mock private WifiTracker2.WifiTrackerCallback mMockWifiTrackerCallback; + @Mock private WifiPickerTracker.WifiPickerTrackerCallback mMockWifiTrackerCallback; private TestLooper mTestLooper; private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - private WifiTracker2 createTestWifiTracker2() { + private WifiPickerTracker createTestWifiTracker2() { final Handler testHandler = new Handler(mTestLooper.getLooper()); - return new WifiTracker2(mMockLifecycle, mMockContext, + return new WifiPickerTracker(mMockLifecycle, mMockContext, mMockWifiManager, mMockConnectivityManager, mMockNetworkScoreManager, @@ -100,8 +100,8 @@ public class WifiTracker2Test { */ @Test public void testWifiStateChangeBroadcast_updatesWifiState() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -110,14 +110,14 @@ public class WifiTracker2Test { mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)); - assertThat(wifiTracker2.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); + assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); // Change the wifi state to enabled when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)); - assertThat(wifiTracker2.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); + assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); } @@ -126,8 +126,8 @@ public class WifiTracker2Test { */ @Test public void testWifiStateChangeBroadcast_NotifiesListener() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -143,22 +143,22 @@ public class WifiTracker2Test { */ @Test public void testOnStart_setsWifiState() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); // Set the wifi state to disabled when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED); - wifiTracker2.onStart(); + wifiPickerTracker.onStart(); mTestLooper.dispatchAll(); - assertThat(wifiTracker2.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); + assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); // Change the wifi state to enabled - wifiTracker2.onStop(); + wifiPickerTracker.onStop(); when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED); - wifiTracker2.onStart(); + wifiPickerTracker.onStart(); mTestLooper.dispatchAll(); - assertThat(wifiTracker2.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); + assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); } /** @@ -166,8 +166,8 @@ public class WifiTracker2Test { */ @Test public void testScanResultsAvailableAction_notifiesListener() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -183,8 +183,8 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_noScans_emptyList() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -193,7 +193,7 @@ public class WifiTracker2Test { mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - assertThat(wifiTracker2.getWifiEntries()).isEmpty(); + assertThat(wifiPickerTracker.getWifiEntries()).isEmpty(); } @@ -203,8 +203,8 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_wifiNetworkEntries_createdForEachSsidAndSecurityPair() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -224,7 +224,7 @@ public class WifiTracker2Test { mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); List<String> seenKeys = new ArrayList<>(); - for (WifiEntry wifiEntry : wifiTracker2.getWifiEntries()) { + for (WifiEntry wifiEntry : wifiPickerTracker.getWifiEntries()) { seenKeys.add(wifiEntry.getKey()); } @@ -238,8 +238,8 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_wifiNetworkEntries_oldEntriesTimedOut() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -257,7 +257,7 @@ public class WifiTracker2Test { when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - assertThat(wifiTracker2.getWifiEntries()).isNotEmpty(); + assertThat(wifiPickerTracker.getWifiEntries()).isNotEmpty(); // Advance the clock to time out old entries @@ -266,7 +266,7 @@ public class WifiTracker2Test { new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); // All entries timed out - assertThat(wifiTracker2.getWifiEntries()).isEmpty(); + assertThat(wifiPickerTracker.getWifiEntries()).isEmpty(); } /** @@ -275,8 +275,8 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_wifiNetworkEntries_useOldEntriesOnFailedScan() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -289,7 +289,7 @@ public class WifiTracker2Test { buildScanResult("ssid4", "bssid4", START_MILLIS))); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - final List<WifiEntry> previousEntries = wifiTracker2.getWifiEntries(); + final List<WifiEntry> previousEntries = wifiPickerTracker.getWifiEntries(); // Advance the clock to time out old entries and simulate failed scan when(mMockClock.millis()) @@ -299,14 +299,14 @@ public class WifiTracker2Test { .putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)); // Failed scan should result in old WifiEntries still being shown - assertThat(previousEntries).containsExactlyElementsIn(wifiTracker2.getWifiEntries()); + assertThat(previousEntries).containsExactlyElementsIn(wifiPickerTracker.getWifiEntries()); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) .putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true)); // Successful scan should time out old entries. - assertThat(wifiTracker2.getWifiEntries()).isEmpty(); + assertThat(wifiPickerTracker.getWifiEntries()).isEmpty(); } /** @@ -315,8 +315,8 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_configuredNetworksChanged_unsavedToSaved() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); - wifiTracker2.onStart(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); @@ -324,7 +324,7 @@ public class WifiTracker2Test { buildScanResult("ssid", "bssid", START_MILLIS))); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - final WifiEntry entry = wifiTracker2.getWifiEntries().get(0); + final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0); assertThat(entry.isSaved()).isFalse(); @@ -345,12 +345,12 @@ public class WifiTracker2Test { */ @Test public void testGetWifiEntries_configuredNetworksChanged_savedToUnsaved() { - final WifiTracker2 wifiTracker2 = createTestWifiTracker2(); + final WifiPickerTracker wifiPickerTracker = createTestWifiTracker2(); final WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"ssid\""; when(mMockWifiManager.getConfiguredNetworks()) .thenReturn(Collections.singletonList(config)); - wifiTracker2.onStart(); + wifiPickerTracker.onStart(); verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any()); mTestLooper.dispatchAll(); @@ -359,7 +359,7 @@ public class WifiTracker2Test { buildScanResult("ssid", "bssid", START_MILLIS))); mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - final WifiEntry entry = wifiTracker2.getWifiEntries().get(0); + final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0); assertThat(entry.isSaved()).isTrue(); |