blob: 90e01719f1ba8d4e2eacfbb7e7c1a558d835ff39 [file] [log] [blame]
/*
* Copyright (C) 2016 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.server.wifi;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.net.MacAddress;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.Builder;
import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
import androidx.test.filters.SmallTest;
import com.android.wifi.resources.R;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
/**
* Unit tests for {@link com.android.server.wifi.WifiApConfigStore}.
*/
@SmallTest
public class WifiApConfigStoreTest extends WifiBaseTest {
private static final String TAG = "WifiApConfigStoreTest";
private static final String TEST_DEFAULT_2G_CHANNEL_LIST = "1,2,3,4,5,6";
private static final String TEST_DEFAULT_AP_SSID = "TestAP";
private static final String TEST_DEFAULT_HOTSPOT_SSID = "TestShare";
private static final int RAND_SSID_INT_MIN = 1000;
private static final int RAND_SSID_INT_MAX = 9999;
private static final String TEST_CHAR_SET_AS_STRING = "abcdefghijklmnopqrstuvwxyz0123456789";
private static final String TEST_STRING_UTF8_WITH_30_BYTES = "智者務其實愚者爭虛名";
private static final String TEST_STRING_UTF8_WITH_32_BYTES = "ΣωκράτηςΣωκράτης";
private static final String TEST_STRING_UTF8_WITH_33_BYTES = "一片汪洋大海中的一條魚";
private static final String TEST_STRING_UTF8_WITH_34_BYTES = "Ευπροσηγοροςγινου";
private static final MacAddress TEST_RANDOMIZED_MAC =
MacAddress.fromString("d2:11:19:34:a5:20");
private final int mBand25G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
@Mock private Context mContext;
@Mock private WifiInjector mWifiInjector;
@Mock private WifiMetrics mWifiMetrics;
private TestLooper mLooper;
private Handler mHandler;
@Mock private BackupManagerProxy mBackupManagerProxy;
@Mock private WifiConfigStore mWifiConfigStore;
@Mock private WifiConfigManager mWifiConfigManager;
@Mock private ActiveModeWarden mActiveModeWarden;
private Random mRandom;
private MockResources mResources;
@Mock private ApplicationInfo mMockApplInfo;
@Mock private MacAddressUtil mMacAddressUtil;
private SoftApStoreData.DataSource mDataStoreSource;
private ArrayList<Integer> mKnownGood2GChannelList;
@Before
public void setUp() throws Exception {
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
MockitoAnnotations.initMocks(this);
mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P;
when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo);
/* Setup expectations for Resources to return some default settings. */
mResources = new MockResources();
mResources.setString(R.string.config_wifiSoftap2gChannelList,
TEST_DEFAULT_2G_CHANNEL_LIST);
mResources.setString(R.string.wifi_tether_configure_ssid_default,
TEST_DEFAULT_AP_SSID);
mResources.setString(R.string.wifi_localhotspot_configure_ssid_default,
TEST_DEFAULT_HOTSPOT_SSID);
/* Default to device that does not require ap band conversion */
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(false);
when(mContext.getResources()).thenReturn(mResources);
// build the known good 2G channel list: TEST_DEFAULT_2G_CHANNEL_LIST
mKnownGood2GChannelList = new ArrayList(Arrays.asList(1, 2, 3, 4, 5, 6));
mRandom = new Random();
when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil);
when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(TEST_RANDOMIZED_MAC);
}
/**
* Helper method to create and verify actions for the ApConfigStore used in the following tests.
*/
private WifiApConfigStore createWifiApConfigStore() throws Exception {
WifiApConfigStore store = new WifiApConfigStore(
mContext, mWifiInjector, mHandler, mBackupManagerProxy,
mWifiConfigStore, mWifiConfigManager, mActiveModeWarden, mWifiMetrics);
verify(mWifiConfigStore).registerStoreData(any());
ArgumentCaptor<SoftApStoreData.DataSource> dataStoreSourceArgumentCaptor =
ArgumentCaptor.forClass(SoftApStoreData.DataSource.class);
verify(mWifiInjector).makeSoftApStoreData(dataStoreSourceArgumentCaptor.capture());
mDataStoreSource = dataStoreSourceArgumentCaptor.getValue();
return store;
}
/**
* Generate a SoftApConfiguration based on the specified parameters.
*/
private SoftApConfiguration setupApConfig(
String ssid, String preSharedKey, int keyManagement, int band, int channel,
boolean hiddenSSID) {
Builder configBuilder = new SoftApConfiguration.Builder();
configBuilder.setSsid(ssid);
configBuilder.setPassphrase(preSharedKey, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
if (channel == 0) {
configBuilder.setBand(band);
} else {
configBuilder.setChannel(channel, band);
}
configBuilder.setHiddenSsid(hiddenSSID);
return configBuilder.build();
}
private void verifyApConfig(SoftApConfiguration config1, SoftApConfiguration config2) {
assertEquals(config1.getSsid(), config2.getSsid());
assertEquals(config1.getPassphrase(), config2.getPassphrase());
assertEquals(config1.getSecurityType(), config2.getSecurityType());
assertEquals(config1.getBand(), config2.getBand());
assertEquals(config1.getChannel(), config2.getChannel());
assertEquals(config1.isHiddenSsid(), config2.isHiddenSsid());
}
private void verifyDefaultApConfig(SoftApConfiguration config, String expectedSsid,
boolean isSaeSupport) {
String[] splitSsid = config.getSsid().split("_");
assertEquals(2, splitSsid.length);
assertEquals(expectedSsid, splitSsid[0]);
assertEquals(SoftApConfiguration.BAND_2GHZ, config.getBand());
assertFalse(config.isHiddenSsid());
int randomPortion = Integer.parseInt(splitSsid[1]);
assertTrue(randomPortion >= RAND_SSID_INT_MIN && randomPortion <= RAND_SSID_INT_MAX);
if (isSaeSupport) {
assertEquals(SECURITY_TYPE_WPA3_SAE_TRANSITION, config.getSecurityType());
} else {
assertEquals(SECURITY_TYPE_WPA2_PSK, config.getSecurityType());
}
assertEquals(15, config.getPassphrase().length());
}
private void verifyDefaultApConfig(SoftApConfiguration config, String expectedSsid) {
// Old test cases will just verify WPA2.
verifyDefaultApConfig(config, expectedSsid, false);
}
private void verifyDefaultLocalOnlyApConfig(SoftApConfiguration config, String expectedSsid,
int expectedApBand, boolean isSaeSupport) {
String[] splitSsid = config.getSsid().split("_");
assertEquals(2, splitSsid.length);
assertEquals(expectedSsid, splitSsid[0]);
assertEquals(expectedApBand, config.getBand());
int randomPortion = Integer.parseInt(splitSsid[1]);
assertTrue(randomPortion >= RAND_SSID_INT_MIN && randomPortion <= RAND_SSID_INT_MAX);
if (isSaeSupport) {
assertEquals(SECURITY_TYPE_WPA3_SAE_TRANSITION, config.getSecurityType());
} else {
assertEquals(SECURITY_TYPE_WPA2_PSK, config.getSecurityType());
}
assertEquals(15, config.getPassphrase().length());
assertFalse(config.isAutoShutdownEnabled());
}
private void verifyDefaultLocalOnlyApConfig(SoftApConfiguration config, String expectedSsid,
int expectedApBand) {
verifyDefaultLocalOnlyApConfig(config, expectedSsid, expectedApBand, false);
}
/**
* AP Configuration is not specified in the config file,
* WifiApConfigStore should fallback to use the default configuration.
*/
@Test
public void initWithDefaultConfiguration() throws Exception {
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
}
/**
* Verify the handling of setting a null ap configuration.
* WifiApConfigStore should fallback to the default configuration when
* null ap configuration is provided.
*/
@Test
public void setNullApConfiguration() throws Exception {
/* Initialize WifiApConfigStore with existing configuration. */
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_5GHZ, /* AP band (5GHz) */
40, /* AP channel */
true /* Hidden SSID */);
WifiApConfigStore store = createWifiApConfigStore();
mDataStoreSource.fromDeserialized(expectedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
store.setApConfiguration(null);
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verifyDefaultApConfig(mDataStoreSource.toSerialize(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
verify(mBackupManagerProxy).notifyDataChanged();
}
/**
* Verify AP configuration is correctly updated via setApConfiguration call.
*/
@Test
public void updateApConfiguration() throws Exception {
/* Initialize WifiApConfigStore with default configuration. */
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
/* Update with a valid configuration. */
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_2GHZ, /* AP band */
0, /* AP channel */
true /* Hidden SSID */);
store.setApConfiguration(expectedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
verifyApConfig(expectedConfig, mDataStoreSource.toSerialize());
verify(mWifiConfigManager, times(2)).saveToStore(true);
verify(mBackupManagerProxy, times(2)).notifyDataChanged();
}
/**
* Due to different countries capabilities, some bands are not available.
* This test verifies that a device will have apBand =
* 5GHz converted to include 2.4GHz.
*/
@Test
public void convertDevice5GhzToAny() throws Exception {
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
/* Initialize WifiApConfigStore with default configuration. */
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
/* Update with a valid configuration. */
SoftApConfiguration providedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_5GHZ, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_2GHZ
| SoftApConfiguration.BAND_5GHZ, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
store.setApConfiguration(providedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
verifyApConfig(expectedConfig, mDataStoreSource.toSerialize());
verify(mWifiConfigManager, times(2)).saveToStore(true);
verify(mBackupManagerProxy, times(2)).notifyDataChanged();
}
/**
* Due to different countries capabilities, some bands are not available.
* This test verifies that a device does not need to conver apBand since it already
* included 2.4G.
*/
@Test
public void deviceAnyNotConverted() throws Exception {
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
/* Initialize WifiApConfigStore with default configuration. */
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
/* Update with a valid configuration. */
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_ANY, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
store.setApConfiguration(expectedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
verifyApConfig(expectedConfig, mDataStoreSource.toSerialize());
verify(mWifiConfigManager, times(2)).saveToStore(true);
verify(mBackupManagerProxy, times(2)).notifyDataChanged();
}
/**
* Due to different countries capabilities, some bands are not available.
* This test verifies that a device does not convert apBand because channel is specific.
*/
@Test
public void deviceWithChannelNotConverted() throws Exception {
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
/* Initialize WifiApConfigStore with default configuration. */
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
verify(mWifiConfigManager).saveToStore(true);
/* Update with a valid configuration. */
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_5GHZ, /* AP band */
40, /* AP channel */
false /* Hidden SSID */);
store.setApConfiguration(expectedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
verifyApConfig(expectedConfig, mDataStoreSource.toSerialize());
verify(mWifiConfigManager, times(2)).saveToStore(true);
verify(mBackupManagerProxy, times(2)).notifyDataChanged();
}
/**
* Due to different countries capabilities, some bands are not available.
* This test verifies that a device converts a persisted ap
* config with 5GHz only set for the apBand to include 2.4GHz.
*/
@Test
public void device5GhzConvertedToAnyAtRetrieval() throws Exception {
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
SoftApConfiguration persistedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_5GHZ, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
SoftApConfiguration expectedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
mBand25G, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
WifiApConfigStore store = createWifiApConfigStore();
mDataStoreSource.fromDeserialized(persistedConfig);
verifyApConfig(expectedConfig, store.getApConfiguration());
verifyApConfig(expectedConfig, mDataStoreSource.toSerialize());
verify(mWifiConfigManager).saveToStore(true);
verify(mBackupManagerProxy).notifyDataChanged();
}
/**
* Due to different countries capabilities, some bands are not available.
* This test verifies that a device does not convert
* a persisted ap config with ANY since it already
* included 2.4G.
*/
@Test
public void deviceNotConvertedAtRetrieval() throws Exception {
when(mActiveModeWarden.isStaApConcurrencySupported())
.thenReturn(true);
SoftApConfiguration persistedConfig = setupApConfig(
"ConfiguredAP", /* SSID */
"randomKey", /* preshared key */
SECURITY_TYPE_WPA2_PSK, /* security type */
SoftApConfiguration.BAND_ANY, /* AP band */
0, /* AP channel */
false /* Hidden SSID */);
WifiApConfigStore store = createWifiApConfigStore();
mDataStoreSource.fromDeserialized(persistedConfig);
verifyApConfig(persistedConfig, store.getApConfiguration());
verify(mWifiConfigManager, never()).saveToStore(true);
verify(mBackupManagerProxy, never()).notifyDataChanged();
}
/**
* Verify a proper SoftApConfiguration is generate by getDefaultApConfiguration().
*/
@Test
public void getDefaultApConfigurationIsValid() throws Exception {
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = store.getApConfiguration();
assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true));
}
/**
* Verify a proper local only hotspot config is generated when called properly with the valid
* context.
*/
@Test
public void generateLocalOnlyHotspotConfigIsValid() {
SoftApConfiguration config = WifiApConfigStore
.generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_2GHZ, null);
verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID,
SoftApConfiguration.BAND_2GHZ);
// verify that the config passes the validateApWifiConfiguration check
assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true));
}
/**
* Verify a proper local only hotspot config is generated for 5Ghz band.
*/
@Test
public void generateLocalOnlyHotspotConfigIsValid5G() {
SoftApConfiguration config = WifiApConfigStore
.generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_5GHZ, null);
verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID,
SoftApConfiguration.BAND_5GHZ);
// verify that the config passes the validateApWifiConfiguration check
assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true));
}
@Test
public void generateLohsConfig_forwardsCustomMac() {
SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
.setBssid(MacAddress.fromString("11:22:33:44:55:66"))
.build();
SoftApConfiguration softApConfig = WifiApConfigStore.generateLocalOnlyHotspotConfig(
mContext, SoftApConfiguration.BAND_2GHZ, customConfig);
assertThat(softApConfig.getBssid().toString()).isNotEmpty();
assertThat(softApConfig.getBssid()).isEqualTo(
MacAddress.fromString("11:22:33:44:55:66"));
}
@Test
public void randomizeBssid_randomizesWhenEnabled() throws Exception {
mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true);
SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build();
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig);
assertEquals(TEST_RANDOMIZED_MAC, config.getBssid());
}
@Test
public void randomizeBssid_fallbackPathWhenMacCalculationFails() throws Exception {
mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true);
// Setup the MAC calculation to fail.
when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(null);
SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build();
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig);
// Verify that some randomized MAC address is still generated
assertNotNull(config.getBssid());
assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, config.getBssid().toString());
}
@Test
public void randomizeBssid_usesFactoryMacWhenRandomizationOff() throws Exception {
mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, false);
SoftApConfiguration baseConfig = new SoftApConfiguration.Builder().build();
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = store.randomizeBssidIfUnset(mContext, baseConfig);
assertThat(config.getBssid()).isNull();
}
@Test
public void randomizeBssid_forwardsCustomMac() throws Exception {
mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true);
Builder baseConfigBuilder = new SoftApConfiguration.Builder();
baseConfigBuilder.setBssid(MacAddress.fromString("11:22:33:44:55:66"));
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = store.randomizeBssidIfUnset(mContext,
baseConfigBuilder.build());
assertThat(config.getBssid().toString()).isNotEmpty();
assertThat(config.getBssid()).isEqualTo(
MacAddress.fromString("11:22:33:44:55:66"));
}
/**
* Helper method to generate random SSIDs.
*
* Note: this method has limited use as a random SSID generator. The characters used in this
* method do no not cover all valid inputs.
* @param length number of characters to generate for the name
* @return String generated string of random characters
*/
private String generateRandomString(int length) {
StringBuilder stringBuilder = new StringBuilder(length);
int index = -1;
while (stringBuilder.length() < length) {
index = mRandom.nextInt(TEST_CHAR_SET_AS_STRING.length());
stringBuilder.append(TEST_CHAR_SET_AS_STRING.charAt(index));
}
return stringBuilder.toString();
}
/**
* Verify the SSID checks in validateApWifiConfiguration.
*
* Cases to check and verify they trigger failed verification:
* null SoftApConfiguration.SSID
* empty SoftApConfiguration.SSID
* invalid WifiConfiguaration.SSID length
*
* Additionally check a valid SSID with a random (within valid ranges) length.
*/
@Test
public void testSsidVerificationInValidateApWifiConfigurationCheck() {
Builder configBuilder = new SoftApConfiguration.Builder();
configBuilder.setSsid(null);
assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// check a string if it's larger than 32 bytes with UTF-8 encode
// Case 1 : one byte per character (use english words and Arabic numerals)
configBuilder.setSsid(generateRandomString(WifiApConfigStore.SSID_MAX_LEN + 1));
assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// Case 2 : two bytes per character
configBuilder.setSsid(TEST_STRING_UTF8_WITH_34_BYTES);
assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// Case 3 : three bytes per character
configBuilder.setSsid(TEST_STRING_UTF8_WITH_33_BYTES);
assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// now check a valid SSID within 32 bytes
// Case 1 : one byte per character with random length
int validLength = WifiApConfigStore.SSID_MAX_LEN - WifiApConfigStore.SSID_MIN_LEN;
configBuilder.setSsid(generateRandomString(
mRandom.nextInt(validLength) + WifiApConfigStore.SSID_MIN_LEN));
assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// Case 2 : two bytes per character
configBuilder.setSsid(TEST_STRING_UTF8_WITH_32_BYTES);
assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
// Case 3 : three bytes per character
configBuilder.setSsid(TEST_STRING_UTF8_WITH_30_BYTES);
assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
}
/**
* Verify the Open network checks in validateApWifiConfiguration.
*
* If the configured network is open, it should not have a password set.
*
* Additionally verify a valid open network passes verification.
*/
@Test
public void testOpenNetworkConfigInValidateApWifiConfigurationCheck() {
assertTrue(WifiApConfigStore.validateApWifiConfiguration(
new SoftApConfiguration.Builder()
.setSsid(TEST_DEFAULT_HOTSPOT_SSID)
.build(), true));
}
/**
* Verify the WPA2_PSK network checks in validateApWifiConfiguration.
*
* If the configured network is configured with a preSharedKey, verify that the passwork is set
* and it meets length requirements.
*/
@Test
public void testWpa2PskNetworkConfigInValidateApWifiConfigurationCheck() {
Builder configBuilder = new SoftApConfiguration.Builder();
configBuilder.setSsid(TEST_DEFAULT_HOTSPOT_SSID);
// Builder will auto check auth type and passphrase
// test random (valid length)
int maxLen = WifiApConfigStore.PSK_MAX_LEN;
int minLen = WifiApConfigStore.PSK_MIN_LEN;
configBuilder.setPassphrase(
generateRandomString(mRandom.nextInt(maxLen - minLen) + minLen),
SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(), true));
}
/**
* Verify the default configuration security when SAE support.
*/
@Test
public void testDefaultConfigurationSecurityTypeIsWpa3SaeTransitionWhenSupport()
throws Exception {
mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true);
WifiApConfigStore store = createWifiApConfigStore();
verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID, true);
}
/**
* Verify the LOHS default configuration security when SAE support.
*/
@Test
public void testLohsDefaultConfigurationSecurityTypeIsWpa3SaeTransitionWhenSupport() {
mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true);
SoftApConfiguration config = WifiApConfigStore
.generateLocalOnlyHotspotConfig(mContext, SoftApConfiguration.BAND_5GHZ, null);
verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID,
SoftApConfiguration.BAND_5GHZ, true);
// verify that the config passes the validateApWifiConfiguration check
assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true));
}
@Test
public void testResetToDefaultForUnsupportedConfig() throws Exception {
mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true);
mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, true);
mResources.setBoolean(R.bool.config_wifi6ghzSupport, true);
mResources.setBoolean(R.bool.config_wifi5ghzSupport, true);
// Test all of the features support and all of the reset config are false.
String testPassphrase = "secretsecret";
SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
configBuilder.setPassphrase(testPassphrase, SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration resetedConfig = store.resetToDefaultForUnsupportedConfig(
configBuilder.build());
assertEquals(resetedConfig, configBuilder.build());
verify(mWifiMetrics).noteSoftApConfigReset(configBuilder.build(), resetedConfig);
// Test SAE not support case.
mResources.setBoolean(R.bool.config_wifi_softap_sae_supported, false);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getSecurityType(), SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
// Test force channel
configBuilder.setChannel(149, SoftApConfiguration.BAND_5GHZ);
mResources.setBoolean(
R.bool.config_wifiSoftapResetChannelConfig, true);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getChannel(), 0);
assertEquals(resetedConfig.getBand(),
SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ);
// Test forced channel band doesn't support.
mResources.setBoolean(R.bool.config_wifi5ghzSupport, false);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getChannel(), 0);
assertEquals(resetedConfig.getBand(),
SoftApConfiguration.BAND_2GHZ);
// Test band not support with auto channel
configBuilder.setBand(SoftApConfiguration.BAND_5GHZ);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getBand(), SoftApConfiguration.BAND_2GHZ);
// Test reset hidden network
mResources.setBoolean(
R.bool.config_wifiSoftapResetHiddenConfig, true);
configBuilder.setHiddenSsid(true);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertFalse(resetedConfig.isHiddenSsid());
// Test auto shutdown timer
mResources.setBoolean(
R.bool.config_wifiSoftapResetAutoShutdownTimerConfig, true);
configBuilder.setShutdownTimeoutMillis(8888);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getShutdownTimeoutMillis(), 0);
// Test max client setting when force client disconnect doesn't support
mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, false);
configBuilder.setMaxNumberOfClients(10);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertEquals(resetedConfig.getMaxNumberOfClients(), 0);
// Test client control setting when force client disconnect doesn't support
mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, false);
ArrayList<MacAddress> blockedClientList = new ArrayList<>();
ArrayList<MacAddress> allowedClientList = new ArrayList<>();
blockedClientList.add(MacAddress.fromString("11:22:33:44:55:66"));
allowedClientList.add(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
configBuilder.setBlockedClientList(blockedClientList);
configBuilder.setAllowedClientList(allowedClientList);
configBuilder.setClientControlByUserEnabled(true);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertFalse(resetedConfig.isClientControlByUserEnabled());
// The blocked list will be clean
assertEquals(resetedConfig.getBlockedClientList().size(), 0);
// The allowed list will be keep
assertEquals(resetedConfig.getAllowedClientList(), allowedClientList);
// Test max client setting when reset enabled but force client disconnect supported
mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true);
mResources.setBoolean(
R.bool.config_wifiSoftapResetMaxClientSettingConfig, true);
assertEquals(resetedConfig.getMaxNumberOfClients(), 0);
// Test client control setting when reset enabled but force client disconnect supported
mResources.setBoolean(R.bool.config_wifiSofapClientForceDisconnectSupported, true);
mResources.setBoolean(
R.bool.config_wifiSoftapResetUserControlConfig, true);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertFalse(resetedConfig.isClientControlByUserEnabled());
assertEquals(resetedConfig.getBlockedClientList().size(), 0);
assertEquals(resetedConfig.getAllowedClientList(), allowedClientList);
// Test blocked list setting will be reset even if client control disabled
mResources.setBoolean(
R.bool.config_wifiSoftapResetUserControlConfig, true);
configBuilder.setClientControlByUserEnabled(false);
resetedConfig = store.resetToDefaultForUnsupportedConfig(configBuilder.build());
assertFalse(resetedConfig.isClientControlByUserEnabled());
assertEquals(resetedConfig.getBlockedClientList().size(), 0);
assertEquals(resetedConfig.getAllowedClientList(), allowedClientList);
}
/**
* Verify Bssid field deny to set if caller without setting permission.
*/
@Test
public void testBssidDenyIfCallerWithoutPrivileged() throws Exception {
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = new SoftApConfiguration.Builder(store.getApConfiguration())
.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")).build();
assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, false));
}
/**
* Verify Bssid field only allow to set if caller own setting permission.
*/
@Test
public void testBssidAllowIfCallerOwnPrivileged() throws Exception {
WifiApConfigStore store = createWifiApConfigStore();
SoftApConfiguration config = new SoftApConfiguration.Builder(store.getApConfiguration())
.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")).build();
assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true));
}
}