summaryrefslogtreecommitdiff
path: root/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
diff options
context:
space:
mode:
Diffstat (limited to 'libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java')
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java798
1 files changed, 540 insertions, 258 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index 90d62f280..9c4f376ac 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
@@ -19,14 +19,6 @@ package com.android.wifitrackerlib;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED;
-import static com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityToStandardWifiEntryKey;
-import static com.android.wifitrackerlib.WifiEntry.SECURITY_EAP;
-import static com.android.wifitrackerlib.WifiEntry.SECURITY_EAP_SUITE_B;
-import static com.android.wifitrackerlib.WifiEntry.SECURITY_NONE;
-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;
@@ -35,7 +27,6 @@ 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;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -46,13 +37,13 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
+import android.net.WifiKey;
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.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
@@ -64,24 +55,37 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.ClickableSpan;
+import android.util.FeatureFlagUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.HelpUtils;
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.StringJoiner;
/**
* Utility methods for WifiTrackerLib.
*/
-class Utils {
+public class Utils {
+ /** Copy of the @hide Settings.Global.USE_OPEN_WIFI_PACKAGE constant. */
+ static final String SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
+
+ @VisibleForTesting
+ static FeatureFlagUtilsWrapper sFeatureFlagUtilsWrapper = new FeatureFlagUtilsWrapper();
+
+ static class FeatureFlagUtilsWrapper {
+ boolean isProviderModelEnabled(Context context) {
+ return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
+ }
+ }
+
private static NetworkScoreManager sNetworkScoreManager;
private static String getActiveScorerPackage(@NonNull Context context) {
@@ -93,234 +97,148 @@ class Utils {
// Returns the ScanResult with the best RSSI from a list of ScanResults.
@Nullable
- static ScanResult getBestScanResultByLevel(@NonNull List<ScanResult> scanResults) {
+ public static ScanResult getBestScanResultByLevel(@NonNull List<ScanResult> scanResults) {
if (scanResults.isEmpty()) return null;
return Collections.max(scanResults, comparingInt(scanResult -> scanResult.level));
}
- // Returns a list of SECURITY types supported by a ScanResult.
- static List<Integer> getSecurityTypesFromScanResult(@NonNull ScanResult scan) {
- final List<Integer> securityTypes = new ArrayList<>();
- if (scan.capabilities == null) {
- securityTypes.add(SECURITY_NONE);
- } else if (scan.capabilities.contains("PSK") && scan.capabilities.contains("SAE")) {
- securityTypes.add(SECURITY_PSK);
- securityTypes.add(SECURITY_SAE);
- } else if (scan.capabilities.contains("OWE_TRANSITION")) {
- securityTypes.add(SECURITY_NONE);
- securityTypes.add(SECURITY_OWE);
- } else if (scan.capabilities.contains("OWE")) {
- securityTypes.add(SECURITY_OWE);
- } else if (scan.capabilities.contains("WEP")) {
- securityTypes.add(SECURITY_WEP);
- } else if (scan.capabilities.contains("SAE")) {
- securityTypes.add(SECURITY_SAE);
- } else if (scan.capabilities.contains("PSK")) {
- securityTypes.add(SECURITY_PSK);
- } else if (scan.capabilities.contains("EAP_SUITE_B_192")) {
- securityTypes.add(SECURITY_EAP_SUITE_B);
- } else if (scan.capabilities.contains("EAP")) {
- securityTypes.add(SECURITY_EAP);
- } else {
- securityTypes.add(SECURITY_NONE);
+ // Returns a list of WifiInfo SECURITY_TYPE_* supported by a ScanResult.
+ // TODO(b/187755981): Move to shared static utils class
+ @NonNull
+ static List<Integer> getSecurityTypesFromScanResult(@NonNull ScanResult scanResult) {
+ List<Integer> securityTypes = new ArrayList<>();
+
+ // Open network & its upgradable types
+ if (isScanResultForOweTransitionNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_OPEN);
+ securityTypes.add(WifiInfo.SECURITY_TYPE_OWE);
+ return securityTypes;
+ } else if (isScanResultForOweNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_OWE);
+ return securityTypes;
+ } else if (isScanResultForOpenNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_OPEN);
+ return securityTypes;
+ }
+
+ // WEP network which has no upgradable type
+ if (isScanResultForWepNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_WEP);
+ return securityTypes;
+ }
+
+ // WAPI PSK network which has no upgradable type
+ if (isScanResultForWapiPskNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_WAPI_PSK);
+ return securityTypes;
+ }
+
+ // WAPI CERT network which has no upgradable type
+ if (isScanResultForWapiCertNetwork(scanResult)) {
+ securityTypes.add(
+ WifiInfo.SECURITY_TYPE_WAPI_CERT);
+ return securityTypes;
+ }
+
+ // WPA2 personal network & its upgradable types
+ if (isScanResultForPskNetwork(scanResult)
+ && isScanResultForSaeNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_PSK);
+ securityTypes.add(WifiInfo.SECURITY_TYPE_SAE);
+ return securityTypes;
+ } else if (isScanResultForPskNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_PSK);
+ return securityTypes;
+ } else if (isScanResultForSaeNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_SAE);
+ return securityTypes;
+ }
+
+ // WPA3 Enterprise 192-bit mode, WPA2/WPA3 enterprise network & its upgradable types
+ if (isScanResultForEapSuiteBNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ } else if (isScanResultForWpa3EnterpriseTransitionNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_EAP);
+ securityTypes.add(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ } else if (isScanResultForWpa3EnterpriseOnlyNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ } else if (isScanResultForEapNetwork(scanResult)) {
+ securityTypes.add(WifiInfo.SECURITY_TYPE_EAP);
}
return securityTypes;
}
- // Returns the SECURITY type supported by a WifiConfiguration
- @WifiEntry.Security
- static int getSecurityTypeFromWifiConfiguration(@NonNull WifiConfiguration config) {
- if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) {
- return SECURITY_SAE;
- }
- if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
- return SECURITY_PSK;
- }
- if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
- return SECURITY_EAP_SUITE_B;
- }
- if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)
- || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
- return SECURITY_EAP;
- }
- if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) {
- return SECURITY_OWE;
+ // Returns a list of WifiInfo SECURITY_TYPE_* supported by a WifiConfiguration
+ // TODO(b/187755473): Use new public APIs to get the security type instead of relying on the
+ // legacy allowedKeyManagement bitset.
+ static List<Integer> getSecurityTypesFromWifiConfiguration(@NonNull WifiConfiguration config) {
+ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_CERT)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_WAPI_CERT);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_WAPI_PSK);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_OWE);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_SAE);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA2_PSK)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_PSK);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
+ if (config.requirePmf
+ && !config.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.TKIP)
+ && config.allowedProtocols.get(WifiConfiguration.Protocol.RSN)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ } else {
+ // WPA2 configs should also be valid for WPA3-Enterprise APs
+ return Arrays.asList(
+ WifiInfo.SECURITY_TYPE_EAP, WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ }
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_PSK);
+ } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
+ if (config.wepKeys != null) {
+ for (int i = 0; i < config.wepKeys.length; i++) {
+ if (config.wepKeys[i] != null) {
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_WEP);
+ }
+ }
+ }
}
- return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
+ return Arrays.asList(WifiInfo.SECURITY_TYPE_OPEN);
}
/**
- * Maps ScanResults into any number of WifiEntry keys each ScanResult matches. If
- * chooseSingleSecurity is true, then ScanResults with multiple security capabilities will be
- * matched to a single security type for the purpose of user selection.
+ * Returns a single WifiInfo security type from the list of multiple WifiInfo security
+ * types supported by an entry.
*
- * @param scanResults ScanResults to be mapped.
- * @param chooseSingleSecurity If this is true, map scan results with multiple security
- * capabilities to a single security for coalescing into a single
- * WifiEntry.
- * @param wifiConfigsByKey Mapping of WifiConfiguration to WifiEntry key. Only used if
- * chooseSingleSecurity is true.
- * @param isWpa3SaeSupported If this is false, do not map to SECURITY_SAE
- * @param isWpa3SuiteBSupported If this is false, do not map to SECURITY_EAP_SUITE_B
- * @param isEnhancedOpenSupported If this is false, do not map to SECURITY_OWE
- * @return Map of WifiEntry key to list of corresponding ScanResults.
+ * Single security types will have a 1-to-1 mapping.
+ * Multiple security type networks will collapse to the lowest security type in the group:
+ * - Open/OWE -> Open
+ * - PSK/SAE -> PSK
+ * - EAP/EAP-WPA3 -> EAP
*/
- static Map<String, List<ScanResult>> mapScanResultsToKey(
- @NonNull List<ScanResult> scanResults,
- boolean chooseSingleSecurity,
- @Nullable Map<String, WifiConfiguration> wifiConfigsByKey,
- boolean isWpa3SaeSupported,
- boolean isWpa3SuiteBSupported,
- boolean isEnhancedOpenSupported) {
- if (wifiConfigsByKey == null) {
- wifiConfigsByKey = new HashMap<>();
- }
- final Map<String, List<ScanResult>> scanResultsBySsid = scanResults.stream()
- .filter(scanResult -> !TextUtils.isEmpty(scanResult.SSID))
- .collect(groupingBy(scanResult -> scanResult.SSID));
- final Map<String, List<ScanResult>> scanResultsByKey = new HashMap<>();
-
- for (String ssid : scanResultsBySsid.keySet()) {
- final boolean pskConfigExists = wifiConfigsByKey.containsKey(
- ssidAndSecurityToStandardWifiEntryKey(ssid, SECURITY_PSK));
- final boolean saeConfigExists = wifiConfigsByKey.containsKey(
- ssidAndSecurityToStandardWifiEntryKey(ssid, SECURITY_SAE));
- final boolean openConfigExists = wifiConfigsByKey.containsKey(
- ssidAndSecurityToStandardWifiEntryKey(ssid, SECURITY_NONE));
- final boolean oweConfigExists = wifiConfigsByKey.containsKey(
- ssidAndSecurityToStandardWifiEntryKey(ssid, SECURITY_OWE));
-
- boolean pskInRange = false;
- boolean saeInRange = false;
- boolean oweInRange = false;
- boolean openInRange = false;
- for (ScanResult scan : scanResultsBySsid.get(ssid)) {
- final List<Integer> securityTypes = getSecurityTypesFromScanResult(scan);
- if (securityTypes.contains(SECURITY_PSK)) {
- pskInRange = true;
- }
- if (securityTypes.contains(SECURITY_SAE)) {
- saeInRange = true;
- }
- if (securityTypes.contains(SECURITY_OWE)) {
- oweInRange = true;
- }
- if (securityTypes.contains(SECURITY_NONE)) {
- openInRange = true;
- }
+ static int getSingleSecurityTypeFromMultipleSecurityTypes(
+ @NonNull List<Integer> securityTypes) {
+ if (securityTypes.size() == 1) {
+ return securityTypes.get(0);
+ } else if (securityTypes.size() == 2) {
+ if (securityTypes.contains(WifiInfo.SECURITY_TYPE_OPEN)) {
+ return WifiInfo.SECURITY_TYPE_OPEN;
}
-
- for (ScanResult scan : scanResultsBySsid.get(ssid)) {
- List<Integer> securityTypes = getSecurityTypesFromScanResult(scan);
- List<Integer> chosenSecurityTypes = new ArrayList<>();
- // Ignore security types that are unsupported
- if (!isWpa3SaeSupported) {
- securityTypes.remove((Integer) SECURITY_SAE);
- }
- if (!isWpa3SuiteBSupported) {
- securityTypes.remove((Integer) SECURITY_EAP_SUITE_B);
- }
- if (!isEnhancedOpenSupported) {
- securityTypes.remove((Integer) SECURITY_OWE);
- }
-
- final boolean isSae = securityTypes.contains(SECURITY_SAE)
- && !securityTypes.contains(SECURITY_PSK);
- final boolean isPsk = securityTypes.contains(SECURITY_PSK)
- && !securityTypes.contains(SECURITY_SAE);
- final boolean isPskSaeTransition = securityTypes.contains(SECURITY_PSK)
- && securityTypes.contains(SECURITY_SAE);
- final boolean isOwe = securityTypes.contains(SECURITY_OWE)
- && !securityTypes.contains(SECURITY_NONE);
- final boolean isOweTransition = securityTypes.contains(SECURITY_NONE)
- && securityTypes.contains(SECURITY_OWE);
- final boolean isOpen = securityTypes.contains(SECURITY_NONE)
- && !securityTypes.contains(SECURITY_OWE);
-
- if (chooseSingleSecurity) {
- if (isPsk) {
- if (!pskConfigExists && saeConfigExists && saeInRange) {
- // If we don't have a PSK config, but there is an SAE AP in-range and
- // an SAE config we can use for connection, then ignore the PSK AP so
- // that the user only has the SAE AP to select.
- continue;
- } else {
- chosenSecurityTypes.add(SECURITY_PSK);
- }
- } else if (isPskSaeTransition) {
- // Map to SAE if we have an SAE config and no PSK config (use SAE config to
- // connect). Else, map to PSK for wider compatibility.
- if (!pskConfigExists && saeConfigExists) {
- chosenSecurityTypes.add(SECURITY_SAE);
- } else {
- chosenSecurityTypes.add(SECURITY_PSK);
- }
- } else if (isSae) {
- // Map to SAE if we either
- // 1) have an SAE config and no PSK config (use SAE config to connect).
- // 2) have no configs at all, and no PSK APs are in range. (save new
- // network with SAE security).
- // Else, map to PSK for wider compatibility.
- if (!pskConfigExists && (saeConfigExists || !pskInRange)) {
- chosenSecurityTypes.add(SECURITY_SAE);
- } else {
- chosenSecurityTypes.add(SECURITY_PSK);
- }
- } else if (isOwe) {
- // If an open AP is in range, use it instead if we have a config for it and
- // no OWE config.
- if (openInRange && openConfigExists && !oweConfigExists) {
- continue;
- } else {
- chosenSecurityTypes.add(SECURITY_OWE);
- }
- } else if (isOweTransition) {
- // Map to OWE if we either
- // 1) have an OWE config (use OWE config to connect).
- // 2) have no configs at all (save new network with OWE security).
- // Otherwise, if we have an open config only, map to open security so that
- // config is used for connection.
- if (oweConfigExists || !openConfigExists) {
- chosenSecurityTypes.add(SECURITY_OWE);
- } else {
- chosenSecurityTypes.add(SECURITY_NONE);
- }
- } else if (isOpen) {
- // If an OWE AP is in-range, then use it instead if we have a config for it
- // or no configs at all.
- if (oweInRange && (oweConfigExists || !openConfigExists)) {
- continue;
- } else {
- chosenSecurityTypes.add(SECURITY_NONE);
- }
- } else {
- chosenSecurityTypes.addAll(securityTypes);
- }
- } else {
- chosenSecurityTypes.addAll(securityTypes);
- if (isSae) {
- // If we don't need to choose a single security type for the user to select,
- // then SAE scans can also match to PSK configs, which will be dynamically
- // upgraded to SAE by the framework at connection time.
- chosenSecurityTypes.add(SECURITY_PSK);
- }
- }
-
- for (int security : chosenSecurityTypes) {
- final String key = ssidAndSecurityToStandardWifiEntryKey(ssid, security);
- if (!scanResultsByKey.containsKey(key)) {
- scanResultsByKey.put(key, new ArrayList<>());
- }
- scanResultsByKey.get(key).add(scan);
- }
+ if (securityTypes.contains(WifiInfo.SECURITY_TYPE_PSK)) {
+ return WifiInfo.SECURITY_TYPE_PSK;
+ }
+ if (securityTypes.contains(WifiInfo.SECURITY_TYPE_EAP)) {
+ return WifiInfo.SECURITY_TYPE_EAP;
}
}
- return scanResultsByKey;
+ return WifiInfo.SECURITY_TYPE_UNKNOWN;
}
@Speed
- static int getAverageSpeedFromScanResults(@NonNull WifiNetworkScoreCache scoreCache,
+ public static int getAverageSpeedFromScanResults(@NonNull WifiNetworkScoreCache scoreCache,
@NonNull List<ScanResult> scanResults) {
int count = 0;
int totalSpeed = 0;
@@ -343,10 +261,16 @@ class Utils {
}
@Speed
- static int getSpeedFromWifiInfo(@NonNull WifiNetworkScoreCache scoreCache,
+ public static int getSpeedFromWifiInfo(@NonNull WifiNetworkScoreCache scoreCache,
@NonNull WifiInfo wifiInfo) {
+ final WifiKey wifiKey;
+ try {
+ wifiKey = new WifiKey(wifiInfo.getSSID(), wifiInfo.getBSSID());
+ } catch (IllegalArgumentException e) {
+ return SPEED_NONE;
+ }
ScoredNetwork scoredNetwork = scoreCache.getScoredNetwork(
- NetworkKey.createFromWifiInfo(wifiInfo));
+ new NetworkKey(wifiKey));
if (scoredNetwork == null) {
return SPEED_NONE;
}
@@ -374,36 +298,172 @@ class Utils {
static String getAppLabel(Context context, String packageName) {
try {
String openWifiPackageName = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.USE_OPEN_WIFI_PACKAGE);
+ SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE);
if (!TextUtils.isEmpty(openWifiPackageName) && TextUtils.equals(packageName,
getActiveScorerPackage(context))) {
packageName = openWifiPackageName;
}
- ApplicationInfo appInfo = context.getPackageManager().getApplicationInfoAsUser(
+ ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
packageName,
- 0 /* flags */,
- UserHandle.getUserId(UserHandle.USER_CURRENT));
+ 0 /* flags */);
return appInfo.loadLabel(context.getPackageManager()).toString();
} catch (PackageManager.NameNotFoundException e) {
return "";
}
}
- static String getDisconnectedStateDescription(Context context, WifiEntry wifiEntry) {
- if (context == null || wifiEntry == null) {
+ static String getConnectedDescription(Context context,
+ WifiConfiguration wifiConfiguration,
+ NetworkCapabilities networkCapabilities,
+ String recommendationServiceLabel,
+ boolean isDefaultNetwork,
+ boolean isLowQuality) {
+ final StringJoiner sj = new StringJoiner(context.getString(
+ R.string.wifitrackerlib_summary_separator));
+ final boolean hideConnected =
+ !isDefaultNetwork && sFeatureFlagUtilsWrapper.isProviderModelEnabled(context);
+
+ if (wifiConfiguration != null) {
+ if (wifiConfiguration.fromWifiNetworkSuggestion
+ || wifiConfiguration.fromWifiNetworkSpecifier) {
+ // For suggestion or specifier networks to show "Connected via ..."
+ final String suggestionOrSpecifierLabel =
+ getSuggestionOrSpecifierLabel(context, wifiConfiguration);
+ if (!TextUtils.isEmpty(suggestionOrSpecifierLabel)) {
+ if (hideConnected) {
+ sj.add(context.getString(R.string.wifitrackerlib_available_via_app,
+ suggestionOrSpecifierLabel));
+ } else {
+ sj.add(context.getString(R.string.wifitrackerlib_connected_via_app,
+ suggestionOrSpecifierLabel));
+ }
+ }
+ } else if (wifiConfiguration.isEphemeral() && !hideConnected) {
+ // For ephemeral networks to show "Automatically connected via ..."
+ if (!TextUtils.isEmpty(recommendationServiceLabel)) {
+ sj.add(String.format(context.getString(
+ R.string.wifitrackerlib_connected_via_network_scorer),
+ recommendationServiceLabel));
+ } else {
+ sj.add(context.getString(
+ R.string.wifitrackerlib_connected_via_network_scorer_default));
+ }
+ }
+ }
+
+ if (isLowQuality) {
+ sj.add(context.getString(R.string.wifi_connected_low_quality));
+ }
+
+ // For displaying network capability info, such as captive portal or no internet
+ String networkCapabilitiesInformation =
+ getCurrentNetworkCapabilitiesInformation(context, networkCapabilities);
+ if (!TextUtils.isEmpty(networkCapabilitiesInformation)) {
+ sj.add(networkCapabilitiesInformation);
+ }
+
+ // Default to "Connected" if nothing else to display
+ if (sj.length() == 0 && !hideConnected) {
+ return context.getResources().getStringArray(R.array.wifitrackerlib_wifi_status)
+ [DetailedState.CONNECTED.ordinal()];
+ }
+
+ return sj.toString();
+ }
+
+ static String getConnectingDescription(Context context, NetworkInfo networkInfo) {
+ if (context == null || networkInfo == null) {
return "";
}
- WifiConfiguration wifiConfiguration = wifiEntry.getWifiConfiguration();
- if (wifiConfiguration == null) {
- return null;
+ DetailedState detailedState = networkInfo.getDetailedState();
+ if (detailedState == null) {
+ return "";
+ }
+
+ final String[] wifiStatusArray = context.getResources()
+ .getStringArray(R.array.wifitrackerlib_wifi_status);
+ final int index = detailedState.ordinal();
+ return index >= wifiStatusArray.length ? "" : wifiStatusArray[index];
+ }
+
+
+ static String getDisconnectedDescription(Context context,
+ WifiConfiguration wifiConfiguration,
+ boolean forSavedNetworksPage,
+ boolean concise) {
+ if (context == null) {
+ return "";
+ }
+ final StringJoiner sj = new StringJoiner(context.getString(
+ R.string.wifitrackerlib_summary_separator));
+
+ // For "Saved", "Saved by ...", and "Available via..."
+ if (concise) {
+ sj.add(context.getString(R.string.wifitrackerlib_wifi_disconnected));
+ } else if (wifiConfiguration != null) {
+ if (forSavedNetworksPage && !wifiConfiguration.isPasspoint()) {
+ final CharSequence appLabel = getAppLabel(context, wifiConfiguration.creatorName);
+ if (!TextUtils.isEmpty(appLabel)) {
+ sj.add(context.getString(R.string.wifitrackerlib_saved_network, appLabel));
+ }
+ } else {
+ if (wifiConfiguration.fromWifiNetworkSuggestion) {
+ final String suggestionOrSpecifierLabel =
+ getSuggestionOrSpecifierLabel(context, wifiConfiguration);
+ if (!TextUtils.isEmpty(suggestionOrSpecifierLabel)) {
+ sj.add(context.getString(
+ R.string.wifitrackerlib_available_via_app,
+ suggestionOrSpecifierLabel));
+ }
+ } else {
+ sj.add(context.getString(R.string.wifitrackerlib_wifi_remembered));
+ }
+ }
}
+ // For failure messages and disabled reasons
+ final String wifiConfigFailureMessage =
+ getWifiConfigurationFailureMessage(context, wifiConfiguration);
+ if (!TextUtils.isEmpty(wifiConfigFailureMessage)) {
+ sj.add(wifiConfigFailureMessage);
+ }
+
+ return sj.toString();
+ }
+
+ private static String getSuggestionOrSpecifierLabel(
+ Context context, WifiConfiguration wifiConfiguration) {
+ if (context == null || wifiConfiguration == null) {
+ return "";
+ }
+
+ final String carrierName = getCarrierNameForSubId(context,
+ getSubIdForConfig(context, wifiConfiguration));
+ if (!TextUtils.isEmpty(carrierName)) {
+ return carrierName;
+ }
+ final String suggestorLabel = getAppLabel(context, wifiConfiguration.creatorName);
+ if (!TextUtils.isEmpty(suggestorLabel)) {
+ return suggestorLabel;
+ }
+ // Fall-back to the package name in case the app label is missing
+ return wifiConfiguration.creatorName;
+ }
+
+ private static String getWifiConfigurationFailureMessage(
+ Context context, WifiConfiguration wifiConfiguration) {
+ if (context == null || wifiConfiguration == null) {
+ return "";
+ }
+
+ // Check for any failure messages to display
if (wifiConfiguration.hasNoInternetAccess()) {
int messageID =
wifiConfiguration.getNetworkSelectionStatus().getNetworkSelectionStatus()
== NETWORK_SELECTION_PERMANENTLY_DISABLED
- ? R.string.wifi_no_internet_no_reconnect : R.string.wifi_no_internet;
+ ? R.string.wifitrackerlib_wifi_no_internet_no_reconnect
+ : R.string.wifitrackerlib_wifi_no_internet;
return context.getString(messageID);
} else if (wifiConfiguration.getNetworkSelectionStatus().getNetworkSelectionStatus()
!= NETWORK_SELECTION_ENABLED) {
@@ -411,22 +471,47 @@ class Utils {
wifiConfiguration.getNetworkSelectionStatus();
switch (networkStatus.getNetworkSelectionDisableReason()) {
case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
- return context.getString(R.string.wifi_disabled_password_failure);
+ case WifiConfiguration.NetworkSelectionStatus
+ .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
+ return context.getString(
+ R.string.wifitrackerlib_wifi_disabled_password_failure);
case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
- return context.getString(R.string.wifi_check_password_try_again);
+ return context.getString(R.string.wifitrackerlib_wifi_check_password_try_again);
case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
- return context.getString(R.string.wifi_disabled_network_failure);
+ return context.getString(R.string.wifitrackerlib_wifi_disabled_network_failure);
case WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
- return context.getString(R.string.wifi_disabled_generic);
+ return context.getString(R.string.wifitrackerlib_wifi_disabled_generic);
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
+ return context.getString(R.string.wifitrackerlib_wifi_no_internet_no_reconnect);
default:
break;
}
- } else if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
- // Do nothing because users know it by signal icon.
} else { // In range, not disabled.
- if (wifiConfiguration.getRecentFailureReason()
- == WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA) {
- return context.getString(R.string.wifi_ap_unable_to_handle_new_sta);
+ switch (wifiConfiguration.getRecentFailureReason()) {
+ case WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA:
+ case WifiConfiguration.RECENT_FAILURE_REFUSED_TEMPORARILY:
+ case WifiConfiguration.RECENT_FAILURE_DISCONNECTION_AP_BUSY:
+ return context.getString(R.string
+ .wifitrackerlib_wifi_ap_unable_to_handle_new_sta);
+ case WifiConfiguration.RECENT_FAILURE_POOR_CHANNEL_CONDITIONS:
+ return context.getString(R.string.wifitrackerlib_wifi_poor_channel_conditions);
+ case WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED:
+ case WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED:
+ case WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED:
+ return context.getString(R.string
+ .wifitrackerlib_wifi_mbo_assoc_disallowed_cannot_connect);
+ case WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED:
+ return context.getString(R.string
+ .wifitrackerlib_wifi_mbo_assoc_disallowed_max_num_sta_associated);
+ case WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI:
+ case WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION:
+ return context.getString(R.string
+ .wifitrackerlib_wifi_mbo_oce_assoc_disallowed_insufficient_rssi);
+ case WifiConfiguration.RECENT_FAILURE_NETWORK_NOT_FOUND:
+ return context.getString(R.string.wifitrackerlib_wifi_network_not_found);
+ default:
+ // do nothing
}
}
return "";
@@ -439,7 +524,7 @@ class Utils {
}
return wifiEntry.isAutoJoinEnabled()
- ? "" : context.getString(R.string.auto_connect_disable);
+ ? "" : context.getString(R.string.wifitrackerlib_auto_connect_disable);
}
static String getMeteredDescription(@NonNull Context context, @Nullable WifiEntry wifiEntry) {
@@ -453,11 +538,12 @@ class Utils {
}
if (wifiEntry.getMeteredChoice() == WifiEntry.METERED_CHOICE_METERED) {
- return context.getString(R.string.wifi_metered_label);
+ return context.getString(R.string.wifitrackerlib_wifi_metered_label);
} else if (wifiEntry.getMeteredChoice() == WifiEntry.METERED_CHOICE_UNMETERED) {
- return context.getString(R.string.wifi_unmetered_label);
+ return context.getString(R.string.wifitrackerlib_wifi_unmetered_label);
} else { // METERED_CHOICE_AUTO
- return wifiEntry.isMetered() ? context.getString(R.string.wifi_metered_label) : "";
+ return wifiEntry.isMetered() ? context.getString(
+ R.string.wifitrackerlib_wifi_metered_label) : "";
}
}
@@ -469,13 +555,13 @@ class Utils {
@Speed int speed = wifiEntry.getSpeed();
switch (speed) {
case SPEED_VERY_FAST:
- return context.getString(R.string.speed_label_very_fast);
+ return context.getString(R.string.wifitrackerlib_speed_label_very_fast);
case SPEED_FAST:
- return context.getString(R.string.speed_label_fast);
+ return context.getString(R.string.wifitrackerlib_speed_label_fast);
case SPEED_MODERATE:
- return context.getString(R.string.speed_label_okay);
+ return context.getString(R.string.wifitrackerlib_speed_label_okay);
case SPEED_SLOW:
- return context.getString(R.string.speed_label_slow);
+ return context.getString(R.string.wifitrackerlib_speed_label_slow);
case SPEED_NONE:
default:
return "";
@@ -558,30 +644,34 @@ class Utils {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
- return context.getString(R.string.wifi_limited_connection);
+ return context.getString(R.string.wifitrackerlib_wifi_limited_connection);
}
if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
if (networkCapabilities.isPrivateDnsBroken()) {
- return context.getString(R.string.private_dns_broken);
+ return context.getString(R.string.wifitrackerlib_private_dns_broken);
}
- return context.getString(R.string.wifi_connected_no_internet);
+ return context.getString(
+ R.string.wifitrackerlib_wifi_connected_cannot_provide_internet);
}
return "";
}
+ /**
+ * Returns the display string corresponding to the detailed state of the given NetworkInfo
+ */
static String getNetworkDetailedState(Context context, NetworkInfo networkInfo) {
if (context == null || networkInfo == null) {
return "";
}
- DetailedState detailState = networkInfo.getDetailedState();
- if (detailState == null) {
+ DetailedState detailedState = networkInfo.getDetailedState();
+ if (detailedState == null) {
return "";
}
String[] wifiStatusArray = context.getResources()
- .getStringArray(R.array.wifi_status);
- int index = detailState.ordinal();
+ .getStringArray(R.array.wifitrackerlib_wifi_status);
+ int index = detailedState.ordinal();
return index >= wifiStatusArray.length ? "" : wifiStatusArray[index];
}
@@ -694,8 +784,9 @@ class Utils {
}
// IMSI protection is not provided, return warning message.
- return linkifyAnnotation(context, context.getText(R.string.imsi_protection_warning), "url",
- context.getString(R.string.help_url_imsi_protection));
+ return linkifyAnnotation(context, context.getText(
+ R.string.wifitrackerlib_imsi_protection_warning), "url",
+ context.getString(R.string.wifitrackerlib_help_url_imsi_protection));
}
/** Find the annotation of specified id in rawText and linkify it with helpUriString. */
@@ -727,4 +818,195 @@ class Utils {
}
return rawText;
}
+
+ // Various utility methods copied from com.android.server.wifi.util.ScanResultUtils for
+ // extracting SecurityType from ScanResult.
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a PSK network or not.
+ * This checks if the provided capabilities string contains PSK encryption type or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForPskNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("PSK");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a WAPI-PSK network or not.
+ * This checks if the provided capabilities string contains PSK encryption type or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForWapiPskNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("WAPI-PSK");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a WAPI-CERT
+ * network or not.
+ * This checks if the provided capabilities string contains PSK encryption type or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForWapiCertNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("WAPI-CERT");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a EAP network or not.
+ * This checks these conditions:
+ * - Enable EAP/SHA1, EAP/SHA256 AKM, FT/EAP, or EAP-FILS.
+ * - Not a WPA3 Enterprise only network.
+ * - Not a WPA3 Enterprise transition network.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForEapNetwork(ScanResult scanResult) {
+ return (scanResult.capabilities.contains("EAP/SHA1")
+ || scanResult.capabilities.contains("EAP/SHA256")
+ || scanResult.capabilities.contains("FT/EAP")
+ || scanResult.capabilities.contains("EAP-FILS"))
+ && !isScanResultForWpa3EnterpriseOnlyNetwork(scanResult)
+ && !isScanResultForWpa3EnterpriseTransitionNetwork(scanResult);
+ }
+
+ // TODO(b/187755981): Move to shared static utils class
+ private static boolean isScanResultForPmfMandatoryNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("[MFPR]");
+ }
+
+ // TODO(b/187755981): Move to shared static utils class
+ private static boolean isScanResultForPmfCapableNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("[MFPC]");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to
+ * a WPA3 Enterprise transition network or not.
+ *
+ * See Section 3.3 WPA3-Enterprise transition mode in WPA3 Specification
+ * - Enable at least EAP/SHA1 and EAP/SHA256 AKM suites.
+ * - Not enable WPA1 version 1, WEP, and TKIP.
+ * - Management Frame Protection Capable is set.
+ * - Management Frame Protection Required is not set.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForWpa3EnterpriseTransitionNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("EAP/SHA1")
+ && scanResult.capabilities.contains("EAP/SHA256")
+ && scanResult.capabilities.contains("RSN")
+ && !scanResult.capabilities.contains("WEP")
+ && !scanResult.capabilities.contains("TKIP")
+ && !isScanResultForPmfMandatoryNetwork(scanResult)
+ && isScanResultForPmfCapableNetwork(scanResult);
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to
+ * a WPA3 Enterprise only network or not.
+ *
+ * See Section 3.2 WPA3-Enterprise only mode in WPA3 Specification
+ * - Enable at least EAP/SHA256 AKM suite.
+ * - Not enable EAP/SHA1 AKM suite.
+ * - Not enable WPA1 version 1, WEP, and TKIP.
+ * - Management Frame Protection Capable is set.
+ * - Management Frame Protection Required is set.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForWpa3EnterpriseOnlyNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("EAP/SHA256")
+ && !scanResult.capabilities.contains("EAP/SHA1")
+ && scanResult.capabilities.contains("RSN")
+ && !scanResult.capabilities.contains("WEP")
+ && !scanResult.capabilities.contains("TKIP")
+ && isScanResultForPmfMandatoryNetwork(scanResult)
+ && isScanResultForPmfCapableNetwork(scanResult);
+ }
+
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a WPA3-Enterprise 192-bit
+ * mode network or not.
+ * This checks if the provided capabilities comply these conditions:
+ * - Enable SUITE-B-192 AKM.
+ * - Not enable EAP/SHA1 AKM suite.
+ * - Not enable WPA1 version 1, WEP, and TKIP.
+ * - Management Frame Protection Required is set.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForEapSuiteBNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("SUITE_B_192")
+ && scanResult.capabilities.contains("RSN")
+ && !scanResult.capabilities.contains("WEP")
+ && !scanResult.capabilities.contains("TKIP")
+ && isScanResultForPmfMandatoryNetwork(scanResult);
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to a WEP network or not.
+ * This checks if the provided capabilities string contains WEP encryption type or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForWepNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("WEP");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to OWE network.
+ * This checks if the provided capabilities string contains OWE or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForOweNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("OWE");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to OWE transition network.
+ * This checks if the provided capabilities string contains OWE_TRANSITION or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForOweTransitionNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("OWE_TRANSITION");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to SAE network.
+ * This checks if the provided capabilities string contains SAE or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForSaeNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("SAE");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to PSK-SAE transition
+ * network. This checks if the provided capabilities string contains both PSK and SAE or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForPskSaeTransitionNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("PSK") && scanResult.capabilities.contains("SAE");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to an unknown amk network.
+ * This checks if the provided capabilities string contains ? or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForUnknownAkmNetwork(ScanResult scanResult) {
+ return scanResult.capabilities.contains("?");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to an open network or not.
+ * This checks if the provided capabilities string does not contain either of WEP, PSK, SAE
+ * EAP, or unknown encryption types or not.
+ * TODO(b/187755981): Move to shared static utils class
+ */
+ public static boolean isScanResultForOpenNetwork(ScanResult scanResult) {
+ return (!(isScanResultForWepNetwork(scanResult) || isScanResultForPskNetwork(scanResult)
+ || isScanResultForEapNetwork(scanResult) || isScanResultForSaeNetwork(scanResult)
+ || isScanResultForWpa3EnterpriseTransitionNetwork(scanResult)
+ || isScanResultForWpa3EnterpriseOnlyNetwork(scanResult)
+ || isScanResultForWapiPskNetwork(scanResult)
+ || isScanResultForWapiCertNetwork(scanResult)
+ || isScanResultForEapSuiteBNetwork(scanResult)
+ || isScanResultForUnknownAkmNetwork(scanResult)));
+ }
}