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

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

Merge changes from topic "Wi-Fi DPP error code handling"

* changes:
  Fix camera stop forever after error occurs while sharing or adding network
  Handle different error codes in DPP
parents 812855c8 ffae615d
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -46,9 +46,14 @@
                    android:layout_height="match_parent"/>
            </com.android.settings.wifi.qrcode.QrPreviewLayout>

            <TextView android:id="@+id/error_message"
            <TextView
                android:id="@+id/error_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
                android:layout_height="wrap_content"
                android:textAlignment="center"
                android:layout_marginTop="8dp"
                android:visibility="invisible"
                android:textColor="?android:attr/colorError"/>

        </LinearLayout>

+1 −1
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@
                android:id="@+id/error_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAlignment="center"
                android:layout_marginTop="8dp"
                android:text="@string/wifi_dpp_could_not_detect_valid_qr_code"
                android:visibility="invisible"
                android:textColor="?android:attr/colorError"/>

+13 −1
Original line number Diff line number Diff line
@@ -2124,7 +2124,19 @@
    <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
    <!-- Hint for QR code detection [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_could_not_detect_valid_qr_code">Couldn\u2019t read QR code</string>
    <string name="wifi_dpp_could_not_detect_valid_qr_code">Couldn\u2019t read QR code. Re-center code and try again</string>
    <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_failure_authentication_or_configuration">Try again. If the issue continues, contact the device manufacturer</string>
    <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_failure_not_compatible">Something went wrong</string>
    <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_failure_timeout">Make sure the device has been plugged in, charged, and turned on</string>
    <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_failure_generic">Make sure the device has been plugged in, charged, and turned on. If the issue continues, contact the device manufacturer</string>
    <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_failure_not_supported">Adding \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d isn\u2019t supported by this device</string>
    <!-- Hint for Wi-Fi connection fail [CHAR LIMIT=NONE]  -->
    <string name="wifi_dpp_check_connection_try_again">Check connection and try again</string>
    <!-- Title for the fragment choose network [CHAR LIMIT=50]  -->
    <string name="wifi_dpp_choose_network">Choose network</string>
    <!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
+190 −36
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.app.ActionBar;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.net.wifi.EasyConnectStatusCallback;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
@@ -30,6 +32,8 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;

import androidx.lifecycle.ViewModelProviders;

import com.android.settings.R;

import java.util.concurrent.Executor;
@@ -46,7 +50,12 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
    private Button mButtonLeft;
    private Button mButtonRight;

    private class EasyConnectStatusCallback extends android.net.wifi.EasyConnectStatusCallback {
    private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE;

    // Key for Bundle usage
    private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code";

    private class EasyConnectConfiguratorStatusCallback extends EasyConnectStatusCallback {
        @Override
        public void onEnrolleeSuccess(int newNetworkId) {
            // Do nothing
@@ -54,7 +63,23 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {

        @Override
        public void onConfiguratorSuccess(int code) {
            // Update success UI.
            showSuccessUi(/* isConfigurationChange */ false);
        }

        @Override
        public void onFailure(int code) {
            Log.d(TAG, "EasyConnectConfiguratorStatusCallback.onFailure " + code);

            showErrorUi(code, /* isConfigurationChange */ false);
        }

        @Override
        public void onProgress(int code) {
            // Do nothing
        }
    }

    private void showSuccessUi(boolean isConfigurationChange) {
        setHeaderIconImageResource(R.drawable.ic_devices_check_circle_green);
        mTitle.setText(R.string.wifi_dpp_wifi_shared_with_device);
        mSummary.setVisibility(View.INVISIBLE);
@@ -68,24 +93,96 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
            activity.setResult(Activity.RESULT_OK);
            activity.finish();
        });

        if (!isConfigurationChange) {
            mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
        }
    }

        @Override
        public void onFailure(int code) {
            Log.d(TAG, "EasyConnectStatusCallback.onFailure " + code);
    private void showErrorUi(int code, boolean isConfigurationChange) {
        switch (code) {
            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI:
                mSummary.setText(R.string.wifi_dpp_could_not_detect_valid_qr_code);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION:
                mSummary.setText(R.string.wifi_dpp_failure_authentication_or_configuration);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE:
                mSummary.setText(R.string.wifi_dpp_failure_not_compatible);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION:
                mSummary.setText(R.string.wifi_dpp_failure_authentication_or_configuration);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY:
                if (isConfigurationChange) {
                    return;
                }

                if (code == mLatestStatusCode) {
                    throw(new IllegalStateException("Tried restarting EasyConnectSession but still"
                            + "receiving EASY_CONNECT_EVENT_FAILURE_BUSY"));
                }

                mLatestStatusCode = code;
                final WifiManager wifiManager =
                        getContext().getSystemService(WifiManager.class);
                wifiManager.stopEasyConnectSession();
                startWifiDppConfiguratorInitiator();
                return;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT:
                mSummary.setText(R.string.wifi_dpp_failure_timeout);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC:
                mSummary.setText(R.string.wifi_dpp_failure_generic);
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED:
                mSummary.setText(getString(R.string.wifi_dpp_failure_not_supported, getSsid()));
                break;

            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK:
                throw(new IllegalStateException("Wi-Fi DPP configurator used a non-PSK/non-SAE"
                        + "network to handshake"));

            default:
                throw(new IllegalStateException("Unexpected Wi-Fi DPP error"));
        }

            // Update fail UI.
        mTitle.setText(R.string.wifi_dpp_could_not_add_device);
            mSummary.setVisibility(View.INVISIBLE);
        mWifiApPictureView.setImageResource(R.drawable.wifi_dpp_error);
        mChooseDifferentNetwork.setVisibility(View.INVISIBLE);
        if (hasRetryButton(code)) {
            mButtonRight.setText(R.string.retry);
        } else {
            mButtonRight.setText(R.string.done);
            mButtonRight.setOnClickListener(v -> getActivity().finish());
            mButtonLeft.setVisibility(View.INVISIBLE);
        }

        @Override
        public void onProgress(int code) {
            // Do nothing
        if (!isConfigurationChange) {
            mLatestStatusCode = code;
        }

        mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE);
    }

    private boolean hasRetryButton(int code) {
        switch (code) {
            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI:
            case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE:
                return false;

            default:
                break;
        }

        return true;
    }

    @Override
@@ -93,6 +190,33 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
        return SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            mLatestStatusCode = savedInstanceState.getInt(KEY_LATEST_ERROR_CODE);
        }

        final WifiDppInitiatorViewModel model =
                ViewModelProviders.of(this).get(WifiDppInitiatorViewModel.class);

        model.getStatusCode().observe(this, statusCode -> {
            // After configuration change, observe callback will be triggered,
            // do nothing for this case if a handshake does not end
            if (model.isGoingInitiator()) {
                return;
            }

            int code = statusCode.intValue();
            if (code == WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS) {
                new EasyConnectConfiguratorStatusCallback().onConfiguratorSuccess(code);
            } else {
                new EasyConnectConfiguratorStatusCallback().onFailure(code);
            }
        });
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
@@ -125,14 +249,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
            mTitle.setText(information);
        }

        final WifiNetworkConfig wifiNetworkConfig = ((WifiDppConfiguratorActivity) getActivity())
                .getWifiNetworkConfig();
        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
            throw new IllegalStateException("Invalid Wi-Fi network for configuring");
        }
        mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi,
                wifiNetworkConfig.getSsid()));

        mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi, getSsid()));
        mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);

        mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
