From b9c865b70431c4a76d0de43abb4440646cc8df7f Mon Sep 17 00:00:00 2001 From: Weng Su Date: Tue, 15 Sep 2020 13:24:34 +0000 Subject: [PATCH] Add Hotspot WPA3 Settings - Add WPA3 SAE security types - "WPA3-Personal" - "WPA2/WPA3-Personal" - Verify valid WPA3 password - Enable QR code scanner for Hotspot WPA3 - Avoid null point exception when settings keyword searching - Screenshot https://screenshot.googleplex.com/B6u54wh8w35Xnyf https://screenshot.googleplex.com/8hWHHUTb6UaS9vB Bug: 167968488 Test: manual test - atest WifiTetherSecurityPreferenceControllerTest - atest WifiUtilsTest Change-Id: I2992040498f8add107a4cce70a92c1c6ee6ab805 --- res/values/arrays.xml | 8 + .../settings/AllInOneTetherSettings.java | 2 +- src/com/android/settings/wifi/WifiUtils.java | 6 +- .../settings/wifi/dpp/WifiDppUtils.java | 16 +- ...ifiTetherPasswordPreferenceController.java | 23 +- ...ifiTetherSecurityPreferenceController.java | 97 +++++++-- .../wifi/tether/WifiTetherSettings.java | 6 +- ...etherSecurityPreferenceControllerTest.java | 105 --------- .../android/settings/wifi/WifiUtilsTest.java | 49 ++++- ...etherSecurityPreferenceControllerTest.java | 206 ++++++++++++++++++ 10 files changed, 368 insertions(+), 150 deletions(-) delete mode 100644 tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java create mode 100644 tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 3528f9f17b2..183dd1e579d 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -222,6 +222,10 @@ + + @string/wifi_security_sae + + @string/wifi_security_psk_sae @string/wifi_security_wpa2 @@ -230,6 +234,10 @@ + + 3 + + 2 1 diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java index 82e3206e498..5442ed7fef3 100644 --- a/src/com/android/settings/AllInOneTetherSettings.java +++ b/src/com/android/settings/AllInOneTetherSettings.java @@ -355,7 +355,7 @@ public class AllInOneTetherSettings extends RestrictedDashboardFragment @Override public void onTetherConfigUpdated(AbstractPreferenceController controller) { final SoftApConfiguration config = buildNewConfig(); - mPasswordPreferenceController.updateVisibility(config.getSecurityType()); + mPasswordPreferenceController.setSecurityType(config.getSecurityType()); mWifiManager.setSoftApConfiguration(config); if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) { diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java index 06f74d54e55..d05260afe1f 100644 --- a/src/com/android/settings/wifi/WifiUtils.java +++ b/src/com/android/settings/wifi/WifiUtils.java @@ -56,12 +56,12 @@ public class WifiUtils { } /** - * Check if the WPA2-PSK hotspot password is valid. + * Check if the hotspot password is valid. */ - public static boolean isHotspotWpa2PasswordValid(String password) { + public static boolean isHotspotPasswordValid(String password, int securityType) { final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); try { - configBuilder.setPassphrase(password, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + configBuilder.setPassphrase(password, securityType); } catch (IllegalArgumentException e) { return false; } diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index 2957e1fb8bd..abf5becfbc3 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -301,7 +301,11 @@ public class WifiDppUtils { final String ssid = removeFirstAndLastDoubleQuotes(softApConfiguration.getSsid()); String security; - if (softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) { + final int securityType = softApConfiguration.getSecurityType(); + if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) { + security = WifiQrCode.SECURITY_SAE; + } else if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK + || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) { security = WifiQrCode.SECURITY_WPA_PSK; } else { security = WifiQrCode.SECURITY_NO_PASSWORD; @@ -431,11 +435,11 @@ public class WifiDppUtils { private static boolean isSupportHotspotConfiguratorQrCodeGenerator( SoftApConfiguration softApConfiguration) { - // QR code generator produces QR code with ZXing's Wi-Fi network config format, - // it supports PSK and WEP and non security - // KeyMgmt.NONE is for WEP or non security - return softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK - || softApConfiguration.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OPEN; + final int securityType = softApConfiguration.getSecurityType(); + return securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE + || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION + || securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK + || securityType == SoftApConfiguration.SECURITY_TYPE_OPEN; } private static boolean isSupportWifiDpp(Context context, int wifiEntrySecurity) { diff --git a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java index be67d22d966..14766f9ee41 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java +++ b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java @@ -37,12 +37,16 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.UUID; +/** + * Controller for logic pertaining to the password of Wi-Fi tethering. + */ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePreferenceController implements ValidatedEditTextPreference.Validator { private static final String PREF_KEY = "wifi_tether_network_password"; private String mPassword; + private int mSecurityType; private final MetricsFeatureProvider mMetricsFeatureProvider; @@ -68,13 +72,13 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer @Override public void updateDisplay() { final SoftApConfiguration config = mWifiManager.getSoftApConfiguration(); - if (config == null - || (config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK - && TextUtils.isEmpty(config.getPassphrase()))) { + if (config.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN + && TextUtils.isEmpty(config.getPassphrase())) { mPassword = generateRandomPassword(); } else { mPassword = config.getPassphrase(); } + mSecurityType = config.getSecurityType(); ((ValidatedEditTextPreference) mPreference).setValidator(this); ((ValidatedEditTextPreference) mPreference).setIsPassword(true); ((ValidatedEditTextPreference) mPreference).setIsSummaryPassword(true); @@ -105,20 +109,27 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer // don't actually overwrite unless we get a new config in case it was accidentally toggled. if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) { return ""; - } else if (!isTextValid(mPassword)) { + } else if (!WifiUtils.isHotspotPasswordValid(mPassword, securityType)) { mPassword = generateRandomPassword(); updatePasswordDisplay((EditTextPreference) mPreference); } return mPassword; } - public void updateVisibility(int securityType) { + /** + * This method set the security type of user selection. Then the controller will based on the + * security type changed to update the password changed on the preference. + * + * @param securityType The security type of SoftApConfiguration. + */ + public void setSecurityType(int securityType) { + mSecurityType = securityType; mPreference.setVisible(securityType != SoftApConfiguration.SECURITY_TYPE_OPEN); } @Override public boolean isTextValid(String value) { - return WifiUtils.isHotspotWpa2PasswordValid(value); + return WifiUtils.isHotspotPasswordValid(value, mSecurityType); } private static String generateRandomPassword() { diff --git a/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java index 56b50314b6d..acb82062496 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java +++ b/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceController.java @@ -1,28 +1,65 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.settings.wifi.tether; import static com.android.settings.AllInOneTetherSettings.DEDUP_POSTFIX; +import android.annotation.NonNull; import android.content.Context; +import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; +import android.net.wifi.WifiManager; import android.util.FeatureFlagUtils; +import android.util.Log; +import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.FeatureFlags; -public class WifiTetherSecurityPreferenceController extends WifiTetherBasePreferenceController { +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Controller for logic pertaining to the security type of Wi-Fi tethering. + */ +public class WifiTetherSecurityPreferenceController extends WifiTetherBasePreferenceController + implements WifiManager.SoftApCallback { private static final String PREF_KEY = "wifi_tether_security"; - private final String[] mSecurityEntries; + private Map mSecurityMap = new LinkedHashMap(); private int mSecurityValue; + @VisibleForTesting + boolean mIsWpa3Supported = true; public WifiTetherSecurityPreferenceController(Context context, OnTetherConfigUpdateListener listener) { super(context, listener); - mSecurityEntries = mContext.getResources().getStringArray(R.array.wifi_tether_security); + final String[] securityNames = mContext.getResources().getStringArray( + R.array.wifi_tether_security); + final String[] securityValues = mContext.getResources().getStringArray( + R.array.wifi_tether_security_values); + for (int i = 0; i < securityNames.length; i++) { + mSecurityMap.put(Integer.parseInt(securityValues[i]), securityNames[i]); + } + mWifiManager.registerSoftApCallback(context.getMainExecutor(), this); } @Override @@ -33,35 +70,55 @@ public class WifiTetherSecurityPreferenceController extends WifiTetherBasePrefer @Override public void updateDisplay() { - final SoftApConfiguration config = mWifiManager.getSoftApConfiguration(); - if (config != null && config.getSecurityType() == SoftApConfiguration.SECURITY_TYPE_OPEN) { - mSecurityValue = SoftApConfiguration.SECURITY_TYPE_OPEN; - } else { - mSecurityValue = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK; + // The mPreference will be ready when the fragment calls displayPreference(). Since the + // capability of WPA3 hotspot callback will update the preference list here, add null point + // checking to avoid the mPreference is not ready when the fragment is loading for settings + // keyword searching only. + if (mPreference == null) { + return; + } + final ListPreference preference = (ListPreference) mPreference; + // If the device is not support WPA3 then remove the WPA3 options. + if (!mIsWpa3Supported && mSecurityMap.keySet() + .removeIf(key -> key > SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)) { + preference.setEntries(mSecurityMap.values().stream().toArray(CharSequence[]::new)); + preference.setEntryValues(mSecurityMap.keySet().stream().map(Integer::toBinaryString) + .toArray(CharSequence[]::new)); } - final ListPreference preference = (ListPreference) mPreference; - preference.setSummary(getSummaryForSecurityType(mSecurityValue)); + final int securityType = mWifiManager.getSoftApConfiguration().getSecurityType(); + mSecurityValue = mSecurityMap.get(securityType) != null + ? securityType : SoftApConfiguration.SECURITY_TYPE_WPA2_PSK; + + preference.setSummary(mSecurityMap.get(mSecurityValue)); preference.setValue(String.valueOf(mSecurityValue)); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { mSecurityValue = Integer.parseInt((String) newValue); - preference.setSummary(getSummaryForSecurityType(mSecurityValue)); - mListener.onTetherConfigUpdated(this); + preference.setSummary(mSecurityMap.get(mSecurityValue)); + if (mListener != null) { + mListener.onTetherConfigUpdated(this); + } return true; } + @Override + public void onCapabilityChanged(@NonNull SoftApCapability softApCapability) { + final boolean isWpa3Supported = + softApCapability.areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE); + if (!isWpa3Supported) { + Log.i(PREF_KEY, "WPA3 SAE is not supported on this device"); + } + if (mIsWpa3Supported != isWpa3Supported) { + mIsWpa3Supported = isWpa3Supported; + updateDisplay(); + } + mWifiManager.unregisterSoftApCallback(this); + } + public int getSecurityType() { return mSecurityValue; } - - private String getSummaryForSecurityType(int securityType) { - if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) { - return mSecurityEntries[1]; - } - // WPA2 PSK - return mSecurityEntries[0]; - } } diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java index d6c49bcda2c..f260298029c 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java +++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java @@ -192,7 +192,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment @Override public void onTetherConfigUpdated(AbstractPreferenceController context) { final SoftApConfiguration config = buildNewConfig(); - mPasswordPreferenceController.updateVisibility(config.getSecurityType()); + mPasswordPreferenceController.setSecurityType(config.getSecurityType()); /** * if soft AP is stopped, bring up @@ -216,10 +216,10 @@ public class WifiTetherSettings extends RestrictedDashboardFragment final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); final int securityType = mSecurityPreferenceController.getSecurityType(); configBuilder.setSsid(mSSIDPreferenceController.getSSID()); - if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) { + if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) { configBuilder.setPassphrase( mPasswordPreferenceController.getPasswordValidated(securityType), - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + securityType); } configBuilder.setBand(mApBandPreferenceController.getBandIndex()); return configBuilder.build(); diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java deleted file mode 100644 index c7d0695d0f5..00000000000 --- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.android.settings.wifi.tether; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.WifiManager; - -import androidx.preference.ListPreference; -import androidx.preference.PreferenceScreen; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class WifiTetherSecurityPreferenceControllerTest { - - private static final String WPA2_PSK = - String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - private static final String NONE = String.valueOf(SoftApConfiguration.SECURITY_TYPE_OPEN); - @Mock - private WifiTetherBasePreferenceController.OnTetherConfigUpdateListener mListener; - private Context mContext; - @Mock - private ConnectivityManager mConnectivityManager; - @Mock - private WifiManager mWifiManager; - @Mock - private PreferenceScreen mScreen; - private WifiTetherSecurityPreferenceController mController; - private ListPreference mPreference; - private SoftApConfiguration mConfig; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mConfig = new SoftApConfiguration.Builder().setSsid("test_1234") - .setPassphrase("test_password", - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build(); - mContext = spy(RuntimeEnvironment.application); - - when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager); - when(mWifiManager.getSoftApConfiguration()).thenReturn(mConfig); - when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) - .thenReturn(mConnectivityManager); - when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"}); - when(mScreen.findPreference(anyString())).thenReturn(mPreference); - - mController = new WifiTetherSecurityPreferenceController(mContext, mListener); - mPreference = new ListPreference(RuntimeEnvironment.application); - mController.mPreference = mPreference; - } - - @Test - public void onPreferenceChange_securityValueUpdated() { - mController.onPreferenceChange(mPreference, WPA2_PSK); - assertThat(mController.getSecurityType()).isEqualTo( - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); - - mController.onPreferenceChange(mPreference, NONE); - assertThat(mController.getSecurityType()).isEqualTo( - SoftApConfiguration.SECURITY_TYPE_OPEN); - assertThat(mPreference.getSummary().toString()).isEqualTo("None"); - } - - @Test - public void updateDisplay_preferenceUpdated() { - // test defaulting to WPA2-Personal on new config - when(mWifiManager.getSoftApConfiguration()).thenReturn(null); - mController.updateDisplay(); - assertThat(mController.getSecurityType()).isEqualTo( - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); - - // test open tether network - SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) - .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build(); - when(mWifiManager.getSoftApConfiguration()).thenReturn(config); - mController.updateDisplay(); - assertThat(mController.getSecurityType()).isEqualTo( - SoftApConfiguration.SECURITY_TYPE_OPEN); - assertThat(mPreference.getSummary().toString()).isEqualTo("None"); - - // test WPA2-Personal tether network - SoftApConfiguration config2 = new SoftApConfiguration.Builder(mConfig) - .setPassphrase("test_password", - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build(); - when(mWifiManager.getSoftApConfiguration()).thenReturn(config2); - mController.updateDisplay(); - assertThat(mController.getSecurityType()).isEqualTo( - SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); - assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); - } -} diff --git a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java index 7a75443f814..1a5e8526dc3 100644 --- a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java +++ b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiConfiguration; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -46,12 +47,48 @@ public class WifiUtilsTest { public void testPassword() { final String longPassword = "123456789012345678901234567890" + "1234567890123456789012345678901234567890"; - assertThat(WifiUtils.isHotspotWpa2PasswordValid("123")).isFalse(); - assertThat(WifiUtils.isHotspotWpa2PasswordValid("12345678")).isTrue(); - assertThat(WifiUtils.isHotspotWpa2PasswordValid("1234567890")).isTrue(); - assertThat(WifiUtils.isHotspotWpa2PasswordValid(longPassword)).isFalse(); - assertThat(WifiUtils.isHotspotWpa2PasswordValid("")).isFalse(); - assertThat(WifiUtils.isHotspotWpa2PasswordValid("€¥£")).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("123", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("12345678", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("1234567890", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid(longPassword, + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("€¥£", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)).isFalse(); + + // The WPA3_SAE_TRANSITION password limitation should be same as WPA2_PSK + assertThat(WifiUtils.isHotspotPasswordValid("123", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("12345678", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("1234567890", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid(longPassword, + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("€¥£", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)).isFalse(); + + // The WA3_SAE password is requested that length > 1 only. + assertThat(WifiUtils.isHotspotPasswordValid("", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isFalse(); + assertThat(WifiUtils.isHotspotPasswordValid("1", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("123", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("12345678", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("1234567890", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid(longPassword, + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); + assertThat(WifiUtils.isHotspotPasswordValid("€¥£", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)).isTrue(); } @Test diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java new file mode 100644 index 00000000000..c86e3e5b7a4 --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi.tether; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.wifi.SoftApConfiguration; +import android.net.wifi.WifiManager; +import android.os.Looper; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(AndroidJUnit4.class) +public class WifiTetherSecurityPreferenceControllerTest { + + private static final String PREF_KEY = "wifi_tether_security"; + private static final String WPA3_SAE = + String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + private static final String WPA3_SAE_TRANSITION = + String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); + private static final String WPA2_PSK = + String.valueOf(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + private static final String NONE = String.valueOf(SoftApConfiguration.SECURITY_TYPE_OPEN); + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private WifiManager mWifiManager; + @Mock + private WifiTetherBasePreferenceController.OnTetherConfigUpdateListener mListener; + + private WifiTetherSecurityPreferenceController mController; + private ListPreference mPreference; + private SoftApConfiguration mConfig; + + @Before + public void setUp() { + final Context context = spy(ApplicationProvider.getApplicationContext()); + mConfig = new SoftApConfiguration.Builder().setSsid("test_1234") + .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build(); + when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager); + when(mWifiManager.getSoftApConfiguration()).thenReturn(mConfig); + + mController = new WifiTetherSecurityPreferenceController(context, mListener); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + final PreferenceManager preferenceManager = new PreferenceManager(context); + final PreferenceScreen screen = preferenceManager.createPreferenceScreen(context); + mPreference = new ListPreference(context); + mPreference.setKey(PREF_KEY); + screen.addPreference(mPreference); + mController.displayPreference(screen); + } + + @Test + public void onPreferenceChange_toWpa3Sae_shouldUpdateSecurityValue() { + mController.onPreferenceChange(mPreference, WPA3_SAE); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA3-Personal"); + } + + @Test + public void onPreferenceChange_toWpa3SaeTransition_shouldUpdateSecurityValue() { + mController.onPreferenceChange(mPreference, WPA3_SAE_TRANSITION); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2/WPA3-Personal"); + } + + @Test + public void onPreferenceChange_toWpa2Psk_shouldUpdateSecurityValue() { + mController.onPreferenceChange(mPreference, WPA2_PSK); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); + } + + @Test + public void onPreferenceChange_toNone_shouldUpdateSecurityValue() { + mController.onPreferenceChange(mPreference, NONE); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN); + assertThat(mPreference.getSummary().toString()).isEqualTo("None"); + } + + @Test + public void updateDisplay_toWpa3Sae_shouldUpdateSecurityValue() { + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase("test_password", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA3-Personal"); + } + + @Test + public void updateDisplay_toWpa3SaeTransition_shouldUpdateSecurityValue() { + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase("test_password", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2/WPA3-Personal"); + } + + @Test + public void updateDisplay_toWpa2Psk_shouldUpdateSecurityValue() { + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase("test_password", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); + } + + @Test + public void updateDisplay_toNone_shouldUpdateSecurityValue() { + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN); + assertThat(mPreference.getSummary().toString()).isEqualTo("None"); + } + + @Test + public void updateDisplay_toWpa3SaeButNotSupportWpa3_shouldBeDefaultToWpa2() { + mController.mIsWpa3Supported = false; + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase("test_password", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); + } + + @Test + public void updateDisplay_toWpa3SaeTransitionButNotSupportWpa3_shouldBeDefaultToWpa2() { + mController.mIsWpa3Supported = false; + SoftApConfiguration config = new SoftApConfiguration.Builder(mConfig) + .setPassphrase("test_password", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION).build(); + when(mWifiManager.getSoftApConfiguration()).thenReturn(config); + + mController.updateDisplay(); + + assertThat(mController.getSecurityType()) + .isEqualTo(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); + assertThat(mPreference.getSummary().toString()).isEqualTo("WPA2-Personal"); + } +}