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

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

Merge "Supports to share Wi-Fi networks of WPA3 security SAE & OWE via QR code...

Merge "Supports to share Wi-Fi networks of WPA3 security SAE & OWE via QR code generator" into qt-dev
parents 73f539d2 4a5ff585
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -409,7 +409,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
                .setButton4Text(R.string.share)
                .setButton4Icon(R.drawable.ic_qrcode_24dp)
                .setButton4OnClickListener(view -> shareNetwork())
                .setButton4Visible(WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mAccessPoint));
                .setButton4Visible(
                        WifiDppUtils.isSupportConfiguratorQrCodeGenerator(mContext, mAccessPoint));

        mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
        mTxLinkSpeedPref = screen.findPreference(KEY_TX_LINK_SPEED);
+68 −48
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.lifecycle.ViewModelProviders;

import com.android.settings.R;
@@ -57,6 +58,7 @@ import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;

import java.util.ArrayList;
import java.util.List;

public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
@@ -104,7 +106,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
    private WifiQrCode mWifiQrCode;

    /** The WifiConfiguration connecting for enrollee usage */
    private WifiConfiguration mWifiConfiguration;
    private WifiConfiguration mEnrolleeWifiConfiguration;

    private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE;

@@ -140,14 +142,8 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
                    break;

                case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
                    if (mCamera != null) {
                        mCamera.stop();
                    }

                    mDecorateView.setFocused(true);
                    mErrorMessage.setVisibility(View.INVISIBLE);

                    if (mScanWifiDppSuccessListener == null) {
                        // mScanWifiDppSuccessListener may be null after onDetach(), do nothing here
                        return;
                    }
                    mScanWifiDppSuccessListener.onScanWifiDppSuccess((WifiQrCode)msg.obj);
@@ -160,10 +156,53 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                    }

                    WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext());
                    notifyUserForQrCodeRecognition();
                    break;

                case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
                    // We may get 2 WifiConfiguration if the QR code has no password in it,
                    // one for open network and one for enhanced open network.
                    final WifiManager wifiManager =
                            getContext().getSystemService(WifiManager.class);
                    final WifiNetworkConfig qrCodeWifiNetworkConfig =
                            (WifiNetworkConfig)msg.obj;
                    final List<WifiConfiguration> qrCodeWifiConfigurations =
                            qrCodeWifiNetworkConfig.getWifiConfigurations();

                    // Adds all Wi-Fi networks in QR code to the set of configured networks and
                    // connects to it if it's reachable.
                    boolean hasReachableWifiNetwork = false;
                    for (WifiConfiguration qrCodeWifiConfiguration : qrCodeWifiConfigurations) {
                        final int id = wifiManager.addNetwork(qrCodeWifiConfiguration);
                        if (id == -1) {
                            continue;
                        }
                        wifiManager.enableNetwork(id, /* attemptConnect */ false);
                        if (isReachableWifiNetwork(qrCodeWifiConfiguration)) {
                            hasReachableWifiNetwork = true;
                            mEnrolleeWifiConfiguration = qrCodeWifiConfiguration;
                            wifiManager.connect(id,
                                    /* listener */ WifiDppQrCodeScannerFragment.this);
                        }
                    }

                    if (hasReachableWifiNetwork == false) {
                        showErrorMessageAndRestartCamera(
                                R.string.wifi_dpp_check_connection_try_again);
                        return;
                    }

                    notifyUserForQrCodeRecognition();
                    break;

                default:
                    return;
            }
        }
    };

    @UiThread
    private void notifyUserForQrCodeRecognition() {
        if (mCamera != null) {
            mCamera.stop();
        }
@@ -171,19 +210,20 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
        mDecorateView.setFocused(true);
        mErrorMessage.setVisibility(View.INVISIBLE);

                    final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj;
                    mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull();
                    wifiNetworkConfig.connect(getContext(),
                            /* listener */ WifiDppQrCodeScannerFragment.this);

        WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext());
                    break;
    }

                default:
                    return;
    private boolean isReachableWifiNetwork(WifiConfiguration wifiConfiguration) {
        final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();

        for (AccessPoint scannedAccessPoint : scannedAccessPoints) {
            if (scannedAccessPoint.matches(wifiConfiguration) &&
                    scannedAccessPoint.isReachable()) {
                return true;
            }
        }
    };
        return false;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
