diff options
author | Quang Luong <qal@google.com> | 2020-04-23 21:39:03 -0700 |
---|---|---|
committer | Quang Luong <qal@google.com> | 2020-04-29 21:12:41 -0700 |
commit | 549f83b742b362ee65c4550d06e9f21ecad04ffd (patch) | |
tree | 7abc9f2d1bb540bed68e7776a1971768b2aefdda /libs/WifiTrackerLib/src | |
parent | 70774fd42719e7dc76a0a23b36f9d474106abb3b (diff) | |
download | frameworks_opt_net_wifi-549f83b742b362ee65c4550d06e9f21ecad04ffd.tar.gz frameworks_opt_net_wifi-549f83b742b362ee65c4550d06e9f21ecad04ffd.tar.bz2 frameworks_opt_net_wifi-549f83b742b362ee65c4550d06e9f21ecad04ffd.zip |
[WifiTrackerLib] Add speed label to network summary
Adds speed label (badging) to the network summary, indicating the
network speed based on an rssi curve.
Test: atest StandardWifiEntryTest, atest PasspointWifiEntryTest
Bug: 152568815
Change-Id: I9c193aa3be0fd684312dad2dd51bb011d0db78c3
Diffstat (limited to 'libs/WifiTrackerLib/src')
10 files changed, 286 insertions, 74 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java index bc551c20d..2f5b56eea 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java @@ -18,6 +18,8 @@ package com.android.wifitrackerlib; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static java.util.stream.Collectors.toList; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -26,9 +28,12 @@ import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; +import android.net.NetworkKey; import android.net.NetworkRequest; import android.net.NetworkScoreManager; +import android.net.ScoredNetwork; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -43,6 +48,9 @@ import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; import java.time.Clock; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * Base class for WifiTracker functionality. @@ -79,13 +87,6 @@ public class BaseWifiTracker implements LifecycleObserver { } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - /** - * TODO (b/70983952): Add the rest of the broadcast handling. - * WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); - * WifiManager.ACTION_LINK_CONFIGURATION_CHANGED); - * WifiManager.NETWORK_STATE_CHANGED_ACTION); - * WifiManager.RSSI_CHANGED_ACTION); - */ @Override @WorkerThread public void onReceive(Context context, Intent intent) { @@ -104,6 +105,10 @@ public class BaseWifiTracker implements LifecycleObserver { notifyOnWifiStateChanged(); handleWifiStateChangedAction(); } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) { + mNetworkScoreManager.requestScores(mWifiManager.getScanResults().stream() + .map(NetworkKey::createFromScanResult) + .filter(mRequestedScoreKeys::add) + .collect(toList())); handleScanResultsAvailableAction(intent); } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)) { handleConfiguredNetworksChangedAction(intent); @@ -126,6 +131,8 @@ public class BaseWifiTracker implements LifecycleObserver { protected final long mMaxScanAgeMillis; protected final long mScanIntervalMillis; protected final ScanResultUpdater mScanResultUpdater; + protected final WifiNetworkScoreCache mWifiNetworkScoreCache; + private final Set<NetworkKey> mRequestedScoreKeys = new HashSet<>(); // Network request for listening on changes to Wifi link properties and network capabilities // such as captive portal availability. @@ -185,6 +192,13 @@ public class BaseWifiTracker implements LifecycleObserver { mScanResultUpdater = new ScanResultUpdater(clock, maxScanAgeMillis + scanIntervalMillis); + mWifiNetworkScoreCache = new WifiNetworkScoreCache(mContext, + new WifiNetworkScoreCache.CacheListener(mWorkerHandler) { + @Override + public void networkCacheUpdated(List<ScoredNetwork> networks) { + handleNetworkScoreCacheUpdated(); + } + }); mScanner = new BaseWifiTracker.Scanner(workerHandler.getLooper()); sVerboseLogging = mWifiManager.isVerboseLoggingEnabled(); } @@ -195,7 +209,6 @@ public class BaseWifiTracker implements LifecycleObserver { @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); @@ -206,6 +219,10 @@ public class BaseWifiTracker implements LifecycleObserver { /* broadcastPermission */ null, mWorkerHandler); mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback, mWorkerHandler); + mNetworkScoreManager.registerNetworkScoreCache( + NetworkKey.TYPE_WIFI, + mWifiNetworkScoreCache, + NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS); if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) { mScanner.start(); } else { @@ -220,10 +237,12 @@ public class BaseWifiTracker implements LifecycleObserver { @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); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); + mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, + mWifiNetworkScoreCache); + mWorkerHandler.post(mRequestedScoreKeys::clear); } /** @@ -306,6 +325,14 @@ public class BaseWifiTracker implements LifecycleObserver { } /** + * Handle updates to the Wifi network score cache, which is stored in mWifiNetworkScoreCache + */ + @WorkerThread + protected void handleNetworkScoreCacheUpdated() { + // Do nothing. + } + + /** * Scanner to handle starting scans every SCAN_INTERVAL_MILLIS */ private class Scanner extends Handler { diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java index 55709d1be..16e55fb96 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java @@ -28,6 +28,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.ProvisioningCallback; @@ -61,16 +62,15 @@ class OsuWifiEntry extends WifiEntry { @NonNull private OsuProvider mOsuProvider; private String mOsuStatusString; - private int mLevel = WIFI_LEVEL_UNREACHABLE; - /** * Create n OsuWifiEntry with the associated OsuProvider */ OsuWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler, @NonNull OsuProvider osuProvider, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { - super(callbackHandler, wifiManager, forSavedNetworksPage); + super(callbackHandler, wifiManager, scoreCache, forSavedNetworksPage); checkNotNull(osuProvider, "Cannot construct with null osuProvider!"); @@ -97,11 +97,6 @@ class OsuWifiEntry extends WifiEntry { } @Override - public int getLevel() { - return mLevel; - } - - @Override public String getSsid() { // TODO(b/70983952): Fill this method in in case we need the SSID for verbose logging return ""; @@ -280,12 +275,11 @@ class OsuWifiEntry extends WifiEntry { } final ScanResult bestScanResult = getBestScanResultByLevel(scanResults); - if (bestScanResult == null) { - mLevel = WIFI_LEVEL_UNREACHABLE; - } else { - mLevel = mWifiManager.calculateSignalLevel(bestScanResult.level); + if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) { + mLevel = bestScanResult != null + ? mWifiManager.calculateSignalLevel(bestScanResult.level) + : WIFI_LEVEL_UNREACHABLE; } - notifyOnUpdated(); } diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java index 21a25ec52..00c786fac 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java @@ -77,7 +77,8 @@ class PasspointNetworkDetailsTracker extends NetworkDetailsTracker { .findAny(); if (optionalPasspointConfig.isPresent()) { mChosenEntry = new PasspointWifiEntry(mContext, mMainHandler, - optionalPasspointConfig.get(), mWifiManager, false /* forSavedNetworksPage */); + optionalPasspointConfig.get(), mWifiManager, mWifiNetworkScoreCache, + false /* forSavedNetworksPage */); } else { Optional<WifiConfiguration> optionalWifiConfig = mWifiManager.getPrivilegedConfiguredNetworks() @@ -88,7 +89,8 @@ class PasspointNetworkDetailsTracker extends NetworkDetailsTracker { .findAny(); if (optionalWifiConfig.isPresent()) { mChosenEntry = new PasspointWifiEntry(mContext, mMainHandler, - optionalWifiConfig.get(), mWifiManager, false /* forSavedNetworksPage */); + optionalWifiConfig.get(), mWifiManager, mWifiNetworkScoreCache, + false /* forSavedNetworksPage */); } else { throw new IllegalArgumentException( "Cannot find config for given PasspointWifiEntry key!"); @@ -157,6 +159,12 @@ class PasspointNetworkDetailsTracker extends NetworkDetailsTracker { } @WorkerThread + @Override + protected void handleNetworkScoreCacheUpdated() { + mChosenEntry.onScoreCacheUpdated(); + } + + @WorkerThread private void updatePasspointWifiEntryScans(@NonNull List<ScanResult> scanResults) { checkNotNull(scanResults, "Scan Result list should not be null!"); diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java index 9b923fa07..350580250 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java @@ -23,6 +23,7 @@ import static androidx.core.util.Preconditions.checkNotNull; import static com.android.wifitrackerlib.Utils.getAppLabel; import static com.android.wifitrackerlib.Utils.getAppLabelForWifiConfiguration; import static com.android.wifitrackerlib.Utils.getAutoConnectDescription; +import static com.android.wifitrackerlib.Utils.getAverageSpeedFromScanResults; import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel; import static com.android.wifitrackerlib.Utils.getCarrierNameForSubId; import static com.android.wifitrackerlib.Utils.getCurrentNetworkCapabilitiesInformation; @@ -32,6 +33,7 @@ import static com.android.wifitrackerlib.Utils.getMeteredDescription; import static com.android.wifitrackerlib.Utils.getNetworkDetailedState; import static com.android.wifitrackerlib.Utils.getSecurityTypeFromWifiConfiguration; import static com.android.wifitrackerlib.Utils.getSpeedDescription; +import static com.android.wifitrackerlib.Utils.getSpeedFromWifiInfo; import static com.android.wifitrackerlib.Utils.getSubIdForConfig; import static com.android.wifitrackerlib.Utils.getVerboseLoggingDescription; @@ -41,6 +43,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.Handler; import android.text.TextUtils; @@ -80,7 +83,6 @@ public class PasspointWifiEntry extends WifiEntry { private @Security int mSecurity = SECURITY_EAP; private boolean mIsRoaming = false; - private int mLevel = WIFI_LEVEL_UNREACHABLE; protected long mSubscriptionExpirationTimeInMillis; // PasspointConfiguration#setMeteredOverride(int meteredOverride) is a hide API and we can't @@ -96,8 +98,9 @@ public class PasspointWifiEntry extends WifiEntry { PasspointWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler, @NonNull PasspointConfiguration passpointConfig, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { - super(callbackHandler, wifiManager, forSavedNetworksPage); + super(callbackHandler, wifiManager, scoreCache, forSavedNetworksPage); checkNotNull(passpointConfig, "Cannot construct with null PasspointConfiguration!"); @@ -119,8 +122,9 @@ public class PasspointWifiEntry extends WifiEntry { PasspointWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler, @NonNull WifiConfiguration wifiConfig, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { - super(callbackHandler, wifiManager, forSavedNetworksPage); + super(callbackHandler, wifiManager, scoreCache, forSavedNetworksPage); checkNotNull(wifiConfig, "Cannot construct with null PasspointConfiguration!"); if (!wifiConfig.isPasspoint()) { @@ -152,12 +156,6 @@ public class PasspointWifiEntry extends WifiEntry { StringJoiner sj = new StringJoiner(mContext.getString(R.string.summary_separator)); - // TODO(b/70983952): Check if it's necessary to add speend information here. - String speedDescription = getSpeedDescription(mContext, this); - if (!TextUtils.isEmpty(speedDescription)) { - sj.add(speedDescription); - } - if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) { String disconnectDescription = getDisconnectedStateDescription(mContext, this); if (TextUtils.isEmpty(disconnectDescription)) { @@ -184,6 +182,11 @@ public class PasspointWifiEntry extends WifiEntry { } } + String speedDescription = getSpeedDescription(mContext, this); + if (!TextUtils.isEmpty(speedDescription)) { + sj.add(speedDescription); + } + String autoConnectDescription = getAutoConnectDescription(mContext, this); if (!TextUtils.isEmpty(autoConnectDescription)) { sj.add(autoConnectDescription); @@ -234,12 +237,11 @@ public class PasspointWifiEntry extends WifiEntry { } @Override - public int getLevel() { - return mLevel; - } - - @Override public String getSsid() { + if (mWifiInfo != null) { + return sanitizeSsid(mWifiInfo.getSSID()); + } + return mWifiConfig != null ? sanitizeSsid(mWifiConfig.SSID) : null; } @@ -511,23 +513,46 @@ public class PasspointWifiEntry extends WifiEntry { } if (mWifiConfig != null) { mSecurity = getSecurityTypeFromWifiConfiguration(wifiConfig); + List<ScanResult> currentScanResults = new ArrayList<>(); ScanResult bestScanResult = null; if (homeScanResults != null && !homeScanResults.isEmpty()) { - bestScanResult = getBestScanResultByLevel(homeScanResults); + currentScanResults.addAll(homeScanResults); } else if (roamingScanResults != null && !roamingScanResults.isEmpty()) { + currentScanResults.addAll(roamingScanResults); mIsRoaming = true; - bestScanResult = getBestScanResultByLevel(roamingScanResults); } - if (bestScanResult == null) { - mLevel = WIFI_LEVEL_UNREACHABLE; - } else { + bestScanResult = getBestScanResultByLevel(currentScanResults); + if (bestScanResult != null) { mWifiConfig.SSID = "\"" + bestScanResult.SSID + "\""; - mLevel = mWifiManager.calculateSignalLevel(bestScanResult.level); + } + if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) { + mLevel = bestScanResult != null + ? mWifiManager.calculateSignalLevel(bestScanResult.level) + : WIFI_LEVEL_UNREACHABLE; + // Average speed is used to prevent speed label flickering from multiple APs. + mSpeed = getAverageSpeedFromScanResults(mScoreCache, currentScanResults); } } else { mLevel = WIFI_LEVEL_UNREACHABLE; } + notifyOnUpdated(); + } + @WorkerThread + void onScoreCacheUpdated() { + if (mWifiInfo != null) { + mSpeed = getSpeedFromWifiInfo(mScoreCache, mWifiInfo); + } else { + synchronized (mLock) { + // Average speed is used to prevent speed label flickering from multiple APs. + if (!mCurrentHomeScanResults.isEmpty()) { + mSpeed = getAverageSpeedFromScanResults(mScoreCache, mCurrentHomeScanResults); + } else { + mSpeed = getAverageSpeedFromScanResults(mScoreCache, + mCurrentRoamingScanResults); + } + } + } notifyOnUpdated(); } diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java index be0c7fd94..c6b5454b0 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java @@ -169,6 +169,17 @@ public class SavedNetworkTracker extends BaseWifiTracker { updateSubscriptionWifiEntries(); } + @WorkerThread + @Override + protected void handleNetworkScoreCacheUpdated() { + for (StandardWifiEntry entry : mStandardWifiEntryCache.values()) { + entry.onScoreCacheUpdated(); + } + for (PasspointWifiEntry entry : mPasspointWifiEntryCache.values()) { + entry.onScoreCacheUpdated(); + } + } + private void updateSavedWifiEntries() { synchronized (mLock) { mSavedWifiEntries.clear(); @@ -300,7 +311,7 @@ public class SavedNetworkTracker extends BaseWifiTracker { if (changeReason != WifiManager.CHANGE_REASON_REMOVED) { mStandardWifiEntryCache.put(key, new StandardWifiEntry(mContext, mMainHandler, key, config, mWifiManager, - true /* forSavedNetworksPage */)); + mWifiNetworkScoreCache, true /* forSavedNetworksPage */)); } } } @@ -328,7 +339,7 @@ public class SavedNetworkTracker extends BaseWifiTracker { for (String key : wifiConfigsByKey.keySet()) { mStandardWifiEntryCache.put(key, new StandardWifiEntry(mContext, mMainHandler, key, wifiConfigsByKey.get(key), - mWifiManager, true /* forSavedNetworksPage */)); + mWifiManager, mWifiNetworkScoreCache, true /* forSavedNetworksPage */)); } } @@ -359,7 +370,7 @@ public class SavedNetworkTracker extends BaseWifiTracker { for (String key : passpointConfigsByKey.keySet()) { mPasspointWifiEntryCache.put(key, new PasspointWifiEntry(mContext, mMainHandler, passpointConfigsByKey.get(key), - mWifiManager, true /* forSavedNetworksPage */)); + mWifiManager, mWifiNetworkScoreCache, true /* forSavedNetworksPage */)); } } diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java index f97ae643f..aee8ca37c 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java @@ -68,7 +68,7 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker { super(lifecycle, context, wifiManager, connectivityManager, networkScoreManager, mainHandler, workerHandler, clock, maxScanAgeMillis, scanIntervalMillis, TAG); mChosenEntry = new StandardWifiEntry(mContext, mMainHandler, key, mWifiManager, - false /* forSavedNetworksPage */); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */); cacheNewScanResults(); conditionallyUpdateScanResults(true /* lastScanSucceeded */); conditionallyUpdateConfig(); @@ -153,6 +153,12 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker { } } + @WorkerThread + @Override + protected void handleNetworkScoreCacheUpdated() { + mChosenEntry.onScoreCacheUpdated(); + } + /** * Updates the tracked entry's scan results up to the max scan age (or more, if the last scan * was unsuccessful). If Wifi is disabled, the tracked entry's level will be cleared. diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java index 4a1be50f4..06b27656a 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java @@ -28,6 +28,7 @@ import static com.android.wifitrackerlib.Utils.getAppLabel; import static com.android.wifitrackerlib.Utils.getAppLabelForSavedNetwork; import static com.android.wifitrackerlib.Utils.getAppLabelForWifiConfiguration; import static com.android.wifitrackerlib.Utils.getAutoConnectDescription; +import static com.android.wifitrackerlib.Utils.getAverageSpeedFromScanResults; import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel; import static com.android.wifitrackerlib.Utils.getCarrierNameForSubId; import static com.android.wifitrackerlib.Utils.getCurrentNetworkCapabilitiesInformation; @@ -37,6 +38,7 @@ import static com.android.wifitrackerlib.Utils.getMeteredDescription; import static com.android.wifitrackerlib.Utils.getNetworkDetailedState; import static com.android.wifitrackerlib.Utils.getSecurityTypeFromWifiConfiguration; import static com.android.wifitrackerlib.Utils.getSpeedDescription; +import static com.android.wifitrackerlib.Utils.getSpeedFromWifiInfo; import static com.android.wifitrackerlib.Utils.getSubIdForConfig; import static com.android.wifitrackerlib.Utils.getVerboseLoggingDescription; @@ -51,6 +53,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.os.Handler; import android.os.SystemClock; import android.text.TextUtils; @@ -129,8 +132,10 @@ public class StandardWifiEntry extends WifiEntry { @NonNull String key, @NonNull List<ScanResult> scanResults, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { - this(context, callbackHandler, key, wifiManager, forSavedNetworksPage); + this(context, callbackHandler, key, wifiManager, scoreCache, + forSavedNetworksPage); checkNotNull(scanResults, "Cannot construct with null ScanResult list!"); if (scanResults.isEmpty()) { @@ -143,8 +148,10 @@ public class StandardWifiEntry extends WifiEntry { StandardWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler, @NonNull String key, @NonNull WifiConfiguration config, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { - this(context, callbackHandler, key, wifiManager, forSavedNetworksPage); + this(context, callbackHandler, key, wifiManager, scoreCache, + forSavedNetworksPage); checkNotNull(config, "Cannot construct with null config!"); checkNotNull(config.SSID, "Supplied config must have an SSID!"); @@ -153,9 +160,11 @@ public class StandardWifiEntry extends WifiEntry { } StandardWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler, - @NonNull String key, @NonNull WifiManager wifiManager, boolean forSavedNetworksPage) { + @NonNull String key, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, + boolean forSavedNetworksPage) { // TODO: second argument (isSaved = false) is bogus in this context - super(callbackHandler, wifiManager, forSavedNetworksPage); + super(callbackHandler, wifiManager, scoreCache, forSavedNetworksPage); if (!key.startsWith(KEY_PREFIX)) { throw new IllegalArgumentException("Key does not start with correct prefix!"); @@ -186,11 +195,6 @@ public class StandardWifiEntry extends WifiEntry { public String getSummary(boolean concise) { StringJoiner sj = new StringJoiner(mContext.getString(R.string.summary_separator)); - final String speedDescription = getSpeedDescription(mContext, this); - if (!TextUtils.isEmpty(speedDescription)) { - sj.add(speedDescription); - } - if (!concise && mForSavedNetworksPage && isSaved()) { final CharSequence appLabel = getAppLabelForSavedNetwork(mContext, this); if (!TextUtils.isEmpty(appLabel)) { @@ -225,6 +229,11 @@ public class StandardWifiEntry extends WifiEntry { } } + final String speedDescription = getSpeedDescription(mContext, this); + if (!TextUtils.isEmpty(speedDescription)) { + sj.add(speedDescription); + } + final String autoConnectDescription = getAutoConnectDescription(mContext, this); if (!TextUtils.isEmpty(autoConnectDescription)) { sj.add(autoConnectDescription); @@ -285,11 +294,6 @@ public class StandardWifiEntry extends WifiEntry { } @Override - public int getLevel() { - return mLevel; - } - - @Override public String getSsid() { return mSsid; } @@ -702,6 +706,10 @@ public class StandardWifiEntry extends WifiEntry { mLevel = bestScanResult != null ? mWifiManager.calculateSignalLevel(bestScanResult.level) : WIFI_LEVEL_UNREACHABLE; + synchronized (mLock) { + // Average speed is used to prevent speed label flickering from multiple APs. + mSpeed = getAverageSpeedFromScanResults(mScoreCache, mCurrentScanResults); + } } notifyOnUpdated(); } @@ -718,6 +726,19 @@ public class StandardWifiEntry extends WifiEntry { } } + @WorkerThread + void onScoreCacheUpdated() { + if (mWifiInfo != null) { + mSpeed = getSpeedFromWifiInfo(mScoreCache, mWifiInfo); + } else { + synchronized (mLock) { + // Average speed is used to prevent speed label flickering from multiple APs. + mSpeed = getAverageSpeedFromScanResults(mScoreCache, mCurrentScanResults); + } + } + notifyOnUpdated(); + } + private void updateEapType(ScanResult result) { if (result.capabilities.contains("RSN-EAP")) { // WPA2-Enterprise and WPA3-Enterprise (non 192-bit) advertise RSN-EAP-CCMP diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java index 00a8dcf30..78617ba5a 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java @@ -27,6 +27,12 @@ import static com.android.wifitrackerlib.WifiEntry.SECURITY_OWE; import static com.android.wifitrackerlib.WifiEntry.SECURITY_PSK; import static com.android.wifitrackerlib.WifiEntry.SECURITY_SAE; import static com.android.wifitrackerlib.WifiEntry.SECURITY_WEP; +import static com.android.wifitrackerlib.WifiEntry.SPEED_FAST; +import static com.android.wifitrackerlib.WifiEntry.SPEED_MODERATE; +import static com.android.wifitrackerlib.WifiEntry.SPEED_NONE; +import static com.android.wifitrackerlib.WifiEntry.SPEED_SLOW; +import static com.android.wifitrackerlib.WifiEntry.SPEED_VERY_FAST; +import static com.android.wifitrackerlib.WifiEntry.Speed; import static java.util.Comparator.comparingInt; import static java.util.stream.Collectors.groupingBy; @@ -39,9 +45,13 @@ import android.content.pm.PackageManager; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; +import android.net.NetworkKey; +import android.net.ScoredNetwork; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiNetworkScoreCache; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.UserHandle; @@ -301,6 +311,53 @@ class Utils { return scanResultsByKey; } + @Speed + static int getAverageSpeedFromScanResults(@NonNull WifiNetworkScoreCache scoreCache, + @NonNull List<ScanResult> scanResults) { + int count = 0; + int totalSpeed = 0; + for (ScanResult scanResult : scanResults) { + ScoredNetwork scoredNetwork = scoreCache.getScoredNetwork(scanResult); + if (scoredNetwork == null) { + continue; + } + @Speed int speed = scoredNetwork.calculateBadge(scanResult.level); + if (speed != SPEED_NONE) { + count++; + totalSpeed += speed; + } + } + if (count == 0) { + return SPEED_NONE; + } else { + return roundToClosestSpeedEnum(totalSpeed / count); + } + } + + @Speed + static int getSpeedFromWifiInfo(@NonNull WifiNetworkScoreCache scoreCache, + @NonNull WifiInfo wifiInfo) { + ScoredNetwork scoredNetwork = scoreCache.getScoredNetwork( + NetworkKey.createFromWifiInfo(wifiInfo)); + if (scoredNetwork == null) { + return SPEED_NONE; + } + return roundToClosestSpeedEnum(scoredNetwork.calculateBadge(wifiInfo.getRssi())); + } + + @Speed + private static int roundToClosestSpeedEnum(int speed) { + if (speed < (SPEED_SLOW + SPEED_MODERATE) / 2) { + return SPEED_SLOW; + } else if (speed < (SPEED_MODERATE + SPEED_FAST) / 2) { + return SPEED_MODERATE; + } else if (speed < (SPEED_FAST + SPEED_VERY_FAST) / 2) { + return SPEED_FAST; + } else { + return SPEED_VERY_FAST; + } + } + static CharSequence getAppLabel(Context context, String packageName) { try { ApplicationInfo appInfo = context.getPackageManager().getApplicationInfoAsUser( @@ -421,11 +478,24 @@ class Utils { } static String getSpeedDescription(@NonNull Context context, @NonNull WifiEntry wifiEntry) { - // TODO(b/70983952): Fill this method in. if (context == null || wifiEntry == null) { return ""; } - return ""; + + @Speed int speed = wifiEntry.getSpeed(); + switch (speed) { + case SPEED_VERY_FAST: + return context.getString(R.string.speed_label_very_fast); + case SPEED_FAST: + return context.getString(R.string.speed_label_fast); + case SPEED_MODERATE: + return context.getString(R.string.speed_label_okay); + case SPEED_SLOW: + return context.getString(R.string.speed_label_slow); + case SPEED_NONE: + default: + return ""; + } } static String getVerboseLoggingDescription(@NonNull WifiEntry wifiEntry) { diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java index fb43d4bd2..e800e4832 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java @@ -20,6 +20,8 @@ import static android.net.wifi.WifiInfo.INVALID_RSSI; import static androidx.core.util.Preconditions.checkNotNull; +import static com.android.wifitrackerlib.Utils.getSpeedFromWifiInfo; + import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkCapabilities; @@ -29,6 +31,7 @@ import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiNetworkScoreCache; import android.os.Handler; import androidx.annotation.AnyThread; @@ -104,6 +107,23 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { @Retention(RetentionPolicy.SOURCE) @IntDef(value = { + SPEED_NONE, + SPEED_SLOW, + SPEED_MODERATE, + SPEED_FAST, + SPEED_VERY_FAST + }) + + public @interface Speed {} + + public static final int SPEED_NONE = 0; + public static final int SPEED_SLOW = 5; + public static final int SPEED_MODERATE = 10; + public static final int SPEED_FAST = 20; + public static final int SPEED_VERY_FAST = 30; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { METERED_CHOICE_AUTO, METERED_CHOICE_METERED, METERED_CHOICE_UNMETERED, @@ -189,10 +209,12 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { protected Handler mCallbackHandler; protected int mLevel = WIFI_LEVEL_UNREACHABLE; + protected int mSpeed = SPEED_NONE; protected WifiInfo mWifiInfo; protected NetworkInfo mNetworkInfo; protected NetworkCapabilities mNetworkCapabilities; protected ConnectedInfo mConnectedInfo; + protected WifiNetworkScoreCache mScoreCache; protected ConnectCallback mConnectCallback; protected DisconnectCallback mDisconnectCallback; @@ -202,12 +224,14 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { protected boolean mCalledDisconnect = false; WifiEntry(@NonNull Handler callbackHandler, @NonNull WifiManager wifiManager, + @NonNull WifiNetworkScoreCache scoreCache, boolean forSavedNetworksPage) throws IllegalArgumentException { checkNotNull(callbackHandler, "Cannot construct with null handler!"); checkNotNull(wifiManager, "Cannot construct with null WifiManager!"); mCallbackHandler = callbackHandler; mForSavedNetworksPage = forSavedNetworksPage; mWifiManager = wifiManager; + mScoreCache = scoreCache; } // Info available for all WifiEntries // @@ -261,7 +285,15 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { * Returns the signal strength level within [WIFI_LEVEL_MIN, WIFI_LEVEL_MAX]. * A value of WIFI_LEVEL_UNREACHABLE indicates an out of range network. */ - public abstract int getLevel(); + public int getLevel() { + return mLevel; + }; + + /** Returns the speed value of the network defined by the SPEED constants */ + @Speed + public int getSpeed() { + return mSpeed; + }; /** * Returns the SSID of the entry, if applicable. Null otherwise. @@ -585,6 +617,7 @@ public abstract class WifiEntry implements Comparable<WifiEntry> { final int wifiInfoRssi = wifiInfo.getRssi(); if (wifiInfoRssi != INVALID_RSSI) { mLevel = mWifiManager.calculateSignalLevel(wifiInfoRssi); + mSpeed = getSpeedFromWifiInfo(mScoreCache, wifiInfo); } if (getConnectedState() == CONNECTED_STATE_CONNECTED) { if (mCalledConnect) { diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java index 6e74e2eba..10c3f65c5 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java @@ -275,6 +275,20 @@ public class WifiPickerTracker extends BaseWifiTracker { } } + @WorkerThread + @Override + protected void handleNetworkScoreCacheUpdated() { + for (StandardWifiEntry entry : mStandardWifiEntryCache.values()) { + entry.onScoreCacheUpdated(); + } + for (StandardWifiEntry entry : mSuggestedWifiEntryCache.values()) { + entry.onScoreCacheUpdated(); + } + for (PasspointWifiEntry entry : mPasspointWifiEntryCache.values()) { + entry.onScoreCacheUpdated(); + } + } + /** * Update the list returned by getWifiEntries() with the current states of the entry caches. */ @@ -375,7 +389,8 @@ public class WifiPickerTracker extends BaseWifiTracker { // Create new StandardWifiEntry objects for each leftover group of scan results. for (Map.Entry<String, List<ScanResult>> e: scanResultsByKey.entrySet()) { final StandardWifiEntry newEntry = new StandardWifiEntry(mContext, mMainHandler, - e.getKey(), e.getValue(), mWifiManager, false /* forSavedNetworksPage */); + e.getKey(), e.getValue(), mWifiManager, mWifiNetworkScoreCache, + false /* forSavedNetworksPage */); // Populate with a saved config, if available newEntry.updateConfig(mWifiConfigCache.get(newEntry.getKey())); mStandardWifiEntryCache.put(newEntry.getKey(), newEntry); @@ -415,7 +430,7 @@ public class WifiPickerTracker extends BaseWifiTracker { if (!mSuggestedWifiEntryCache.containsKey(key)) { mSuggestedWifiEntryCache.put(key, new StandardWifiEntry(mContext, mMainHandler, key, userSharedConfigsByKey.get(key), mWifiManager, - false /* forSavedNetworksPage */)); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */)); } final StandardWifiEntry entry = mSuggestedWifiEntryCache.get(key); entry.setUserShareable(true); @@ -457,11 +472,11 @@ public class WifiPickerTracker extends BaseWifiTracker { if (wifiConfig.fromWifiNetworkSuggestion) { mPasspointWifiEntryCache.put(key, new PasspointWifiEntry(mContext, mMainHandler, wifiConfig, mWifiManager, - false /* forSavedNetworksPage */)); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */)); } else if (mPasspointConfigCache.containsKey(key)) { mPasspointWifiEntryCache.put(key, new PasspointWifiEntry(mContext, mMainHandler, mPasspointConfigCache.get(key), mWifiManager, - false /* forSavedNetworksPage */)); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */)); } else { // Failed to find PasspointConfig for a provisioned Passpoint network continue; @@ -494,7 +509,7 @@ public class WifiPickerTracker extends BaseWifiTracker { // Create a new entry for each OsuProvider not already matched to an OsuWifiEntry for (OsuProvider provider : osuProviderToScans.keySet()) { OsuWifiEntry newEntry = new OsuWifiEntry(mContext, mMainHandler, provider, mWifiManager, - false /* forSavedNetworksPage */); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */); newEntry.updateScanResultInfo(osuProviderToScans.get(provider)); mOsuWifiEntryCache.put(osuProviderToOsuWifiEntryKey(provider), newEntry); } @@ -691,7 +706,7 @@ public class WifiPickerTracker extends BaseWifiTracker { final StandardWifiEntry connectedEntry = new StandardWifiEntry(mContext, mMainHandler, wifiConfigToStandardWifiEntryKey(config), config, mWifiManager, - false /* forSavedNetworksPage */); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */); connectedEntry.updateConnectionInfo(wifiInfo, networkInfo); mStandardWifiEntryCache.put(connectedEntry.getKey(), connectedEntry); }); @@ -720,7 +735,7 @@ public class WifiPickerTracker extends BaseWifiTracker { final StandardWifiEntry connectedEntry = new StandardWifiEntry(mContext, mMainHandler, wifiConfigToStandardWifiEntryKey(config), config, mWifiManager, - false /* forSavedNetworksPage */); + mWifiNetworkScoreCache, false /* forSavedNetworksPage */); connectedEntry.updateConnectionInfo(wifiInfo, networkInfo); mSuggestedWifiEntryCache.put(connectedEntry.getKey(), connectedEntry); }); @@ -752,11 +767,13 @@ public class WifiPickerTracker extends BaseWifiTracker { PasspointWifiEntry connectedEntry; if (passpointConfig != null) { connectedEntry = new PasspointWifiEntry(mContext, mMainHandler, - passpointConfig, mWifiManager, false /* forSavedNetworksPage */); + passpointConfig, mWifiManager, mWifiNetworkScoreCache, + false /* forSavedNetworksPage */); } else { // Suggested PasspointWifiEntry without a corresponding Passpoint config connectedEntry = new PasspointWifiEntry(mContext, mMainHandler, - wifiConfig, mWifiManager, false /* forSavedNetworksPage */); + wifiConfig, mWifiManager, mWifiNetworkScoreCache, + false /* forSavedNetworksPage */); } connectedEntry.updateConnectionInfo(wifiInfo, networkInfo); mPasspointWifiEntryCache.put(connectedEntry.getKey(), connectedEntry); |