From 6e810df9b8b15ffa25696b675731dba5b6ebf6a6 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Mon, 9 Dec 2019 19:16:10 +0800 Subject: [PATCH] [Wi-Fi] Fix transition mode problems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. In AccessPoint#updateBestRssiInfo, if bestResult is available, cache if it’s transition mode at new variables. 2. Remove SECURITY_PSK_SAE_TRANSITION & SECURITY_OWE_TRANSITION since we will cache if an Wi-Fi AP is transition mode. 3. Enhance getSecurity(ScanResult result). For a PSK/SAE transition mode ScanResult, return SAE. For a open/OWE transition mode ScanResult, return OWE. 4. Enhance all AccessPoint#matches methods 5. Use enhanced AccessPoint#matches to replace AccessPoint#isKeyEqual 6. In WifiTracker#updateAccessPoints, it associates an AccessPoint with a configured WifiConfiguration I. If an AccessPoint is PSK/SAE transition mode, update it with a configured network of the same SSID and PSK/SAE security if it’s available. (SAE has higher priority). II. If an AccessPoint is Open/OWE transition mode, update it with a configured network of the same SSID and open/OWE security if it’s available. (OWE has higher priority). Bug: 144320676 Bug: 144320649 Bug: 144325162 Bug: 144321574 Test: atest SettingsLibTests manual: In Wi-Fi picker 1. Save a PSK network, click a PSK/SAE transition mode AP of the same SSID, it should connects. 2. Save a SAE network, click a PSK/SAE transition mode AP of the same SSID, it should connects. 3. For 1. and 2., the transition mode AP should show 'Saved'. 4. For 1. and 2., looking at saved network page, each saved network should shows correct connection status of the transition mode AP. Change-Id: Ida858af791bc60f0ccb11025901de2a79eacba3c Merged-In: I9688f51f4a4b8e3d5c080fb0d0103abb4e3fd79b --- .../android/settingslib/wifi/AccessPoint.java | 325 +++++++++++++----- .../wifi/AccessPointPreference.java | 3 +- .../android/settingslib/wifi/WifiTracker.java | 41 ++- .../settingslib/wifi/AccessPointTest.java | 150 +++++++- 4 files changed, 413 insertions(+), 106 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 6b1ceae4bed86..1d9e4ae890eb6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -176,6 +176,8 @@ public class AccessPoint implements Comparable { static final String KEY_CARRIER_AP_EAP_TYPE = "key_carrier_ap_eap_type"; static final String KEY_CARRIER_NAME = "key_carrier_name"; static final String KEY_EAPTYPE = "eap_psktype"; + static final String KEY_IS_PSK_SAE_TRANSITION_MODE = "key_is_psk_sae_transition_mode"; + static final String KEY_IS_OWE_TRANSITION_MODE = "key_is_owe_transition_mode"; static final AtomicInteger sLastId = new AtomicInteger(0); /* @@ -190,15 +192,12 @@ public class AccessPoint implements Comparable { public static final int SECURITY_OWE = 4; public static final int SECURITY_SAE = 5; public static final int SECURITY_EAP_SUITE_B = 6; - public static final int SECURITY_PSK_SAE_TRANSITION = 7; - public static final int SECURITY_OWE_TRANSITION = 8; - public static final int SECURITY_MAX_VAL = 9; // Has to be the last + public static final int SECURITY_MAX_VAL = 7; // Has to be the last private static final int PSK_UNKNOWN = 0; private static final int PSK_WPA = 1; private static final int PSK_WPA2 = 2; private static final int PSK_WPA_WPA2 = 3; - private static final int PSK_SAE = 4; private static final int EAP_UNKNOWN = 0; private static final int EAP_WPA = 1; // WPA-EAP @@ -259,6 +258,9 @@ public class AccessPoint implements Comparable { private String mOsuFailure; private boolean mOsuProvisioningComplete = false; + private boolean mIsPskSaeTransitionMode = false; + private boolean mIsOweTransitionMode = false; + /** * The EAP type {@link WifiEnterpriseConfig.Eap} associated with this AP if it is a carrier AP. */ @@ -322,6 +324,13 @@ public class AccessPoint implements Comparable { if (savedState.containsKey(KEY_CARRIER_NAME)) { mCarrierName = savedState.getString(KEY_CARRIER_NAME); } + if (savedState.containsKey(KEY_IS_PSK_SAE_TRANSITION_MODE)) { + mIsPskSaeTransitionMode = savedState.getBoolean(KEY_IS_PSK_SAE_TRANSITION_MODE); + } + if (savedState.containsKey(KEY_IS_OWE_TRANSITION_MODE)) { + mIsOweTransitionMode = savedState.getBoolean(KEY_IS_OWE_TRANSITION_MODE); + } + update(mConfig, mInfo, mNetworkInfo); // Calculate required fields @@ -647,8 +656,15 @@ public class AccessPoint implements Comparable { return oldMetering == mIsScoredNetworkMetered; } - public static String getKey(ScanResult result) { - return getKey(result.SSID, result.BSSID, getSecurity(result)); + /** + * Generates an AccessPoint key for a given scan result + * + * @param context + * @param result Scan result + * @return AccessPoint key + */ + public static String getKey(Context context, ScanResult result) { + return getKey(result.SSID, result.BSSID, getSecurity(context, result)); } /** @@ -706,7 +722,42 @@ public class AccessPoint implements Comparable { * Determines if the other AccessPoint represents the same network as this AccessPoint */ public boolean matches(AccessPoint other) { - return getKey().equals(other.getKey()); + if (isPasspoint() || isPasspointConfig() || isOsuProvider()) { + return getKey().equals(other.getKey()); + } + + if (!isSameSsidOrBssid(other)) { + return false; + } + + final int otherApSecurity = other.getSecurity(); + if (mIsPskSaeTransitionMode) { + if (otherApSecurity == SECURITY_SAE && getWifiManager().isWpa3SaeSupported()) { + return true; + } else if (otherApSecurity == SECURITY_PSK) { + return true; + } + } else { + if ((security == SECURITY_SAE || security == SECURITY_PSK) + && other.isPskSaeTransitionMode()) { + return true; + } + } + + if (mIsOweTransitionMode) { + if (otherApSecurity == SECURITY_OWE && getWifiManager().isEnhancedOpenSupported()) { + return true; + } else if (otherApSecurity == SECURITY_NONE) { + return true; + } + } else { + if ((security == SECURITY_OWE || security == SECURITY_NONE) + && other.isOweTransitionMode()) { + return true; + } + } + + return security == other.getSecurity(); } public boolean matches(WifiConfiguration config) { @@ -720,18 +771,77 @@ public class AccessPoint implements Comparable { } final int configSecurity = getSecurity(config); - final WifiManager wifiManager = getWifiManager(); - switch (security) { - case SECURITY_PSK_SAE_TRANSITION: - return configSecurity == SECURITY_PSK - || (wifiManager.isWpa3SaeSupported() && configSecurity == SECURITY_SAE); - case SECURITY_OWE_TRANSITION: - return configSecurity == SECURITY_NONE - || (wifiManager.isEnhancedOpenSupported() - && configSecurity == SECURITY_OWE); - default: - return security == configSecurity; + if (mIsPskSaeTransitionMode) { + if (configSecurity == SECURITY_SAE && getWifiManager().isWpa3SaeSupported()) { + return true; + } else if (configSecurity == SECURITY_PSK) { + return true; + } } + + if (mIsOweTransitionMode) { + if (configSecurity == SECURITY_OWE && getWifiManager().isEnhancedOpenSupported()) { + return true; + } else if (configSecurity == SECURITY_NONE) { + return true; + } + } + + return security == getSecurity(config); + } + + private boolean matches(WifiConfiguration config, WifiInfo wifiInfo) { + if (config == null || wifiInfo == null) { + return false; + } + if (!config.isPasspoint() && !isSameSsidOrBssid(wifiInfo)) { + return false; + } + return matches(config); + } + + @VisibleForTesting + boolean matches(ScanResult scanResult) { + if (scanResult == null) { + return false; + } + if (isPasspoint() || isOsuProvider()) { + throw new IllegalStateException("Should not matches a Passpoint by ScanResult"); + } + + if (!isSameSsidOrBssid(scanResult)) { + return false; + } + + if (mIsPskSaeTransitionMode) { + if (scanResult.capabilities.contains("SAE") + && getWifiManager().isWpa3SaeSupported()) { + return true; + } else if (scanResult.capabilities.contains("PSK")) { + return true; + } + } else { + if ((security == SECURITY_SAE || security == SECURITY_PSK) + && AccessPoint.isPskSaeTransitionMode(scanResult)) { + return true; + } + } + + if (mIsOweTransitionMode) { + final int scanResultSccurity = getSecurity(mContext, scanResult); + if (scanResultSccurity == SECURITY_OWE && getWifiManager().isEnhancedOpenSupported()) { + return true; + } else if (scanResultSccurity == SECURITY_NONE) { + return true; + } + } else { + if ((security == SECURITY_OWE || security == SECURITY_NONE) + && AccessPoint.isOweTransitionMode(scanResult)) { + return true; + } + } + + return security == getSecurity(mContext, scanResult); } public WifiConfiguration getConfig() { @@ -818,14 +928,17 @@ public class AccessPoint implements Comparable { if (bestResult != null) { ssid = bestResult.SSID; bssid = bestResult.BSSID; - security = getSecurity(bestResult); - if (security == SECURITY_PSK || security == SECURITY_SAE - || security == SECURITY_PSK_SAE_TRANSITION) { + security = getSecurity(mContext, bestResult); + if (security == SECURITY_PSK || security == SECURITY_SAE) { pskType = getPskType(bestResult); } if (security == SECURITY_EAP) { mEapType = getEapType(bestResult); } + + mIsPskSaeTransitionMode = AccessPoint.isPskSaeTransitionMode(bestResult); + mIsOweTransitionMode = AccessPoint.isOweTransitionMode(bestResult); + mIsCarrierAp = bestResult.isCarrierAp; mCarrierApEapType = bestResult.carrierApEapType; mCarrierName = bestResult.carrierName; @@ -858,6 +971,12 @@ public class AccessPoint implements Comparable { return concise ? context.getString(R.string.wifi_security_short_eap) : context.getString(R.string.wifi_security_eap); } + + if (mIsPskSaeTransitionMode) { + return concise ? context.getString(R.string.wifi_security_short_psk_sae) : + context.getString(R.string.wifi_security_psk_sae); + } + switch(security) { case SECURITY_EAP: switch (mEapType) { @@ -897,20 +1016,8 @@ public class AccessPoint implements Comparable { return concise ? context.getString(R.string.wifi_security_short_wep) : context.getString(R.string.wifi_security_wep); case SECURITY_SAE: - case SECURITY_PSK_SAE_TRANSITION: - if (pskType == PSK_SAE) { - return concise ? context.getString(R.string.wifi_security_short_psk_sae) : - context.getString(R.string.wifi_security_psk_sae); - } else { - return concise ? context.getString(R.string.wifi_security_short_sae) : - context.getString(R.string.wifi_security_sae); - } - case SECURITY_OWE_TRANSITION: - if (mConfig != null && getSecurity(mConfig) == SECURITY_OWE) { - return concise ? context.getString(R.string.wifi_security_short_owe) : - context.getString(R.string.wifi_security_owe); - } - return concise ? "" : context.getString(R.string.wifi_security_none); + return concise ? context.getString(R.string.wifi_security_short_sae) : + context.getString(R.string.wifi_security_sae); case SECURITY_OWE: return concise ? context.getString(R.string.wifi_security_short_owe) : context.getString(R.string.wifi_security_owe); @@ -1194,7 +1301,7 @@ public class AccessPoint implements Comparable { if (networkId != WifiConfiguration.INVALID_NETWORK_ID) { return networkId == info.getNetworkId(); } else if (config != null) { - return isKeyEqual(getKey(config)); + return matches(config, info); } else { // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID. // (Note that we only do this if the WifiConfiguration explicitly equals INVALID). @@ -1220,8 +1327,7 @@ public class AccessPoint implements Comparable { * Can only be called for unsecured networks. */ public void generateOpenNetworkConfig() { - if ((security != SECURITY_NONE) && (security != SECURITY_OWE) - && (security != SECURITY_OWE_TRANSITION)) { + if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) { throw new IllegalStateException(); } if (mConfig != null) @@ -1264,43 +1370,14 @@ public class AccessPoint implements Comparable { savedState.putBoolean(KEY_IS_CARRIER_AP, mIsCarrierAp); savedState.putInt(KEY_CARRIER_AP_EAP_TYPE, mCarrierApEapType); savedState.putString(KEY_CARRIER_NAME, mCarrierName); + savedState.putBoolean(KEY_IS_PSK_SAE_TRANSITION_MODE, mIsPskSaeTransitionMode); + savedState.putBoolean(KEY_IS_OWE_TRANSITION_MODE, mIsOweTransitionMode); } public void setListener(AccessPointListener listener) { mAccessPointListener = listener; } - private static final String sPskSuffix = "," + String.valueOf(SECURITY_PSK); - private static final String sSaeSuffix = "," + String.valueOf(SECURITY_SAE); - private static final String sPskSaeSuffix = "," + String.valueOf(SECURITY_PSK_SAE_TRANSITION); - private static final String sOweSuffix = "," + String.valueOf(SECURITY_OWE); - private static final String sOpenSuffix = "," + String.valueOf(SECURITY_NONE); - private static final String sOweTransSuffix = "," + String.valueOf(SECURITY_OWE_TRANSITION); - - private boolean isKeyEqual(String compareTo) { - if (mKey == null) { - return false; - } - - if (compareTo.endsWith(sPskSuffix) || compareTo.endsWith(sSaeSuffix)) { - if (mKey.endsWith(sPskSaeSuffix)) { - // Special handling for PSK-SAE transition mode. If the AP has advertised both, - // we compare the key with both PSK and SAE for a match. - return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')), - compareTo.substring(0, compareTo.lastIndexOf(','))); - } - } - if (compareTo.endsWith(sOpenSuffix) || compareTo.endsWith(sOweSuffix)) { - if (mKey.endsWith(sOweTransSuffix)) { - // Special handling for OWE/Open networks. If AP advertises OWE in transition mode - // and we have an Open network saved, allow this connection to be established. - return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')), - compareTo.substring(0, compareTo.lastIndexOf(','))); - } - } - return mKey.equals(compareTo); - } - /** * Sets {@link #mScanResults} to the given collection and updates info based on the best RSSI * scan result. @@ -1317,11 +1394,10 @@ public class AccessPoint implements Comparable { // Passpoint networks are not bound to a specific SSID/BSSID, so skip this for passpoint. if (mKey != null && !isPasspoint() && !isOsuProvider()) { for (ScanResult result : scanResults) { - String scanResultKey = AccessPoint.getKey(result); - if (!isKeyEqual(scanResultKey)) { + if (!matches(result)) { Log.d(TAG, String.format( - "ScanResult %s\nkey of %s did not match current AP key %s", - result, scanResultKey, mKey)); + "ScanResult %s\nkey of %s did not match current AP key %s", + result, getKey(mContext, result), mKey)); return; } } @@ -1594,11 +1670,8 @@ public class AccessPoint implements Comparable { private static int getPskType(ScanResult result) { boolean wpa = result.capabilities.contains("WPA-PSK"); boolean wpa2 = result.capabilities.contains("RSN-PSK"); - boolean wpa3TransitionMode = result.capabilities.contains("PSK+SAE"); boolean wpa3 = result.capabilities.contains("RSN-SAE"); - if (wpa3TransitionMode) { - return PSK_SAE; - } else if (wpa2 && wpa) { + if (wpa2 && wpa) { return PSK_WPA_WPA2; } else if (wpa2) { return PSK_WPA2; @@ -1625,22 +1698,37 @@ public class AccessPoint implements Comparable { return EAP_UNKNOWN; } - private static int getSecurity(ScanResult result) { - if (result.capabilities.contains("WEP")) { + private static int getSecurity(Context context, ScanResult result) { + final boolean isWep = result.capabilities.contains("WEP"); + final boolean isSae = result.capabilities.contains("SAE"); + final boolean isPsk = result.capabilities.contains("PSK"); + final boolean isEapSuiteB192 = result.capabilities.contains("EAP_SUITE_B_192"); + final boolean isEap = result.capabilities.contains("EAP"); + final boolean isOwe = result.capabilities.contains("OWE"); + final boolean isOweTransition = result.capabilities.contains("OWE_TRANSITION"); + + if (isSae && isPsk) { + final WifiManager wifiManager = (WifiManager) + context.getSystemService(Context.WIFI_SERVICE); + return wifiManager.isWpa3SaeSupported() ? SECURITY_SAE : SECURITY_PSK; + } + if (isOweTransition) { + final WifiManager wifiManager = (WifiManager) + context.getSystemService(Context.WIFI_SERVICE); + return wifiManager.isEnhancedOpenSupported() ? SECURITY_OWE : SECURITY_NONE; + } + + if (isWep) { return SECURITY_WEP; - } else if (result.capabilities.contains("PSK+SAE")) { - return SECURITY_PSK_SAE_TRANSITION; - } else if (result.capabilities.contains("SAE")) { + } else if (isSae) { return SECURITY_SAE; - } else if (result.capabilities.contains("PSK")) { + } else if (isPsk) { return SECURITY_PSK; - } else if (result.capabilities.contains("EAP_SUITE_B_192")) { + } else if (isEapSuiteB192) { return SECURITY_EAP_SUITE_B; - } else if (result.capabilities.contains("EAP")) { + } else if (isEap) { return SECURITY_EAP; - } else if (result.capabilities.contains("OWE_TRANSITION")) { - return SECURITY_OWE_TRANSITION; - } else if (result.capabilities.contains("OWE")) { + } else if (isOwe) { return SECURITY_OWE; } return SECURITY_NONE; @@ -1686,10 +1774,6 @@ public class AccessPoint implements Comparable { return "SUITE_B"; } else if (security == SECURITY_OWE) { return "OWE"; - } else if (security == SECURITY_PSK_SAE_TRANSITION) { - return "PSK+SAE"; - } else if (security == SECURITY_OWE_TRANSITION) { - return "OWE_TRANSITION"; } return "NONE"; } @@ -1859,4 +1943,61 @@ public class AccessPoint implements Comparable { } } } + + public boolean isPskSaeTransitionMode() { + return mIsPskSaeTransitionMode; + } + + public boolean isOweTransitionMode() { + return mIsOweTransitionMode; + } + + private static boolean isPskSaeTransitionMode(ScanResult scanResult) { + return scanResult.capabilities.contains("PSK") + && scanResult.capabilities.contains("SAE"); + } + + private static boolean isOweTransitionMode(ScanResult scanResult) { + return scanResult.capabilities.contains("OWE_TRANSITION"); + } + + private boolean isSameSsidOrBssid(ScanResult scanResult) { + if (scanResult == null) { + return false; + } + + if (TextUtils.equals(ssid, scanResult.SSID)) { + return true; + } else if (scanResult.BSSID != null && TextUtils.equals(bssid, scanResult.BSSID)) { + return true; + } + return false; + } + + private boolean isSameSsidOrBssid(WifiInfo wifiInfo) { + if (wifiInfo == null) { + return false; + } + + if (TextUtils.equals(ssid, removeDoubleQuotes(wifiInfo.getSSID()))) { + return true; + } else if (wifiInfo.getBSSID() != null && TextUtils.equals(bssid, wifiInfo.getBSSID())) { + return true; + } + return false; + } + + private boolean isSameSsidOrBssid(AccessPoint accessPoint) { + if (accessPoint == null) { + return false; + } + + if (TextUtils.equals(ssid, accessPoint.getSsid())) { + return true; + } else if (accessPoint.getBssid() != null + && TextUtils.equals(bssid, accessPoint.getBssid())) { + return true; + } + return false; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index dae546497aba6..6269a717b3335 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -201,8 +201,7 @@ public class AccessPointPreference extends Preference { return; } if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) - && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE) - && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE_TRANSITION)) { + && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) { mFrictionSld.setState(STATE_SECURED); } else if (mAccessPoint.isMetered()) { mFrictionSld.setState(STATE_METERED); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index 3e359d2162347..f1c5f46a30e87 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -70,8 +70,10 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; /** * Tracks saved or available wifi networks and their state. @@ -475,7 +477,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro continue; } - String apKey = AccessPoint.getKey(result); + String apKey = AccessPoint.getKey(mContext, result); List resultList; if (scanResultsByApKey.containsKey(apKey)) { resultList = scanResultsByApKey.get(apKey); @@ -548,14 +550,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro private void updateAccessPoints(final List newScanResults, List configs) { - // Map configs and scan results necessary to make AccessPoints - final Map configsByKey = new ArrayMap(configs.size()); - if (configs != null) { - for (WifiConfiguration config : configs) { - configsByKey.put(AccessPoint.getKey(config), config); - } - } - WifiConfiguration connectionConfig = null; if (mLastInfo != null) { connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId(), configs); @@ -587,7 +581,26 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro getCachedOrCreate(entry.getValue(), cachedAccessPoints); // Update the matching config if there is one, to populate saved network info - accessPoint.update(configsByKey.get(entry.getKey())); + final List matchedConfigs = configs.stream() + .filter(config -> accessPoint.matches(config)) + .collect(Collectors.toList()); + + final int matchedConfigCount = matchedConfigs.size(); + if (matchedConfigCount == 0) { + accessPoint.update(null); + } else if (matchedConfigCount == 1) { + accessPoint.update(matchedConfigs.get(0)); + } else { + // We may have 2 matched configured WifiCongiguration if the AccessPoint is + // of PSK/SAE transition mode or open/OWE transition mode. + Optional preferredConfig = matchedConfigs.stream() + .filter(config -> isSaeOrOwe(config)).findFirst(); + if (preferredConfig.isPresent()) { + accessPoint.update(preferredConfig.get()); + } else { + accessPoint.update(matchedConfigs.get(0)); + } + } accessPoints.add(accessPoint); } @@ -653,6 +666,11 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro conditionallyNotifyListeners(); } + private static boolean isSaeOrOwe(WifiConfiguration config) { + final int security = AccessPoint.getSecurity(config); + return security == AccessPoint.SECURITY_SAE || security == AccessPoint.SECURITY_OWE; + } + @VisibleForTesting List updatePasspointAccessPoints( List>>> passpointConfigsAndScans, @@ -701,7 +719,8 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro private AccessPoint getCachedOrCreate( List scanResults, List cache) { - AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(scanResults.get(0))); + AccessPoint accessPoint = getCachedByKey(cache, + AccessPoint.getKey(mContext, scanResults.get(0))); if (accessPoint == null) { accessPoint = new AccessPoint(mContext, scanResults); } else { diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java index af4704c3618e7..77473f52f4bea 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java @@ -39,6 +39,7 @@ import android.net.ScoredNetwork; import android.net.WifiKey; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; @@ -1272,7 +1273,7 @@ public class AccessPointTest { @Test public void testGetKey_matchesKeysCorrectly() { AccessPoint ap = new AccessPoint(mContext, mScanResults); - assertThat(ap.getKey()).isEqualTo(AccessPoint.getKey(mScanResults.get(0))); + assertThat(ap.getKey()).isEqualTo(AccessPoint.getKey(mContext, mScanResults.get(0))); WifiConfiguration spyConfig = spy(new WifiConfiguration()); when(spyConfig.isPasspoint()).thenReturn(true); @@ -1293,6 +1294,44 @@ public class AccessPointTest { assertThat(osuAp.getKey()).isEqualTo(AccessPoint.getKey(provider)); } + /** + * Test that getKey returns a key of SAE type for a PSK/SAE transition mode ScanResult. + */ + @Test + public void testGetKey_supportSaeTransitionMode_shouldGetSaeKey() { + ScanResult scanResult = createScanResult(TEST_SSID, TEST_BSSID, DEFAULT_RSSI); + scanResult.capabilities = + "[WPA2-FT/PSK-CCMP][RSN-FT/PSK+PSK-SHA256+SAE+FT/SAE-CCMP][ESS][WPS]"; + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true); + when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); + StringBuilder key = new StringBuilder(); + key.append(AccessPoint.KEY_PREFIX_AP); + key.append(TEST_SSID); + key.append(','); + key.append(AccessPoint.SECURITY_SAE); + + assertThat(AccessPoint.getKey(mMockContext, scanResult)).isEqualTo(key.toString()); + } + + /** + * Test that getKey returns a key of PSK type for a PSK/SAE transition mode ScanResult. + */ + @Test + public void testGetKey_notSupportSaeTransitionMode_shouldGetPskKey() { + ScanResult scanResult = createScanResult(TEST_SSID, TEST_BSSID, DEFAULT_RSSI); + scanResult.capabilities = + "[WPA2-FT/PSK-CCMP][RSN-FT/PSK+PSK-SHA256+SAE+FT/SAE-CCMP][ESS][WPS]"; + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(false); + when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); + StringBuilder key = new StringBuilder(); + key.append(AccessPoint.KEY_PREFIX_AP); + key.append(TEST_SSID); + key.append(','); + key.append(AccessPoint.SECURITY_PSK); + + assertThat(AccessPoint.getKey(mMockContext, scanResult)).isEqualTo(key.toString()); + } + /** * Verifies that the Passpoint AccessPoint constructor creates AccessPoints whose isPasspoint() * returns true. @@ -1522,4 +1561,113 @@ public class AccessPointTest { verify(mMockConnectListener).onFailure(anyInt()); } + + /** + * Verifies that matches(AccessPoint other) matches a PSK/SAE transition mode AP to a PSK or a + * SAE AP. + */ + @Test + public void testMatches1_transitionModeApMatchesNotTransitionModeAp_shouldMatchCorrectly() { + when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true); + AccessPoint pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + + // Transition mode AP matches a SAE AP. + AccessPoint saeAccessPoint = new TestAccessPointBuilder(mContext) + .setSsid(AccessPoint.removeDoubleQuotes(TEST_SSID)) + .setSecurity(AccessPoint.SECURITY_SAE) + .build(); + assertThat(pskSaeTransitionModeAp.matches(saeAccessPoint)).isTrue(); + + // Transition mode AP matches a PSK AP. + AccessPoint pskAccessPoint = new TestAccessPointBuilder(mContext) + .setSsid(AccessPoint.removeDoubleQuotes(TEST_SSID)) + .setSecurity(AccessPoint.SECURITY_PSK) + .build(); + + assertThat(pskSaeTransitionModeAp.matches(pskAccessPoint)).isTrue(); + + // Transition mode AP does not match a SAE AP if the device does not support SAE. + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(false); + pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + saeAccessPoint = new TestAccessPointBuilder(mContext) + .setSsid(AccessPoint.removeDoubleQuotes(TEST_SSID)) + .setSecurity(AccessPoint.SECURITY_SAE) + .build(); + + assertThat(pskSaeTransitionModeAp.matches(saeAccessPoint)).isFalse(); + } + + /** + * Verifies that matches(WifiConfiguration config) matches a PSK/SAE transition mode AP to a PSK + * or a SAE WifiConfiguration. + */ + @Test + public void testMatches2_transitionModeApMatchesNotTransitionModeAp_shouldMatchCorrectly() { + when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true); + AccessPoint pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + + // Transition mode AP matches a SAE WifiConfiguration. + WifiConfiguration saeConfig = new WifiConfiguration(); + saeConfig.SSID = TEST_SSID; + saeConfig.allowedKeyManagement.set(KeyMgmt.SAE); + + assertThat(pskSaeTransitionModeAp.matches(saeConfig)).isTrue(); + + // Transition mode AP matches a PSK WifiConfiguration. + WifiConfiguration pskConfig = new WifiConfiguration(); + pskConfig.SSID = TEST_SSID; + pskConfig.allowedKeyManagement.set(KeyMgmt.WPA_PSK); + + assertThat(pskSaeTransitionModeAp.matches(pskConfig)).isTrue(); + + // Transition mode AP does not matches a SAE WifiConfiguration if the device does not + // support SAE. + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(false); + pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + + assertThat(pskSaeTransitionModeAp.matches(saeConfig)).isFalse(); + } + + /** + * Verifies that matches(ScanResult scanResult) matches a PSK/SAE transition mode AP to a PSK + * or a SAE ScanResult. + */ + @Test + public void testMatches3_transitionModeApMatchesNotTransitionModeAp_shouldMatchCorrectly() { + when(mMockContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager); + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true); + AccessPoint pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + + // Transition mode AP matches a SAE ScanResult. + ScanResult saeScanResult = createScanResult(AccessPoint.removeDoubleQuotes(TEST_SSID), + TEST_BSSID, DEFAULT_RSSI); + saeScanResult.capabilities = "[SAE-CCMP][ESS][WPS]"; + + assertThat(pskSaeTransitionModeAp.matches(saeScanResult)).isTrue(); + + // Transition mode AP matches a PSK ScanResult. + ScanResult pskScanResult = createScanResult(AccessPoint.removeDoubleQuotes(TEST_SSID), + TEST_BSSID, DEFAULT_RSSI); + pskScanResult.capabilities = "[RSN-PSK-CCMP][ESS][WPS]"; + + assertThat(pskSaeTransitionModeAp.matches(pskScanResult)).isTrue(); + + // Transition mode AP does not matches a SAE ScanResult if the device does not support SAE. + when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(false); + pskSaeTransitionModeAp = getPskSaeTransitionModeAp(); + + assertThat(pskSaeTransitionModeAp.matches(saeScanResult)).isFalse(); + } + + private AccessPoint getPskSaeTransitionModeAp() { + ScanResult scanResult = createScanResult(AccessPoint.removeDoubleQuotes(TEST_SSID), + TEST_BSSID, DEFAULT_RSSI); + scanResult.capabilities = + "[WPA2-FT/PSK-CCMP][RSN-FT/PSK+PSK-SHA256+SAE+FT/SAE-CCMP][ESS][WPS]"; + return new TestAccessPointBuilder(mMockContext) + .setScanResults(new ArrayList(Arrays.asList(scanResult))) + .build(); + } }