@@ -192,7 +232,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
        if (savedInstanceState != null) {
            mIsConfiguratorMode = savedInstanceState.getBoolean(KEY_IS_CONFIGURATOR_MODE);
            mLatestStatusCode = savedInstanceState.getInt(KEY_LATEST_ERROR_CODE);
            mWifiConfiguration = savedInstanceState.getParcelable(KEY_WIFI_CONFIGURATION);
            mEnrolleeWifiConfiguration = savedInstanceState.getParcelable(KEY_WIFI_CONFIGURATION);
        }

        final WifiDppInitiatorViewModel model =
@@ -480,7 +520,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
    public void onSaveInstanceState(Bundle outState) {
        outState.putBoolean(KEY_IS_CONFIGURATOR_MODE, mIsConfiguratorMode);
        outState.putInt(KEY_LATEST_ERROR_CODE, mLatestStatusCode);
        outState.putParcelable(KEY_WIFI_CONFIGURATION, mWifiConfiguration);
        outState.putParcelable(KEY_WIFI_CONFIGURATION, mEnrolleeWifiConfiguration);

        super.onSaveInstanceState(outState);
    }
@@ -496,7 +536,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
            for (WifiConfiguration wifiConfig : wifiConfigs) {
                if (wifiConfig.networkId == newNetworkId) {
                    mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
                    mWifiConfiguration = wifiConfig;
                    mEnrolleeWifiConfiguration = wifiConfig;
                    wifiManager.connect(wifiConfig, WifiDppQrCodeScannerFragment.this);
                    return;
                }
@@ -588,17 +628,13 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl

    @Override
    public void onSuccess() {
        if (isEnrollingWifiNetworkReachable()) {
        final Intent resultIntent = new Intent();
            resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION, mWifiConfiguration);
        resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION,
                mEnrolleeWifiConfiguration);

        final Activity hostActivity = getActivity();
        hostActivity.setResult(Activity.RESULT_OK, resultIntent);
        hostActivity.finish();
        } else {
            Log.d(TAG, "Enroll Wi-Fi network succeeded but it's not reachable");
            showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
        }
    }

    @Override
