From 9d33313735e8f4860057d602d1582d49bcba3dde Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Thu, 31 Jan 2019 11:07:38 +0800 Subject: [PATCH] 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 --- .../wifi/dpp/WifiDppConfiguratorActivity.java | 107 ++++++++++++++---- .../wifi/dpp/WifiDppEnrolleeActivity.java | 24 +++- .../settings/wifi/dpp/WifiDppUtils.java | 12 ++ .../wifi/dpp/WifiNetworkListFragment.java | 17 --- .../wifi/dpp/WifiNetworkListFragmentTest.java | 3 +- 5 files changed, 114 insertions(+), 49 deletions(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java index 4aac538ec58..65be11cef4b 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java @@ -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,13 +112,10 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid, networkId); + } else { + handleIntent(getIntent()); } - setContentView(R.layout.wifi_dpp_activity); - mFragmentManager = getSupportFragmentManager(); - - handleIntent(getIntent()); - ActionBar actionBar = getActionBar(); if (actionBar != null) { actionBar.setElevation(0); @@ -150,7 +156,13 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements if (mWifiDppQrCode == null || !isDppSupported) { cancelActivity = true; } else { - showChooseSavedWifiNetworkFragment(/* addToBackStack */ false); + 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; + } + + // 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; } - - fragment = new WifiDppQrCodeGeneratorFragment(); 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) { - return; - } - if (fragment == null) { fragment = new WifiDppAddDeviceFragment(); + } 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(); @@ -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 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; + } } diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java index df36ae52ce3..143f87f943b 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java @@ -100,7 +100,9 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements setContentView(R.layout.wifi_dpp_activity); mFragmentManager = getSupportFragmentManager(); - handleIntent(getIntent()); + 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; + } + + // 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; } - - WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment(ssid); - FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); + final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragment_container, fragment, WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER); diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index 9c69032992d..7bc80e00ee0 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -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 diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java index 89efc31d65c..ce92f900bc6 100644 --- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java @@ -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); diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java index 18d62c25a0b..c1c1d546398 100644 --- a/tests/unit/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java +++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java @@ -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. */ @@ -173,4 +172,4 @@ public class WifiNetworkListFragmentTest { onView(withText(resourceString(WIFI_DISPLAY_STATUS_CONNECTED))).check( matches(isDisplayed())); } -} \ No newline at end of file +}