diff options
3 files changed, 223 insertions, 45 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java index d30fcc407..68f58ddc3 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java @@ -45,7 +45,6 @@ import androidx.lifecycle.Lifecycle; import java.time.Clock; import java.util.Collections; -import java.util.Optional; /** * Implementation of NetworkDetailsTracker that tracks a single StandardWifiEntry. @@ -107,7 +106,8 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker { checkNotNull(intent, "Intent cannot be null!"); final WifiConfiguration updatedConfig = (WifiConfiguration) intent.getExtra(WifiManager.EXTRA_WIFI_CONFIGURATION); - if (updatedConfig != null && TextUtils.equals( + if (updatedConfig != null && !updatedConfig.isPasspoint() + && !updatedConfig.fromWifiNetworkSuggestion && TextUtils.equals( wifiConfigToStandardWifiEntryKey(updatedConfig), mChosenEntry.getKey())) { final int changeReason = intent.getIntExtra(WifiManager.EXTRA_CHANGE_REASON, -1 /* defaultValue*/); @@ -172,11 +172,15 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker { * null if it does not exist. */ private void conditionallyUpdateConfig() { - Optional<WifiConfiguration> optionalConfig = mWifiManager.getConfiguredNetworks() - .stream().filter(config -> TextUtils.equals( - wifiConfigToStandardWifiEntryKey(config), mChosenEntry.getKey())) - .findAny(); - mChosenEntry.updateConfig(optionalConfig.orElse(null)); + WifiConfiguration config = mWifiManager.getConfiguredNetworks().stream() + .filter(savedConfig -> TextUtils.equals( + wifiConfigToStandardWifiEntryKey(savedConfig), mChosenEntry.getKey())) + .findAny().orElse(mWifiManager.getPrivilegedConfiguredNetworks().stream() + .filter(suggestedConfig -> TextUtils.equals( + wifiConfigToStandardWifiEntryKey(suggestedConfig), + mChosenEntry.getKey())) + .findAny().orElse(null)); + mChosenEntry.updateConfig(config); } /** diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java index 642313a2b..429219886 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java @@ -107,6 +107,7 @@ public class StandardWifiEntry extends WifiEntry { private @EapType int mEapType = EAP_UNKNOWN; private @PskType int mPskType = PSK_UNKNOWN; @Nullable private WifiConfiguration mWifiConfig; + private boolean mIsUserShareable = false; @Nullable private String mRecommendationServiceLabel; private boolean mShouldAutoOpenCaptivePortal = false; @@ -225,14 +226,6 @@ public class StandardWifiEntry extends WifiEntry { private String getConnectStateDescription() { if (getConnectedState() == CONNECTED_STATE_CONNECTED) { if (!isSaved()) { - // For ephemeral networks. - final String suggestionOrSpecifierPackageName = mWifiInfo != null - ? mWifiInfo.getRequestingPackageName() : null; - if (!TextUtils.isEmpty(suggestionOrSpecifierPackageName)) { - return mContext.getString(R.string.connected_via_app, - getAppLabel(mContext, suggestionOrSpecifierPackageName)); - } - // Special case for connected + ephemeral networks. if (!TextUtils.isEmpty(mRecommendationServiceLabel)) { return String.format(mContext.getString(R.string.connected_via_network_scorer), @@ -241,6 +234,14 @@ public class StandardWifiEntry extends WifiEntry { return mContext.getString(R.string.connected_via_network_scorer_default); } + // For network suggestions + final String suggestionOrSpecifierPackageName = mWifiInfo != null + ? mWifiInfo.getRequestingPackageName() : null; + if (!TextUtils.isEmpty(suggestionOrSpecifierPackageName)) { + return mContext.getString(R.string.connected_via_app, + getAppLabel(mContext, suggestionOrSpecifierPackageName)); + } + String networkCapabilitiesinformation = getCurrentNetworkCapabilitiesInformation(mContext, mNetworkCapabilities); if (!TextUtils.isEmpty(networkCapabilitiesinformation)) { @@ -300,7 +301,10 @@ public class StandardWifiEntry extends WifiEntry { @Override public WifiConfiguration getWifiConfiguration() { - return mWifiConfig; + if (mWifiConfig != null && !mWifiConfig.fromWifiNetworkSuggestion) { + return mWifiConfig; + } + return null; } @Override @@ -373,12 +377,12 @@ public class StandardWifiEntry extends WifiEntry { @Override public boolean canForget() { - return isSaved(); + return getWifiConfiguration() != null; } @Override public void forget(@Nullable ForgetCallback callback) { - if (mWifiConfig != null) { + if (canForget()) { mForgetCallback = callback; mWifiManager.forget(mWifiConfig.networkId, new ForgetActionListener()); } @@ -407,7 +411,7 @@ public class StandardWifiEntry extends WifiEntry { */ @Override public boolean canShare() { - if (!isSaved()) { + if (getWifiConfiguration() == null) { return false; } @@ -429,7 +433,7 @@ public class StandardWifiEntry extends WifiEntry { */ @Override public boolean canEasyConnect() { - if (!isSaved()) { + if (getWifiConfiguration() == null) { return false; } @@ -467,8 +471,8 @@ public class StandardWifiEntry extends WifiEntry { @Override @MeteredChoice public int getMeteredChoice() { - if (mWifiConfig != null) { - final int meteredOverride = mWifiConfig.meteredOverride; + if (getWifiConfiguration() != null) { + final int meteredOverride = getWifiConfiguration().meteredOverride; if (meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { return METERED_CHOICE_METERED; } else if (meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) { @@ -480,12 +484,12 @@ public class StandardWifiEntry extends WifiEntry { @Override public boolean canSetMeteredChoice() { - return isSaved(); + return getWifiConfiguration() != null; } @Override public void setMeteredChoice(int meteredChoice) { - if (mWifiConfig == null) { + if (!canSetMeteredChoice()) { return; } @@ -501,17 +505,14 @@ public class StandardWifiEntry extends WifiEntry { @Override public boolean canSetPrivacy() { - return isSaved(); + return getWifiConfiguration() != null; } @Override @Privacy public int getPrivacy() { - if (mWifiConfig == null) { - return PRIVACY_UNKNOWN; - } - - if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE) { + if (mWifiConfig != null + && mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE) { return PRIVACY_DEVICE_MAC; } else { return PRIVACY_RANDOMIZED_MAC; @@ -531,7 +532,7 @@ public class StandardWifiEntry extends WifiEntry { @Override public boolean isAutoJoinEnabled() { - if (mWifiConfig == null) { + if (!isSaved()) { return false; } @@ -697,6 +698,22 @@ public class StandardWifiEntry extends WifiEntry { notifyOnUpdated(); } + /** + * Sets whether the suggested config for this entry is shareable to the user or not. + */ + @WorkerThread + void setUserShareable(boolean isUserShareable) { + mIsUserShareable = isUserShareable; + } + + /** + * Returns whether the suggested config for this entry is shareable to the user or not. + */ + @WorkerThread + boolean isUserShareable() { + return mIsUserShareable; + } + @WorkerThread protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo, @NonNull NetworkInfo networkInfo) { @@ -704,7 +721,16 @@ public class StandardWifiEntry extends WifiEntry { return false; } - return mWifiConfig != null && mWifiConfig.networkId == wifiInfo.getNetworkId(); + if (mWifiConfig != null) { + if (mWifiConfig.fromWifiNetworkSuggestion) { + // Match network suggestions with SSID since the net id is prone to change. + return TextUtils.equals(mSsid, sanitizeSsid(wifiInfo.getSSID())); + } + if (mWifiConfig.networkId == wifiInfo.getNetworkId()) { + return true; + } + } + return false; } private void updateRecommendationServiceLabel() { diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java index 0c6d7d6c0..c08b47cd1 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java @@ -44,6 +44,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.Handler; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -91,9 +92,14 @@ public class WifiPickerTracker extends BaseWifiTracker { // Cache containing saved WifiConfigurations mapped by StandardWifiEntry key private final Map<String, WifiConfiguration> mWifiConfigCache = new HashMap<>(); + + private final Map<String, WifiConfiguration> mSuggestedConfigCache = new HashMap<>(); // Cache containing visible StandardWifiEntries. Must be accessed only by the worker thread. private final Map<String, StandardWifiEntry> mStandardWifiEntryCache = new HashMap<>(); - + // Cache containing available suggested StandardWifiEntries. These entries may be already + // represented in mStandardWifiEntryCache, so filtering must be done before they are returned in + // getWifiEntry() and getConnectedWifiEntry(). + private final Map<String, StandardWifiEntry> mSuggestedWifiEntryCache = new HashMap<>(); // Cache containing saved PasspointConfigurations mapped by PasspointWifiEntry key. private final Map<String, PasspointConfiguration> mPasspointConfigCache = new HashMap<>(); // Cache containing visible PasspointWifiEntries. Must be accessed only by the worker thread. @@ -173,6 +179,8 @@ public class WifiPickerTracker extends BaseWifiTracker { @Override protected void handleOnStart() { updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); + updateSuggestedWifiEntryConfigs(mWifiManager.getPrivilegedConfiguredNetworks().stream() + .filter(config -> config.fromWifiNetworkSuggestion).collect(toList())); updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations()); mScanResultUpdater.update(mWifiManager.getScanResults()); conditionallyUpdateScanResults(true /* lastScanSucceeded */); @@ -181,6 +189,7 @@ public class WifiPickerTracker extends BaseWifiTracker { updateConnectionInfo(wifiInfo, networkInfo); // Create a StandardWifiEntry for the current connection if there are no scan results yet. conditionallyCreateConnectedStandardWifiEntry(wifiInfo, networkInfo); + conditionallyCreateConnectedSuggestedWifiEntry(wifiInfo, networkInfo); conditionallyCreateConnectedPasspointWifiEntry(wifiInfo, networkInfo); handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties( mWifiManager.getCurrentNetwork())); @@ -213,11 +222,14 @@ public class WifiPickerTracker extends BaseWifiTracker { final WifiConfiguration config = (WifiConfiguration) intent.getExtra(WifiManager.EXTRA_WIFI_CONFIGURATION); - if (config != null) { + if (config != null && !config.isPasspoint() && !config.fromWifiNetworkSuggestion) { updateStandardWifiEntryConfig( config, (Integer) intent.getExtra(WifiManager.EXTRA_CHANGE_REASON)); } else { updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); + updateSuggestedWifiEntryConfigs(mWifiManager.getPrivilegedConfiguredNetworks().stream() + .filter((privilegedConfig) -> privilegedConfig.fromWifiNetworkSuggestion) + .collect(toList())); } updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations()); // Update scans since config changes may result in different entries being shown. @@ -240,6 +252,7 @@ public class WifiPickerTracker extends BaseWifiTracker { updateConnectionInfo(wifiInfo, networkInfo); // Create a StandardWifiEntry for the current connection if there are no scan results yet. conditionallyCreateConnectedStandardWifiEntry(wifiInfo, networkInfo); + conditionallyCreateConnectedSuggestedWifiEntry(wifiInfo, networkInfo); conditionallyCreateConnectedPasspointWifiEntry(wifiInfo, networkInfo); updateWifiEntries(); } @@ -268,19 +281,19 @@ public class WifiPickerTracker extends BaseWifiTracker { @WorkerThread private void updateWifiEntries() { synchronized (mLock) { - mWifiEntries.clear(); - mWifiEntries.addAll(mStandardWifiEntryCache.values().stream().filter(entry -> - entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList())); - mWifiEntries.addAll(mPasspointWifiEntryCache.values().stream().filter(entry -> - entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList())); - mWifiEntries.addAll(mOsuWifiEntryCache.values().stream().filter(entry -> - entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList())); mConnectedWifiEntry = mStandardWifiEntryCache.values().stream().filter(entry -> { final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState(); return connectedState == CONNECTED_STATE_CONNECTED || connectedState == CONNECTED_STATE_CONNECTING; }).findAny().orElse(null /* other */); if (mConnectedWifiEntry == null) { + mConnectedWifiEntry = mSuggestedWifiEntryCache.values().stream().filter(entry -> { + final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState(); + return connectedState == CONNECTED_STATE_CONNECTED + || connectedState == CONNECTED_STATE_CONNECTING; + }).findAny().orElse(null /* other */); + } + if (mConnectedWifiEntry == null) { mConnectedWifiEntry = mPasspointWifiEntryCache.values().stream().filter(entry -> { final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState(); return connectedState == CONNECTED_STATE_CONNECTED @@ -294,6 +307,32 @@ public class WifiPickerTracker extends BaseWifiTracker { || connectedState == CONNECTED_STATE_CONNECTING; }).findAny().orElse(null /* other */); } + mWifiEntries.clear(); + for (String key : mStandardWifiEntryCache.keySet()) { + // Continue if we're connected to this network with a non-user-shareable config. + if (mConnectedWifiEntry != null + && TextUtils.equals(key, mConnectedWifiEntry.getKey())) { + continue; + } + StandardWifiEntry entry = mStandardWifiEntryCache.get(key); + StandardWifiEntry suggestedEntry = mSuggestedWifiEntryCache.get(key); + // Return a user-shareable suggested network to the user if one exists + if (!entry.isSaved() + && suggestedEntry != null && suggestedEntry.isUserShareable()) { + if (suggestedEntry.getConnectedState() == CONNECTED_STATE_DISCONNECTED) { + mWifiEntries.add(suggestedEntry); + } + } else { + if (entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED) { + mWifiEntries.add(entry); + } + } + + } + mWifiEntries.addAll(mPasspointWifiEntryCache.values().stream().filter(entry -> + entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList())); + mWifiEntries.addAll(mOsuWifiEntryCache.values().stream().filter(entry -> + entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList())); Collections.sort(mWifiEntries); if (isVerboseLoggingEnabled()) { Log.v(TAG, "Connected WifiEntry: " + mConnectedWifiEntry); @@ -343,6 +382,59 @@ public class WifiPickerTracker extends BaseWifiTracker { } } + /** + * 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 updateSuggestedWifiEntryScans(@NonNull List<ScanResult> scanResults) { + checkNotNull(scanResults, "Scan Result list should not be null!"); + + // Group scans by StandardWifiEntry key + final Map<String, List<ScanResult>> scanResultsByKey = mapScanResultsToKey( + scanResults, + true /* chooseSingleSecurity */, + mWifiConfigCache, + mWifiManager.isWpa3SaeSupported(), + mWifiManager.isWpa3SuiteBSupported(), + mWifiManager.isEnhancedOpenSupported()); + + Map<String, WifiConfiguration> userSharedConfigsByKey = + mWifiManager.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults) + .stream() + .collect(Collectors.toMap( + StandardWifiEntry::wifiConfigToStandardWifiEntryKey, + Function.identity())); + + Set<String> seenKeys = new TreeSet<>(); + for (String key : userSharedConfigsByKey.keySet()) { + seenKeys.add(key); + if (!mSuggestedWifiEntryCache.containsKey(key)) { + mSuggestedWifiEntryCache.put(key, new StandardWifiEntry(mContext, mMainHandler, key, + userSharedConfigsByKey.get(key), mWifiManager, + false /* forSavedNetworksPage */)); + } + final StandardWifiEntry entry = mSuggestedWifiEntryCache.get(key); + entry.setUserShareable(true); + entry.updateScanResultInfo(scanResultsByKey.get(key)); + } + + // Remove entries without configs + mSuggestedWifiEntryCache.entrySet() + .removeIf(entry -> { + StandardWifiEntry wifiEntry = entry.getValue(); + String key = entry.getKey(); + if (!seenKeys.contains(key)) { + wifiEntry.updateConfig(mSuggestedConfigCache.get(key)); + wifiEntry.setUserShareable(false); + } + return !wifiEntry.isSaved(); + }); + } + @WorkerThread private void updatePasspointWifiEntryScans(@NonNull List<ScanResult> scanResults) { checkNotNull(scanResults, "Scan Result list should not be null!"); @@ -415,6 +507,7 @@ public class WifiPickerTracker extends BaseWifiTracker { private void conditionallyUpdateScanResults(boolean lastScanSucceeded) { if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) { updateStandardWifiEntryScans(Collections.emptyList()); + updateSuggestedWifiEntryScans(Collections.emptyList()); updatePasspointWifiEntryScans(Collections.emptyList()); updateOsuWifiEntryScans(Collections.emptyList()); return; @@ -432,6 +525,7 @@ public class WifiPickerTracker extends BaseWifiTracker { List<ScanResult> scanResults = mScanResultUpdater.getScanResults(scanAgeWindow); updateStandardWifiEntryScans(scanResults); + updateSuggestedWifiEntryScans(scanResults); updatePasspointWifiEntryScans(scanResults); updateOsuWifiEntryScans(scanResults); } @@ -483,12 +577,33 @@ public class WifiPickerTracker extends BaseWifiTracker { } @WorkerThread - private void updatePasspointWifiEntryConfigs(@NonNull List<PasspointConfiguration> configs) { + private void updateSuggestedWifiEntryConfigs(@NonNull List<WifiConfiguration> configs) { checkNotNull(configs, "Config list should not be null!"); + mSuggestedConfigCache.clear(); + mSuggestedConfigCache.putAll(configs.stream().collect(Collectors.toMap( + StandardWifiEntry::wifiConfigToStandardWifiEntryKey, + Function.identity()))); + // Iterate through current entries and update each entry's config + mSuggestedWifiEntryCache.entrySet().removeIf((entry) -> { + final StandardWifiEntry wifiEntry = entry.getValue(); + final String key = wifiEntry.getKey(); + final WifiConfiguration cachedConfig = mSuggestedConfigCache.get(key); + if (cachedConfig != null) { + wifiEntry.updateConfig(cachedConfig); + return false; + } else { + return true; + } + }); + } + + @WorkerThread + private void updatePasspointWifiEntryConfigs(@NonNull List<PasspointConfiguration> configs) { + checkNotNull(configs, "Config list should not be null!"); mPasspointConfigCache.clear(); mPasspointConfigCache.putAll(configs.stream().collect( - toMap((config) -> uniqueIdToPasspointWifiEntryKey( + toMap(config -> uniqueIdToPasspointWifiEntryKey( config.getUniqueId()), Function.identity()))); // Iterate through current entries and update each entry's config or remove if no config @@ -517,6 +632,9 @@ public class WifiPickerTracker extends BaseWifiTracker { for (WifiEntry entry : mStandardWifiEntryCache.values()) { entry.updateConnectionInfo(wifiInfo, networkInfo); } + for (WifiEntry entry : mSuggestedWifiEntryCache.values()) { + entry.updateConnectionInfo(wifiInfo, networkInfo); + } for (WifiEntry entry : mPasspointWifiEntryCache.values()) { entry.updateConnectionInfo(wifiInfo, networkInfo); } @@ -534,7 +652,7 @@ public class WifiPickerTracker extends BaseWifiTracker { @WorkerThread private void conditionallyCreateConnectedStandardWifiEntry(@Nullable WifiInfo wifiInfo, @Nullable NetworkInfo networkInfo) { - if (wifiInfo.isPasspointAp()) { + if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) { return; } @@ -554,7 +672,37 @@ public class WifiPickerTracker extends BaseWifiTracker { } /** - * Creates and caches a StandardWifiEntry representing the current connection using the current + * Creates and caches a suggested StandardWifiEntry representing the current connection using + * the current WifiInfo and NetworkInfo if there are no scans results available for the network + * yet. + * @param wifiInfo WifiInfo of the current connection + * @param networkInfo NetworkInfo of the current connection + */ + @WorkerThread + private void conditionallyCreateConnectedSuggestedWifiEntry(@Nullable WifiInfo wifiInfo, + @Nullable NetworkInfo networkInfo) { + if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) { + return; + } + + mSuggestedConfigCache.values().stream() + .filter(config -> + TextUtils.equals(config.SSID, wifiInfo.getSSID()) + && !mSuggestedWifiEntryCache.containsKey( + wifiConfigToStandardWifiEntryKey(config))) + .findAny().ifPresent(config -> { + final StandardWifiEntry connectedEntry = + new StandardWifiEntry(mContext, mMainHandler, + wifiConfigToStandardWifiEntryKey(config), config, mWifiManager, + false /* forSavedNetworksPage */); + connectedEntry.updateConnectionInfo(wifiInfo, networkInfo); + mSuggestedWifiEntryCache.put(connectedEntry.getKey(), connectedEntry); + }); + } + + + /** + * Creates and caches a PasspointWifiEntry representing the current connection using the current * WifiInfo and NetworkInfo if there are no scans results available for the network yet. * @param wifiInfo WifiInfo of the current connection * @param networkInfo NetworkInfo of the current connection |