@@ -146,19 +263,48 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {

        mButtonRight = view.findViewById(R.id.button_right);
        mButtonRight.setText(R.string.wifi_dpp_share_wifi);
        mButtonRight.setOnClickListener(v -> startWifiDppInitiator());
        mButtonRight.setOnClickListener(v -> {
            mButtonRight.setVisibility(View.INVISIBLE);
            startWifiDppConfiguratorInitiator();
        });

        if (savedInstanceState != null) {
            if (mLatestStatusCode == WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS) {
                showSuccessUi(/* isConfigurationChange */ true);
            } else if (mLatestStatusCode == WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE) {
                mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE);
            } else {
                showErrorUi(mLatestStatusCode, /* isConfigurationChange */ true);
            }
        }
    }

    private void startWifiDppInitiator() {
    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putInt(KEY_LATEST_ERROR_CODE, mLatestStatusCode);

        super.onSaveInstanceState(outState);
    }

    private String getSsid() {
        final WifiNetworkConfig wifiNetworkConfig = ((WifiDppConfiguratorActivity) getActivity())
                .getWifiNetworkConfig();
        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
            throw new IllegalStateException("Invalid Wi-Fi network for configuring");
        }
        return wifiNetworkConfig.getSsid();
    }

    private void startWifiDppConfiguratorInitiator() {
        final WifiQrCode wifiQrCode = ((WifiDppConfiguratorActivity) getActivity())
                .getWifiDppQrCode();
        final String qrCode = wifiQrCode.getQrCode();
        final int networkId =
                ((WifiDppConfiguratorActivity) getActivity()).getWifiNetworkConfig().getNetworkId();
        final WifiManager wifiManager = getContext().getSystemService(WifiManager.class);
        wifiManager.startEasyConnectAsConfiguratorInitiator(qrCode, networkId,
                WifiManager.EASY_CONNECT_NETWORK_ROLE_STA, getContext().getMainExecutor(),
                new EasyConnectStatusCallback());
        final WifiDppInitiatorViewModel model =
                ViewModelProviders.of(this).get(WifiDppInitiatorViewModel.class);

        model.startEasyConnectAsConfiguratorInitiator(qrCode, networkId);
    }

    // Container Activity must implement this interface
