diff options
author | Luca Stefani <luca.stefani.ge1@gmail.com> | 2020-03-07 13:20:46 +0100 |
---|---|---|
committer | Luca Stefani <luca.stefani.ge1@gmail.com> | 2020-03-07 13:20:46 +0100 |
commit | 876987a7579be182a3e4f86947bec75434be9bc4 (patch) | |
tree | 9a2d569d8fdbb69ca255c0c87c04eafca5e4bf33 /tests/wifitests/src/com | |
parent | fb7bd6cb89ad593e571f864866c88d577bff2ce5 (diff) | |
parent | aa0a79a0e9aa1a6c0c6a1c83360f6f1048fc59db (diff) | |
download | android_frameworks_opt_net_wifi-876987a7579be182a3e4f86947bec75434be9bc4.tar.gz android_frameworks_opt_net_wifi-876987a7579be182a3e4f86947bec75434be9bc4.tar.bz2 android_frameworks_opt_net_wifi-876987a7579be182a3e4f86947bec75434be9bc4.zip |
Merge tag 'android-10.0.0_r31' into lineage-17.1-android-10.0.0_r31
Android 10.0.0 release 31
* tag 'android-10.0.0_r31': (36 commits)
fix soft reboot caused by KeyStore exception
p2p: validate the network name of a group
Notification to set MAC randomization setting
MAC randomization SSID hotlist support
Fix race in StaEvents metrics collection
Wifi: Fix connectivity issues with PSK-SHA256+SAE mode APs
Reset num saved networks with mac randomization before counting
Fix boot regression from KeyStore being slow
[MAC rand] Fix unit test slowness
WifiConfigStoreEncryptionUtil: Use 256 bit secret key
Update the WifiConfig each time evalutor return a candidate.
Revert submission
[WPA3] Fix WPA3-Personal transition mode
WifiConfigStore: Encrypt credentials for networks (4/4)
WifiConfigStore: Encrypt credentials for networks (3/4)
WifiConfigStore: Encrypt credentials for networks (2/4)
WifiConfigStore: Encrypt credentials for networks (1/4)
[EAP-SIM] Add NAI realm decoration to pseudonym
[WifiRtt] add check to verify bw and preamble combination valid
[MAC rand] Removing persistent storage
...
Change-Id: I66be9db60b65cdd4ed515a48bb8b0c69b66f860a
Diffstat (limited to 'tests/wifitests/src/com')
26 files changed, 1084 insertions, 476 deletions
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index 7896a8f0b..afb3ef5f4 100644 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -384,7 +384,7 @@ public class ClientModeImplTest { @Mock AsyncChannel mNullAsyncChannel; @Mock CarrierNetworkConfig mCarrierNetworkConfig; @Mock Handler mNetworkAgentHandler; - + @Mock ConnectionFailureNotifier mConnectionFailureNotifier; final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor = ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class); @@ -441,6 +441,8 @@ public class ClientModeImplTest { when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard); when(mWifiInjector.getWifiLockManager()).thenReturn(mWifiLockManager); when(mWifiInjector.getCarrierNetworkConfig()).thenReturn(mCarrierNetworkConfig); + when(mWifiInjector.makeConnectionFailureNotifier(any())) + .thenReturn(mConnectionFailureNotifier); when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any())) .thenReturn(Pair.create(Process.INVALID_UID, "")); when(mWifiNative.initialize()).thenReturn(true); @@ -1047,6 +1049,9 @@ public class ClientModeImplTest { when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); + // Initial value should be "not set" + assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); + triggerConnect(); // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm> @@ -1066,15 +1071,15 @@ public class ClientModeImplTest { mLooper.dispatchAll(); verify(mWifiNative).getEapAnonymousIdentity(any()); - // check that the anonymous identity remains anonymous@<realm> for subsequent connections. - assertEquals(expectedAnonymousIdentity, - mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); - // verify that WifiConfigManager#addOrUpdateNetwork() was never called if there is no - // real pseudonym to be stored. i.e. Encrypted IMSI will be always used + + // Post connection value should remain "not set" + assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); + // verify that WifiConfigManager#addOrUpdateNetwork() was called to clear any previously + // stored pseudonym. i.e. to enable Encrypted IMSI for subsequent connections. // Note: This test will fail if future logic will have additional conditions that would // trigger "add or update network" operation. The test needs to be updated to account for // this change. - verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt()); + verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt()); } /** @@ -1127,6 +1132,55 @@ public class ClientModeImplTest { } /** + * Tests anonymous identity is set again whenever a connection is established for the carrier + * that supports encrypted IMSI and anonymous identity but real but not decorated pseudonym was + * provided for subsequent connections. + */ + @Test + public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym() + throws Exception { + mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork( + WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE)); + when(mDataTelephonyManager.getSimOperator()).thenReturn("123456"); + when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); + mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(""); + + String realm = "wlan.mnc456.mcc123.3gppnetwork.org"; + String expectedAnonymousIdentity = "anonymous"; + String pseudonym = "83bcca9384fca"; + + when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); + + triggerConnect(); + + // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm> + assertEquals(expectedAnonymousIdentity + "@" + realm, + mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); + + when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) + .thenReturn(mScanDetailCache); + when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn( + getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq)); + when(mScanDetailCache.getScanResult(sBSSID)).thenReturn( + getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult()); + when(mWifiNative.getEapAnonymousIdentity(anyString())) + .thenReturn(pseudonym); + + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); + mLooper.dispatchAll(); + + verify(mWifiNative).getEapAnonymousIdentity(any()); + assertEquals(pseudonym + "@" + realm, + mConnectedNetwork.enterpriseConfig.getAnonymousIdentity()); + // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a + // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by + // pseudonym usage in all subsequent connections. + // Note: This test will fail if future logic will have additional conditions that would + // trigger "add or update network" operation. The test needs to be updated to account for + // this change. + verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt()); + } + /** * Tests the Passpoint information is set in WifiInfo for Passpoint AP connection. */ @Test @@ -1789,10 +1843,10 @@ public class ClientModeImplTest { /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ @Test public void syncGetSupportedFeatures() { - final int featureAware = WifiManager.WIFI_FEATURE_AWARE; - final int featureInfra = WifiManager.WIFI_FEATURE_INFRA; - final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; - final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; + final long featureAware = WifiManager.WIFI_FEATURE_AWARE; + final long featureInfra = WifiManager.WIFI_FEATURE_INFRA; + final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; + final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; final long featureLongBits = 0x1100000000L; assertEquals(0, testGetSupportedFeaturesCase(0, false)); @@ -1866,15 +1920,15 @@ public class ClientModeImplTest { @Test public void syncRemovePasspointConfig() throws Exception { String fqdn = "test.com"; - when(mPasspointManager.removeProvider(fqdn)).thenReturn(true); + when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), eq(fqdn))).thenReturn(true); mLooper.startAutoDispatch(); - assertTrue(mCmi.syncRemovePasspointConfig(mCmiAsyncChannel, fqdn)); + assertTrue(mCmi.syncRemovePasspointConfig(mCmiAsyncChannel, true, fqdn)); mLooper.stopAutoDispatch(); reset(mPasspointManager); - when(mPasspointManager.removeProvider(fqdn)).thenReturn(false); + when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), eq(fqdn))).thenReturn(false); mLooper.startAutoDispatch(); - assertFalse(mCmi.syncRemovePasspointConfig(mCmiAsyncChannel, fqdn)); + assertFalse(mCmi.syncRemovePasspointConfig(mCmiAsyncChannel, true, fqdn)); mLooper.stopAutoDispatch(); } @@ -1902,16 +1956,17 @@ public class ClientModeImplTest { config.setHomeSp(homeSp); expectedConfigs.add(config); - when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs); + when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) + .thenReturn(expectedConfigs); mLooper.startAutoDispatch(); - assertEquals(expectedConfigs, mCmi.syncGetPasspointConfigs(mCmiAsyncChannel)); + assertEquals(expectedConfigs, mCmi.syncGetPasspointConfigs(mCmiAsyncChannel, true)); mLooper.stopAutoDispatch(); reset(mPasspointManager); - when(mPasspointManager.getProviderConfigs()) - .thenReturn(new ArrayList<PasspointConfiguration>()); + when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) + .thenReturn(new ArrayList<>()); mLooper.startAutoDispatch(); - assertTrue(mCmi.syncGetPasspointConfigs(mCmiAsyncChannel).isEmpty()); + assertTrue(mCmi.syncGetPasspointConfigs(mCmiAsyncChannel, true).isEmpty()); mLooper.stopAutoDispatch(); } @@ -2748,6 +2803,59 @@ public class ClientModeImplTest { } /** + * Verify that we don't crash when WifiNative returns null as the current MAC address. + * @throws Exception + */ + @Test + public void testMacRandomizationWifiNativeReturningNull() throws Exception { + when(mWifiNative.getMacAddress(anyString())).thenReturn(null); + initializeAndAddNetworkAndVerifySuccess(); + assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest()); + assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState()); + + connect(); + verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS); + } + + /** + * Verifies that a notification is posted when a connection failure happens on a network + * in the hotlist. Then verify that tapping on the notification launches an dialog, which + * could be used to set the randomization setting for a network to "Trusted". + */ + @Test + public void testConnectionFailureSendRandomizationSettingsNotification() throws Exception { + when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true); + // Setup CONNECT_MODE & a WifiConfiguration + initializeAndAddNetworkAndVerifySuccess(); + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID); + mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, + WifiManager.ERROR_AUTH_FAILURE_TIMEOUT); + mLooper.dispatchAll(); + + WifiConfiguration config = mCmi.getCurrentWifiConfiguration(); + verify(mConnectionFailureNotifier) + .showFailedToConnectDueToNoRandomizedMacSupportNotification(FRAMEWORK_NETWORK_ID); + } + + /** + * Verifies that a notification is not posted when a wrong password failure happens on a + * network in the hotlist. + */ + @Test + public void testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword() throws Exception { + when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true); + // Setup CONNECT_MODE & a WifiConfiguration + initializeAndAddNetworkAndVerifySuccess(); + mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID); + mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, + WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); + mLooper.dispatchAll(); + + verify(mConnectionFailureNotifier, never()) + .showFailedToConnectDueToNoRandomizedMacSupportNotification(anyInt()); + } + + /** * Verifies that CMD_START_CONNECT make WifiDiagnostics report * CONNECTION_EVENT_STARTED * @throws Exception @@ -3544,14 +3652,15 @@ public class ClientModeImplTest { @Test public void testRemovePasspointConfig() throws Exception { String fqdn = "test.com"; - when(mPasspointManager.removeProvider(anyString())).thenReturn(true); + when(mPasspointManager.removeProvider(anyInt(), anyBoolean(), anyString())) + .thenReturn(true); // switch to connect mode and verify wifi is reported as enabled startSupplicantAndDispatchMessages(); - mCmi.sendMessage(ClientModeImpl.CMD_REMOVE_PASSPOINT_CONFIG, fqdn); + mCmi.sendMessage(ClientModeImpl.CMD_REMOVE_PASSPOINT_CONFIG, TEST_UID, 0, fqdn); mLooper.dispatchAll(); - verify(mWifiConfigManager).removePasspointConfiguredNetwork(eq(fqdn)); + verify(mWifiConfigManager).removePasspointConfiguredNetwork(fqdn); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java new file mode 100644 index 000000000..8bf07b8c3 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/ConnectionFailureNotifierTest.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2019 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 org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AlertDialog; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Resources; +import android.net.wifi.WifiConfiguration; +import android.os.Handler; +import android.os.Process; +import android.os.test.TestLooper; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for {@link ConnectionFailureNotifier}. + */ +@SmallTest +public class ConnectionFailureNotifierTest { + @Mock private Context mContext; + @Mock private WifiInjector mWifiInjector; + @Mock private Resources mResources; + @Mock private FrameworkFacade mFrameworkFacade; + @Mock private WifiConfigManager mWifiConfigManager; + @Mock private WifiConnectivityManager mWifiConnectivityManager; + @Mock private NotificationManager mNotificationManager; + @Mock private ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder; + @Mock private Notification mNotification; + @Mock private AlertDialog mAlertDialog; + + final ArgumentCaptor<BroadcastReceiver> mBroadCastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + private ConnectionFailureNotifier mConnectionFailureNotifier; + TestLooper mLooper; + + /** Initialize objects before each test run. */ + @Before + public void setUp() throws Exception { + // Ensure looper exists + mLooper = new TestLooper(); + MockitoAnnotations.initMocks(this); + when(mContext.getResources()).thenReturn(mResources); + when(mWifiInjector.getNotificationManager()).thenReturn(mNotificationManager); + when(mWifiInjector.getConnectionFailureNotificationBuilder()) + .thenReturn(mConnectionFailureNotificationBuilder); + when(mConnectionFailureNotificationBuilder + .buildNoMacRandomizationSupportNotification(any())).thenReturn(mNotification); + when(mConnectionFailureNotificationBuilder.buildChangeMacRandomizationSettingDialog(any(), + any())).thenReturn(mAlertDialog); + mConnectionFailureNotifier = new ConnectionFailureNotifier(mContext, mWifiInjector, + mFrameworkFacade, mWifiConfigManager, mWifiConnectivityManager, + new Handler(mLooper.getLooper())); + + verify(mContext).registerReceiver(mBroadCastReceiverCaptor.capture(), any()); + } + + private class DisableMacRandomizationMatcher implements ArgumentMatcher<WifiConfiguration> { + @Override + public boolean matches(WifiConfiguration config) { + return config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE; + } + } + + // Returns an intent that simulates the broadcast which is received when the user tap + // on the notification to change MAC randomization settings. + private Intent buildBroadcastForRandomizationSettingsDialog(WifiConfiguration config) { + Intent intent = mock(Intent.class); + when(intent.getAction()).thenReturn(ConnectionFailureNotificationBuilder + .ACTION_SHOW_SET_RANDOMIZATION_DETAILS); + when(intent.getIntExtra(eq(ConnectionFailureNotificationBuilder + .RANDOMIZATION_SETTINGS_NETWORK_ID), anyInt())).thenReturn(config.networkId); + when(intent.getStringExtra( + eq(ConnectionFailureNotificationBuilder.RANDOMIZATION_SETTINGS_NETWORK_SSID))) + .thenReturn(config.getSsidAndSecurityTypeString()); + return intent; + } + + /** + * Verify that a notification is posted when a connection failure happens on a network + * in the hotlist. Then verify that tapping on the notification launches an dialog, which + * could be used to set the randomization setting for a network to "Trusted". + */ + @Test + public void testConnectionFailureSendRandomizationSettingsNotification() { + // Verify that the network is using randomized MAC at the start. + WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); + when(mWifiConfigManager.getConfiguredNetwork(config.networkId)).thenReturn(config); + assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT, config.macRandomizationSetting); + + mConnectionFailureNotifier.showFailedToConnectDueToNoRandomizedMacSupportNotification( + config.networkId); + // verify that a notification is sent + verify(mNotificationManager).notify( + eq(ConnectionFailureNotifier.NO_RANDOMIZED_MAC_SUPPORT_NOTIFICATION_ID), + eq(mNotification)); + + // sets up the intent that simulates the user tapping on the notification. + Intent intent = buildBroadcastForRandomizationSettingsDialog(config); + + // simulate the user tapping on the notification, then verify the dialog shows up, and + // the appropriate callback is registered + ArgumentCaptor<DialogInterface.OnClickListener> onClickListenerArgumentCaptor = + ArgumentCaptor.forClass(DialogInterface.OnClickListener.class); + mBroadCastReceiverCaptor.getValue().onReceive(mContext, intent); + verify(mConnectionFailureNotificationBuilder).buildChangeMacRandomizationSettingDialog( + eq(config.SSID), onClickListenerArgumentCaptor.capture()); + + // simulate the user tapping on the option to reset MAC address to factory MAC + onClickListenerArgumentCaptor.getValue().onClick(null, 0); + mLooper.dispatchAll(); + + // verify the WifiConfiguration is updated properly. + verify(mWifiConfigManager).addOrUpdateNetwork( + argThat(new DisableMacRandomizationMatcher()), eq(Process.SYSTEM_UID)); + // verify that we try to connect to the updated network. + verify(mWifiConnectivityManager).forceConnectivityScan(any()); + } + + /** + * Verify that if the WifiConfiguration if not found (may have been deleted by the timed the + * notification is tapped), then the AlertDialog does not show up. + */ + @Test + public void testWifiConfigurationMismatch() { + WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); + when(mWifiConfigManager.getConfiguredNetwork(config.networkId)).thenReturn(config); + mConnectionFailureNotifier.showFailedToConnectDueToNoRandomizedMacSupportNotification( + config.networkId); + // verify that a notification is sent + verify(mNotificationManager).notify( + eq(ConnectionFailureNotifier.NO_RANDOMIZED_MAC_SUPPORT_NOTIFICATION_ID), + any()); + + // sets up the intent that simulates the user tapping on the notification. + Intent intent = buildBroadcastForRandomizationSettingsDialog(config); + + // the WifiConfiguration that is found doesn't match with the one received from broadcast. + when(mWifiConfigManager.getConfiguredNetwork(anyInt())) + .thenReturn(WifiConfigurationTestUtil.createOpenNetwork()); + mBroadCastReceiverCaptor.getValue().onReceive(mContext, intent); + + // verify that the AlertDialog is not launched in this case + verify(mConnectionFailureNotificationBuilder, never()) + .buildChangeMacRandomizationSettingDialog(any(), any()); + + verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any()); + // instead we are showings a toast due to failing to find the network + verify(mFrameworkFacade).showToast(any(), any()); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java index 702aa99df..17b9d1c2e 100644 --- a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java @@ -24,6 +24,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -78,7 +79,8 @@ public class DeletedEphemeralSsidsStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mDeletedEphemeralSsidsStoreData.serializeData(out); + mDeletedEphemeralSsidsStoreData.serializeData( + out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -94,7 +96,9 @@ public class DeletedEphemeralSsidsStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth()); + mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mDeletedEphemeralSsidsStoreData.getSsidToTimeMap(); } diff --git a/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java b/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java new file mode 100644 index 000000000..7e598db31 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/MacAddressUtilTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 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 org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import android.net.MacAddress; +import android.net.wifi.WifiConfiguration; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.security.ProviderException; +import java.util.Random; + +import javax.crypto.Mac; + +/** + * Unit tests for {@link com.android.server.wifi.MacAddressUtil}. + */ +@SmallTest +public class MacAddressUtilTest { + private MacAddressUtil mMacAddressUtil; + + @Mock private Mac mMac; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mMacAddressUtil = new MacAddressUtil(); + } + + /** + * Verifies that calculatePersistentMacForConfiguration valid randomized MACs. + */ + @Test + public void testCalculatePersistentMacForConfiguration() { + // verify null inputs + assertNull(mMacAddressUtil.calculatePersistentMacForConfiguration(null, null)); + + Random rand = new Random(); + // Verify that a the MAC address calculated is valid + for (int i = 0; i < 10; i++) { + WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); + + byte[] bytes = new byte[32]; + rand.nextBytes(bytes); + when(mMac.doFinal(any())).thenReturn(bytes); + MacAddress macAddress = mMacAddressUtil.calculatePersistentMacForConfiguration( + config, mMac); + assertTrue(WifiConfiguration.isValidMacAddressForRandomization(macAddress)); + } + } + + /** + * Verify the java.security.ProviderException is caught. + */ + @Test + public void testCalculatePersistentMacCatchesException() { + when(mMac.doFinal(any())).thenThrow(new ProviderException("error occurred")); + try { + WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); + assertNull(mMacAddressUtil.calculatePersistentMacForConfiguration(config, mMac)); + } catch (Exception e) { + fail("Exception not caught."); + } + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java index 7336c4119..20b6c4f76 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java @@ -31,6 +31,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtilTest; import org.junit.Before; @@ -213,7 +214,7 @@ public class NetworkListStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.serializeData(out); + mNetworkListSharedStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -229,7 +230,9 @@ public class NetworkListStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.deserializeData(in, in.getDepth()); + mNetworkListSharedStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mNetworkListSharedStoreData.getConfigurations(); } diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java index f40f71bcf..c0f03505e 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java @@ -27,6 +27,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -80,7 +81,7 @@ public class NetworkRequestStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out); + mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -92,7 +93,9 @@ public class NetworkRequestStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth()); + mNetworkRequestStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java index 5c1dcb459..a35c510fc 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java @@ -28,6 +28,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -119,7 +120,7 @@ public class NetworkSuggestionStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.serializeData(out); + mNetworkSuggestionStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -131,7 +132,9 @@ public class NetworkSuggestionStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.deserializeData(in, in.getDepth()); + mNetworkSuggestionStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java index 4df560fd2..cdd4e6c84 100644 --- a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java @@ -24,6 +24,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -62,7 +63,7 @@ public class RandomizedMacStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.serializeData(out); + mRandomizedMacStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -78,7 +79,9 @@ public class RandomizedMacStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.deserializeData(in, in.getDepth()); + mRandomizedMacStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mRandomizedMacStoreData.getMacMapping(); } diff --git a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java index ac6ae21a2..feedc0d2a 100644 --- a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,6 +30,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -80,7 +82,7 @@ public class SsidSetStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.serializeData(out); + mSsidSetStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -95,7 +97,9 @@ public class SsidSetStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.deserializeData(in, in.getDepth()); + mSsidSetStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java index c814aef1a..df93eb4fb 100644 --- a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -28,6 +29,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.google.android.collect.Sets; @@ -74,7 +76,7 @@ public class WakeupConfigStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.serializeData(out); + mWakeupConfigData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -88,7 +90,9 @@ public class WakeupConfigStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.deserializeData(in, in.getDepth()); + mWakeupConfigData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** @@ -177,7 +181,9 @@ public class WakeupConfigStoreDataTest { */ @Test public void hasBeenReadIsTrueWhenUserStoreIsLoaded() throws Exception { - mWakeupConfigData.deserializeData(null /* in */, 0 /* outerTagDepth */); + mWakeupConfigData.deserializeData(null /* in */, 0 /* outerTagDepth */, + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); assertTrue(mWakeupConfigData.hasBeenRead()); } diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java index 009429b3f..a004995b9 100644 --- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,6 +39,7 @@ import android.provider.Settings; import androidx.test.filters.SmallTest; import com.android.server.wifi.util.ScanResultUtil; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -149,7 +151,9 @@ public class WakeupControllerTest { private void readUserStore() { try { - mWakeupConfigStoreData.deserializeData(null, 0); + mWakeupConfigStoreData.deserializeData(null, 0, + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } catch (XmlPullParserException | IOException e) { // unreachable } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 0badc6fbd..6fa1868cb 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -42,6 +42,7 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.os.test.TestLooper; +import android.provider.DeviceConfig.OnPropertiesChangedListener; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -70,6 +71,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -135,7 +137,11 @@ public class WifiConfigManagerTest { @Mock private WifiConfigManager.OnSavedNetworkUpdateListener mWcmListener; @Mock private FrameworkFacade mFrameworkFacade; @Mock private CarrierNetworkConfig mCarrierNetworkConfig; + @Mock private MacAddressUtil mMacAddressUtil; + @Mock DeviceConfigFacade mDeviceConfigFacade; + final ArgumentCaptor<OnPropertiesChangedListener> mOnPropertiesChangedListenerCaptor = + ArgumentCaptor.forClass(OnPropertiesChangedListener.class); private MockResources mResources; private InOrder mContextConfigStoreMockOrder; private InOrder mNetworkListStoreDataMockOrder; @@ -169,6 +175,8 @@ public class WifiConfigManagerTest { TEST_MAX_NUM_ACTIVE_CHANNELS_FOR_PARTIAL_SCAN); mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, true); when(mContext.getResources()).thenReturn(mResources); + when(mDeviceConfigFacade.getRandomizationFlakySsidHotlist()).thenReturn( + Collections.emptySet()); // Setup UserManager profiles for the default user. setupUserProfiles(TEST_DEFAULT_USER); @@ -216,6 +224,10 @@ public class WifiConfigManagerTest { when(mWifiInjector.getWifiLastResortWatchdog().shouldIgnoreSsidUpdate()) .thenReturn(false); when(mWifiInjector.getCarrierNetworkConfig()).thenReturn(mCarrierNetworkConfig); + when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil); + when(mMacAddressUtil.calculatePersistentMacForConfiguration(any(), any())) + .thenReturn(TEST_RANDOMIZED_MAC); + createWifiConfigManager(); mWifiConfigManager.setOnSavedNetworkUpdateListener(mWcmListener); ArgumentCaptor<ContentObserver> observerCaptor = @@ -231,13 +243,12 @@ public class WifiConfigManagerTest { // static mocking mSession = ExtendedMockito.mockitoSession() .mockStatic(WifiConfigStore.class, withSettings().lenient()) - .spyStatic(WifiConfigurationUtil.class) .strictness(Strictness.LENIENT) .startMocking(); - when(WifiConfigStore.createUserFiles(anyInt())).thenReturn(mock(List.class)); + when(WifiConfigStore.createUserFiles(anyInt(), anyBoolean())).thenReturn(mock(List.class)); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); - when(WifiConfigurationUtil.calculatePersistentMacForConfiguration(any(), any())) - .thenReturn(TEST_RANDOMIZED_MAC); + verify(mDeviceConfigFacade).addOnPropertiesChangedListener(any(), + mOnPropertiesChangedListenerCaptor.capture()); } /** @@ -292,6 +303,30 @@ public class WifiConfigManagerTest { } /** + * Verify that a randomized MAC address is generated even if the KeyStore operation fails. + */ + @Test + public void testRandomizedMacIsGeneratedEvenIfKeyStoreFails() { + when(mMacAddressUtil.calculatePersistentMacForConfiguration(any(), any())).thenReturn(null); + + // Try adding a network. + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + List<WifiConfiguration> networks = new ArrayList<>(); + networks.add(openNetwork); + verifyAddNetworkToWifiConfigManager(openNetwork); + List<WifiConfiguration> retrievedNetworks = + mWifiConfigManager.getConfiguredNetworksWithPasswords(); + + // Verify that we have attempted to generate the MAC address twice (1 retry) + verify(mMacAddressUtil, times(2)).calculatePersistentMacForConfiguration(any(), any()); + assertEquals(1, retrievedNetworks.size()); + + // Verify that despite KeyStore returning null, we are still getting a valid MAC address. + assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, + retrievedNetworks.get(0).getRandomizedMacAddress().toString()); + } + + /** * Verifies the addition of a single network using * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} */ @@ -4620,7 +4655,7 @@ public class WifiConfigManagerTest { mWifiPermissionsUtil, mWifiPermissionsWrapper, mWifiInjector, mNetworkListSharedStoreData, mNetworkListUserStoreData, mDeletedEphemeralSsidsStoreData, mRandomizedMacStoreData, - mFrameworkFacade, mLooper.getLooper()); + mFrameworkFacade, mLooper.getLooper(), mDeviceConfigFacade); mWifiConfigManager.enableVerboseLogging(1); } @@ -5349,4 +5384,32 @@ public class WifiConfigManagerTest { assertFalse(mWifiConfigManager.getConfiguredNetwork(networkId) .getNetworkSelectionStatus().isNetworkTemporaryDisabled()); } + + /** + * Verifies that isInFlakyRandomizationSsidHotlist returns true if the network's SSID is in + * the hotlist and the network is using randomized MAC. + */ + @Test + public void testFlakyRandomizationSsidHotlist() { + WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(); + NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(openNetwork); + int networkId = result.getNetworkId(); + + // should return false when there is nothing in the hotlist + assertFalse(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); + + // add the network's SSID to the hotlist and verify the method returns true + Set<String> ssidHotlist = new HashSet<>(); + ssidHotlist.add(openNetwork.SSID); + when(mDeviceConfigFacade.getRandomizationFlakySsidHotlist()).thenReturn(ssidHotlist); + mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); + assertTrue(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); + + // Now change the macRandomizationSetting to "trusted" and then verify + // isInFlakyRandomizationSsidHotlist returns false + openNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE; + NetworkUpdateResult networkUpdateResult = updateNetworkToWifiConfigManager(openNetwork); + assertNotEquals(WifiConfiguration.INVALID_NETWORK_ID, networkUpdateResult.getNetworkId()); + assertFalse(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(networkId)); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java index b59e367dd..efa2d4336 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java @@ -16,12 +16,9 @@ package com.android.server.wifi; -import static com.android.server.wifi.WifiConfigStore.ZEROED_ENCRYPTED_DATA; - import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.app.test.TestAlarmManager; import android.content.Context; import android.content.pm.PackageManager; @@ -34,8 +31,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.WifiConfigStore.StoreData; import com.android.server.wifi.WifiConfigStore.StoreFile; -import com.android.server.wifi.util.DataIntegrityChecker; import com.android.server.wifi.util.EncryptedData; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import libcore.util.HexEncoding; @@ -43,7 +40,6 @@ import libcore.util.HexEncoding; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.xmlpull.v1.XmlPullParser; @@ -73,13 +69,7 @@ public class WifiConfigStoreTest { private static final String TEST_DATA_XML_STRING_FORMAT = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"2\" />\n" - + "<Integrity>\n" - + "<byte-array name=\"EncryptedData\" num=\"48\">000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000" - + "</byte-array>\n" - + "<byte-array name=\"IV\" num=\"12\">000000000000000000000000</byte-array>\n" - + "</Integrity>\n" + + "<int name=\"Version\" value=\"3\" />\n" + "<NetworkList>\n" + "<Network>\n" + "<WifiConfiguration>\n" @@ -172,7 +162,7 @@ public class WifiConfigStoreTest { private TestLooper mLooper; @Mock private Clock mClock; @Mock private WifiMetrics mWifiMetrics; - @Mock private DataIntegrityChecker mDataIntegrityChecker; + @Mock private WifiConfigStoreEncryptionUtil mEncryptionUtil; private MockStoreFile mSharedStore; private MockStoreFile mUserStore; private MockStoreFile mUserNetworkSuggestionsStore; @@ -196,10 +186,10 @@ public class WifiConfigStoreTest { .thenReturn(mAlarmManager.getAlarmManager()); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME); - when(mDataIntegrityChecker.compute(any(byte[].class))) - .thenReturn(ZEROED_ENCRYPTED_DATA); - when(mDataIntegrityChecker.isOk(any(byte[].class), any(EncryptedData.class))) - .thenReturn(true); + when(mEncryptionUtil.encrypt(any(byte[].class))) + .thenReturn(new EncryptedData(new byte[0], new byte[0])); + when(mEncryptionUtil.decrypt(any(EncryptedData.class))) + .thenReturn(new byte[0]); mSharedStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_GENERAL); mUserStore = new MockStoreFile(WifiConfigStore.STORE_FILE_USER_GENERAL); mUserNetworkSuggestionsStore = @@ -432,9 +422,9 @@ public class WifiConfigStoreTest { // Ensure that we got the call to deserialize empty shared data, but no user data. verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt()); + verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); verify(userStoreData, never()).resetData(); - verify(userStoreData, never()).deserializeData(any(), anyInt()); + verify(userStoreData, never()).deserializeData(any(), anyInt(), anyInt(), any()); } /** @@ -462,9 +452,9 @@ public class WifiConfigStoreTest { // Ensure that we got the call to deserialize empty shared & user data. verify(userStoreData).resetData(); - verify(userStoreData).deserializeData(eq(null), anyInt()); + verify(userStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt()); + verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); } /** @@ -639,9 +629,9 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(null); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 2: StoreData2 in user store file. @@ -655,9 +645,9 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); mWifiConfigStore.read(); - verify(storeData1).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 3: StoreData1 in shared store file & StoreData2 in user store file. @@ -671,10 +661,10 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 4: StoreData1 & StoreData2 in shared store file. @@ -689,10 +679,10 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(null); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); } @@ -739,9 +729,9 @@ public class WifiConfigStoreTest { verify(userStoreNetworkSuggestionsData).hasNewDataToSerialize(); // Verify that we serialized data from the first 2 data source, but not from the last one. - verify(sharedStoreData).serializeData(any()); - verify(userStoreData).serializeData(any()); - verify(userStoreNetworkSuggestionsData, never()).serializeData(any()); + verify(sharedStoreData).serializeData(any(), any()); + verify(userStoreData).serializeData(any(), any()); + verify(userStoreNetworkSuggestionsData, never()).serializeData(any(), any()); } /** @@ -815,190 +805,21 @@ public class WifiConfigStoreTest { // Read and verify the data content in the store file (metadata stripped out) has been sent // to the corresponding store data when integrity check passes. mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // We shouldn't perform any data integrity checks on version 1 file. - verifyZeroInteractions(mDataIntegrityChecker); - } - - /** - * Tests the read API behaviour when integrity check fails. - * Expected behaviour: The read should return an empty store data. - */ - @Test - public void testReadWhenIntegrityCheckFails() throws Exception { - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Now store some content in the shared and user data files. - mUserStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA).getBytes()); - mSharedStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA).getBytes()); - - // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data when integrity check passes. - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // Read and verify the data content in the store file (metadata stripped out) has not been - // sent to the corresponding store data when integrity check fails. - when(mDataIntegrityChecker.isOk(any(byte[].class), any(EncryptedData.class))) - .thenReturn(false); - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); + verify(sharedStoreData, times(1)).deserializeData( + any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); + verify(userStoreData, times(1)).deserializeData( + any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); } /** - * Tests the write API behaviour when integrity check fails. - * Expected behaviour: The read should return an empty store data. + * Tests the read API behaviour to ensure that the integrity data is parsed from the file. */ @Test - public void testWriteWhenIntegrityComputeFails() throws Exception { - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Reset store file contents & ensure that the user and store data files are empty. - mUserStore.storeRawDataToWrite(null); - mSharedStore.storeRawDataToWrite(null); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - - // Write and verify that the data is written to the config store file when integrity - // computation passes. - mWifiConfigStore.write(true); - assertNotNull(mUserStore.getStoreBytes()); - assertNotNull(mSharedStore.getStoreBytes()); - assertTrue(new String(mUserStore.getStoreBytes()).contains(TEST_USER_DATA)); - assertTrue(new String(mSharedStore.getStoreBytes()).contains(TEST_SHARE_DATA)); - - // Reset store file contents & ensure that the user and store data files are empty. - mUserStore.storeRawDataToWrite(null); - mSharedStore.storeRawDataToWrite(null); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - - // Write and verify that the data is not written to the config store file when integrity - // computation fails. - when(mDataIntegrityChecker.compute(any(byte[].class))).thenReturn(null); - mWifiConfigStore.write(true); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - } - - /** - * Tests the write API behaviour to ensure that the integrity data is written to the file. - */ - @Test - public void testWriteContainsIntegrityData() throws Exception { - byte[] encryptedData = new byte[EncryptedData.ENCRYPTED_DATA_LENGTH]; - byte[] iv = new byte[EncryptedData.IV_LENGTH]; - Random random = new Random(); - random.nextBytes(encryptedData); - random.nextBytes(iv); - final EncryptedData testEncryptedData = new EncryptedData(encryptedData, iv); - - doAnswer(new AnswerWithArguments() { - public EncryptedData answer(byte[] data) { - String storeXmlString = new String(data); - // Verify that we fill in zeros to the data when we compute integrity. - if (storeXmlString.contains(TEST_SHARE_DATA)) { - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA), storeXmlString); - } else if (storeXmlString.contains(TEST_USER_DATA)) { - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA), storeXmlString); - } - return testEncryptedData; - } - }).when(mDataIntegrityChecker).compute(any(byte[].class)); - - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Write and verify that the data is written to the config store file when integrity - // computation passes. - mWifiConfigStore.write(true); - - // Verify that we fill in zeros to the data when we computed integrity. - verify(mDataIntegrityChecker, times(2)).compute(any(byte[].class)); - - // Verify the parsed integrity data - assertNotNull(mUserStore.getStoreBytes()); - assertNotNull(mSharedStore.getStoreBytes()); - String userStoreXmlString = new String(mUserStore.getStoreBytes()); - String sharedStoreXmlString = new String(mSharedStore.getStoreBytes()); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData).toLowerCase(), - HexEncoding.encodeToString(iv).toLowerCase(), - TEST_USER_DATA), userStoreXmlString); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData).toLowerCase(), - HexEncoding.encodeToString(iv).toLowerCase(), - TEST_SHARE_DATA), sharedStoreXmlString); - } - - /** - * Tests the read API behaviour to ensure that the integrity data is parsed from the file and - * used for checking integrity of the file. - */ - @Test - public void testReadParsesIntegrityData() throws Exception { - byte[] encryptedData = new byte[EncryptedData.ENCRYPTED_DATA_LENGTH]; - byte[] iv = new byte[EncryptedData.IV_LENGTH]; + public void testReadVersion2StoreFile() throws Exception { + byte[] encryptedData = new byte[0]; + byte[] iv = new byte[0]; Random random = new Random(); random.nextBytes(encryptedData); random.nextBytes(iv); @@ -1033,40 +854,14 @@ public class WifiConfigStoreTest { TEST_SHARE_DATA).getBytes()); // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data when integrity check passes. + // to the corresponding store data. mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // Verify that we parsed the integrity data and used it for checking integrity of the file. - ArgumentCaptor<EncryptedData> integrityCaptor = - ArgumentCaptor.forClass(EncryptedData.class); - ArgumentCaptor<byte[]> dataCaptor = ArgumentCaptor.forClass(byte[].class); - // Will be invoked twice for each file - shared & user store file. - verify(mDataIntegrityChecker, times(2)).isOk( - dataCaptor.capture(), integrityCaptor.capture()); - // Verify the parsed integrity data - assertEquals(2, integrityCaptor.getAllValues().size()); - EncryptedData parsedEncryptedData1 = integrityCaptor.getAllValues().get(0); - assertArrayEquals(encryptedData, parsedEncryptedData1.getEncryptedData()); - assertArrayEquals(iv, parsedEncryptedData1.getIv()); - EncryptedData parsedEncryptedData2 = integrityCaptor.getAllValues().get(1); - assertArrayEquals(encryptedData, parsedEncryptedData2.getEncryptedData()); - assertArrayEquals(iv, parsedEncryptedData2.getIv()); - - // Verify that we fill in zeros to the data when we performed integrity checked. - assertEquals(2, dataCaptor.getAllValues().size()); - String sharedStoreXmlStringWithZeroedIntegrity = - new String(dataCaptor.getAllValues().get(0)); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA), sharedStoreXmlStringWithZeroedIntegrity); - String userStoreXmlStringWithZeroedIntegrity = new String(dataCaptor.getAllValues().get(1)); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA), userStoreXmlStringWithZeroedIntegrity); + verify(sharedStoreData, times(1)) + .deserializeData(any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); + verify(userStoreData, times(1)) + .deserializeData(any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); } /** @@ -1078,7 +873,7 @@ public class WifiConfigStoreTest { private boolean mStoreWritten; MockStoreFile(@WifiConfigStore.StoreFileId int fileId) { - super(new File("MockStoreFile"), fileId, mDataIntegrityChecker); + super(new File("MockStoreFile"), fileId, mEncryptionUtil); } @Override @@ -1129,13 +924,14 @@ public class WifiConfigStoreTest { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mData); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, int version, + WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (in == null) { return; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java index a40de55e9..255073b8b 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java @@ -161,17 +161,6 @@ public class WifiLockManagerTest { } /** - * Test to verify that the lock mode is verified before adding a lock. - * - * Steps: call acquireWifiLock with an invalid lock mode. - * Expected: the call should throw an IllegalArgumentException. - */ - @Test(expected = IllegalArgumentException.class) - public void acquireWifiLockShouldThrowExceptionOnInivalidLockMode() throws Exception { - mWifiLockManager.acquireWifiLock(WIFI_LOCK_MODE_INVALID, "", mBinder, mWorkSource); - } - - /** * Test that a call to acquireWifiLock with valid parameters works. * * Steps: call acquireWifiLock on the empty WifiLockManager. diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index 7e086d4ce..73ac30f41 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -2999,9 +2999,10 @@ public class WifiMetricsTest { dumpProtoAndDeserialize(); assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD, mDecodedProto.wifiUsabilityStatsList.length); - for (int i = 0; i < mDecodedProto.wifiUsabilityStatsList.length; i++) { + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) { assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE, - mDecodedProto.wifiUsabilityStatsList[i].stats.length); + mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length); + assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index 63cc8bf60..d20c99c4f 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -68,6 +68,7 @@ import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; import com.android.server.wifi.nano.WifiMetricsProto; import com.android.server.wifi.util.ScanResultUtil; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.WifiPermissionsUtil; import org.junit.After; @@ -84,6 +85,8 @@ import org.xmlpull.v1.XmlSerializer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -184,6 +187,7 @@ public class WifiNetworkFactoryTest { when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl); when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString())) .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID_1)); + when(mWifiScanner.getSingleScanResults()).thenReturn(Collections.emptyList()); mWifiNetworkFactory = new WifiNetworkFactory(mLooper.getLooper(), mContext, mNetworkCapabilities, mActivityManager, mAlarmManager, mAppOpsManager, mClock, @@ -951,16 +955,11 @@ public class WifiNetworkFactoryTest { verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); // We expect no network match in this case. - assertEquals(0, matchedScanResultsCaptor.getValue().size()); + verify(mNetworkRequestMatchCallback, never()).onMatch(any()); - verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( - matchedScanResultsCaptor.getValue().size()); + // Don't increment metrics until we have a match + verify(mWifiMetrics, never()).incrementNetworkRequestApiMatchSizeHistogram(anyInt()); } /** @@ -996,13 +995,8 @@ public class WifiNetworkFactoryTest { verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); - - assertNotNull(matchedScanResultsCaptor.getValue()); // We expect no network match in this case. - assertEquals(0, matchedScanResultsCaptor.getValue().size()); + verify(mNetworkRequestMatchCallback, never()).onMatch(any()); } /** @@ -1615,9 +1609,17 @@ public class WifiNetworkFactoryTest { verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); // Now release the network request. + WifiConfiguration wcmNetwork = new WifiConfiguration(mSelectedNetwork); + wcmNetwork.networkId = TEST_NETWORK_ID_1; + wcmNetwork.creatorUid = TEST_UID_1; + wcmNetwork.fromWifiNetworkSpecifier = true; + wcmNetwork.ephemeral = true; + when(mWifiConfigManager.getConfiguredNetwork(mSelectedNetwork.configKey())) + .thenReturn(wcmNetwork); mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); // Verify that we triggered a disconnect. verify(mClientModeImpl, times(2)).disconnectCommand(); + verify(mWifiConfigManager).removeNetwork(TEST_NETWORK_ID_1, TEST_UID_1); // Re-enable connectivity manager . verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false); } @@ -1676,6 +1678,7 @@ public class WifiNetworkFactoryTest { mLooper.dispatchAll(); verify(mNetworkRequestMatchCallback).onAbort(); + verify(mWifiScanner, times(2)).getSingleScanResults(); verify(mWifiScanner, times(2)).startScan(any(), any(), any()); verifyUnfullfillableDispatched(mConnectivityMessenger); @@ -1717,6 +1720,7 @@ public class WifiNetworkFactoryTest { mLooper.dispatchAll(); verify(mNetworkRequestMatchCallback).onAbort(); + verify(mWifiScanner, times(2)).getSingleScanResults(); verify(mWifiScanner, times(2)).startScan(any(), any(), any()); verify(mAlarmManager).cancel(mPeriodicScanListenerArgumentCaptor.getValue()); verifyUnfullfillableDispatched(mConnectivityMessenger); @@ -1751,6 +1755,7 @@ public class WifiNetworkFactoryTest { verify(mNetworkRequestMatchCallback).onAbort(); verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).getSingleScanResults(); verify(mWifiScanner, times(2)).startScan(any(), any(), any()); verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue()); @@ -1790,6 +1795,7 @@ public class WifiNetworkFactoryTest { mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); verify(mWifiConnectivityManager, times(1)).setSpecificNetworkRequestInProgress(true); + verify(mWifiScanner, times(2)).getSingleScanResults(); verify(mWifiScanner, times(2)).startScan(any(), any(), any()); // we shouldn't disconnect until the user accepts the next request. verify(mClientModeImpl, times(1)).disconnectCommand(); @@ -2082,10 +2088,10 @@ public class WifiNetworkFactoryTest { /** * Verify the user approval bypass for a specific request for an access point that was already - * approved previously. + * approved previously with no cached scan results matching. */ @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchPreviouslyApproved() + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedWithNoCache() throws Exception { // 1. First request (no user approval bypass) sendNetworkRequestAndSetupForConnectionStatus(); @@ -2105,6 +2111,9 @@ public class WifiNetworkFactoryTest { WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + validateUiStartParams(true); + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, TEST_CALLBACK_IDENTIFIER); // Trigger scan results & ensure we triggered a connect. @@ -2126,8 +2135,7 @@ public class WifiNetworkFactoryTest { * approved previously, but then the user forgot it sometime after. */ @Test - public void - testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchPreviouslyApprovedNForgot() + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedNForgot() throws Exception { // 1. First request (no user approval bypass) sendNetworkRequestAndSetupForConnectionStatus(); @@ -2171,7 +2179,7 @@ public class WifiNetworkFactoryTest { * not approved previously. */ @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchNotPreviouslyApproved() + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchNotApproved() throws Exception { // 1. First request (no user approval bypass) sendNetworkRequestAndSetupForConnectionStatus(); @@ -2212,7 +2220,7 @@ public class WifiNetworkFactoryTest { * (not access point) that was approved previously. */ @Test - public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchPreviouslyApproved() + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchApproved() throws Exception { // 1. First request (no user approval bypass) sendNetworkRequestAndSetupForConnectionStatus(); @@ -2404,7 +2412,7 @@ public class WifiNetworkFactoryTest { * Verify the config store save and load could preserve the elements order. */ @Test - public void testStoteConfigSaveAndLoadPreserveOrder() throws Exception { + public void testStoreConfigSaveAndLoadPreserveOrder() throws Exception { LinkedHashSet<AccessPoint> approvedApSet = new LinkedHashSet<>(); approvedApSet.add(new AccessPoint(TEST_SSID_1, MacAddress.fromString(TEST_BSSID_1), WifiConfiguration.SECURITY_TYPE_PSK)); @@ -2429,6 +2437,159 @@ public class WifiNetworkFactoryTest { assertArrayEquals(approvedApSet.toArray(), storedApSet.toArray()); } + /** + * Verify the user approval bypass for a specific request for an access point that was already + * approved previously and the scan result is present in the cached scan results. + */ + @Test + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedWithCache() + throws Exception { + // 1. First request (no user approval bypass) + sendNetworkRequestAndSetupForConnectionStatus(); + + mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); + reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); + + // 2. Second request for the same access point (user approval bypass). + ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; + // simulate no cache expiry + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + // Simulate the cached results matching. + when(mWifiScanner.getSingleScanResults()) + .thenReturn(Arrays.asList(mTestScanDatas[0].getResults())); + + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); + Pair<MacAddress, MacAddress> bssidPatternMatch = + Pair.create(MacAddress.fromString(matchingScanResult.BSSID), + MacAddress.BROADCAST_ADDRESS); + WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( + ssidPatternMatch, bssidPatternMatch, + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + // Verify we did not trigger the UI for the second request. + verify(mContext, times(1)).startActivityAsUser(any(), any()); + // Verify we did not trigger a scan. + verify(mWifiScanner, never()).startScan(any(), any(), any()); + // Verify we did not trigger the match callback. + verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); + // Verify that we sent a connection attempt to ClientModeImpl + verify(mClientModeImpl).sendMessage(any()); + + verify(mWifiMetrics).incrementNetworkRequestApiNumUserApprovalBypass(); + } + + /** + * Verify the user approval bypass for a specific request for an access point that was already + * approved previously and the scan result is present in the cached scan results, but the + * results are stale. + */ + @Test + public void + testNetworkSpecifierMatchSuccessUsingLiteralSsidAndBssidMatchApprovedWithStaleCache() + throws Exception { + // 1. First request (no user approval bypass) + sendNetworkRequestAndSetupForConnectionStatus(); + + mWifiNetworkFactory.removeCallback(TEST_CALLBACK_IDENTIFIER); + reset(mNetworkRequestMatchCallback, mWifiScanner, mAlarmManager, mClientModeImpl); + + long scanResultsTimestampInUs = 39484839202L; + mTestScanDatas[0].getResults()[0].timestamp = scanResultsTimestampInUs; + mTestScanDatas[0].getResults()[1].timestamp = scanResultsTimestampInUs; + mTestScanDatas[0].getResults()[2].timestamp = scanResultsTimestampInUs; + mTestScanDatas[0].getResults()[3].timestamp = scanResultsTimestampInUs; + + // 2. Second request for the same access point (user approval bypass). + ScanResult matchingScanResult = mTestScanDatas[0].getResults()[0]; + // simulate cache expiry + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(Long.valueOf( + scanResultsTimestampInUs / 1000 + + WifiNetworkFactory.CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS + 1)); + // Simulate the cached results matching. + when(mWifiScanner.getSingleScanResults()) + .thenReturn(Arrays.asList(mTestScanDatas[0].getResults())); + + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); + Pair<MacAddress, MacAddress> bssidPatternMatch = + Pair.create(MacAddress.fromString(matchingScanResult.BSSID), + MacAddress.BROADCAST_ADDRESS); + WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( + ssidPatternMatch, bssidPatternMatch, + WifiConfigurationTestUtil.createPskNetwork(), TEST_UID_1, TEST_PACKAGE_NAME_1); + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + // Ensure we brought up the UI while the scan is ongoing. + validateUiStartParams(true); + + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, + TEST_CALLBACK_IDENTIFIER); + // Trigger scan results & ensure we triggered a connect. + verify(mWifiScanner).startScan(any(), mScanListenerArgumentCaptor.capture(), any()); + ScanListener scanListener = mScanListenerArgumentCaptor.getValue(); + assertNotNull(scanListener); + scanListener.onResults(mTestScanDatas); + + // Verify we did not trigger the match callback. + verify(mNetworkRequestMatchCallback, never()).onMatch(anyList()); + // Verify that we sent a connection attempt to ClientModeImpl + verify(mClientModeImpl).sendMessage(any()); + + verify(mWifiMetrics).incrementNetworkRequestApiNumUserApprovalBypass(); + } + + /** + * Verify network specifier matching for a specifier containing a specific SSID match using + * 4 WPA_PSK scan results, each with unique SSID when the UI callback registration is delayed. + */ + @Test + public void testNetworkSpecifierMatchSuccessUsingLiteralSsidMatchCallbackRegistrationDelayed() + throws Exception { + // Setup scan data for open networks. + setupScanData(SCAN_RESULT_TYPE_WPA_PSK, + TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); + + // Setup network specifier for open networks. + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); + Pair<MacAddress, MacAddress> bssidPatternMatch = + Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS); + WifiConfiguration wifiConfiguration = new WifiConfiguration(); + wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( + ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, + TEST_PACKAGE_NAME_1); + + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + validateUiStartParams(true); + + verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); + + // Ensure we did not send any match callbacks, until the callback is registered + verify(mNetworkRequestMatchCallback, never()).onMatch(any()); + + // Register the callback & ensure we triggered the on match callback. + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, + TEST_CALLBACK_IDENTIFIER); + ArgumentCaptor<List<ScanResult>> matchedScanResultsCaptor = + ArgumentCaptor.forClass(List.class); + verify(mNetworkRequestMatchCallback).onMatch(matchedScanResultsCaptor.capture()); + + assertNotNull(matchedScanResultsCaptor.getValue()); + // We only expect 1 network match in this case. + validateScanResults(matchedScanResultsCaptor.getValue(), mTestScanDatas[0].getResults()[0]); + + verify(mWifiMetrics).incrementNetworkRequestApiMatchSizeHistogram( + matchedScanResultsCaptor.getValue().size()); + } + private Messenger sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException { return sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); } @@ -2498,6 +2659,8 @@ public class WifiNetworkFactoryTest { mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + validateUiStartParams(true); + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, TEST_CALLBACK_IDENTIFIER); verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( @@ -2505,7 +2668,7 @@ public class WifiNetworkFactoryTest { verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); - verify(mNetworkRequestMatchCallback).onMatch(anyList()); + verify(mNetworkRequestMatchCallback, atLeastOnce()).onMatch(anyList()); } // Simulates the periodic scans performed to find a matching network. @@ -2520,6 +2683,10 @@ public class WifiNetworkFactoryTest { ScanListener scanListener = null; mInOrder = inOrder(mWifiScanner, mAlarmManager); + + // Before we start scans, ensure that we look at the latest cached scan results. + mInOrder.verify(mWifiScanner).getSingleScanResults(); + for (int i = 0; i < expectedIntervalsInSeconds.length - 1; i++) { long expectedCurrentIntervalInMs = expectedIntervalsInSeconds[i]; long expectedNextIntervalInMs = expectedIntervalsInSeconds[i + 1]; @@ -2697,7 +2864,7 @@ public class WifiNetworkFactoryTest { private void validateUiStartParams(boolean expectedIsReqForSingeNetwork) { ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).startActivityAsUser( + verify(mContext, atLeastOnce()).startActivityAsUser( intentArgumentCaptor.capture(), eq(UserHandle.getUserHandleForUid(TEST_UID_1))); Intent intent = intentArgumentCaptor.getValue(); assertNotNull(intent); @@ -2766,7 +2933,7 @@ public class WifiNetworkFactoryTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out); + mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -2781,6 +2948,8 @@ public class WifiNetworkFactoryTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth()); + mNetworkRequestStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 9a3bd75be..d5f7dd981 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -174,6 +174,7 @@ public class WifiServiceImplTest { private static final String WIFI_IFACE_NAME2 = "wlan1"; private static final String TEST_COUNTRY_CODE = "US"; private static final String TEST_FACTORY_MAC = "10:22:34:56:78:92"; + private static final String TEST_FQDN = "testfqdn"; private static final List<WifiConfiguration> TEST_WIFI_CONFIGURATION_LIST = Arrays.asList( WifiConfigurationTestUtil.generateWifiConfig( 0, 1000000, "\"red\"", true, true, null, null), @@ -2788,77 +2789,57 @@ public class WifiServiceImplTest { } /** - * Verify that the call to getPasspointConfigurations is not redirected to specific API - * syncGetPasspointConfigs when the caller doesn't have NETWORK_SETTINGS permissions and - * NETWORK_SETUP_WIZARD. + * Verify the call to getPasspointConfigurations when the caller doesn't have + * NETWORK_SETTINGS and NETWORK_SETUP_WIZARD permissions. */ - @Test(expected = SecurityException.class) - public void testGetPasspointConfigurationsWithOutPermissions() { + @Test + public void testGetPasspointConfigurationsWithOutPrivilegedPermissions() { when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME); + + verify(mClientModeImpl).syncGetPasspointConfigs(any(), eq(false)); } /** - * Verify that getPasspointConfigurations called by apps that has invalid package will - * throw {@link SecurityException}. + * Verify that the call to getPasspointConfigurations when the caller does have + * NETWORK_SETTINGS permission. */ - @Test(expected = SecurityException.class) - public void testGetPasspointConfigurationWithInvalidPackage() { - doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), - eq(TEST_PACKAGE_NAME)); + @Test + public void testGetPasspointConfigurationsWithPrivilegedPermissions() { when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(true); mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE_NAME); - } - /** - * Verify that getPasspointConfigurations called by apps targeting below Q SDK will return - * empty list if the caller doesn't have NETWORK_SETTINGS permissions and NETWORK_SETUP_WIZARD. - */ - @Test - public void testGetPasspointConfigurationForAppsTargetingBelowQSDK() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false); - when(mWifiPermissionsUtil.isTargetSdkLessThan(eq(TEST_PACKAGE_NAME), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); - - List<PasspointConfiguration> result = mWifiServiceImpl.getPasspointConfigurations( - TEST_PACKAGE_NAME); - assertNotNull(result); - assertEquals(0, result.size()); + verify(mClientModeImpl).syncGetPasspointConfigs(any(), eq(true)); } /** - * Verify that the call to removePasspointConfiguration is not redirected to specific API - * syncRemovePasspointConfig when the caller doesn't have NETWORK_SETTINGS and - * NETWORK_CARRIER_PROVISIONING permission. + * Verify the call to removePasspointConfigurations when the caller doesn't have + * NETWORK_SETTINGS and NETWORK_CARRIER_PROVISIONING permissions. */ - @Test(expected = SecurityException.class) - public void testRemovePasspointConfigurationWithOutPermissions() { + @Test + public void testRemovePasspointConfigurationWithOutPrivilegedPermissions() { when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn( false); - mWifiServiceImpl.removePasspointConfiguration(null, null); + mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME); + verify(mClientModeImpl).syncRemovePasspointConfig(any(), eq(false), eq(TEST_FQDN)); } /** - * Verify that the call to removePasspointConfiguration for apps targeting below Q SDK will - * return false if the caller doesn't have NETWORK_SETTINGS and NETWORK_CARRIER_PROVISIONING - * permission. + * Verify the call to removePasspointConfigurations when the caller does have + * NETWORK_CARRIER_PROVISIONING permission. */ @Test - public void testRemovePasspointConfigurationForAppsTargetingBelowQSDK() { - when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); + public void testRemovePasspointConfigurationWithPrivilegedPermissions() { when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(anyInt())).thenReturn( - false); - when(mWifiPermissionsUtil.isTargetSdkLessThan(isNull(), - eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); + true); - assertFalse(mWifiServiceImpl.removePasspointConfiguration(null, null)); + mWifiServiceImpl.removePasspointConfiguration(TEST_FQDN, TEST_PACKAGE_NAME); + verify(mClientModeImpl).syncRemovePasspointConfig(any(), eq(true), eq(TEST_FQDN)); } /** @@ -3449,6 +3430,25 @@ public class WifiServiceImplTest { } /** + * Verifies that entering airplane mode does not reset country code. + */ + @Test + public void testEnterAirplaneModeNotResetCountryCode() { + mWifiServiceImpl.checkAndStartWifi(); + verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), + (IntentFilter) argThat((IntentFilter filter) -> + filter.hasAction(Intent.ACTION_AIRPLANE_MODE_CHANGED))); + + when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); + + // Send the broadcast + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); + + verifyNoMoreInteractions(mWifiCountryCode); + } + + /** * Verify calls to notify users of a softap config change check the NETWORK_SETTINGS permission. */ @Test @@ -3650,13 +3650,14 @@ public class WifiServiceImplTest { mWifiServiceImpl.mClientModeImplChannel = mAsyncChannel; when(mClientModeImpl.syncGetConfiguredNetworks(anyInt(), any(), anyInt())) .thenReturn(Arrays.asList(network)); - when(mClientModeImpl.syncGetPasspointConfigs(any())).thenReturn(Arrays.asList(config)); + when(mClientModeImpl.syncGetPasspointConfigs(any(), anyBoolean())) + .thenReturn(Arrays.asList(config)); mWifiServiceImpl.factoryReset(TEST_PACKAGE_NAME); mLooper.dispatchAll(); verify(mClientModeImpl).syncRemoveNetwork(mAsyncChannel, network.networkId); - verify(mClientModeImpl).syncRemovePasspointConfig(mAsyncChannel, fqdn); + verify(mClientModeImpl).syncRemovePasspointConfig(mAsyncChannel, true, fqdn); verify(mWifiConfigManager).clearDeletedEphemeralNetworks(); verify(mClientModeImpl).clearNetworkRequestUserApprovedAccessPoints(); verify(mWifiNetworkSuggestionsManager).clear(); @@ -3679,8 +3680,9 @@ public class WifiServiceImplTest { mLooper.dispatchAll(); verify(mClientModeImpl).syncGetConfiguredNetworks(anyInt(), any(), anyInt()); - verify(mClientModeImpl, never()).syncGetPasspointConfigs(any()); - verify(mClientModeImpl, never()).syncRemovePasspointConfig(any(), anyString()); + verify(mClientModeImpl, never()).syncGetPasspointConfigs(any(), anyBoolean()); + verify(mClientModeImpl, never()).syncRemovePasspointConfig( + any(), anyBoolean(), anyString()); verify(mWifiConfigManager).clearDeletedEphemeralNetworks(); verify(mClientModeImpl).clearNetworkRequestUserApprovedAccessPoints(); verify(mWifiNetworkSuggestionsManager).clear(); @@ -3703,7 +3705,7 @@ public class WifiServiceImplTest { } catch (SecurityException e) { } verify(mClientModeImpl, never()).syncGetConfiguredNetworks(anyInt(), any(), anyInt()); - verify(mClientModeImpl, never()).syncGetPasspointConfigs(any()); + verify(mClientModeImpl, never()).syncGetPasspointConfigs(any(), eq(false)); } /** @@ -4269,4 +4271,17 @@ public class WifiServiceImplTest { } catch (RemoteException e) { } } + + /** + * Test to verify that the lock mode is verified before dispatching the operation + * + * Steps: call acquireWifiLock with an invalid lock mode. + * Expected: the call should throw an IllegalArgumentException. + */ + @Test(expected = IllegalArgumentException.class) + public void acquireWifiLockShouldThrowExceptionOnInvalidLockMode() throws Exception { + final int wifiLockModeInvalid = -1; + + mWifiServiceImpl.acquireWifiLock(mAppBinder, wifiLockModeInvalid, "", null); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java index aa44023ae..c33a4d55e 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -730,7 +730,7 @@ public class WifiVendorHalTest { IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS ); - int expected = ( + long expected = ( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps)); @@ -749,7 +749,7 @@ public class WifiVendorHalTest { | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT ); - int expected = ( + long expected = ( WifiManager.WIFI_FEATURE_TX_POWER_LIMIT | WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT @@ -768,7 +768,7 @@ public class WifiVendorHalTest { android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT ); - int expected = ( + long expected = ( WifiManager.WIFI_FEATURE_LOW_LATENCY | WifiManager.WIFI_FEATURE_D2D_RTT ); @@ -794,7 +794,7 @@ public class WifiVendorHalTest { add(IfaceType.STA); add(IfaceType.P2P); }}; - int expectedFeatureSet = ( + long expectedFeatureSet = ( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS | WifiManager.WIFI_FEATURE_TX_POWER_LIMIT diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java index c76e2c878..7a815001c 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiConfigStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -62,7 +63,7 @@ public class PasspointConfigSharedStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out); + mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -77,7 +78,9 @@ public class PasspointConfigSharedStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth()); + mConfigStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java index 82cdb5a90..5278e1933 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java @@ -32,6 +32,7 @@ import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -213,7 +214,7 @@ public class PasspointConfigUserStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out); + mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -228,7 +229,9 @@ public class PasspointConfigUserStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth()); + mConfigStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java index 338f7bc40..131425af8 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java @@ -268,7 +268,8 @@ public class PasspointManagerTest { * @param expectedConfig The expected installed Passpoint configuration */ private void verifyInstalledConfig(PasspointConfiguration expectedConfig) { - List<PasspointConfiguration> installedConfigs = mManager.getProviderConfigs(); + List<PasspointConfiguration> installedConfigs = + mManager.getProviderConfigs(TEST_CREATOR_UID, true); assertEquals(1, installedConfigs.size()); assertEquals(expectedConfig, installedConfigs.get(0)); } @@ -283,6 +284,7 @@ public class PasspointManagerTest { PasspointProvider provider = mock(PasspointProvider.class); when(provider.installCertsAndKeys()).thenReturn(true); lenient().when(provider.getConfig()).thenReturn(config); + lenient().when(provider.getCreatorUid()).thenReturn(TEST_CREATOR_UID); return provider; } @@ -651,14 +653,14 @@ public class PasspointManagerTest { // Provider index start with 0, should be 1 after adding a provider. assertEquals(1, mSharedDataSource.getProviderIndex()); - // Remove the provider. - assertTrue(mManager.removeProvider(TEST_FQDN)); + // Remove the provider as the creator app. + assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, TEST_FQDN)); verify(provider).uninstallCertsAndKeys(); verify(mWifiConfigManager).saveToStore(true); verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class)); - assertTrue(mManager.getProviderConfigs().isEmpty()); + assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); // Verify content in the data source. assertTrue(mUserDataSource.getProviders().isEmpty()); @@ -694,13 +696,13 @@ public class PasspointManagerTest { // Provider index start with 0, should be 1 after adding a provider. assertEquals(1, mSharedDataSource.getProviderIndex()); - // Remove the provider. - assertTrue(mManager.removeProvider(TEST_FQDN)); + // Remove the provider as a privileged non-creator app. + assertTrue(mManager.removeProvider(TEST_UID, true, TEST_FQDN)); verify(provider).uninstallCertsAndKeys(); verify(mWifiConfigManager).saveToStore(true); verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); - assertTrue(mManager.getProviderConfigs().isEmpty()); + assertTrue(mManager.getProviderConfigs(TEST_UID, true).isEmpty()); // Verify content in the data source. assertTrue(mUserDataSource.getProviders().isEmpty()); @@ -824,7 +826,7 @@ public class PasspointManagerTest { */ @Test public void removeNonExistingProvider() throws Exception { - assertFalse(mManager.removeProvider(TEST_FQDN)); + assertFalse(mManager.removeProvider(TEST_CREATOR_UID, true, TEST_FQDN)); verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); } @@ -1285,8 +1287,8 @@ public class PasspointManagerTest { mUserDataSource.setProviders(providers); // Verify the providers maintained by PasspointManager. - assertEquals(1, mManager.getProviderConfigs().size()); - assertEquals(config, mManager.getProviderConfigs().get(0)); + assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size()); + assertEquals(config, mManager.getProviderConfigs(TEST_CREATOR_UID, true).get(0)); } /** @@ -1800,7 +1802,7 @@ public class PasspointManagerTest { verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE), mAppOpChangedListenerCaptor.capture()); - assertEquals(1, mManager.getProviderConfigs().size()); + assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size()); AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue(); assertNotNull(listener); @@ -1814,6 +1816,45 @@ public class PasspointManagerTest { verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue()); verify(mClientModeImpl).disconnectCommand(); - assertTrue(mManager.getProviderConfigs().isEmpty()); + assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, true).isEmpty()); + } + + /** + * Verify that removing a provider with a different UID will not succeed. + * + * @throws Exception + */ + @Test + public void removeGetProviderWithDifferentUid() throws Exception { + PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, + TEST_REALM); + PasspointProvider provider = createMockProvider(config); + when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), + eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn( + provider); + assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE)); + verifyInstalledConfig(config); + verify(mWifiConfigManager).saveToStore(true); + verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); + verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); + reset(mWifiMetrics); + reset(mWifiConfigManager); + + // no profiles available for TEST_UID + assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty()); + // 1 profile available for TEST_CREATOR_UID + assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); + + // Remove the provider as a non-privileged non-creator app. + assertFalse(mManager.removeProvider(TEST_UID, false, TEST_FQDN)); + verify(provider, never()).uninstallCertsAndKeys(); + verify(mWifiConfigManager, never()).saveToStore(true); + verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); + verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); + + // no profiles available for TEST_UID + assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty()); + // 1 profile available for TEST_CREATOR_UID + assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty()); } } diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java index 15d9ef915..1091c1dac 100644 --- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java @@ -3812,4 +3812,28 @@ public class WifiP2pServiceImplTest { mLooper.dispatchAll(); verify(mWifiNative).p2pStopFind(); } + + /** + * Verify a network name which is too long is rejected. + */ + @Test + public void testSendConnectMsgWithTooLongNetworkName() throws Exception { + mTestWifiP2pFastConnectionConfig.networkName = "DIRECT-xy-abcdefghijklmnopqrstuvw"; + sendConnectMsg(mClientMessenger, mTestWifiP2pFastConnectionConfig); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_FAILED, message.what); + } + + /** + * Verify a network name which is too short is rejected. + */ + @Test + public void testSendConnectMsgWithTooShortNetworkName() throws Exception { + mTestWifiP2pFastConnectionConfig.networkName = "DIRECT-x"; + sendConnectMsg(mClientMessenger, mTestWifiP2pFastConnectionConfig); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_FAILED, message.what); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java b/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java index d2f22da6a..bd0ad321d 100644 --- a/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java +++ b/tests/wifitests/src/com/android/server/wifi/rtt/RttNativeTest.java @@ -18,6 +18,7 @@ package com.android.server.wifi.rtt; import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -42,6 +43,7 @@ import android.hardware.wifi.V1_0.WifiStatus; import android.hardware.wifi.V1_0.WifiStatusCode; import android.net.MacAddress; import android.net.wifi.rtt.RangingRequest; +import android.net.wifi.rtt.ResponderConfig; import androidx.test.filters.SmallTest; @@ -465,6 +467,28 @@ public class RttNativeTest { } } + /** + * Validation ranging with invalid bw and preamble combination will be ignored. + */ + @Test + public void testRangingWithInvalidParameterCombination() throws Exception { + int cmdId = 88; + RangingRequest request = new RangingRequest.Builder().build(); + ResponderConfig invalidConfig = new ResponderConfig( + MacAddress.fromString("08:09:08:07:06:88"), ResponderConfig.RESPONDER_AP, true, + ResponderConfig.CHANNEL_WIDTH_80MHZ, 0, 0, 0, ResponderConfig.PREAMBLE_HT); + ResponderConfig config = new ResponderConfig(MacAddress.fromString("08:09:08:07:06:89"), + ResponderConfig.RESPONDER_AP, true, + ResponderConfig.CHANNEL_WIDTH_80MHZ, 0, 0, 0, ResponderConfig.PREAMBLE_VHT); + + // Add a ResponderConfig with invalid parameter, should be ignored. + request.mRttPeers.add(invalidConfig); + request.mRttPeers.add(config); + mDut.rangeRequest(cmdId, request, true); + verify(mockRttController).rangeRequest(eq(cmdId), mRttConfigCaptor.capture()); + assertEquals(request.mRttPeers.size() - 1, mRttConfigCaptor.getValue().size()); + } + // Utilities /** diff --git a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java b/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java deleted file mode 100644 index c281b6440..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 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.util; - -import static org.junit.Assert.*; - -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; - -/** - * Unit tests for {@link com.android.server.wifi.util.DataIntegrityChecker}. - */ -public class DataIntegrityCheckerTest { - private static byte[] sGoodData = {1, 2, 3, 4}; - private static byte[] sBadData = {5, 6, 7, 8}; - - /** - * Verify that updating the integrity token with known data and alias will - * pass the integrity test. This test ensure the expected outcome for - * unedited data succeeds. - * - * @throws Exception - */ - @Test - @Ignore - public void testIntegrityWithKnownDataAndKnownAlias() throws Exception { - File integrityFile = File.createTempFile("testIntegrityWithKnownDataAndKnownAlias", - ".tmp"); - DataIntegrityChecker dataIntegrityChecker = new DataIntegrityChecker( - integrityFile.getParent()); - EncryptedData encryptedData = dataIntegrityChecker.compute(sGoodData); - assertTrue(dataIntegrityChecker.isOk(sGoodData, encryptedData)); - } - - /** - * Verify that checking the integrity of unknown data and a known alias - * will fail the integrity test. This test ensure the expected failure for - * altered data, in fact, fails. - * - * - * @throws Exception - */ - @Test - @Ignore - public void testIntegrityWithUnknownDataAndKnownAlias() throws Exception { - File integrityFile = File.createTempFile("testIntegrityWithUnknownDataAndKnownAlias", - ".tmp"); - DataIntegrityChecker dataIntegrityChecker = new DataIntegrityChecker( - integrityFile.getParent()); - EncryptedData encryptedData = dataIntegrityChecker.compute(sGoodData); - assertFalse(dataIntegrityChecker.isOk(sBadData, encryptedData)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java index 45adffd1d..266a2ce23 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java @@ -116,6 +116,82 @@ public class ScanResultUtilTest { assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)); } + /** + * Test that a PSK-SHA256+SAE network is detected as transition mode + */ + @Test + public void testPskSha256SaeTransitionModeCheck() { + final String ssid = "WPA3-Transition"; + String caps = "[WPA2-FT/PSK-CCMP][RSN-FT/PSK+PSK-SHA256+SAE+FT/SAE-CCMP][ESS][WPS]"; + + ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + + input.informationElements = new InformationElement[] { + createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) + }; + + assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); + } + + /** + * Test that a PSK+SAE network is detected as transition mode + */ + @Test + public void testPskSaeTransitionModeCheck() { + final String ssid = "WPA3-Transition"; + String caps = "[WPA2-FT/PSK+PSK+SAE+FT/SAE-CCMP][ESS][WPS]"; + + ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + + input.informationElements = new InformationElement[] { + createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) + }; + + assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); + } + + /** + * Test that a PSK network is not detected as transition mode + */ + @Test + public void testPskNotInTransitionModeCheck() { + final String ssid = "WPA2-Network"; + String caps = "[WPA2-FT/PSK+PSK][ESS][WPS]"; + + ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + + input.informationElements = new InformationElement[] { + createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) + }; + + assertFalse(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); + } + + /** + * Test that an SAE network is not detected as transition mode + */ + @Test + public void testSaeNotInTransitionModeCheck() { + final String ssid = "WPA3-Network"; + String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]"; + + ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid, + "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0, + 0, true); + + input.informationElements = new InformationElement[] { + createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) + }; + + assertFalse(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); + } + private static InformationElement createIE(int id, byte[] bytes) { InformationElement ie = new InformationElement(); ie.id = id; diff --git a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java index 85b4a9370..8f96bc106 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java @@ -35,7 +35,9 @@ import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil; import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil; +import org.junit.Before; import org.junit.Test; +import org.mockito.MockitoAnnotations; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -73,6 +75,13 @@ public class XmlUtilTest { private static final int TEST_PHASE2_METHOD = WifiEnterpriseConfig.Phase2.MSCHAPV2; private final String mXmlDocHeader = "XmlUtilTest"; + private WifiConfigStoreEncryptionUtil mWifiConfigStoreEncryptionUtil = null; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + /** * Verify that a open WifiConfiguration is serialized & deserialized correctly. */ @@ -101,6 +110,22 @@ public class XmlUtilTest { } /** + * Verify that a psk WifiConfiguration is serialized & deserialized correctly. + */ + @Test + public void testPskWifiConfigurationSerializeDeserializeWithEncryption() + throws IOException, XmlPullParserException { + mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); + WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); + EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); + when(mWifiConfigStoreEncryptionUtil.encrypt(pskNetwork.preSharedKey.getBytes())) + .thenReturn(encryptedData); + when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) + .thenReturn(pskNetwork.preSharedKey.getBytes()); + serializeDeserializeWifiConfiguration(pskNetwork); + } + + /** * Verify that a psk hidden WifiConfiguration is serialized & deserialized correctly. */ @Test @@ -382,6 +407,37 @@ public class XmlUtilTest { } /** + * Verify that a WifiEnterpriseConfig object is serialized & deserialized correctly. + */ + @Test + public void testWifiEnterpriseConfigSerializeDeserializeWithEncryption() + throws IOException, XmlPullParserException { + WifiEnterpriseConfig config = new WifiEnterpriseConfig(); + config.setFieldValue(WifiEnterpriseConfig.IDENTITY_KEY, TEST_IDENTITY); + config.setFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY, TEST_ANON_IDENTITY); + config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, TEST_PASSWORD); + config.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, TEST_CLIENT_CERT); + config.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, TEST_CA_CERT); + config.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, TEST_SUBJECT_MATCH); + config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, TEST_ENGINE); + config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, TEST_ENGINE_ID); + config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, TEST_PRIVATE_KEY_ID); + config.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, TEST_ALTSUBJECT_MATCH); + config.setFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, TEST_DOM_SUFFIX_MATCH); + config.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, TEST_CA_PATH); + config.setEapMethod(TEST_EAP_METHOD); + config.setPhase2Method(TEST_PHASE2_METHOD); + + mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); + EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); + when(mWifiConfigStoreEncryptionUtil.encrypt(TEST_PASSWORD.getBytes())) + .thenReturn(encryptedData); + when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) + .thenReturn(TEST_PASSWORD.getBytes()); + serializeDeserializeWifiEnterpriseConfig(config); + } + + /** * Verify that an illegal argument exception is thrown when trying to parse out a corrupted * WifiEnterpriseConfig. * @@ -473,7 +529,8 @@ public class XmlUtilTest { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, configuration); + WifiConfigurationXmlUtil.writeToXmlForConfigStore( + out, configuration, mWifiConfigStoreEncryptionUtil); XmlUtil.writeDocumentEnd(out, mXmlDocHeader); return outputStream.toByteArray(); } @@ -485,7 +542,10 @@ public class XmlUtilTest { ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiConfigurationXmlUtil.parseFromXml(in, in.getDepth()); + return WifiConfigurationXmlUtil.parseFromXml( + in, in.getDepth(), + mWifiConfigStoreEncryptionUtil != null, + mWifiConfigStoreEncryptionUtil); } /** @@ -593,7 +653,8 @@ public class XmlUtilTest { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiEnterpriseConfigXmlUtil.writeToXml(out, config); + WifiEnterpriseConfigXmlUtil.writeToXml( + out, config, mWifiConfigStoreEncryptionUtil); XmlUtil.writeDocumentEnd(out, mXmlDocHeader); return outputStream.toByteArray(); } @@ -604,7 +665,9 @@ public class XmlUtilTest { ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiEnterpriseConfigXmlUtil.parseFromXml(in, in.getDepth()); + return WifiEnterpriseConfigXmlUtil.parseFromXml( + in, in.getDepth(), mWifiConfigStoreEncryptionUtil != null, + mWifiConfigStoreEncryptionUtil); } private void serializeDeserializeWifiEnterpriseConfig(WifiEnterpriseConfig config) |