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

Commit 9d333137 authored by Arc Wang's avatar Arc Wang
Browse files

Fix Wi-Fi DPP fragment back stack problems

1. When a Wi-Fi network connected and receiving
   intent android.settings.PROCESS_WIFI_EASY_CONNECT_QR_CODE,
   show WifiDppAddDeviceFragment from WifiDppConfiguratorActivity
   instead of WifiNetworkListFragment

2. Only handle intent when savedInstanceState is null

3. To show a fragment
   I. do nothing when a fragment is already visible on screen,
   II. pop back stack if it's in back stack, we can do this because
   current fragment transactions are arranged in an order

Bug: 124194531
Test: atest WifiQrCodeTest
      atest WifiDppConfiguratorActivityTest
      atest WifiDppEnrolleeActivityTest
      atest WifiDppQrCodeGeneratorFragmentTest
      atest WifiDppQrCodeScannerFragmentTest
      atest WifiNetworkListFragmentTest
      atest WifiDppChooseSavedWifiNetworkFragmentTest

Change-Id: I1d44eeb3bdc7bfb2ec2e4d81efaab64b066651ad
parent fd9cdb50
Loading
Loading
Loading
Loading
+83 −24
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.settings.wifi.dpp;
import android.app.ActionBar;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
@@ -31,6 +34,8 @@ import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R;
import com.android.settings.core.InstrumentedActivity;

import java.util.List;

/**
 * To provision "other" device with specified Wi-Fi network.
 *
@@ -78,6 +83,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements

    /** The Wi-Fi DPP QR code from intent ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE */
    private WifiQrCode mWifiDppQrCode;

    /** Secret extra that allows fake networks to show in UI for testing purposes */
    private boolean mIsTest;

@@ -90,6 +96,9 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.wifi_dpp_activity);
        mFragmentManager = getSupportFragmentManager();

        if (savedInstanceState != null) {
            String qrCode = savedInstanceState.getString(KEY_QR_CODE);

@@ -103,12 +112,9 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements

            mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid,
                    preSharedKey, hiddenSsid, networkId);
        }

        setContentView(R.layout.wifi_dpp_activity);
        mFragmentManager = getSupportFragmentManager();

        } else {
            handleIntent(getIntent());
        }

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
@@ -150,7 +156,13 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
                if (mWifiDppQrCode == null || !isDppSupported) {
                    cancelActivity = true;
                } else {
                    final WifiNetworkConfig connectedConfig = getConnectedWifiNetworkConfigOrNull();
                    if (connectedConfig == null) {
                        showChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
                    } else {
                        mWifiNetworkConfig = connectedConfig;
                        showAddDeviceFragment(/* addToBackStack */ false);
                    }
                }
                break;
            default:
