Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d5732ca authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Wi-Fi] Fix transition mode problems" into qt-qpr1-dev

parents 730fc5b2 6e810df9
Loading
Loading
Loading
Loading
+233 −92
Original line number Diff line number Diff line
@@ -176,6 +176,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
    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<AccessPoint> {
    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<AccessPoint> {
    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<AccessPoint> {
        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<AccessPoint> {
        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,9 +722,44 @@ public class AccessPoint implements Comparable<AccessPoint> {
     * Determines if the other AccessPoint represents the same network as this AccessPoint
     */
    public boolean matches(AccessPoint other) {
        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) {
        if (config.isPasspoint()) {
            return (isPasspoint() && config.FQDN.equals(mConfig.FQDN));
@@ -720,20 +771,79 @@ public class AccessPoint implements Comparable<AccessPoint> {
        }

        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() {
        return mConfig;
    }
@@ -818,14 +928,17 @@ public class AccessPoint implements Comparable<AccessPoint> {
        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<AccessPoint> {
            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<AccessPoint> {
                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);
            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<AccessPoint> {
        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<AccessPoint> {
     * 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<AccessPoint> {
        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<AccessPoint> {
        // 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));
                            result, getKey(mContext, result), mKey));
                    return;
                }
            }
@@ -1594,11 +1670,8 @@ public class AccessPoint implements Comparable<AccessPoint> {
    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<AccessPoint> {
        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<AccessPoint> {
            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<AccessPoint> {
            }
        }
    }

    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;
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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);
+30 −11
Original line number Diff line number Diff line
@@ -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<ScanResult> 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<ScanResult> newScanResults,
            List<WifiConfiguration> configs) {

        // Map configs and scan results necessary to make AccessPoints
        final Map<String, WifiConfiguration> 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<WifiConfiguration> 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<WifiConfiguration> 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<AccessPoint> updatePasspointAccessPoints(
            List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> passpointConfigsAndScans,
@@ -701,7 +719,8 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    private AccessPoint getCachedOrCreate(
            List<ScanResult> scanResults,
            List<AccessPoint> 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 {
+149 −1

File changed.

Preview size limit exceeded, changes collapsed.