@@ -180,4 +326,12 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {

        super.onDetach();
    }

    // Check is Easy Connect handshaking or not
    private boolean isGoingInitiator() {
        final WifiDppInitiatorViewModel model =
                ViewModelProviders.of(this).get(WifiDppInitiatorViewModel.class);

        return model.isGoingInitiator();
    }
}
+2 −23
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        WifiNetworkConfig.Retriever,
        WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener,
        WifiDppQrCodeScannerFragment.OnScanWifiDppSuccessListener,
        WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener,
        WifiDppAddDeviceFragment.OnClickChooseDifferentNetworkListener,
        WifiNetworkListFragment.OnChooseNetworkListener {

@@ -102,7 +101,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        if (savedInstanceState != null) {
            String qrCode = savedInstanceState.getString(KEY_QR_CODE);

            mWifiDppQrCode = getValidWifiDppQrCodeOrNull(qrCode);
            mWifiDppQrCode = WifiQrCode.getValidWifiDppQrCodeOrNull(qrCode);

            String security = savedInstanceState.getString(KEY_WIFI_SECURITY);
            String ssid = savedInstanceState.getString(KEY_WIFI_SSID);
@@ -148,7 +147,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
            case Settings.ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE:
                String qrCode = intent.getStringExtra(Settings.EXTRA_QR_CODE);
                mIsTest = intent.getBooleanExtra(WifiDppUtils.EXTRA_TEST, false);
                mWifiDppQrCode = getValidWifiDppQrCodeOrNull(qrCode);
                mWifiDppQrCode = WifiQrCode.getValidWifiDppQrCodeOrNull(qrCode);
                final boolean isDppSupported = WifiDppUtils.isWifiDppEnabled(this);
                if (!isDppSupported) {
                    Log.d(TAG, "Device doesn't support Wifi DPP");
@@ -285,21 +284,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        fragmentTransaction.commit();
    }

    private WifiQrCode getValidWifiDppQrCodeOrNull(String qrCode) {
        WifiQrCode wifiQrCode;
        try {
            wifiQrCode = new WifiQrCode(qrCode);
        } catch(IllegalArgumentException e) {
            return null;
        }

        if (WifiQrCode.SCHEME_DPP.equals(wifiQrCode.getScheme())) {
            return wifiQrCode;
        }

        return null;
    }

    @Override
    public WifiNetworkConfig getWifiNetworkConfig() {
        return mWifiNetworkConfig;
@@ -358,11 +342,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        showAddDeviceFragment(/* addToBackStack */ true);
    }

    @Override
    public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
        // Do nothing, it's impossible to be a configurator without a Wi-Fi DPP QR code
    }

    @Override
    public void onClickChooseDifferentNetwork() {
        showChooseSavedWifiNetworkFragment(/* addToBackStack */ true);
Loading