@@ -607,22 +643,6 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
        showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
    }

    private boolean isEnrollingWifiNetworkReachable() {
        if (mWifiConfiguration == null) {
            Log.e(TAG, "Connect succeeded but lost WifiConfiguration");
            return false;
        }

        final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
        for (AccessPoint accessPoint : scannedAccessPoints) {
            if (accessPoint.matches(mWifiConfiguration) &&
                    accessPoint.isReachable()) {
                return true;
            }
        }
        return false;
    }

    // Check is Easy Connect handshaking or not
    private boolean isGoingInitiator() {
        final WifiDppInitiatorViewModel model =
+38 −14
Original line number Diff line number Diff line
@@ -162,6 +162,9 @@ public class WifiDppUtils {
        if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
            return WifiQrCode.SECURITY_SAE;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
            return WifiQrCode.SECURITY_NO_PASSWORD;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ||
                config.allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
            return WifiQrCode.SECURITY_WPA_PSK;
@@ -185,7 +188,7 @@ public class WifiDppUtils {
    public static Intent getConfiguratorQrCodeGeneratorIntentOrNull(Context context,
            WifiManager wifiManager, AccessPoint accessPoint) {
        final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
        if (isSupportConfiguratorQrCodeGenerator(accessPoint)) {
        if (isSupportConfiguratorQrCodeGenerator(context, accessPoint)) {
            intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
        } else {
            return null;
@@ -343,22 +346,24 @@ public class WifiDppUtils {
    /**
     * Checks if QR code generator supports to config other devices with the Wi-Fi network
     *
     * @param context The context to use for {@code WifiManager}
     * @param accessPoint The {@link AccessPoint} of the Wi-Fi network
     */
    public static boolean isSupportConfiguratorQrCodeGenerator(AccessPoint accessPoint) {
        return isSupportZxing(accessPoint.getSecurity());
    public static boolean isSupportConfiguratorQrCodeGenerator(Context context,
            AccessPoint accessPoint) {
        return isSupportZxing(context, accessPoint.getSecurity());
    }

    /**
     * Checks if this device supports to be configured by the Wi-Fi network of the security
     *
     * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
     * @param context The context to use for {@code WifiManager}
     * @param accesspointSecurity The security constants defined in {@link AccessPoint}
     */
    public static boolean isSupportEnrolleeQrCodeScanner(Context context,
            int accesspointSecurity) {
        return isSupportWifiDpp(context, accesspointSecurity) ||
                isSupportZxing(accesspointSecurity);
                isSupportZxing(context, accesspointSecurity);
    }

    private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
@@ -376,19 +381,38 @@ public class WifiDppUtils {
        }

        // DPP 1.0 only supports SAE and PSK.
        if (accesspointSecurity == AccessPoint.SECURITY_SAE ||
                accesspointSecurity == AccessPoint.SECURITY_PSK) {
        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
        switch (accesspointSecurity) {
            case AccessPoint.SECURITY_SAE:
                if (wifiManager.isWpa3SaeSupported()) {
                    return true;
                }
                break;
            case AccessPoint.SECURITY_PSK:
                return true;
            default:
        }
        return false;
    }

    // TODO (b/124131581 b/129396816): TO support WPA3 securities (SAE & OWE), change here at first
    private static boolean isSupportZxing(int accesspointSecurity) {
        if (accesspointSecurity == AccessPoint.SECURITY_PSK ||
                accesspointSecurity == AccessPoint.SECURITY_WEP ||
                accesspointSecurity == AccessPoint.SECURITY_NONE) {
    private static boolean isSupportZxing(Context context, int accesspointSecurity) {
        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
        switch (accesspointSecurity) {
            case AccessPoint.SECURITY_PSK:
            case AccessPoint.SECURITY_WEP:
            case AccessPoint.SECURITY_NONE:
                return true;
            case AccessPoint.SECURITY_SAE:
                if (wifiManager.isWpa3SaeSupported()) {
                    return true;
                }
                break;
            case AccessPoint.SECURITY_OWE:
                if (wifiManager.isEnhancedOpenSupported()) {
                    return true;
                }
                break;
            default:
        }
        return false;
    }
+58 −26
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ import android.util.Log;

import androidx.annotation.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;

/**
 * Wraps the parameters of ZXing reader library's Wi-Fi Network config format.
 * Please check {@code WifiQrCode} for detail of the format.
@@ -203,50 +206,63 @@ public class WifiNetworkConfig {
        return mIsHotspot;
    }

    public void connect(Context context, WifiManager.ActionListener listener) {
        WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull();
        if (wifiConfiguration == null) {
            if (listener != null) {
                listener.onFailure(WifiManager.ERROR);
            }
            return;
        }

        WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        wifiManager.connect(wifiConfiguration, listener);
    }

    public boolean isSupportWifiDpp(Context context) {
        if (!WifiDppUtils.isWifiDppEnabled(context)) {
            return false;
        }

        if (TextUtils.isEmpty(mSecurity)) {
            return false;
        }

        // DPP 1.0 only supports SAE and PSK.
        if (SECURITY_SAE.equals(mSecurity) || SECURITY_WPA_PSK.equals(mSecurity)) {
        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
        switch (mSecurity) {
            case SECURITY_SAE:
                if (wifiManager.isWpa3SaeSupported()) {
                    return true;
                }

                break;
            case SECURITY_WPA_PSK:
                return true;
            default:
        }
        return false;
    }

    /**
     * This is a simplified method from {@code WifiConfigController.getConfig()}
     *
     * TODO (b/129021867): WifiConfiguration is a deprecated class, should replace it with
     *       {@code android.net.wifi.WifiNetworkSuggestion}
     *
     * @return When it's a open network, returns 2 WifiConfiguration in the List, the 1st is
     *         open network and the 2nd is enhanced open network. Returns 1 WifiConfiguration in the
     *         List for all other supported Wi-Fi securities.
     */
    WifiConfiguration getWifiConfigurationOrNull() {
    List<WifiConfiguration> getWifiConfigurations() {
        final List<WifiConfiguration> wifiConfigurations = new ArrayList<>();

        if (!isValidConfig(this)) {
            return null;
            return wifiConfigurations;
        }

        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
        wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
        wifiConfiguration.hiddenSSID = mHiddenSsid;
        wifiConfiguration.networkId = mNetworkId;

        if (TextUtils.isEmpty(mSecurity) || SECURITY_NO_PASSWORD.equals(mSecurity)) {
            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
            return wifiConfiguration;
            // TODO (b/129835824): we add both open network and enhanced open network to WifiManager
            //                     for android Q, should improve it in the future.
            final WifiConfiguration openNetworkWifiConfiguration = getBasicWifiConfiguration();
            openNetworkWifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
            wifiConfigurations.add(openNetworkWifiConfiguration);

            final WifiConfiguration enhancedOpenNetworkWifiConfiguration =
                    getBasicWifiConfiguration();
            enhancedOpenNetworkWifiConfiguration.allowedKeyManagement.set(KeyMgmt.OWE);
            enhancedOpenNetworkWifiConfiguration.requirePMF = true;
            wifiConfigurations.add(enhancedOpenNetworkWifiConfiguration);
            return wifiConfigurations;
        }

        final WifiConfiguration wifiConfiguration = getBasicWifiConfiguration();
        if (mSecurity.startsWith(SECURITY_WEP)) {
            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
            wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
@@ -268,11 +284,27 @@ public class WifiNetworkConfig {
            } else {
                wifiConfiguration.preSharedKey = addQuotationIfNeeded(mPreSharedKey);
            }
        } else if (mSecurity.startsWith(SECURITY_SAE)) {
            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.SAE);
            wifiConfiguration.requirePMF = true;
            if (mPreSharedKey.length() != 0) {
                wifiConfiguration.preSharedKey = addQuotationIfNeeded(mPreSharedKey);
            }
        } else {
            Log.w(TAG, "Unsupported security");
            return null;
            return wifiConfigurations;
        }

        wifiConfigurations.add(wifiConfiguration);
        return wifiConfigurations;
    }

    private WifiConfiguration getBasicWifiConfiguration() {
        final WifiConfiguration wifiConfiguration = new WifiConfiguration();

        wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
        wifiConfiguration.hiddenSSID = mHiddenSsid;
        wifiConfiguration.networkId = mNetworkId;
        return wifiConfiguration;
    }

+2 −2
Original line number Diff line number Diff line
@@ -64,10 +64,10 @@ public class WifiQrCode {
    public static final String DELIMITER_QR_CODE = ";";

    // Ignores password if security is SECURITY_NO_PASSWORD or absent
    public static final String SECURITY_NO_PASSWORD = "nopass";
    public static final String SECURITY_NO_PASSWORD = "nopass"; //open network or OWE
    public static final String SECURITY_WEP = "WEP";
    public static final String SECURITY_WPA_PSK = "WPA";
    public static final String SECURITY_SAE = "WPA3";
    public static final String SECURITY_SAE = "SAE";

    private String mQrCode;

Loading