@@ -167,13 +179,18 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        WifiDppQrCodeScannerFragment fragment =
                (WifiDppQrCodeScannerFragment) mFragmentManager.findFragmentByTag(
                        WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
        // Avoid to replace the same fragment during configuration change
        if (fragment != null && fragment.isVisible()) {
            return;
        }

        if (fragment == null) {
            fragment = new WifiDppQrCodeScannerFragment();
        } else {
            if (fragment.isVisible()) {
                return;
            }

            // When the fragment in back stack but not on top of the stack, we can simply pop
            // stack because current fragment transactions are arranged in an order
            mFragmentManager.popBackStackImmediate();
            return;
        }
        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

@@ -189,12 +206,19 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        WifiDppQrCodeGeneratorFragment fragment =
                (WifiDppQrCodeGeneratorFragment) mFragmentManager.findFragmentByTag(
                        WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
        // Avoid to replace the same fragment during configuration change
        if (fragment != null && fragment.isVisible()) {

        if (fragment == null) {
            fragment = new WifiDppQrCodeGeneratorFragment();
        } else {
            if (fragment.isVisible()) {
                return;
            }

        fragment = new WifiDppQrCodeGeneratorFragment();
            // When the fragment in back stack but not on top of the stack, we can simply pop
            // stack because current fragment transactions are arranged in an order
            mFragmentManager.popBackStackImmediate();
            return;
        }
        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.fragment_container, fragment,
@@ -206,10 +230,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
        WifiDppChooseSavedWifiNetworkFragment fragment =
                (WifiDppChooseSavedWifiNetworkFragment) mFragmentManager.findFragmentByTag(
                        WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK);
        // Avoid to replace the same fragment during configuration change
        if (fragment != null && fragment.isVisible()) {
            return;
        }

        if (fragment == null) {
            fragment = new WifiDppChooseSavedWifiNetworkFragment();
@@ -218,6 +238,15 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
                bundle.putBoolean(WifiDppUtils.EXTRA_TEST, true);
                fragment.setArguments(bundle);
            }
        } else {
            if (fragment.isVisible()) {
                return;
            }

            // When the fragment in back stack but not on top of the stack, we can simply pop
            // stack because current fragment transactions are arranged in an order
            mFragmentManager.popBackStackImmediate();
            return;
        }
        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

@@ -234,14 +263,17 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
                (WifiDppAddDeviceFragment) mFragmentManager.findFragmentByTag(
                        WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE);

        // Avoid to replace the same fragment during configuration change
        if (mFragmentManager.findFragmentByTag(
                WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE) != null) {
        if (fragment == null) {
            fragment = new WifiDppAddDeviceFragment();
        } else {
            if (fragment.isVisible()) {
                return;
            }

        if (fragment == null) {
            fragment = new WifiDppAddDeviceFragment();
            // When the fragment in back stack but not on top of the stack, we can simply pop
            // stack because current fragment transactions are arranged in an order
            mFragmentManager.popBackStackImmediate();
            return;
        }
        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

@@ -359,4 +391,31 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements

        showAddDeviceFragment(/* addToBackStack */ true);
    }

    private WifiNetworkConfig getConnectedWifiNetworkConfigOrNull() {
        final WifiManager wifiManager = getSystemService(WifiManager.class);
        if (!wifiManager.isWifiEnabled()) {
            return null;
        }

        final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
        if (connectionInfo == null) {
            return null;
        }

        final int connectionNetworkId = connectionInfo.getNetworkId();
        final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
        for (WifiConfiguration wifiConfiguration : configs) {
            if (wifiConfiguration.networkId == connectionNetworkId) {
                return WifiNetworkConfig.getValidConfigOrNull(
                    WifiDppUtils.getSecurityString(wifiConfiguration),
                    wifiConfiguration.getPrintableSsid(),
                    wifiConfiguration.preSharedKey,
                    /* hiddenSsid */ false,
                    wifiConfiguration.networkId);
            }
        }

        return null;
    }
}
+18 −6
Original line number Diff line number Diff line
@@ -100,7 +100,9 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements
        setContentView(R.layout.wifi_dpp_activity);
        mFragmentManager = getSupportFragmentManager();

        if (savedInstanceState == null) {
            handleIntent(getIntent());
        }

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
@@ -122,13 +124,23 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements
    }

    private void showQrCodeScannerFragment(boolean addToBackStack, String ssid) {
        // Avoid to replace the same fragment during configuration change
        if (mFragmentManager.findFragmentByTag(WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER) != null) {
        WifiDppQrCodeScannerFragment fragment =
                (WifiDppQrCodeScannerFragment) mFragmentManager.findFragmentByTag(
                        WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);

        if (fragment == null) {
            fragment = new WifiDppQrCodeScannerFragment(ssid);
        } else {
            if (fragment.isVisible()) {
                return;
            }

        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment(ssid);
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
            // When the fragment in back stack but not on top of the stack, we can simply pop
            // stack because current fragment transactions are arranged in an order
            mFragmentManager.popBackStackImmediate();
            return;
        }
        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.fragment_container, fragment,
                WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.wifi.dpp;

import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
@@ -147,6 +148,17 @@ public class WifiDppUtils {
        }
    }

    static String getSecurityString(WifiConfiguration config) {
        if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
            return WifiQrCode.SECURITY_SAE;
        }
        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
            return WifiQrCode.SECURITY_WPA_PSK;
        }
        return (config.wepKeys[0] == null) ?
                WifiQrCode.SECURITY_NO_PASSWORD : WifiQrCode.SECURITY_WEP;
    }

    /**
     * Returns an intent to launch QR code generator or scanner according to the Wi-Fi network
     * security. It may return null if the security is not supported by QR code generator nor
+0 −17
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -28,7 +27,6 @@ import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;

@@ -64,9 +62,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
    private WifiManager.ActionListener mSaveListener;
    private boolean mIsTest;

    @VisibleForTesting
    boolean mUseConnectedAccessPointDirectly;

    // Container Activity must implement this interface
    public interface OnChooseNetworkListener {
        public void onChooseNetwork(WifiNetworkConfig wifiNetworkConfig);
@@ -123,8 +118,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
                }
            }
        };

        mUseConnectedAccessPointDirectly = true;
    }

    @Override
@@ -310,16 +303,6 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen
            if (isValidForDppConfiguration(accessPoint)) {
                final String key = accessPoint.getKey();

                // Check if this access point is already connected.
                if (mUseConnectedAccessPointDirectly
                        && accessPoint.getDetailedState() == DetailedState.CONNECTED) {
                    // Uses connected access point to start DPP in Configurator-Initiator role
                    // directly.
                    onPreferenceTreeClick(createAccessPointPreference(accessPoint));
                    removeCachedPrefs(mAccessPointsPreferenceCategory);
                    return;
                }

                final AccessPointPreference pref = (AccessPointPreference) getCachedPreference(key);
                if (pref != null) {
                    pref.setOrder(index);
+1 −2
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ public class WifiNetworkListFragmentTest {
    private void callOnWifiStateChanged(int state) {
        mActivityRule.getActivity().getMainThreadHandler()
                .post(() -> mWifiNetworkListFragment.onWifiStateChanged(state));
        mWifiNetworkListFragment.mUseConnectedAccessPointDirectly = false;
    }

    /** Launch the activity via an Intent with a String extra. */