diff options
-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(); |