diff options
author | Rebecca Silberstein <silberst@google.com> | 2016-04-14 15:25:13 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-04-14 15:25:14 +0000 |
commit | c38419bd95b0934cb1dfc6f1e1f29eca9929da8c (patch) | |
tree | 32aff69b2e1ac1a6037000eeb00b6f039229b1ee | |
parent | deaf58e6f2c5fb93543f3ead79c1f160cc2248a8 (diff) | |
parent | 93332917bf29ddbe853a495816e486150f49da40 (diff) |
Merge "Update hasEverConnected for wifi networks" into nyc-dev
4 files changed, 691 insertions, 11 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 2a8c78f0f..408269e6e 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -83,8 +83,10 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; +import java.security.cert.X509Certificate; import java.text.DateFormat; import java.util.ArrayList; +import java.util.BitSet; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -1971,6 +1973,11 @@ public class WifiConfigManager { // Fetch the existing config using networkID currentConfig = mConfiguredNetworks.getForCurrentUser(config.networkId); } + + // originalConfig is used to check for credential and config changes that would cause + // HasEverConnected to be set to false. + WifiConfiguration originalConfig = new WifiConfiguration(currentConfig); + if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig)) { return new NetworkUpdateResult(INVALID_NETWORK_ID); } @@ -2097,6 +2104,16 @@ public class WifiConfigManager { } } + boolean passwordChanged = false; + // check passed in config to see if it has more than a password set. + if (!newNetwork && config.preSharedKey != null && !config.preSharedKey.equals("*")) { + passwordChanged = true; + } + + if (newNetwork || passwordChanged || wasCredentialChange(originalConfig, currentConfig)) { + currentConfig.getNetworkSelectionStatus().setHasEverConnected(false); + } + // Persist configuration paramaters that are not saved by supplicant. if (config.lastUpdateName != null) { currentConfig.lastUpdateName = config.lastUpdateName; @@ -2122,6 +2139,119 @@ public class WifiConfigManager { return result; } + private boolean wasBitSetUpdated(BitSet originalBitSet, BitSet currentBitSet) { + if (originalBitSet != null && currentBitSet != null) { + // both configs have values set, check if they are different + if (!originalBitSet.equals(currentBitSet)) { + // the BitSets are different + return true; + } + } else if (originalBitSet != null || currentBitSet != null) { + return true; + } + return false; + } + + private boolean wasCredentialChange(WifiConfiguration originalConfig, + WifiConfiguration currentConfig) { + // Check if any core WifiConfiguration parameters changed that would impact new connections + if (originalConfig == null) { + return true; + } + + if (wasBitSetUpdated(originalConfig.allowedKeyManagement, + currentConfig.allowedKeyManagement)) { + return true; + } + + if (wasBitSetUpdated(originalConfig.allowedProtocols, currentConfig.allowedProtocols)) { + return true; + } + + if (wasBitSetUpdated(originalConfig.allowedAuthAlgorithms, + currentConfig.allowedAuthAlgorithms)) { + return true; + } + + if (wasBitSetUpdated(originalConfig.allowedPairwiseCiphers, + currentConfig.allowedPairwiseCiphers)) { + return true; + } + + if (wasBitSetUpdated(originalConfig.allowedGroupCiphers, + currentConfig.allowedGroupCiphers)) { + return true; + } + + if (originalConfig.wepKeys != null && currentConfig.wepKeys != null) { + if (originalConfig.wepKeys.length == currentConfig.wepKeys.length) { + for (int i = 0; i < originalConfig.wepKeys.length; i++) { + if (originalConfig.wepKeys[i] != currentConfig.wepKeys[i]) { + return true; + } + } + } else { + return true; + } + } + + if (originalConfig.hiddenSSID != currentConfig.hiddenSSID) { + return true; + } + + if (originalConfig.requirePMF != currentConfig.requirePMF) { + return true; + } + + if (wasEnterpriseConfigChange(originalConfig.enterpriseConfig, + currentConfig.enterpriseConfig)) { + return true; + } + return false; + } + + + protected boolean wasEnterpriseConfigChange(WifiEnterpriseConfig originalEnterpriseConfig, + WifiEnterpriseConfig currentEnterpriseConfig) { + if (originalEnterpriseConfig != null && currentEnterpriseConfig != null) { + if (originalEnterpriseConfig.getEapMethod() != currentEnterpriseConfig.getEapMethod()) { + return true; + } + + if (originalEnterpriseConfig.getPhase2Method() + != currentEnterpriseConfig.getPhase2Method()) { + return true; + } + + X509Certificate[] originalCaCerts = originalEnterpriseConfig.getCaCertificates(); + X509Certificate[] currentCaCerts = currentEnterpriseConfig.getCaCertificates(); + + if (originalCaCerts != null && currentCaCerts != null) { + if (originalCaCerts.length == currentCaCerts.length) { + for (int i = 0; i < originalCaCerts.length; i++) { + if (!originalCaCerts[i].equals(currentCaCerts[i])) { + return true; + } + } + } else { + // number of aliases is different, so the configs are different + return true; + } + } else { + // one of the enterprise configs may have aliases + if (originalCaCerts != null || currentCaCerts != null) { + return true; + } + } + } else { + // One of the configs may have an enterpriseConfig + if (originalEnterpriseConfig != null || currentEnterpriseConfig != null) { + return true; + } + } + return false; + } + public WifiConfiguration getWifiConfigForHomeSP(HomeSP homeSP) { WifiConfiguration config = mConfiguredNetworks.getByFQDNForCurrentUser(homeSP.getFQDN()); if (config == null) { diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 19489bfe4..529774333 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -5174,8 +5174,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss //Here we will clear all disable counters once a network is connected //records how long this network is connected in future config.lastConnected = System.currentTimeMillis(); - config.getNetworkSelectionStatus().clearDisableReasonCounter(); config.numAssociation++; + WifiConfiguration.NetworkSelectionStatus networkSelectionStatus = + config.getNetworkSelectionStatus(); + networkSelectionStatus.clearDisableReasonCounter(); + networkSelectionStatus.setHasEverConnected(true); } // On connect, reset wifiScoreReport mWifiScoreReport = null; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 59cbd48b9..53353f997 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -38,7 +38,11 @@ import android.content.Context; import android.content.pm.UserInfo; import android.net.wifi.FakeKeys; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; @@ -130,6 +134,14 @@ public class WifiConfigManagerTest { } } + /** + * Set of WifiConfigs for HasEverConnected tests. + */ + private static final int HAS_EVER_CONNECTED_USER = 20; + private static final WifiConfiguration BASE_HAS_EVER_CONNECTED_CONFIG = + WifiConfigurationTestUtil.generateWifiConfig( + 0, HAS_EVER_CONNECTED_USER, "testHasEverConnected", false, true, null, null, 0); + public static final String TAG = "WifiConfigManagerTest"; @Mock private Context mContext; @Mock private WifiNative mWifiNative; @@ -216,21 +228,27 @@ public class WifiConfigManagerTest { } private void addNetworks() throws Exception { + for (int i = 0; i < CONFIGS.size(); ++i) { + assertEquals(i, CONFIGS.get(i).networkId); + addNetwork(CONFIGS.get(i)); + } + } + + private void addNetwork(WifiConfiguration config) throws Exception { final int originalUserId = mWifiConfigManager.getCurrentUserId(); when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) .thenReturn(true); - for (int i = 0; i < CONFIGS.size(); ++i) { - assertEquals(i, CONFIGS.get(i).networkId); - switchUserToCreatorOrParentOf(CONFIGS.get(i)); - final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i)); - config.networkId = -1; - when(mWifiNative.addNetwork()).thenReturn(i); - when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) - .thenReturn(encodeConfigSSID(CONFIGS.get(i))); - mWifiConfigManager.saveNetwork(config, config.creatorUid); - } + + switchUserToCreatorOrParentOf(config); + final WifiConfiguration configCopy = new WifiConfiguration(config); + int networkId = config.networkId; + config.networkId = -1; + when(mWifiNative.addNetwork()).thenReturn(networkId); + when(mWifiNative.getNetworkVariable(networkId, WifiConfiguration.ssidVarName)) + .thenReturn(encodeConfigSSID(config)); + mWifiConfigManager.saveNetwork(config, configCopy.creatorUid); switchUser(originalUserId); } @@ -1156,4 +1174,470 @@ public class WifiConfigManagerTest { new ArrayList(networkSelectionStatusToNetworkIdMap.values())); } } + + /** + * Verifies that hasEverConnected is false for a newly added network + */ + @Test + public void testAddNetworkHasEverConnectedFalse() throws Exception { + addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG); + WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + assertFalse("Adding a new network should not have hasEverConnected set to true.", + checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + + /** + * Verifies that hasEverConnected is false for a newly added network even when new config has + * mistakenly set HasEverConnected to true. + */ + @Test + public void testAddNetworkOverridesHasEverConnectedWhenTrueInNewConfig() throws Exception { + WifiConfiguration newNetworkWithHasEverConnectedTrue = + new WifiConfiguration(BASE_HAS_EVER_CONNECTED_CONFIG); + newNetworkWithHasEverConnectedTrue.getNetworkSelectionStatus().setHasEverConnected(true); + addNetwork(newNetworkWithHasEverConnectedTrue); + // check if addNetwork clears the bit. + WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( + newNetworkWithHasEverConnectedTrue.networkId); + assertFalse("Adding a new network should not have hasEverConnected set to true.", + checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + + /** + * Verify that setting HasEverConnected with a config update can be read back. + */ + @Test + public void testUpdateConfigToHasEverConnectedTrue() throws Exception { + addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG); + + // Get the newly saved config and update HasEverConnected + WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + assertFalse("Adding a new network should not have hasEverConnected set to true.", + checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + checkConfig.getNetworkSelectionStatus().setHasEverConnected(true); + mWifiConfigManager.addOrUpdateNetwork(checkConfig, HAS_EVER_CONNECTED_USER); + + // verify that HasEverConnected was properly written and read back + checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + } + + + /** + * Verifies that hasEverConnected is cleared when a network config preSharedKey is updated. + */ + @Test + public void testUpdatePreSharedKeyClearsHasEverConnected() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration original = mWifiConfigManager.getWifiConfiguration( + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + WifiConfiguration updatePreSharedKeyConfig = new WifiConfiguration(); + updatePreSharedKeyConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updatePreSharedKeyConfig.SSID = original.SSID; + updatePreSharedKeyConfig.preSharedKey = "newpassword"; + switchUserToCreatorOrParentOf(original); + mWifiConfigManager.addOrUpdateNetwork(updatePreSharedKeyConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config allowedKeyManagement is + * updated. + */ + @Test + public void testUpdateAllowedKeyManagementChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateAllowedKeyManagementConfig = new WifiConfiguration(); + updateAllowedKeyManagementConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateAllowedKeyManagementConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateAllowedKeyManagementConfig.allowedKeyManagement.set(KeyMgmt.WPA_PSK); + + // Set up mock to allow the new value to be read back into the config + String allowedKeyManagementString = makeString( + updateAllowedKeyManagementConfig.allowedKeyManagement, + WifiConfiguration.KeyMgmt.strings); + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + KeyMgmt.varName)).thenReturn(allowedKeyManagementString); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateAllowedKeyManagementConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config allowedProtocols is + * updated. + */ + @Test + public void testUpdateAllowedProtocolsChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateAllowedProtocolsConfig = new WifiConfiguration(); + updateAllowedProtocolsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateAllowedProtocolsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateAllowedProtocolsConfig.allowedProtocols.set( + WifiConfiguration.Protocol.RSN); + + // Set up mock to allow the new value to be read back into the config + String allowedProtocolsString = makeString( + updateAllowedProtocolsConfig.allowedProtocols, + WifiConfiguration.Protocol.strings); + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + Protocol.varName)).thenReturn(allowedProtocolsString); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateAllowedProtocolsConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config allowedAuthAlgorithms is + * updated. + */ + @Test + public void testUpdateAllowedAuthAlgorithmsChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateAllowedAuthAlgorithmsConfig = new WifiConfiguration(); + updateAllowedAuthAlgorithmsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateAllowedAuthAlgorithmsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms.set( + WifiConfiguration.AuthAlgorithm.SHARED); + + // Set up mock to allow the new value to be read back into the config + String allowedAuthAlgorithmsString = makeString( + updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms, + WifiConfiguration.AuthAlgorithm.strings); + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + AuthAlgorithm.varName)).thenReturn(allowedAuthAlgorithmsString); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateAllowedAuthAlgorithmsConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config allowedPairwiseCiphers is + * updated. + */ + @Test + public void testUpdateAllowedPairwiseCiphersChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateAllowedPairwiseCiphersConfig = new WifiConfiguration(); + updateAllowedPairwiseCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateAllowedPairwiseCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers.set( + WifiConfiguration.PairwiseCipher.CCMP); + + // Set up mock to allow the new value to be read back into the config + String allowedPairwiseCiphersString = makeString( + updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers, + WifiConfiguration.PairwiseCipher.strings); + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + PairwiseCipher.varName)).thenReturn(allowedPairwiseCiphersString); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateAllowedPairwiseCiphersConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config allowedGroupCiphers is + * updated. + */ + @Test + public void testUpdateAllowedGroupCiphersChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateAllowedGroupCiphersConfig = new WifiConfiguration(); + updateAllowedGroupCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateAllowedGroupCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateAllowedGroupCiphersConfig.allowedGroupCiphers.set( + WifiConfiguration.GroupCipher.CCMP); + + // Set up mock to allow the new value to be read back into the config + String allowedGroupCiphersString = makeString( + updateAllowedGroupCiphersConfig.allowedGroupCiphers, + WifiConfiguration.GroupCipher.strings); + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + GroupCipher.varName)).thenReturn(allowedGroupCiphersString); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateAllowedGroupCiphersConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config wepKeys is + * updated. + */ + @Test + public void testUpdateWepKeysChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + String tempKey = "hereisakey"; + WifiConfiguration updateWepKeysConfig = new WifiConfiguration(); + updateWepKeysConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateWepKeysConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateWepKeysConfig.wepKeys = new String[] {tempKey}; + + // Set up mock to allow the new value to be read back into the config + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + WifiConfiguration.wepKeyVarNames[0])).thenReturn(tempKey); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateWepKeysConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config hiddenSSID is + * updated. + */ + @Test + public void testUpdateHiddenSSIDChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateHiddenSSIDConfig = new WifiConfiguration(); + updateHiddenSSIDConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateHiddenSSIDConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateHiddenSSIDConfig.hiddenSSID = true; + + // Set up mock to allow the new value to be read back into the config + when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + WifiConfiguration.hiddenSSIDVarName)).thenReturn("1"); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateHiddenSSIDConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verifies that hasEverConnected is cleared when a network config pmfVarName is + * updated. + */ + @Test + public void testUpdateRequirePMFChanged() throws Exception { + final int originalUserId = mWifiConfigManager.getCurrentUserId(); + + testUpdateConfigToHasEverConnectedTrue(); + + WifiConfiguration updateRequirePMFConfig = new WifiConfiguration(); + updateRequirePMFConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; + updateRequirePMFConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; + updateRequirePMFConfig.requirePMF = true; + + // Set up mock to allow the new value to be read back into the config + // TODO: please see b/28088226 - this test is implemented as if WifiConfigStore correctly + // read back the boolean value. When fixed, uncomment the following line and the + // checkHasEverConnectedFalse below. + //when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, + // WifiConfiguration.pmfVarName)).thenReturn("2"); + + switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); + mWifiConfigManager.addOrUpdateNetwork(updateRequirePMFConfig, + BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + + //checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); + switchUser(originalUserId); + } + + /** + * Verify WifiEnterpriseConfig changes are detected in WifiConfigManager. + */ + @Test + public void testEnterpriseConfigAdded() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(null, eapConfig.enterpriseConfig)); + } + + /** + * Verify WifiEnterpriseConfig eap change is detected. + */ + @Test + public void testEnterpriseConfigEapChangeDetected() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS); + EnterpriseConfig peapConfig = new EnterpriseConfig(Eap.PEAP); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, + peapConfig.enterpriseConfig)); + } + + /** + * Verify WifiEnterpriseConfig phase2 method change is detected. + */ + @Test + public void testEnterpriseConfigPhase2ChangeDetected() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.MSCHAPV2); + EnterpriseConfig papConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.PAP); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, + papConfig.enterpriseConfig)); + } + + /** + * Verify WifiEnterpriseConfig added Certificate is detected. + */ + @Test + public void testCaCertificateAddedDetected() { + EnterpriseConfig eapConfigNoCerts = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password"); + + EnterpriseConfig eapConfig1Cert = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfigNoCerts.enterpriseConfig, + eapConfig1Cert.enterpriseConfig)); + } + + /** + * Verify WifiEnterpriseConfig Certificate change is detected. + */ + @Test + public void testDifferentCaCertificateDetected() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); + + EnterpriseConfig eapConfigNewCert = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1}); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, + eapConfigNewCert.enterpriseConfig)); + } + + /** + * Verify WifiEnterpriseConfig added Certificate changes are detected. + */ + @Test + public void testCaCertificateChangesDetected() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); + + EnterpriseConfig eapConfigAddedCert = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); + + assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, + eapConfigAddedCert.enterpriseConfig)); + } + + /** + * Verify that WifiEnterpriseConfig does not detect changes for identical configs. + */ + @Test + public void testWifiEnterpriseConfigNoChanges() { + EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); + + // Just to be clear that check is not against the same object + EnterpriseConfig eapConfigSame = new EnterpriseConfig(Eap.TTLS) + .setPhase2(Phase2.MSCHAPV2) + .setIdentity("username", "password") + .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); + + assertFalse(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, + eapConfigSame.enterpriseConfig)); + } + + + private void checkHasEverConnectedTrue(int networkId) { + WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId); + assertTrue("hasEverConnected expected to be true.", + checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + private void checkHasEverConnectedFalse(int networkId) { + WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId); + assertFalse("Updating credentials network config should clear hasEverConnected.", + checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + /** + * Helper function to translate from WifiConfiguration BitSet to String. + */ + private static String makeString(BitSet set, String[] strings) { + StringBuffer buf = new StringBuffer(); + int nextSetBit = -1; + + /* Make sure all set bits are in [0, strings.length) to avoid + * going out of bounds on strings. (Shouldn't happen, but...) */ + set = set.get(0, strings.length); + + while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { + buf.append(strings[nextSetBit].replace('_', '-')).append(' '); + } + + // remove trailing space + if (set.cardinality() > 0) { + buf.setLength(buf.length() - 1); + } + + return buf.toString(); + } + + } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java index c16a416cc..24d6a81cc 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java @@ -113,6 +113,7 @@ public class WifiStateMachineTest { (ActivityManager.isLowRamDeviceStatic() ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY : WifiStateMachine.NUM_LOG_RECS_VERBOSE); + private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\""; private long mBinderToken; @@ -727,6 +728,24 @@ public class WifiStateMachineTest { } /** + * Helper method to retrieve WifiConfiguration by SSID. + * + * Returns the associated WifiConfiguration if it is found, null otherwise. + */ + private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { + mLooper.startAutoDispatch(); + List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); + mLooper.stopAutoDispatch(); + + for (WifiConfiguration checkConfig : configs) { + if (checkConfig.SSID.equals(ssid)) { + return checkConfig; + } + } + return null; + } + + /** * Verifies that the current foreground user is allowed to forget a network. */ @Test @@ -923,6 +942,50 @@ public class WifiStateMachineTest { assertEquals("DisconnectedState", getCurrentState().getName()); } + /** + * WifiConfigurations default to HasEverConnected to false, creating and adding a config should + * not update this value to true. + * + * Test: Successfully add a network. Check the config and verify + * WifiConfiguration.getHasEverConnected() is false. + */ + @Test + public void addNetworkDoesNotSetHasEverConnectedTrue() throws Exception { + addNetworkAndVerifySuccess(); + + WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); + assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + /** + * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected + * to true. + * + * Test: Successfully create and connect to a network. Check the config and verify + * WifiConfiguration.getHasEverConnected() is true. + */ + @Test + public void setHasEverConnectedTrueOnConnect() throws Exception { + connect(); + + WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); + assertTrue(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + + /** + * Fail network connection attempt and verify HasEverConnected remains false. + * + * Test: Successfully create a network but fail when connecting. Check the config and verify + * WifiConfiguration.getHasEverConnected() is false. + */ + @Test + public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { + testDhcpFailure(); + + WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); + assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); + } + @Test public void handleUserSwitch() throws Exception { assertEquals(UserHandle.USER_SYSTEM, mWifiConfigManager.getCurrentUserId()); |