WifiConfigManagerTest.java revision e70ba4d25583efb1528f5e7bb32e0fea39a7ab41
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.server.wifi; 18 19import static org.hamcrest.CoreMatchers.not; 20import static org.junit.Assert.assertEquals; 21import static org.junit.Assert.assertFalse; 22import static org.junit.Assert.assertNotNull; 23import static org.junit.Assert.assertNull; 24import static org.junit.Assert.assertTrue; 25import static org.junit.Assert.fail; 26import static org.mockito.Mockito.anyInt; 27import static org.mockito.Mockito.anyObject; 28import static org.mockito.Mockito.anyString; 29import static org.mockito.Mockito.doAnswer; 30import static org.mockito.Mockito.eq; 31import static org.mockito.Mockito.intThat; 32import static org.mockito.Mockito.never; 33import static org.mockito.Mockito.reset; 34import static org.mockito.Mockito.verify; 35import static org.mockito.Mockito.when; 36 37import android.content.Context; 38import android.content.pm.UserInfo; 39import android.net.wifi.FakeKeys; 40import android.net.wifi.WifiConfiguration; 41import android.net.wifi.WifiConfiguration.AuthAlgorithm; 42import android.net.wifi.WifiConfiguration.GroupCipher; 43import android.net.wifi.WifiConfiguration.KeyMgmt; 44import android.net.wifi.WifiConfiguration.PairwiseCipher; 45import android.net.wifi.WifiConfiguration.Protocol; 46import android.net.wifi.WifiEnterpriseConfig; 47import android.net.wifi.WifiEnterpriseConfig.Eap; 48import android.net.wifi.WifiEnterpriseConfig.Phase2; 49import android.net.wifi.WifiScanner; 50import android.os.Process; 51import android.os.UserHandle; 52import android.os.UserManager; 53import android.security.Credentials; 54import android.support.test.InstrumentationRegistry; 55import android.test.suitebuilder.annotation.SmallTest; 56import android.text.TextUtils; 57import android.util.Log; 58import android.util.SparseArray; 59 60import com.android.server.net.DelayedDiskWrite; 61import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 62import com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager; 63import com.android.server.wifi.hotspot2.pps.Credential; 64import com.android.server.wifi.hotspot2.pps.HomeSP; 65 66import org.junit.Before; 67import org.junit.Test; 68import org.mockito.Mock; 69import org.mockito.MockitoAnnotations; 70 71import java.io.ByteArrayInputStream; 72import java.io.ByteArrayOutputStream; 73import java.io.DataInputStream; 74import java.io.DataOutputStream; 75import java.io.EOFException; 76import java.io.File; 77import java.io.FileOutputStream; 78import java.io.IOException; 79import java.lang.reflect.Field; 80import java.math.BigInteger; 81import java.security.cert.CertificateEncodingException; 82import java.security.cert.X509Certificate; 83import java.util.ArrayDeque; 84import java.util.ArrayList; 85import java.util.Arrays; 86import java.util.BitSet; 87import java.util.Collection; 88import java.util.Collections; 89import java.util.HashMap; 90import java.util.HashSet; 91import java.util.List; 92import java.util.Map; 93import java.util.Random; 94import java.util.Set; 95import java.util.TreeMap; 96 97/** 98 * Unit tests for {@link com.android.server.wifi.WifiConfigManager}. 99 */ 100@SmallTest 101public class WifiConfigManagerTest { 102 private static final List<WifiConfiguration> CONFIGS = Arrays.asList( 103 WifiConfigurationTestUtil.generateWifiConfig( 104 0, 1000000, "\"red\"", true, true, null, null), 105 WifiConfigurationTestUtil.generateWifiConfig( 106 1, 1000001, "\"green\"", true, true, "example.com", "Green"), 107 WifiConfigurationTestUtil.generateWifiConfig( 108 2, 1100000, "\"blue\"", false, true, "example.org", "Blue"), 109 WifiConfigurationTestUtil.generateWifiConfig( 110 3, 1200000, "\"cyan\"", false, true, null, null)); 111 112 private static final int[] USER_IDS = {0, 10, 11}; 113 private static final int MANAGED_PROFILE_USER_ID = 12; 114 private static final int MANAGED_PROFILE_PARENT_USER_ID = 0; 115 private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>(); 116 static { 117 USER_PROFILES.put(0, Arrays.asList(new UserInfo(0, "Owner", 0), 118 new UserInfo(12, "Managed Profile", 0))); 119 USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0))); 120 USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0))); 121 } 122 123 private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>(); 124 static { 125 for (int userId : USER_IDS) { 126 List<WifiConfiguration> configs = new ArrayList<>(); 127 for (int i = 0; i < CONFIGS.size(); ++i) { 128 if (WifiConfigurationUtil.isVisibleToAnyProfile(CONFIGS.get(i), 129 USER_PROFILES.get(userId))) { 130 configs.add(CONFIGS.get(i)); 131 } 132 } 133 VISIBLE_CONFIGS.put(userId, configs); 134 } 135 } 136 137 /** 138 * Set of WifiConfigs for HasEverConnected tests. 139 */ 140 private static final int HAS_EVER_CONNECTED_USER = 20; 141 private static final WifiConfiguration BASE_HAS_EVER_CONNECTED_CONFIG = 142 WifiConfigurationTestUtil.generateWifiConfig( 143 0, HAS_EVER_CONNECTED_USER, "testHasEverConnected", false, true, null, null, 0); 144 145 public static final String TAG = "WifiConfigManagerTest"; 146 @Mock private Context mContext; 147 @Mock private WifiNative mWifiNative; 148 @Mock private FrameworkFacade mFrameworkFacade; 149 @Mock private UserManager mUserManager; 150 @Mock private DelayedDiskWrite mWriter; 151 @Mock private PasspointManagementObjectManager mMOManager; 152 @Mock private Clock mClock; 153 private WifiConfigManager mWifiConfigManager; 154 private ConfigurationMap mConfiguredNetworks; 155 public byte[] mNetworkHistoryBytes; 156 private MockKeyStore mMockKeyStore; 157 158 /** 159 * Called before each test 160 */ 161 @Before 162 public void setUp() throws Exception { 163 MockitoAnnotations.initMocks(this); 164 165 final Context realContext = InstrumentationRegistry.getContext(); 166 when(mContext.getPackageName()).thenReturn(realContext.getPackageName()); 167 when(mContext.getResources()).thenReturn(realContext.getResources()); 168 when(mContext.getPackageManager()).thenReturn(realContext.getPackageManager()); 169 170 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)) 171 .thenReturn(USER_PROFILES.get(UserHandle.USER_SYSTEM)); 172 173 for (int userId : USER_IDS) { 174 when(mUserManager.getProfiles(userId)).thenReturn(USER_PROFILES.get(userId)); 175 } 176 177 mMockKeyStore = new MockKeyStore(); 178 179 mWifiConfigManager = new WifiConfigManager(mContext, mWifiNative, mFrameworkFacade, mClock, 180 mUserManager, mMockKeyStore.createMock()); 181 182 final Field configuredNetworksField = 183 WifiConfigManager.class.getDeclaredField("mConfiguredNetworks"); 184 configuredNetworksField.setAccessible(true); 185 mConfiguredNetworks = (ConfigurationMap) configuredNetworksField.get(mWifiConfigManager); 186 187 // Intercept writes to networkHistory.txt. 188 doAnswer(new AnswerWithArguments() { 189 public void answer(String filePath, DelayedDiskWrite.Writer writer) throws Exception { 190 final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 191 final DataOutputStream stream = new DataOutputStream(buffer); 192 writer.onWriteCalled(stream); 193 stream.close(); 194 mNetworkHistoryBytes = buffer.toByteArray(); 195 }}).when(mWriter).write(anyString(), (DelayedDiskWrite.Writer) anyObject()); 196 final Field writerField = WifiConfigManager.class.getDeclaredField("mWriter"); 197 writerField.setAccessible(true); 198 writerField.set(mWifiConfigManager, mWriter); 199 final Field networkHistoryField = 200 WifiConfigManager.class.getDeclaredField("mWifiNetworkHistory"); 201 networkHistoryField.setAccessible(true); 202 WifiNetworkHistory wifiNetworkHistory = 203 (WifiNetworkHistory) networkHistoryField.get(mWifiConfigManager); 204 final Field networkHistoryWriterField = 205 WifiNetworkHistory.class.getDeclaredField("mWriter"); 206 networkHistoryWriterField.setAccessible(true); 207 networkHistoryWriterField.set(wifiNetworkHistory, mWriter); 208 209 when(mMOManager.isEnabled()).thenReturn(true); 210 final Field moManagerField = WifiConfigManager.class.getDeclaredField("mMOManager"); 211 moManagerField.setAccessible(true); 212 moManagerField.set(mWifiConfigManager, mMOManager); 213 } 214 215 private void switchUser(int newUserId) { 216 when(mUserManager.getProfiles(newUserId)) 217 .thenReturn(USER_PROFILES.get(newUserId)); 218 mWifiConfigManager.handleUserSwitch(newUserId); 219 } 220 221 private void switchUserToCreatorOrParentOf(WifiConfiguration config) { 222 final int creatorUserId = UserHandle.getUserId(config.creatorUid); 223 if (creatorUserId == MANAGED_PROFILE_USER_ID) { 224 switchUser(MANAGED_PROFILE_PARENT_USER_ID); 225 } else { 226 switchUser(creatorUserId); 227 } 228 } 229 230 private void addNetworks() throws Exception { 231 for (int i = 0; i < CONFIGS.size(); ++i) { 232 assertEquals(i, CONFIGS.get(i).networkId); 233 addNetwork(CONFIGS.get(i)); 234 } 235 } 236 237 private void addNetwork(WifiConfiguration config) throws Exception { 238 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 239 240 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); 241 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 242 .thenReturn(true); 243 244 switchUserToCreatorOrParentOf(config); 245 final WifiConfiguration configCopy = new WifiConfiguration(config); 246 int networkId = config.networkId; 247 config.networkId = -1; 248 when(mWifiNative.addNetwork()).thenReturn(networkId); 249 when(mWifiNative.getNetworkVariable(networkId, WifiConfiguration.ssidVarName)) 250 .thenReturn(encodeConfigSSID(config)); 251 mWifiConfigManager.saveNetwork(config, configCopy.creatorUid); 252 253 switchUser(originalUserId); 254 } 255 256 private String encodeConfigSSID(WifiConfiguration config) throws Exception { 257 return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1) 258 .getBytes("UTF-8")).toString(16); 259 } 260 261 /** 262 * Verifies that getConfiguredNetworksSize() returns the number of network configurations 263 * visible to the current user. 264 */ 265 @Test 266 public void testGetConfiguredNetworksSize() throws Exception { 267 addNetworks(); 268 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 269 switchUser(entry.getKey()); 270 assertEquals(entry.getValue().size(), mWifiConfigManager.getConfiguredNetworksSize()); 271 } 272 } 273 274 private void verifyNetworkConfig(WifiConfiguration expectedConfig, 275 WifiConfiguration actualConfig) { 276 assertNotNull(actualConfig); 277 assertEquals(expectedConfig.SSID, actualConfig.SSID); 278 assertEquals(expectedConfig.FQDN, actualConfig.FQDN); 279 assertEquals(expectedConfig.providerFriendlyName, 280 actualConfig.providerFriendlyName); 281 assertEquals(expectedConfig.configKey(), actualConfig.configKey(false)); 282 } 283 284 private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, 285 Collection<WifiConfiguration> actualConfigs) { 286 assertEquals(expectedConfigs.size(), actualConfigs.size()); 287 for (WifiConfiguration expectedConfig : expectedConfigs) { 288 WifiConfiguration actualConfig = null; 289 // Find the network configuration to test (assume that |actualConfigs| contains them in 290 // undefined order). 291 for (final WifiConfiguration candidate : actualConfigs) { 292 if (candidate.networkId == expectedConfig.networkId) { 293 actualConfig = candidate; 294 break; 295 } 296 } 297 verifyNetworkConfig(expectedConfig, actualConfig); 298 } 299 } 300 301 /** 302 * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the 303 * current user. 304 */ 305 @Test 306 public void testGetConfiguredNetworks() throws Exception { 307 addNetworks(); 308 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 309 switchUser(entry.getKey()); 310 verifyNetworkConfigs(entry.getValue(), mWifiConfigManager.getSavedNetworks()); 311 } 312 } 313 314 /** 315 * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to 316 * the current user. 317 */ 318 @Test 319 public void testGetPrivilegedConfiguredNetworks() throws Exception { 320 addNetworks(); 321 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 322 switchUser(entry.getKey()); 323 verifyNetworkConfigs(entry.getValue(), 324 mWifiConfigManager.getPrivilegedSavedNetworks()); 325 } 326 } 327 328 /** 329 * Verifies that getWifiConfiguration(int netId) can be used to access network configurations 330 * visible to the current user only. 331 */ 332 @Test 333 public void testGetWifiConfigurationByNetworkId() throws Exception { 334 addNetworks(); 335 for (int userId : USER_IDS) { 336 switchUser(userId); 337 for (WifiConfiguration expectedConfig: CONFIGS) { 338 final WifiConfiguration actualConfig = 339 mWifiConfigManager.getWifiConfiguration(expectedConfig.networkId); 340 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 341 USER_PROFILES.get(userId))) { 342 verifyNetworkConfig(expectedConfig, actualConfig); 343 } else { 344 assertNull(actualConfig); 345 } 346 } 347 } 348 } 349 350 /** 351 * Verifies that getWifiConfiguration(String key) can be used to access network configurations 352 * visible to the current user only. 353 */ 354 @Test 355 public void testGetWifiConfigurationByConfigKey() throws Exception { 356 addNetworks(); 357 for (int userId : USER_IDS) { 358 switchUser(userId); 359 for (WifiConfiguration expectedConfig: CONFIGS) { 360 final WifiConfiguration actualConfig = 361 mWifiConfigManager.getWifiConfiguration(expectedConfig.configKey()); 362 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 363 USER_PROFILES.get(userId))) { 364 verifyNetworkConfig(expectedConfig, actualConfig); 365 } else { 366 assertNull(actualConfig); 367 } 368 } 369 } 370 } 371 372 /** 373 * Verifies that enableAllNetworks() enables all temporarily disabled network configurations 374 * visible to the current user. 375 */ 376 @Test 377 public void testEnableAllNetworks() throws Exception { 378 addNetworks(); 379 for (int userId : USER_IDS) { 380 switchUser(userId); 381 382 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 383 final WifiConfiguration.NetworkSelectionStatus status = 384 config.getNetworkSelectionStatus(); 385 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus 386 .NETWORK_SELECTION_TEMPORARY_DISABLED); 387 status.setNetworkSelectionDisableReason( 388 WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE); 389 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000); 390 } 391 392 mWifiConfigManager.enableAllNetworks(); 393 394 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 395 assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config, 396 USER_PROFILES.get(userId)), 397 config.getNetworkSelectionStatus().isNetworkEnabled()); 398 } 399 } 400 } 401 402 /** 403 * Verifies that selectNetwork() disables all network configurations visible to the current user 404 * except the selected one. 405 */ 406 @Test 407 public void testSelectNetwork() throws Exception { 408 addNetworks(); 409 410 for (int userId : USER_IDS) { 411 switchUser(userId); 412 413 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 414 // Enable all network configurations. 415 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 416 config2.status = WifiConfiguration.Status.ENABLED; 417 } 418 419 // Try to select a network configuration. 420 reset(mWifiNative); 421 when(mWifiNative.selectNetwork(config.networkId)).thenReturn(true); 422 final boolean success = 423 mWifiConfigManager.selectNetwork(config, false, config.creatorUid); 424 if (!WifiConfigurationUtil.isVisibleToAnyProfile(config, 425 USER_PROFILES.get(userId))) { 426 // If the network configuration is not visible to the current user, verify that 427 // nothing changed. 428 assertFalse(success); 429 verify(mWifiNative, never()).selectNetwork(anyInt()); 430 verify(mWifiNative, never()).enableNetwork(anyInt()); 431 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 432 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 433 } 434 } else { 435 // If the network configuration is visible to the current user, verify that 436 // a connection attempt was made to it. This does not modify the status of 437 // other networks. 438 assertTrue(success); 439 verify(mWifiNative).selectNetwork(config.networkId); 440 verify(mWifiNative, never()).selectNetwork(intThat(not(config.networkId))); 441 verify(mWifiNative, never()).enableNetwork(config.networkId); 442 verify(mWifiNative, never()).enableNetwork(intThat(not(config.networkId))); 443 assertEquals(WifiConfiguration.Status.ENABLED, config.status); 444 } 445 } 446 } 447 } 448 449 /** 450 * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant 451 * variables and the networkHistory.txt file. 452 * TODO: Test all variables. Currently, only the following variables are tested: 453 * - In the wpa_supplicant: "ssid", "id_str" 454 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 455 */ 456 private void verifySaveNetwork(int network) throws Exception { 457 // Switch to the correct user. 458 switchUserToCreatorOrParentOf(CONFIGS.get(network)); 459 460 // Set up wpa_supplicant. 461 when(mWifiNative.addNetwork()).thenReturn(0); 462 when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString())) 463 .thenReturn(true); 464 when(mWifiNative.setNetworkExtra(eq(network), anyString(), 465 (Map<String, String>) anyObject())).thenReturn(true); 466 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName)) 467 .thenReturn(encodeConfigSSID(CONFIGS.get(network))); 468 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.pmfVarName)) 469 .thenReturn(""); 470 471 // Store a network configuration. 472 mWifiConfigManager.saveNetwork(CONFIGS.get(network), CONFIGS.get(network).creatorUid); 473 474 // Verify that wpa_supplicant variables were written correctly for the network 475 // configuration. 476 final Map<String, String> metadata = new HashMap<String, String>(); 477 if (CONFIGS.get(network).FQDN != null) { 478 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(network).FQDN); 479 } 480 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(network).configKey()); 481 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 482 Integer.toString(CONFIGS.get(network).creatorUid)); 483 verify(mWifiNative).setNetworkExtra(network, WifiConfigStore.ID_STRING_VAR_NAME, 484 metadata); 485 486 // Verify that an attempt to read back the requirePMF variable was made. 487 verify(mWifiNative).getNetworkVariable(network, WifiConfiguration.pmfVarName); 488 489 // Verify that no wpa_supplicant variables were read or written for any other network 490 // configurations. 491 verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(), 492 (Map<String, String>) anyObject()); 493 verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(), 494 anyString()); 495 verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString()); 496 497 // Parse networkHistory.txt. 498 assertNotNull(mNetworkHistoryBytes); 499 final DataInputStream stream = 500 new DataInputStream(new ByteArrayInputStream(mNetworkHistoryBytes)); 501 List<String> keys = new ArrayList<>(); 502 List<String> values = new ArrayList<>(); 503 try { 504 while (true) { 505 final String[] tokens = stream.readUTF().split(":", 2); 506 if (tokens.length == 2) { 507 keys.add(tokens[0].trim()); 508 values.add(tokens[1].trim()); 509 } 510 } 511 } catch (EOFException e) { 512 // Ignore. This is expected. 513 } 514 515 // Verify that a networkHistory.txt entry was written correctly for the network 516 // configuration. 517 assertTrue(keys.size() >= 3); 518 assertEquals(WifiNetworkHistory.CONFIG_KEY, keys.get(0)); 519 assertEquals(CONFIGS.get(network).configKey(), values.get(0)); 520 final int creatorUidIndex = keys.indexOf(WifiNetworkHistory.CREATOR_UID_KEY); 521 assertTrue(creatorUidIndex != -1); 522 assertEquals(Integer.toString(CONFIGS.get(network).creatorUid), 523 values.get(creatorUidIndex)); 524 final int sharedIndex = keys.indexOf(WifiNetworkHistory.SHARED_KEY); 525 assertTrue(sharedIndex != -1); 526 assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex)); 527 528 // Verify that no networkHistory.txt entries were written for any other network 529 // configurations. 530 final int lastConfigIndex = keys.lastIndexOf(WifiNetworkHistory.CONFIG_KEY); 531 assertEquals(0, lastConfigIndex); 532 } 533 534 /** 535 * Verifies that saveNetwork() correctly stores a regular network configuration. 536 */ 537 @Test 538 public void testSaveNetworkRegular() throws Exception { 539 verifySaveNetwork(0); 540 } 541 542 /** 543 * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration. 544 */ 545 @Test 546 public void testSaveNetworkHotspot20() throws Exception { 547 verifySaveNetwork(1); 548 } 549 550 /** 551 * Verifies that saveNetwork() correctly stores a private network configuration. 552 */ 553 @Test 554 public void testSaveNetworkPrivate() throws Exception { 555 verifySaveNetwork(2); 556 } 557 558 /** 559 * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the 560 * networkHistory.txt file and the MOManager, correlating the three sources based on the 561 * configKey and the FQDN for HotSpot 2.0 networks. 562 * TODO: Test all variables. Currently, only the following variables are tested: 563 * - In the wpa_supplicant: "ssid", "id_str" 564 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 565 */ 566 @Test 567 public void testLoadConfiguredNetworks() throws Exception { 568 // Set up list of network configurations returned by wpa_supplicant. 569 final String header = "network id / ssid / bssid / flags"; 570 String networks = header; 571 for (WifiConfiguration config : CONFIGS) { 572 networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany"; 573 } 574 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 575 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 576 577 // Set up variables returned by wpa_supplicant for the individual network configurations. 578 for (int i = 0; i < CONFIGS.size(); ++i) { 579 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 580 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 581 } 582 // Legacy regular network configuration: No "id_str". 583 when(mWifiNative.getNetworkExtra(0, WifiConfigStore.ID_STRING_VAR_NAME)) 584 .thenReturn(null); 585 // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str". 586 when(mWifiNative.getNetworkExtra(1, WifiConfigStore.ID_STRING_VAR_NAME)) 587 .thenReturn(null); 588 when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME)) 589 .thenReturn('"' + CONFIGS.get(1).FQDN + '"'); 590 // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str". 591 Map<String, String> metadata = new HashMap<String, String>(); 592 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey()); 593 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 594 Integer.toString(CONFIGS.get(2).creatorUid)); 595 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN); 596 when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME)) 597 .thenReturn(metadata); 598 // Up-to-date regular network configuration: Metadata in "id_str". 599 metadata = new HashMap<String, String>(); 600 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey()); 601 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 602 Integer.toString(CONFIGS.get(3).creatorUid)); 603 when(mWifiNative.getNetworkExtra(3, WifiConfigStore.ID_STRING_VAR_NAME)) 604 .thenReturn(metadata); 605 606 // Set up networkHistory.txt file. 607 final File file = File.createTempFile("networkHistory.txt", null); 608 file.deleteOnExit(); 609 610 Field wifiNetworkHistoryConfigFile = 611 WifiNetworkHistory.class.getDeclaredField("NETWORK_HISTORY_CONFIG_FILE"); 612 wifiNetworkHistoryConfigFile.setAccessible(true); 613 wifiNetworkHistoryConfigFile.set(null, file.getAbsolutePath()); 614 615 final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); 616 for (WifiConfiguration config : CONFIGS) { 617 stream.writeUTF(WifiNetworkHistory.CONFIG_KEY + ": " + config.configKey() + '\n'); 618 stream.writeUTF(WifiNetworkHistory.CREATOR_UID_KEY + ": " 619 + Integer.toString(config.creatorUid) + '\n'); 620 stream.writeUTF(WifiNetworkHistory.SHARED_KEY + ": " 621 + Boolean.toString(config.shared) + '\n'); 622 } 623 stream.close(); 624 625 // Set up list of home service providers returned by MOManager. 626 final List<HomeSP> homeSPs = new ArrayList<HomeSP>(); 627 for (WifiConfiguration config : CONFIGS) { 628 if (config.FQDN != null) { 629 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(), 630 new HashSet<String>(), 631 new HashSet<Long>(), new ArrayList<Long>(), 632 config.providerFriendlyName, null, 633 new Credential(0, 0, null, false, null, null), 634 null, 0, null, null, null, 0)); 635 } 636 } 637 when(mMOManager.loadAllSPs()).thenReturn(homeSPs); 638 639 // Load network configurations. 640 mWifiConfigManager.loadConfiguredNetworks(); 641 642 // Verify that network configurations were loaded and correlated correctly across the three 643 // sources. 644 verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers()); 645 } 646 647 /** 648 * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network 649 * configurations from the wpa_supplicant: The second configuration overwrites the first. 650 */ 651 @Test 652 public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception { 653 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0)); 654 config.networkId = 1; 655 656 // Set up list of network configurations returned by wpa_supplicant. The two configurations 657 // are identical except for their network IDs. 658 final String header = "network id / ssid / bssid / flags"; 659 final String networks = 660 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany"; 661 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 662 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 663 664 // Set up variables returned by wpa_supplicant. 665 when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName))) 666 .thenReturn(encodeConfigSSID(config)); 667 final Map<String, String> metadata = new HashMap<String, String>(); 668 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, config.configKey()); 669 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 670 Integer.toString(config.creatorUid)); 671 when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigStore.ID_STRING_VAR_NAME))) 672 .thenReturn(metadata); 673 674 // Load network configurations. 675 mWifiConfigManager.loadConfiguredNetworks(); 676 677 // Verify that the second network configuration (network ID 1) overwrote the first (network 678 // ID 0). 679 verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers()); 680 } 681 682 /** 683 * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network 684 * configurations that should no longer be visible and enables network configurations that 685 * should become visible. 686 */ 687 private void verifyHandleUserSwitch(int oldUserId, int newUserId, 688 boolean makeOneConfigEphemeral) throws Exception { 689 addNetworks(); 690 switchUser(oldUserId); 691 692 reset(mWifiNative); 693 final Field lastSelectedConfigurationField = 694 WifiConfigManager.class.getDeclaredField("mLastSelectedConfiguration"); 695 lastSelectedConfigurationField.setAccessible(true); 696 WifiConfiguration removedEphemeralConfig = null; 697 final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>(); 698 final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>(); 699 final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>(); 700 final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers(); 701 int expectedNumberOfConfigs = oldConfigs.size(); 702 for (WifiConfiguration config : oldConfigs) { 703 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) { 704 config.status = WifiConfiguration.Status.ENABLED; 705 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 706 USER_PROFILES.get(newUserId))) { 707 if (makeOneConfigEphemeral && removedEphemeralConfig == null) { 708 config.ephemeral = true; 709 lastSelectedConfigurationField.set(mWifiConfigManager, config.configKey()); 710 removedEphemeralConfig = config; 711 } 712 } else { 713 oldUserOnlyConfigs.add(config); 714 } 715 } else { 716 config.status = WifiConfiguration.Status.DISABLED; 717 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 718 USER_PROFILES.get(newUserId))) { 719 newUserOnlyConfigs.add(config); 720 } else { 721 neitherUserConfigs.add(config); 722 } 723 } 724 } 725 726 when(mWifiNative.disableNetwork(anyInt())).thenReturn(true); 727 when(mWifiNative.removeNetwork(anyInt())).thenReturn(true); 728 729 switchUser(newUserId); 730 if (makeOneConfigEphemeral) { 731 // Verify that the ephemeral network configuration was removed. 732 assertNotNull(removedEphemeralConfig); 733 assertNull(mConfiguredNetworks.getForAllUsers(removedEphemeralConfig.networkId)); 734 assertNull(lastSelectedConfigurationField.get(mWifiConfigManager)); 735 verify(mWifiNative).removeNetwork(removedEphemeralConfig.networkId); 736 --expectedNumberOfConfigs; 737 } else { 738 assertNull(removedEphemeralConfig); 739 } 740 741 // Verify that the other network configurations were revealed/hidden and enabled/disabled as 742 // appropriate. 743 final Collection<WifiConfiguration> newConfigs = mConfiguredNetworks.valuesForAllUsers(); 744 assertEquals(expectedNumberOfConfigs, newConfigs.size()); 745 for (WifiConfiguration config : newConfigs) { 746 if (oldUserOnlyConfigs.contains(config)) { 747 verify(mWifiNative).disableNetwork(config.networkId); 748 assertNetworkStatus( 749 config, 750 WifiConfiguration.NetworkSelectionStatus.DISABLED_DUE_TO_USER_SWITCH); 751 } else { 752 verify(mWifiNative, never()).disableNetwork(config.networkId); 753 if (neitherUserConfigs.contains(config)) { 754 assertNetworkStatus( 755 config, 756 WifiConfiguration.NetworkSelectionStatus.DISABLED_DUE_TO_USER_SWITCH); 757 } else { 758 assertNetworkStatus( 759 config, 760 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 761 } 762 } 763 } 764 } 765 766 /** 767 * Verifies that handleUserSwitch() behaves correctly when the user switch removes an ephemeral 768 * network configuration and reveals a private network configuration. 769 */ 770 @Test 771 public void testHandleUserSwitchWithEphemeral() throws Exception { 772 verifyHandleUserSwitch(USER_IDS[2], USER_IDS[0], true); 773 } 774 775 /** 776 * Verifies that handleUserSwitch() behaves correctly when the user switch hides a private 777 * network configuration. 778 */ 779 @Test 780 public void testHandleUserSwitchWithoutEphemeral() throws Exception { 781 verifyHandleUserSwitch(USER_IDS[0], USER_IDS[2], false); 782 } 783 784 @Test 785 public void testSaveLoadEapNetworks() { 786 testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS) 787 .setPhase2(Phase2.MSCHAPV2) 788 .setIdentity("username", "password") 789 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0})); 790 testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS) 791 .setPhase2(Phase2.MSCHAPV2) 792 .setIdentity("username", "password") 793 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1, FakeKeys.CA_CERT0})); 794 795 } 796 797 private void testSaveLoadSingleEapNetwork(String ssid, EnterpriseConfig eapConfig) { 798 final HashMap<String, String> networkVariables = new HashMap<String, String>(); 799 reset(mWifiNative); 800 when(mWifiNative.addNetwork()).thenReturn(0); 801 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenAnswer( 802 new AnswerWithArguments() { 803 public boolean answer(int netId, String name, String value) { 804 // Verify that no wpa_supplicant variables were written for any other 805 // network configurations. 806 assertEquals(netId, 0); 807 networkVariables.put(name, value); 808 return true; 809 } 810 }); 811 when(mWifiNative.getNetworkVariable(anyInt(), anyString())).then( 812 new AnswerWithArguments() { 813 public String answer(int netId, String name) { 814 // Verify that no wpa_supplicant variables were read for any other 815 // network configurations. 816 assertEquals(netId, 0); 817 return networkVariables.get(name); 818 } 819 }); 820 when(mWifiNative.setNetworkExtra(eq(0), anyString(), (Map<String, String>) anyObject())) 821 .thenReturn(true); 822 823 WifiConfiguration config = new WifiConfiguration(); 824 config.SSID = ssid; 825 config.creatorUid = Process.WIFI_UID; 826 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 827 config.enterpriseConfig = eapConfig.enterpriseConfig; 828 829 // Store a network configuration. 830 mWifiConfigManager.saveNetwork(config, Process.WIFI_UID); 831 832 // Verify that wpa_supplicant variables were written correctly for the network 833 // configuration. 834 verify(mWifiNative).addNetwork(); 835 assertEquals(eapConfig.eap, 836 unquote(networkVariables.get(WifiEnterpriseConfig.EAP_KEY))); 837 assertEquals(eapConfig.phase2, 838 unquote(networkVariables.get(WifiEnterpriseConfig.PHASE2_KEY))); 839 assertEquals(eapConfig.identity, 840 unquote(networkVariables.get(WifiEnterpriseConfig.IDENTITY_KEY))); 841 assertEquals(eapConfig.password, 842 unquote(networkVariables.get(WifiEnterpriseConfig.PASSWORD_KEY))); 843 assertSavedCaCerts(eapConfig, 844 unquote(networkVariables.get(WifiEnterpriseConfig.CA_CERT_KEY))); 845 846 // Prepare the scan result. 847 final String header = "network id / ssid / bssid / flags"; 848 String networks = header + "\n" + Integer.toString(0) + "\t" + ssid + "\tany"; 849 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 850 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 851 852 // Load back the configuration. 853 mWifiConfigManager.loadConfiguredNetworks(); 854 List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(); 855 assertEquals(1, configs.size()); 856 WifiConfiguration loadedConfig = configs.get(0); 857 assertEquals(ssid, unquote(loadedConfig.SSID)); 858 BitSet keyMgmt = new BitSet(); 859 keyMgmt.set(KeyMgmt.WPA_EAP); 860 assertEquals(keyMgmt, loadedConfig.allowedKeyManagement); 861 assertEquals(eapConfig.enterpriseConfig.getEapMethod(), 862 loadedConfig.enterpriseConfig.getEapMethod()); 863 assertEquals(eapConfig.enterpriseConfig.getPhase2Method(), 864 loadedConfig.enterpriseConfig.getPhase2Method()); 865 assertEquals(eapConfig.enterpriseConfig.getIdentity(), 866 loadedConfig.enterpriseConfig.getIdentity()); 867 assertEquals(eapConfig.enterpriseConfig.getPassword(), 868 loadedConfig.enterpriseConfig.getPassword()); 869 asserCaCertsAliasesMatch(eapConfig.caCerts, 870 loadedConfig.enterpriseConfig.getCaCertificateAliases()); 871 } 872 873 private String unquote(String value) { 874 if (value == null) { 875 return null; 876 } 877 int length = value.length(); 878 if ((length > 1) && (value.charAt(0) == '"') 879 && (value.charAt(length - 1) == '"')) { 880 return value.substring(1, length - 1); 881 } else { 882 return value; 883 } 884 } 885 886 private void asserCaCertsAliasesMatch(X509Certificate[] certs, String[] aliases) { 887 assertEquals(certs.length, aliases.length); 888 List<String> aliasList = new ArrayList<String>(Arrays.asList(aliases)); 889 try { 890 for (int i = 0; i < certs.length; i++) { 891 byte[] certPem = Credentials.convertToPem(certs[i]); 892 boolean found = false; 893 for (int j = 0; j < aliasList.size(); j++) { 894 byte[] keystoreCert = mMockKeyStore.getKeyBlob(Process.WIFI_UID, 895 Credentials.CA_CERTIFICATE + aliasList.get(j)).blob; 896 if (Arrays.equals(keystoreCert, certPem)) { 897 found = true; 898 aliasList.remove(j); 899 break; 900 } 901 } 902 assertTrue(found); 903 } 904 } catch (CertificateEncodingException | IOException e) { 905 fail("Cannot convert CA certificate to encoded form."); 906 } 907 } 908 909 private void assertSavedCaCerts(EnterpriseConfig eapConfig, String caCertVariable) { 910 ArrayList<String> aliases = new ArrayList<String>(); 911 if (TextUtils.isEmpty(caCertVariable)) { 912 // Do nothing. 913 } else if (caCertVariable.startsWith(WifiEnterpriseConfig.CA_CERT_PREFIX)) { 914 aliases.add(caCertVariable.substring(WifiEnterpriseConfig.CA_CERT_PREFIX.length())); 915 } else if (caCertVariable.startsWith(WifiEnterpriseConfig.KEYSTORES_URI)) { 916 String[] encodedAliases = TextUtils.split( 917 caCertVariable.substring(WifiEnterpriseConfig.KEYSTORES_URI.length()), 918 WifiEnterpriseConfig.CA_CERT_ALIAS_DELIMITER); 919 for (String encodedAlias : encodedAliases) { 920 String alias = WifiEnterpriseConfig.decodeCaCertificateAlias(encodedAlias); 921 assertTrue(alias.startsWith(Credentials.CA_CERTIFICATE)); 922 aliases.add(alias.substring(Credentials.CA_CERTIFICATE.length())); 923 } 924 } else { 925 fail("Unrecognized ca_cert variable: " + caCertVariable); 926 } 927 asserCaCertsAliasesMatch(eapConfig.caCerts, aliases.toArray(new String[aliases.size()])); 928 } 929 930 private static class EnterpriseConfig { 931 public String eap; 932 public String phase2; 933 public String identity; 934 public String password; 935 public X509Certificate[] caCerts; 936 public WifiEnterpriseConfig enterpriseConfig; 937 938 public EnterpriseConfig(int eapMethod) { 939 enterpriseConfig = new WifiEnterpriseConfig(); 940 enterpriseConfig.setEapMethod(eapMethod); 941 eap = Eap.strings[eapMethod]; 942 } 943 public EnterpriseConfig setPhase2(int phase2Method) { 944 enterpriseConfig.setPhase2Method(phase2Method); 945 phase2 = "auth=" + Phase2.strings[phase2Method]; 946 return this; 947 } 948 public EnterpriseConfig setIdentity(String identity, String password) { 949 enterpriseConfig.setIdentity(identity); 950 enterpriseConfig.setPassword(password); 951 this.identity = identity; 952 this.password = password; 953 return this; 954 } 955 public EnterpriseConfig setCaCerts(X509Certificate[] certs) { 956 enterpriseConfig.setCaCertificates(certs); 957 caCerts = certs; 958 return this; 959 } 960 } 961 962 /** 963 * Generates an array of unique random numbers below the specified maxValue. 964 * Values range from 0 to maxValue-1. 965 */ 966 private static ArrayDeque<Integer> getUniqueRandomNumberValues( 967 int seed, 968 int maxValue, 969 int numValues) { 970 assertTrue(numValues <= maxValue); 971 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode() + seed); 972 ArrayDeque<Integer> randomNumberList = new ArrayDeque<>(); 973 for (int i = 0; i < numValues; i++) { 974 int num = rand.nextInt(maxValue); 975 while (randomNumberList.contains(num)) { 976 num = rand.nextInt(maxValue); 977 } 978 randomNumberList.push(num); 979 } 980 return randomNumberList; 981 } 982 983 /** 984 * Verifies that the networks in pnoNetworkList is sorted in the same order as the 985 * network in expectedNetworkIDOrder list. 986 */ 987 private static void verifyPnoNetworkListOrder( 988 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList, 989 ArrayList<Integer> expectedNetworkIdOrder) throws Exception { 990 int i = 0; 991 for (WifiScanner.PnoSettings.PnoNetwork pnoNetwork : pnoNetworkList) { 992 Log.i(TAG, "PNO Network List Index: " + i + ", networkID: " + pnoNetwork.networkId); 993 assertEquals("Expected network ID: " + pnoNetwork.networkId, 994 pnoNetwork.networkId, expectedNetworkIdOrder.get(i++).intValue()); 995 } 996 } 997 998 /** 999 * Verifies the retrieveDisconnectedPnoNetworkList API. The test verifies that the list 1000 * returned from the API is sorted as expected. 1001 */ 1002 @Test 1003 public void testDisconnectedPnoNetworkListCreation() throws Exception { 1004 addNetworks(); 1005 1006 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode()); 1007 1008 // First assign random |numAssociation| values and verify that the list is sorted 1009 // in descending order of |numAssociation| values. Keep NetworkSelectionStatus 1010 // values constant. 1011 for (int userId : USER_IDS) { 1012 switchUser(userId); 1013 TreeMap<Integer, Integer> numAssociationToNetworkIdMap = 1014 new TreeMap<>(Collections.reverseOrder()); 1015 ArrayDeque<Integer> numAssociationValues = 1016 getUniqueRandomNumberValues( 1017 1, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1018 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1019 config.numAssociation = numAssociationValues.pop(); 1020 config.priority = rand.nextInt(10000); 1021 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1022 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1023 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId); 1024 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: " 1025 + config.numAssociation); 1026 } 1027 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1028 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1029 verifyPnoNetworkListOrder(pnoNetworkList, 1030 new ArrayList(numAssociationToNetworkIdMap.values())); 1031 } 1032 1033 // Assign random |priority| values and verify that the list is sorted in descending order 1034 // of |priority| values. Keep numAssociation/NetworkSelectionStatus values constant. 1035 for (int userId : USER_IDS) { 1036 switchUser(userId); 1037 TreeMap<Integer, Integer> priorityToNetworkIdMap = 1038 new TreeMap<>(Collections.reverseOrder()); 1039 ArrayDeque<Integer> priorityValues = 1040 getUniqueRandomNumberValues( 1041 2, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1042 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1043 config.numAssociation = 0; 1044 config.priority = priorityValues.pop(); 1045 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1046 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1047 priorityToNetworkIdMap.put(config.priority, config.networkId); 1048 Log.i(TAG, "networkID: " + config.networkId + ", priority: " + config.priority); 1049 } 1050 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1051 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1052 verifyPnoNetworkListOrder(pnoNetworkList, 1053 new ArrayList(priorityToNetworkIdMap.values())); 1054 } 1055 1056 // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in 1057 // ascending order of |NetworkSelectionStatus| values. 1058 for (int userId : USER_IDS) { 1059 switchUser(userId); 1060 TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>(); 1061 ArrayDeque<Integer> networkSelectionStatusValues = 1062 getUniqueRandomNumberValues( 1063 3, 1064 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX, 1065 mConfiguredNetworks.valuesForCurrentUser().size()); 1066 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1067 config.numAssociation = rand.nextInt(10000); 1068 config.priority = rand.nextInt(10000); 1069 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1070 networkSelectionStatusValues.pop()); 1071 networkSelectionStatusToNetworkIdMap.put( 1072 config.getNetworkSelectionStatus().getNetworkSelectionStatus(), 1073 config.networkId); 1074 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: " 1075 + config.getNetworkSelectionStatus().getNetworkSelectionStatus()); 1076 } 1077 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1078 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1079 verifyPnoNetworkListOrder(pnoNetworkList, 1080 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1081 } 1082 } 1083 1084 /** 1085 * Verifies the retrieveConnectedPnoNetworkList API. The test verifies that the list 1086 * returned from the API is sorted as expected. 1087 */ 1088 @Test 1089 public void testConnectedPnoNetworkListCreation() throws Exception { 1090 addNetworks(); 1091 1092 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode()); 1093 1094 // First assign |lastSeen| values and verify that the list is sorted 1095 // in descending order of |lastSeen| values. Keep NetworkSelectionStatus 1096 // values constant. 1097 for (int userId : USER_IDS) { 1098 switchUser(userId); 1099 TreeMap<Boolean, Integer> lastSeenToNetworkIdMap = 1100 new TreeMap<>(Collections.reverseOrder()); 1101 ArrayDeque<Integer> lastSeenValues = getUniqueRandomNumberValues(1, 2, 2); 1102 if (mConfiguredNetworks.valuesForCurrentUser().size() > 2) continue; 1103 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1104 config.numAssociation = rand.nextInt(10000); 1105 config.priority = rand.nextInt(10000); 1106 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1107 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1108 boolean lastSeenValue = (lastSeenValues.pop() == 1); 1109 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection( 1110 lastSeenValue); 1111 lastSeenToNetworkIdMap.put(lastSeenValue, config.networkId); 1112 Log.i(TAG, "networkID: " + config.networkId + ", lastSeen: " + lastSeenValue); 1113 } 1114 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1115 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1116 verifyPnoNetworkListOrder(pnoNetworkList, 1117 new ArrayList(lastSeenToNetworkIdMap.values())); 1118 } 1119 1120 // Assign random |numAssociation| values and verify that the list is sorted 1121 // in descending order of |numAssociation| values. Keep NetworkSelectionStatus/lastSeen 1122 // values constant. 1123 for (int userId : USER_IDS) { 1124 switchUser(userId); 1125 TreeMap<Integer, Integer> numAssociationToNetworkIdMap = 1126 new TreeMap<>(Collections.reverseOrder()); 1127 ArrayDeque<Integer> numAssociationValues = 1128 getUniqueRandomNumberValues( 1129 1, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1130 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1131 config.numAssociation = numAssociationValues.pop(); 1132 config.priority = rand.nextInt(10000); 1133 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1134 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1135 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true); 1136 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId); 1137 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: " 1138 + config.numAssociation); 1139 } 1140 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1141 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1142 verifyPnoNetworkListOrder(pnoNetworkList, 1143 new ArrayList(numAssociationToNetworkIdMap.values())); 1144 } 1145 1146 // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in 1147 // ascending order of |NetworkSelectionStatus| values. 1148 for (int userId : USER_IDS) { 1149 switchUser(userId); 1150 TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>(); 1151 ArrayDeque<Integer> networkSelectionStatusValues = 1152 getUniqueRandomNumberValues( 1153 3, 1154 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX, 1155 mConfiguredNetworks.valuesForCurrentUser().size()); 1156 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1157 config.numAssociation = rand.nextInt(10000); 1158 config.priority = rand.nextInt(10000); 1159 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1160 networkSelectionStatusValues.pop()); 1161 networkSelectionStatusToNetworkIdMap.put( 1162 config.getNetworkSelectionStatus().getNetworkSelectionStatus(), 1163 config.networkId); 1164 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: " 1165 + config.getNetworkSelectionStatus().getNetworkSelectionStatus()); 1166 } 1167 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1168 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1169 verifyPnoNetworkListOrder(pnoNetworkList, 1170 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1171 } 1172 } 1173 1174 /** 1175 * Verifies that hasEverConnected is false for a newly added network 1176 */ 1177 @Test 1178 public void testAddNetworkHasEverConnectedFalse() throws Exception { 1179 addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG); 1180 WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( 1181 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1182 assertFalse("Adding a new network should not have hasEverConnected set to true.", 1183 checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 1184 } 1185 1186 1187 /** 1188 * Verifies that hasEverConnected is false for a newly added network even when new config has 1189 * mistakenly set HasEverConnected to true. 1190 */ 1191 @Test 1192 public void testAddNetworkOverridesHasEverConnectedWhenTrueInNewConfig() throws Exception { 1193 WifiConfiguration newNetworkWithHasEverConnectedTrue = 1194 new WifiConfiguration(BASE_HAS_EVER_CONNECTED_CONFIG); 1195 newNetworkWithHasEverConnectedTrue.getNetworkSelectionStatus().setHasEverConnected(true); 1196 addNetwork(newNetworkWithHasEverConnectedTrue); 1197 // check if addNetwork clears the bit. 1198 WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( 1199 newNetworkWithHasEverConnectedTrue.networkId); 1200 assertFalse("Adding a new network should not have hasEverConnected set to true.", 1201 checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 1202 } 1203 1204 1205 /** 1206 * Verify that setting HasEverConnected with a config update can be read back. 1207 */ 1208 @Test 1209 public void testUpdateConfigToHasEverConnectedTrue() throws Exception { 1210 addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG); 1211 1212 // Get the newly saved config and update HasEverConnected 1213 WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration( 1214 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1215 assertFalse("Adding a new network should not have hasEverConnected set to true.", 1216 checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 1217 checkConfig.getNetworkSelectionStatus().setHasEverConnected(true); 1218 mWifiConfigManager.addOrUpdateNetwork(checkConfig, HAS_EVER_CONNECTED_USER); 1219 1220 // verify that HasEverConnected was properly written and read back 1221 checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1222 } 1223 1224 1225 /** 1226 * Verifies that hasEverConnected is cleared when a network config preSharedKey is updated. 1227 */ 1228 @Test 1229 public void testUpdatePreSharedKeyClearsHasEverConnected() throws Exception { 1230 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1231 1232 testUpdateConfigToHasEverConnectedTrue(); 1233 1234 WifiConfiguration original = mWifiConfigManager.getWifiConfiguration( 1235 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1236 1237 WifiConfiguration updatePreSharedKeyConfig = new WifiConfiguration(); 1238 updatePreSharedKeyConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1239 updatePreSharedKeyConfig.SSID = original.SSID; 1240 updatePreSharedKeyConfig.preSharedKey = "newpassword"; 1241 switchUserToCreatorOrParentOf(original); 1242 mWifiConfigManager.addOrUpdateNetwork(updatePreSharedKeyConfig, 1243 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1244 1245 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1246 switchUser(originalUserId); 1247 } 1248 1249 /** 1250 * Verifies that hasEverConnected is cleared when a network config allowedKeyManagement is 1251 * updated. 1252 */ 1253 @Test 1254 public void testUpdateAllowedKeyManagementChanged() throws Exception { 1255 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1256 1257 testUpdateConfigToHasEverConnectedTrue(); 1258 1259 WifiConfiguration updateAllowedKeyManagementConfig = new WifiConfiguration(); 1260 updateAllowedKeyManagementConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1261 updateAllowedKeyManagementConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1262 updateAllowedKeyManagementConfig.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 1263 1264 // Set up mock to allow the new value to be read back into the config 1265 String allowedKeyManagementString = makeString( 1266 updateAllowedKeyManagementConfig.allowedKeyManagement, 1267 WifiConfiguration.KeyMgmt.strings); 1268 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1269 KeyMgmt.varName)).thenReturn(allowedKeyManagementString); 1270 1271 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1272 mWifiConfigManager.addOrUpdateNetwork(updateAllowedKeyManagementConfig, 1273 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1274 1275 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1276 switchUser(originalUserId); 1277 } 1278 1279 /** 1280 * Verifies that hasEverConnected is cleared when a network config allowedProtocols is 1281 * updated. 1282 */ 1283 @Test 1284 public void testUpdateAllowedProtocolsChanged() throws Exception { 1285 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1286 1287 testUpdateConfigToHasEverConnectedTrue(); 1288 1289 WifiConfiguration updateAllowedProtocolsConfig = new WifiConfiguration(); 1290 updateAllowedProtocolsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1291 updateAllowedProtocolsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1292 updateAllowedProtocolsConfig.allowedProtocols.set( 1293 WifiConfiguration.Protocol.RSN); 1294 1295 // Set up mock to allow the new value to be read back into the config 1296 String allowedProtocolsString = makeString( 1297 updateAllowedProtocolsConfig.allowedProtocols, 1298 WifiConfiguration.Protocol.strings); 1299 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1300 Protocol.varName)).thenReturn(allowedProtocolsString); 1301 1302 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1303 mWifiConfigManager.addOrUpdateNetwork(updateAllowedProtocolsConfig, 1304 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1305 1306 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1307 switchUser(originalUserId); 1308 } 1309 1310 /** 1311 * Verifies that hasEverConnected is cleared when a network config allowedAuthAlgorithms is 1312 * updated. 1313 */ 1314 @Test 1315 public void testUpdateAllowedAuthAlgorithmsChanged() throws Exception { 1316 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1317 1318 testUpdateConfigToHasEverConnectedTrue(); 1319 1320 WifiConfiguration updateAllowedAuthAlgorithmsConfig = new WifiConfiguration(); 1321 updateAllowedAuthAlgorithmsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1322 updateAllowedAuthAlgorithmsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1323 updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms.set( 1324 WifiConfiguration.AuthAlgorithm.SHARED); 1325 1326 // Set up mock to allow the new value to be read back into the config 1327 String allowedAuthAlgorithmsString = makeString( 1328 updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms, 1329 WifiConfiguration.AuthAlgorithm.strings); 1330 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1331 AuthAlgorithm.varName)).thenReturn(allowedAuthAlgorithmsString); 1332 1333 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1334 mWifiConfigManager.addOrUpdateNetwork(updateAllowedAuthAlgorithmsConfig, 1335 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1336 1337 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1338 switchUser(originalUserId); 1339 } 1340 1341 /** 1342 * Verifies that hasEverConnected is cleared when a network config allowedPairwiseCiphers is 1343 * updated. 1344 */ 1345 @Test 1346 public void testUpdateAllowedPairwiseCiphersChanged() throws Exception { 1347 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1348 1349 testUpdateConfigToHasEverConnectedTrue(); 1350 1351 WifiConfiguration updateAllowedPairwiseCiphersConfig = new WifiConfiguration(); 1352 updateAllowedPairwiseCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1353 updateAllowedPairwiseCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1354 updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers.set( 1355 WifiConfiguration.PairwiseCipher.CCMP); 1356 1357 // Set up mock to allow the new value to be read back into the config 1358 String allowedPairwiseCiphersString = makeString( 1359 updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers, 1360 WifiConfiguration.PairwiseCipher.strings); 1361 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1362 PairwiseCipher.varName)).thenReturn(allowedPairwiseCiphersString); 1363 1364 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1365 mWifiConfigManager.addOrUpdateNetwork(updateAllowedPairwiseCiphersConfig, 1366 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1367 1368 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1369 switchUser(originalUserId); 1370 } 1371 1372 /** 1373 * Verifies that hasEverConnected is cleared when a network config allowedGroupCiphers is 1374 * updated. 1375 */ 1376 @Test 1377 public void testUpdateAllowedGroupCiphersChanged() throws Exception { 1378 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1379 1380 testUpdateConfigToHasEverConnectedTrue(); 1381 1382 WifiConfiguration updateAllowedGroupCiphersConfig = new WifiConfiguration(); 1383 updateAllowedGroupCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1384 updateAllowedGroupCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1385 updateAllowedGroupCiphersConfig.allowedGroupCiphers.set( 1386 WifiConfiguration.GroupCipher.CCMP); 1387 1388 // Set up mock to allow the new value to be read back into the config 1389 String allowedGroupCiphersString = makeString( 1390 updateAllowedGroupCiphersConfig.allowedGroupCiphers, 1391 WifiConfiguration.GroupCipher.strings); 1392 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1393 GroupCipher.varName)).thenReturn(allowedGroupCiphersString); 1394 1395 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1396 mWifiConfigManager.addOrUpdateNetwork(updateAllowedGroupCiphersConfig, 1397 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1398 1399 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1400 switchUser(originalUserId); 1401 } 1402 1403 /** 1404 * Verifies that hasEverConnected is cleared when a network config wepKeys is 1405 * updated. 1406 */ 1407 @Test 1408 public void testUpdateWepKeysChanged() throws Exception { 1409 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1410 1411 testUpdateConfigToHasEverConnectedTrue(); 1412 1413 String tempKey = "hereisakey"; 1414 WifiConfiguration updateWepKeysConfig = new WifiConfiguration(); 1415 updateWepKeysConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1416 updateWepKeysConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1417 updateWepKeysConfig.wepKeys = new String[] {tempKey}; 1418 1419 // Set up mock to allow the new value to be read back into the config 1420 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1421 WifiConfiguration.wepKeyVarNames[0])).thenReturn(tempKey); 1422 1423 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1424 mWifiConfigManager.addOrUpdateNetwork(updateWepKeysConfig, 1425 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1426 1427 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1428 switchUser(originalUserId); 1429 } 1430 1431 /** 1432 * Verifies that hasEverConnected is cleared when a network config hiddenSSID is 1433 * updated. 1434 */ 1435 @Test 1436 public void testUpdateHiddenSSIDChanged() throws Exception { 1437 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1438 1439 testUpdateConfigToHasEverConnectedTrue(); 1440 1441 WifiConfiguration updateHiddenSSIDConfig = new WifiConfiguration(); 1442 updateHiddenSSIDConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1443 updateHiddenSSIDConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1444 updateHiddenSSIDConfig.hiddenSSID = true; 1445 1446 // Set up mock to allow the new value to be read back into the config 1447 when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1448 WifiConfiguration.hiddenSSIDVarName)).thenReturn("1"); 1449 1450 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1451 mWifiConfigManager.addOrUpdateNetwork(updateHiddenSSIDConfig, 1452 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1453 1454 checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1455 switchUser(originalUserId); 1456 } 1457 1458 /** 1459 * Verifies that hasEverConnected is cleared when a network config pmfVarName is 1460 * updated. 1461 */ 1462 @Test 1463 public void testUpdateRequirePMFChanged() throws Exception { 1464 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 1465 1466 testUpdateConfigToHasEverConnectedTrue(); 1467 1468 WifiConfiguration updateRequirePMFConfig = new WifiConfiguration(); 1469 updateRequirePMFConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId; 1470 updateRequirePMFConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID; 1471 updateRequirePMFConfig.requirePMF = true; 1472 1473 // Set up mock to allow the new value to be read back into the config 1474 // TODO: please see b/28088226 - this test is implemented as if WifiConfigStore correctly 1475 // read back the boolean value. When fixed, uncomment the following line and the 1476 // checkHasEverConnectedFalse below. 1477 //when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId, 1478 // WifiConfiguration.pmfVarName)).thenReturn("2"); 1479 1480 switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG); 1481 mWifiConfigManager.addOrUpdateNetwork(updateRequirePMFConfig, 1482 BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1483 1484 //checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1485 checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId); 1486 switchUser(originalUserId); 1487 } 1488 1489 /** 1490 * Verify WifiEnterpriseConfig changes are detected in WifiConfigManager. 1491 */ 1492 @Test 1493 public void testEnterpriseConfigAdded() { 1494 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) 1495 .setPhase2(Phase2.MSCHAPV2) 1496 .setIdentity("username", "password") 1497 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); 1498 1499 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(null, eapConfig.enterpriseConfig)); 1500 } 1501 1502 /** 1503 * Verify WifiEnterpriseConfig eap change is detected. 1504 */ 1505 @Test 1506 public void testEnterpriseConfigEapChangeDetected() { 1507 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS); 1508 EnterpriseConfig peapConfig = new EnterpriseConfig(Eap.PEAP); 1509 1510 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, 1511 peapConfig.enterpriseConfig)); 1512 } 1513 1514 /** 1515 * Verify WifiEnterpriseConfig phase2 method change is detected. 1516 */ 1517 @Test 1518 public void testEnterpriseConfigPhase2ChangeDetected() { 1519 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.MSCHAPV2); 1520 EnterpriseConfig papConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.PAP); 1521 1522 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, 1523 papConfig.enterpriseConfig)); 1524 } 1525 1526 /** 1527 * Verify WifiEnterpriseConfig added Certificate is detected. 1528 */ 1529 @Test 1530 public void testCaCertificateAddedDetected() { 1531 EnterpriseConfig eapConfigNoCerts = new EnterpriseConfig(Eap.TTLS) 1532 .setPhase2(Phase2.MSCHAPV2) 1533 .setIdentity("username", "password"); 1534 1535 EnterpriseConfig eapConfig1Cert = new EnterpriseConfig(Eap.TTLS) 1536 .setPhase2(Phase2.MSCHAPV2) 1537 .setIdentity("username", "password") 1538 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); 1539 1540 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfigNoCerts.enterpriseConfig, 1541 eapConfig1Cert.enterpriseConfig)); 1542 } 1543 1544 /** 1545 * Verify WifiEnterpriseConfig Certificate change is detected. 1546 */ 1547 @Test 1548 public void testDifferentCaCertificateDetected() { 1549 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) 1550 .setPhase2(Phase2.MSCHAPV2) 1551 .setIdentity("username", "password") 1552 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); 1553 1554 EnterpriseConfig eapConfigNewCert = new EnterpriseConfig(Eap.TTLS) 1555 .setPhase2(Phase2.MSCHAPV2) 1556 .setIdentity("username", "password") 1557 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1}); 1558 1559 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, 1560 eapConfigNewCert.enterpriseConfig)); 1561 } 1562 1563 /** 1564 * Verify WifiEnterpriseConfig added Certificate changes are detected. 1565 */ 1566 @Test 1567 public void testCaCertificateChangesDetected() { 1568 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) 1569 .setPhase2(Phase2.MSCHAPV2) 1570 .setIdentity("username", "password") 1571 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}); 1572 1573 EnterpriseConfig eapConfigAddedCert = new EnterpriseConfig(Eap.TTLS) 1574 .setPhase2(Phase2.MSCHAPV2) 1575 .setIdentity("username", "password") 1576 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); 1577 1578 assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, 1579 eapConfigAddedCert.enterpriseConfig)); 1580 } 1581 1582 /** 1583 * Verify that WifiEnterpriseConfig does not detect changes for identical configs. 1584 */ 1585 @Test 1586 public void testWifiEnterpriseConfigNoChanges() { 1587 EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS) 1588 .setPhase2(Phase2.MSCHAPV2) 1589 .setIdentity("username", "password") 1590 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); 1591 1592 // Just to be clear that check is not against the same object 1593 EnterpriseConfig eapConfigSame = new EnterpriseConfig(Eap.TTLS) 1594 .setPhase2(Phase2.MSCHAPV2) 1595 .setIdentity("username", "password") 1596 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1}); 1597 1598 assertFalse(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig, 1599 eapConfigSame.enterpriseConfig)); 1600 } 1601 1602 private void checkHasEverConnectedTrue(int networkId) { 1603 WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId); 1604 assertTrue("hasEverConnected expected to be true.", 1605 checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 1606 } 1607 1608 private void checkHasEverConnectedFalse(int networkId) { 1609 WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId); 1610 assertFalse("Updating credentials network config should clear hasEverConnected.", 1611 checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 1612 } 1613 1614 /** 1615 * Helper function to translate from WifiConfiguration BitSet to String. 1616 */ 1617 private static String makeString(BitSet set, String[] strings) { 1618 StringBuffer buf = new StringBuffer(); 1619 int nextSetBit = -1; 1620 1621 /* Make sure all set bits are in [0, strings.length) to avoid 1622 * going out of bounds on strings. (Shouldn't happen, but...) */ 1623 set = set.get(0, strings.length); 1624 1625 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1626 buf.append(strings[nextSetBit].replace('_', '-')).append(' '); 1627 } 1628 1629 // remove trailing space 1630 if (set.cardinality() > 0) { 1631 buf.setLength(buf.length() - 1); 1632 } 1633 1634 return buf.toString(); 1635 } 1636 1637 /** 1638 * Test whether enableNetwork with the disableOthers flag set to false enables the 1639 * input network, but does not attempt a connection. 1640 */ 1641 @Test 1642 public void testEnableNetworkWithoutDisableOthers() throws Exception { 1643 addNetworks(); 1644 1645 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 1646 switchUser(entry.getKey()); 1647 // Iterate through all the configs for the current user and invoke |enableNetwork| 1648 // on the corresponding config retrieved from WifiConfigManager. 1649 for (WifiConfiguration config : entry.getValue()) { 1650 WifiConfiguration retrievedConfig = 1651 mWifiConfigManager.getWifiConfiguration(config.networkId); 1652 assertTrue(mWifiConfigManager.enableNetwork(retrievedConfig, false, 0)); 1653 assertNetworkStatus(retrievedConfig, 1654 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 1655 verify(mWifiNative, never()).selectNetwork(anyInt()); 1656 } 1657 } 1658 } 1659 1660 /** 1661 * Test whether enableNetwork without the disableOthers flag set to true enables the input 1662 * network and attempts a connection to it immediately. It also checks if all the other 1663 * networks are disabled. 1664 */ 1665 @Test 1666 public void testEnableNetworkWithDisableOthers() throws Exception { 1667 addNetworks(); 1668 1669 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 1670 switchUser(entry.getKey()); 1671 // Iterate through all the configs for the current user and invoke |enableNetwork| 1672 // on the corresponding config retrieved from WifiConfigManager. 1673 for (WifiConfiguration config : entry.getValue()) { 1674 reset(mWifiNative); 1675 when(mWifiNative.selectNetwork(anyInt())).thenReturn(true); 1676 WifiConfiguration retrievedConfig = 1677 mWifiConfigManager.getWifiConfiguration(config.networkId); 1678 assertTrue(mWifiConfigManager.enableNetwork(retrievedConfig, true, 0)); 1679 assertNetworkStatus(retrievedConfig, 1680 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 1681 assertAllNetworksDisabledExcept(retrievedConfig.networkId, 1682 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER); 1683 verify(mWifiNative).selectNetwork(retrievedConfig.networkId); 1684 verify(mWifiNative, never()).selectNetwork(intThat(not(retrievedConfig.networkId))); 1685 } 1686 } 1687 } 1688 1689 private void assertNetworkStatus(WifiConfiguration config, int disableReason) { 1690 final WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus(); 1691 assertEquals(disableReason, status.getNetworkSelectionDisableReason()); 1692 if (disableReason 1693 == WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) { 1694 assertEquals(WifiConfiguration.Status.ENABLED, config.status); 1695 assertTrue(config.getNetworkSelectionStatus().isNetworkEnabled()); 1696 } else if (disableReason 1697 < WifiConfiguration.NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) { 1698 assertEquals(WifiConfiguration.Status.ENABLED, config.status); 1699 assertTrue(config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()); 1700 } else { 1701 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 1702 assertTrue(config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()); 1703 } 1704 } 1705 1706 private void assertAllNetworksDisabledExcept(int netId, int disableReason) { 1707 for (WifiConfiguration config : mWifiConfigManager.getSavedNetworks()) { 1708 if (config.networkId != netId) { 1709 assertNetworkStatus(config, disableReason); 1710 } 1711 } 1712 } 1713} 1714