WifiConfigManagerTest.java revision 49db6a0f9104fea99013fa6cfe6fcf2bdc7aa661
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.KeyMgmt; 42import android.net.wifi.WifiEnterpriseConfig; 43import android.net.wifi.WifiEnterpriseConfig.Eap; 44import android.net.wifi.WifiEnterpriseConfig.Phase2; 45import android.net.wifi.WifiScanner; 46import android.os.Process; 47import android.os.UserHandle; 48import android.os.UserManager; 49import android.security.Credentials; 50import android.support.test.InstrumentationRegistry; 51import android.test.suitebuilder.annotation.SmallTest; 52import android.text.TextUtils; 53import android.util.Log; 54import android.util.SparseArray; 55 56import com.android.server.net.DelayedDiskWrite; 57import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 58import com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager; 59import com.android.server.wifi.hotspot2.pps.Credential; 60import com.android.server.wifi.hotspot2.pps.HomeSP; 61 62import org.junit.Before; 63import org.junit.Test; 64import org.mockito.Mock; 65import org.mockito.MockitoAnnotations; 66 67import java.io.ByteArrayInputStream; 68import java.io.ByteArrayOutputStream; 69import java.io.DataInputStream; 70import java.io.DataOutputStream; 71import java.io.EOFException; 72import java.io.File; 73import java.io.FileOutputStream; 74import java.io.IOException; 75import java.lang.reflect.Field; 76import java.math.BigInteger; 77import java.security.cert.CertificateEncodingException; 78import java.security.cert.X509Certificate; 79import java.util.ArrayDeque; 80import java.util.ArrayList; 81import java.util.Arrays; 82import java.util.BitSet; 83import java.util.Collection; 84import java.util.Collections; 85import java.util.HashMap; 86import java.util.HashSet; 87import java.util.List; 88import java.util.Map; 89import java.util.Random; 90import java.util.Set; 91import java.util.TreeMap; 92 93/** 94 * Unit tests for {@link com.android.server.wifi.WifiConfigManager}. 95 */ 96@SmallTest 97public class WifiConfigManagerTest { 98 private static final List<WifiConfiguration> CONFIGS = Arrays.asList( 99 WifiConfigurationTestUtil.generateWifiConfig( 100 0, 1000000, "\"red\"", true, true, null, null), 101 WifiConfigurationTestUtil.generateWifiConfig( 102 1, 1000001, "\"green\"", true, true, "example.com", "Green"), 103 WifiConfigurationTestUtil.generateWifiConfig( 104 2, 1100000, "\"blue\"", false, true, "example.org", "Blue"), 105 WifiConfigurationTestUtil.generateWifiConfig( 106 3, 1200000, "\"cyan\"", false, true, null, null)); 107 108 private static final int[] USER_IDS = {0, 10, 11}; 109 private static final int MANAGED_PROFILE_USER_ID = 12; 110 private static final int MANAGED_PROFILE_PARENT_USER_ID = 0; 111 private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>(); 112 static { 113 USER_PROFILES.put(0, Arrays.asList(new UserInfo(0, "Owner", 0), 114 new UserInfo(12, "Managed Profile", 0))); 115 USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0))); 116 USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0))); 117 } 118 119 private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>(); 120 static { 121 for (int userId : USER_IDS) { 122 List<WifiConfiguration> configs = new ArrayList<>(); 123 for (int i = 0; i < CONFIGS.size(); ++i) { 124 if (WifiConfigurationUtil.isVisibleToAnyProfile(CONFIGS.get(i), 125 USER_PROFILES.get(userId))) { 126 configs.add(CONFIGS.get(i)); 127 } 128 } 129 VISIBLE_CONFIGS.put(userId, configs); 130 } 131 } 132 133 public static final String TAG = "WifiConfigManagerTest"; 134 @Mock private Context mContext; 135 @Mock private WifiNative mWifiNative; 136 @Mock private FrameworkFacade mFrameworkFacade; 137 @Mock private UserManager mUserManager; 138 @Mock private DelayedDiskWrite mWriter; 139 @Mock private PasspointManagementObjectManager mMOManager; 140 @Mock private Clock mClock; 141 private WifiConfigManager mWifiConfigManager; 142 private ConfigurationMap mConfiguredNetworks; 143 public byte[] mNetworkHistoryBytes; 144 private MockKeyStore mMockKeyStore; 145 146 /** 147 * Called before each test 148 */ 149 @Before 150 public void setUp() throws Exception { 151 MockitoAnnotations.initMocks(this); 152 153 final Context realContext = InstrumentationRegistry.getContext(); 154 when(mContext.getPackageName()).thenReturn(realContext.getPackageName()); 155 when(mContext.getResources()).thenReturn(realContext.getResources()); 156 when(mContext.getPackageManager()).thenReturn(realContext.getPackageManager()); 157 158 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)) 159 .thenReturn(USER_PROFILES.get(UserHandle.USER_SYSTEM)); 160 161 for (int userId : USER_IDS) { 162 when(mUserManager.getProfiles(userId)).thenReturn(USER_PROFILES.get(userId)); 163 } 164 165 mMockKeyStore = new MockKeyStore(); 166 167 mWifiConfigManager = new WifiConfigManager(mContext, mWifiNative, mFrameworkFacade, mClock, 168 mUserManager, mMockKeyStore.createMock()); 169 170 final Field configuredNetworksField = 171 WifiConfigManager.class.getDeclaredField("mConfiguredNetworks"); 172 configuredNetworksField.setAccessible(true); 173 mConfiguredNetworks = (ConfigurationMap) configuredNetworksField.get(mWifiConfigManager); 174 175 // Intercept writes to networkHistory.txt. 176 doAnswer(new AnswerWithArguments() { 177 public void answer(String filePath, DelayedDiskWrite.Writer writer) throws Exception { 178 final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 179 final DataOutputStream stream = new DataOutputStream(buffer); 180 writer.onWriteCalled(stream); 181 stream.close(); 182 mNetworkHistoryBytes = buffer.toByteArray(); 183 }}).when(mWriter).write(anyString(), (DelayedDiskWrite.Writer) anyObject()); 184 final Field writerField = WifiConfigManager.class.getDeclaredField("mWriter"); 185 writerField.setAccessible(true); 186 writerField.set(mWifiConfigManager, mWriter); 187 final Field networkHistoryField = 188 WifiConfigManager.class.getDeclaredField("mWifiNetworkHistory"); 189 networkHistoryField.setAccessible(true); 190 WifiNetworkHistory wifiNetworkHistory = 191 (WifiNetworkHistory) networkHistoryField.get(mWifiConfigManager); 192 final Field networkHistoryWriterField = 193 WifiNetworkHistory.class.getDeclaredField("mWriter"); 194 networkHistoryWriterField.setAccessible(true); 195 networkHistoryWriterField.set(wifiNetworkHistory, mWriter); 196 197 when(mMOManager.isEnabled()).thenReturn(true); 198 final Field moManagerField = WifiConfigManager.class.getDeclaredField("mMOManager"); 199 moManagerField.setAccessible(true); 200 moManagerField.set(mWifiConfigManager, mMOManager); 201 } 202 203 private void switchUser(int newUserId) { 204 when(mUserManager.getProfiles(newUserId)) 205 .thenReturn(USER_PROFILES.get(newUserId)); 206 mWifiConfigManager.handleUserSwitch(newUserId); 207 } 208 209 private void switchUserToCreatorOrParentOf(WifiConfiguration config) { 210 final int creatorUserId = UserHandle.getUserId(config.creatorUid); 211 if (creatorUserId == MANAGED_PROFILE_USER_ID) { 212 switchUser(MANAGED_PROFILE_PARENT_USER_ID); 213 } else { 214 switchUser(creatorUserId); 215 } 216 } 217 218 private void addNetworks() throws Exception { 219 final int originalUserId = mWifiConfigManager.getCurrentUserId(); 220 221 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); 222 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 223 .thenReturn(true); 224 for (int i = 0; i < CONFIGS.size(); ++i) { 225 assertEquals(i, CONFIGS.get(i).networkId); 226 switchUserToCreatorOrParentOf(CONFIGS.get(i)); 227 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i)); 228 config.networkId = -1; 229 when(mWifiNative.addNetwork()).thenReturn(i); 230 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 231 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 232 mWifiConfigManager.saveNetwork(config, config.creatorUid); 233 } 234 235 switchUser(originalUserId); 236 } 237 238 private String encodeConfigSSID(WifiConfiguration config) throws Exception { 239 return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1) 240 .getBytes("UTF-8")).toString(16); 241 } 242 243 /** 244 * Verifies that getConfiguredNetworksSize() returns the number of network configurations 245 * visible to the current user. 246 */ 247 @Test 248 public void testGetConfiguredNetworksSize() throws Exception { 249 addNetworks(); 250 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 251 switchUser(entry.getKey()); 252 assertEquals(entry.getValue().size(), mWifiConfigManager.getConfiguredNetworksSize()); 253 } 254 } 255 256 private void verifyNetworkConfig(WifiConfiguration expectedConfig, 257 WifiConfiguration actualConfig) { 258 assertNotNull(actualConfig); 259 assertEquals(expectedConfig.SSID, actualConfig.SSID); 260 assertEquals(expectedConfig.FQDN, actualConfig.FQDN); 261 assertEquals(expectedConfig.providerFriendlyName, 262 actualConfig.providerFriendlyName); 263 assertEquals(expectedConfig.configKey(), actualConfig.configKey(false)); 264 } 265 266 private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, 267 Collection<WifiConfiguration> actualConfigs) { 268 assertEquals(expectedConfigs.size(), actualConfigs.size()); 269 for (WifiConfiguration expectedConfig : expectedConfigs) { 270 WifiConfiguration actualConfig = null; 271 // Find the network configuration to test (assume that |actualConfigs| contains them in 272 // undefined order). 273 for (final WifiConfiguration candidate : actualConfigs) { 274 if (candidate.networkId == expectedConfig.networkId) { 275 actualConfig = candidate; 276 break; 277 } 278 } 279 verifyNetworkConfig(expectedConfig, actualConfig); 280 } 281 } 282 283 /** 284 * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the 285 * current user. 286 */ 287 @Test 288 public void testGetConfiguredNetworks() throws Exception { 289 addNetworks(); 290 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 291 switchUser(entry.getKey()); 292 verifyNetworkConfigs(entry.getValue(), mWifiConfigManager.getSavedNetworks()); 293 } 294 } 295 296 /** 297 * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to 298 * the current user. 299 */ 300 @Test 301 public void testGetPrivilegedConfiguredNetworks() throws Exception { 302 addNetworks(); 303 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 304 switchUser(entry.getKey()); 305 verifyNetworkConfigs(entry.getValue(), 306 mWifiConfigManager.getPrivilegedSavedNetworks()); 307 } 308 } 309 310 /** 311 * Verifies that getWifiConfiguration(int netId) can be used to access network configurations 312 * visible to the current user only. 313 */ 314 @Test 315 public void testGetWifiConfigurationByNetworkId() throws Exception { 316 addNetworks(); 317 for (int userId : USER_IDS) { 318 switchUser(userId); 319 for (WifiConfiguration expectedConfig: CONFIGS) { 320 final WifiConfiguration actualConfig = 321 mWifiConfigManager.getWifiConfiguration(expectedConfig.networkId); 322 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 323 USER_PROFILES.get(userId))) { 324 verifyNetworkConfig(expectedConfig, actualConfig); 325 } else { 326 assertNull(actualConfig); 327 } 328 } 329 } 330 } 331 332 /** 333 * Verifies that getWifiConfiguration(String key) can be used to access network configurations 334 * visible to the current user only. 335 */ 336 @Test 337 public void testGetWifiConfigurationByConfigKey() throws Exception { 338 addNetworks(); 339 for (int userId : USER_IDS) { 340 switchUser(userId); 341 for (WifiConfiguration expectedConfig: CONFIGS) { 342 final WifiConfiguration actualConfig = 343 mWifiConfigManager.getWifiConfiguration(expectedConfig.configKey()); 344 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 345 USER_PROFILES.get(userId))) { 346 verifyNetworkConfig(expectedConfig, actualConfig); 347 } else { 348 assertNull(actualConfig); 349 } 350 } 351 } 352 } 353 354 /** 355 * Verifies that enableAllNetworks() enables all temporarily disabled network configurations 356 * visible to the current user. 357 */ 358 @Test 359 public void testEnableAllNetworks() throws Exception { 360 addNetworks(); 361 for (int userId : USER_IDS) { 362 switchUser(userId); 363 364 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 365 final WifiConfiguration.NetworkSelectionStatus status = 366 config.getNetworkSelectionStatus(); 367 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus 368 .NETWORK_SELECTION_TEMPORARY_DISABLED); 369 status.setNetworkSelectionDisableReason( 370 WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE); 371 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000); 372 } 373 374 mWifiConfigManager.enableAllNetworks(); 375 376 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 377 assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config, 378 USER_PROFILES.get(userId)), 379 config.getNetworkSelectionStatus().isNetworkEnabled()); 380 } 381 } 382 } 383 384 /** 385 * Verifies that selectNetwork() disables all network configurations visible to the current user 386 * except the selected one. 387 */ 388 @Test 389 public void testSelectNetwork() throws Exception { 390 addNetworks(); 391 392 for (int userId : USER_IDS) { 393 switchUser(userId); 394 395 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 396 // Enable all network configurations. 397 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 398 config2.status = WifiConfiguration.Status.ENABLED; 399 } 400 401 // Try to select a network configuration. 402 reset(mWifiNative); 403 when(mWifiNative.selectNetwork(config.networkId)).thenReturn(true); 404 final boolean success = 405 mWifiConfigManager.selectNetwork(config, false, config.creatorUid); 406 if (!WifiConfigurationUtil.isVisibleToAnyProfile(config, 407 USER_PROFILES.get(userId))) { 408 // If the network configuration is not visible to the current user, verify that 409 // nothing changed. 410 assertFalse(success); 411 verify(mWifiNative, never()).selectNetwork(anyInt()); 412 verify(mWifiNative, never()).enableNetwork(anyInt()); 413 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 414 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 415 } 416 } else { 417 // If the network configuration is visible to the current user, verify that it 418 // was enabled and all other network configurations visible to the user were 419 // disabled. 420 assertTrue(success); 421 verify(mWifiNative).selectNetwork(config.networkId); 422 verify(mWifiNative, never()).selectNetwork(intThat(not(config.networkId))); 423 verify(mWifiNative, never()).enableNetwork(config.networkId); 424 verify(mWifiNative, never()).enableNetwork(intThat(not(config.networkId))); 425 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 426 if (WifiConfigurationUtil.isVisibleToAnyProfile(config2, 427 USER_PROFILES.get(userId)) 428 && config2.networkId != config.networkId) { 429 assertEquals(WifiConfiguration.Status.DISABLED, config2.status); 430 } else { 431 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 432 } 433 } 434 } 435 } 436 } 437 } 438 439 /** 440 * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant 441 * variables and the networkHistory.txt file. 442 * TODO: Test all variables. Currently, only the following variables are tested: 443 * - In the wpa_supplicant: "ssid", "id_str" 444 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 445 */ 446 private void verifySaveNetwork(int network) throws Exception { 447 // Switch to the correct user. 448 switchUserToCreatorOrParentOf(CONFIGS.get(network)); 449 450 // Set up wpa_supplicant. 451 when(mWifiNative.addNetwork()).thenReturn(0); 452 when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString())) 453 .thenReturn(true); 454 when(mWifiNative.setNetworkExtra(eq(network), anyString(), 455 (Map<String, String>) anyObject())).thenReturn(true); 456 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName)) 457 .thenReturn(encodeConfigSSID(CONFIGS.get(network))); 458 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.pmfVarName)) 459 .thenReturn(""); 460 461 // Store a network configuration. 462 mWifiConfigManager.saveNetwork(CONFIGS.get(network), CONFIGS.get(network).creatorUid); 463 464 // Verify that wpa_supplicant variables were written correctly for the network 465 // configuration. 466 final Map<String, String> metadata = new HashMap<String, String>(); 467 if (CONFIGS.get(network).FQDN != null) { 468 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(network).FQDN); 469 } 470 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(network).configKey()); 471 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 472 Integer.toString(CONFIGS.get(network).creatorUid)); 473 verify(mWifiNative).setNetworkExtra(network, WifiConfigStore.ID_STRING_VAR_NAME, 474 metadata); 475 476 // Verify that an attempt to read back the requirePMF variable was made. 477 verify(mWifiNative).getNetworkVariable(network, WifiConfiguration.pmfVarName); 478 479 // Verify that no wpa_supplicant variables were read or written for any other network 480 // configurations. 481 verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(), 482 (Map<String, String>) anyObject()); 483 verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(), 484 anyString()); 485 verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString()); 486 487 // Parse networkHistory.txt. 488 assertNotNull(mNetworkHistoryBytes); 489 final DataInputStream stream = 490 new DataInputStream(new ByteArrayInputStream(mNetworkHistoryBytes)); 491 List<String> keys = new ArrayList<>(); 492 List<String> values = new ArrayList<>(); 493 try { 494 while (true) { 495 final String[] tokens = stream.readUTF().split(":", 2); 496 if (tokens.length == 2) { 497 keys.add(tokens[0].trim()); 498 values.add(tokens[1].trim()); 499 } 500 } 501 } catch (EOFException e) { 502 // Ignore. This is expected. 503 } 504 505 // Verify that a networkHistory.txt entry was written correctly for the network 506 // configuration. 507 assertTrue(keys.size() >= 3); 508 assertEquals(WifiNetworkHistory.CONFIG_KEY, keys.get(0)); 509 assertEquals(CONFIGS.get(network).configKey(), values.get(0)); 510 final int creatorUidIndex = keys.indexOf(WifiNetworkHistory.CREATOR_UID_KEY); 511 assertTrue(creatorUidIndex != -1); 512 assertEquals(Integer.toString(CONFIGS.get(network).creatorUid), 513 values.get(creatorUidIndex)); 514 final int sharedIndex = keys.indexOf(WifiNetworkHistory.SHARED_KEY); 515 assertTrue(sharedIndex != -1); 516 assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex)); 517 518 // Verify that no networkHistory.txt entries were written for any other network 519 // configurations. 520 final int lastConfigIndex = keys.lastIndexOf(WifiNetworkHistory.CONFIG_KEY); 521 assertEquals(0, lastConfigIndex); 522 } 523 524 /** 525 * Verifies that saveNetwork() correctly stores a regular network configuration. 526 */ 527 @Test 528 public void testSaveNetworkRegular() throws Exception { 529 verifySaveNetwork(0); 530 } 531 532 /** 533 * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration. 534 */ 535 @Test 536 public void testSaveNetworkHotspot20() throws Exception { 537 verifySaveNetwork(1); 538 } 539 540 /** 541 * Verifies that saveNetwork() correctly stores a private network configuration. 542 */ 543 @Test 544 public void testSaveNetworkPrivate() throws Exception { 545 verifySaveNetwork(2); 546 } 547 548 /** 549 * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the 550 * networkHistory.txt file and the MOManager, correlating the three sources based on the 551 * configKey and the FQDN for HotSpot 2.0 networks. 552 * TODO: Test all variables. Currently, only the following variables are tested: 553 * - In the wpa_supplicant: "ssid", "id_str" 554 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 555 */ 556 @Test 557 public void testLoadConfiguredNetworks() throws Exception { 558 // Set up list of network configurations returned by wpa_supplicant. 559 final String header = "network id / ssid / bssid / flags"; 560 String networks = header; 561 for (WifiConfiguration config : CONFIGS) { 562 networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany"; 563 } 564 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 565 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 566 567 // Set up variables returned by wpa_supplicant for the individual network configurations. 568 for (int i = 0; i < CONFIGS.size(); ++i) { 569 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 570 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 571 } 572 // Legacy regular network configuration: No "id_str". 573 when(mWifiNative.getNetworkExtra(0, WifiConfigStore.ID_STRING_VAR_NAME)) 574 .thenReturn(null); 575 // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str". 576 when(mWifiNative.getNetworkExtra(1, WifiConfigStore.ID_STRING_VAR_NAME)) 577 .thenReturn(null); 578 when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME)) 579 .thenReturn('"' + CONFIGS.get(1).FQDN + '"'); 580 // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str". 581 Map<String, String> metadata = new HashMap<String, String>(); 582 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey()); 583 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 584 Integer.toString(CONFIGS.get(2).creatorUid)); 585 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN); 586 when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME)) 587 .thenReturn(metadata); 588 // Up-to-date regular network configuration: Metadata in "id_str". 589 metadata = new HashMap<String, String>(); 590 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey()); 591 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 592 Integer.toString(CONFIGS.get(3).creatorUid)); 593 when(mWifiNative.getNetworkExtra(3, WifiConfigStore.ID_STRING_VAR_NAME)) 594 .thenReturn(metadata); 595 596 // Set up networkHistory.txt file. 597 final File file = File.createTempFile("networkHistory.txt", null); 598 file.deleteOnExit(); 599 600 Field wifiNetworkHistoryConfigFile = 601 WifiNetworkHistory.class.getDeclaredField("NETWORK_HISTORY_CONFIG_FILE"); 602 wifiNetworkHistoryConfigFile.setAccessible(true); 603 wifiNetworkHistoryConfigFile.set(null, file.getAbsolutePath()); 604 605 final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); 606 for (WifiConfiguration config : CONFIGS) { 607 stream.writeUTF(WifiNetworkHistory.CONFIG_KEY + ": " + config.configKey() + '\n'); 608 stream.writeUTF(WifiNetworkHistory.CREATOR_UID_KEY + ": " 609 + Integer.toString(config.creatorUid) + '\n'); 610 stream.writeUTF(WifiNetworkHistory.SHARED_KEY + ": " 611 + Boolean.toString(config.shared) + '\n'); 612 } 613 stream.close(); 614 615 // Set up list of home service providers returned by MOManager. 616 final List<HomeSP> homeSPs = new ArrayList<HomeSP>(); 617 for (WifiConfiguration config : CONFIGS) { 618 if (config.FQDN != null) { 619 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(), 620 new HashSet<String>(), 621 new HashSet<Long>(), new ArrayList<Long>(), 622 config.providerFriendlyName, null, 623 new Credential(0, 0, null, false, null, null), 624 null, 0, null, null, null, 0)); 625 } 626 } 627 when(mMOManager.loadAllSPs()).thenReturn(homeSPs); 628 629 // Load network configurations. 630 mWifiConfigManager.loadConfiguredNetworks(); 631 632 // Verify that network configurations were loaded and correlated correctly across the three 633 // sources. 634 verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers()); 635 } 636 637 /** 638 * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network 639 * configurations from the wpa_supplicant: The second configuration overwrites the first. 640 */ 641 @Test 642 public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception { 643 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0)); 644 config.networkId = 1; 645 646 // Set up list of network configurations returned by wpa_supplicant. The two configurations 647 // are identical except for their network IDs. 648 final String header = "network id / ssid / bssid / flags"; 649 final String networks = 650 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany"; 651 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 652 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 653 654 // Set up variables returned by wpa_supplicant. 655 when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName))) 656 .thenReturn(encodeConfigSSID(config)); 657 final Map<String, String> metadata = new HashMap<String, String>(); 658 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, config.configKey()); 659 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 660 Integer.toString(config.creatorUid)); 661 when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigStore.ID_STRING_VAR_NAME))) 662 .thenReturn(metadata); 663 664 // Load network configurations. 665 mWifiConfigManager.loadConfiguredNetworks(); 666 667 // Verify that the second network configuration (network ID 1) overwrote the first (network 668 // ID 0). 669 verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers()); 670 } 671 672 /** 673 * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network 674 * configurations that should no longer be visible and enables network configurations that 675 * should become visible. 676 */ 677 private void verifyHandleUserSwitch(int oldUserId, int newUserId, 678 boolean makeOneConfigEphemeral) throws Exception { 679 addNetworks(); 680 switchUser(oldUserId); 681 682 reset(mWifiNative); 683 final Field lastSelectedConfigurationField = 684 WifiConfigManager.class.getDeclaredField("mLastSelectedConfiguration"); 685 lastSelectedConfigurationField.setAccessible(true); 686 WifiConfiguration removedEphemeralConfig = null; 687 final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>(); 688 final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>(); 689 final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>(); 690 final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers(); 691 int expectedNumberOfConfigs = oldConfigs.size(); 692 for (WifiConfiguration config : oldConfigs) { 693 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) { 694 config.status = WifiConfiguration.Status.ENABLED; 695 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 696 USER_PROFILES.get(newUserId))) { 697 if (makeOneConfigEphemeral && removedEphemeralConfig == null) { 698 config.ephemeral = true; 699 lastSelectedConfigurationField.set(mWifiConfigManager, config.configKey()); 700 removedEphemeralConfig = config; 701 } 702 } else { 703 oldUserOnlyConfigs.add(config); 704 } 705 } else { 706 config.status = WifiConfiguration.Status.DISABLED; 707 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 708 USER_PROFILES.get(newUserId))) { 709 newUserOnlyConfigs.add(config); 710 } else { 711 neitherUserConfigs.add(config); 712 } 713 } 714 } 715 716 when(mWifiNative.disableNetwork(anyInt())).thenReturn(true); 717 when(mWifiNative.removeNetwork(anyInt())).thenReturn(true); 718 719 switchUser(newUserId); 720 if (makeOneConfigEphemeral) { 721 // Verify that the ephemeral network configuration was removed. 722 assertNotNull(removedEphemeralConfig); 723 assertNull(mConfiguredNetworks.getForAllUsers(removedEphemeralConfig.networkId)); 724 assertNull(lastSelectedConfigurationField.get(mWifiConfigManager)); 725 verify(mWifiNative).removeNetwork(removedEphemeralConfig.networkId); 726 --expectedNumberOfConfigs; 727 } else { 728 assertNull(removedEphemeralConfig); 729 } 730 731 // Verify that the other network configurations were revealed/hidden and enabled/disabled as 732 // appropriate. 733 final Collection<WifiConfiguration> newConfigs = mConfiguredNetworks.valuesForAllUsers(); 734 assertEquals(expectedNumberOfConfigs, newConfigs.size()); 735 for (WifiConfiguration config : newConfigs) { 736 if (oldUserOnlyConfigs.contains(config)) { 737 verify(mWifiNative).disableNetwork(config.networkId); 738 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 739 } else { 740 verify(mWifiNative, never()).disableNetwork(config.networkId); 741 if (neitherUserConfigs.contains(config)) { 742 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 743 } else { 744 // Only enabled in networkSelection. 745 assertTrue(config.getNetworkSelectionStatus().isNetworkEnabled()); 746 } 747 748 } 749 } 750 } 751 752 /** 753 * Verifies that handleUserSwitch() behaves correctly when the user switch removes an ephemeral 754 * network configuration and reveals a private network configuration. 755 */ 756 @Test 757 public void testHandleUserSwitchWithEphemeral() throws Exception { 758 verifyHandleUserSwitch(USER_IDS[2], USER_IDS[0], true); 759 } 760 761 /** 762 * Verifies that handleUserSwitch() behaves correctly when the user switch hides a private 763 * network configuration. 764 */ 765 @Test 766 public void testHandleUserSwitchWithoutEphemeral() throws Exception { 767 verifyHandleUserSwitch(USER_IDS[0], USER_IDS[2], false); 768 } 769 770 @Test 771 public void testSaveLoadEapNetworks() { 772 testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS) 773 .setPhase2(Phase2.MSCHAPV2) 774 .setIdentity("username", "password") 775 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0})); 776 testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS) 777 .setPhase2(Phase2.MSCHAPV2) 778 .setIdentity("username", "password") 779 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1, FakeKeys.CA_CERT0})); 780 781 } 782 783 private void testSaveLoadSingleEapNetwork(String ssid, EnterpriseConfig eapConfig) { 784 final HashMap<String, String> networkVariables = new HashMap<String, String>(); 785 reset(mWifiNative); 786 when(mWifiNative.addNetwork()).thenReturn(0); 787 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenAnswer( 788 new AnswerWithArguments() { 789 public boolean answer(int netId, String name, String value) { 790 // Verify that no wpa_supplicant variables were written for any other 791 // network configurations. 792 assertEquals(netId, 0); 793 networkVariables.put(name, value); 794 return true; 795 } 796 }); 797 when(mWifiNative.getNetworkVariable(anyInt(), anyString())).then( 798 new AnswerWithArguments() { 799 public String answer(int netId, String name) { 800 // Verify that no wpa_supplicant variables were read for any other 801 // network configurations. 802 assertEquals(netId, 0); 803 return networkVariables.get(name); 804 } 805 }); 806 when(mWifiNative.setNetworkExtra(eq(0), anyString(), (Map<String, String>) anyObject())) 807 .thenReturn(true); 808 809 WifiConfiguration config = new WifiConfiguration(); 810 config.SSID = ssid; 811 config.creatorUid = Process.WIFI_UID; 812 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 813 config.enterpriseConfig = eapConfig.enterpriseConfig; 814 815 // Store a network configuration. 816 mWifiConfigManager.saveNetwork(config, Process.WIFI_UID); 817 818 // Verify that wpa_supplicant variables were written correctly for the network 819 // configuration. 820 verify(mWifiNative).addNetwork(); 821 assertEquals(eapConfig.eap, 822 unquote(networkVariables.get(WifiEnterpriseConfig.EAP_KEY))); 823 assertEquals(eapConfig.phase2, 824 unquote(networkVariables.get(WifiEnterpriseConfig.PHASE2_KEY))); 825 assertEquals(eapConfig.identity, 826 unquote(networkVariables.get(WifiEnterpriseConfig.IDENTITY_KEY))); 827 assertEquals(eapConfig.password, 828 unquote(networkVariables.get(WifiEnterpriseConfig.PASSWORD_KEY))); 829 assertSavedCaCerts(eapConfig, 830 unquote(networkVariables.get(WifiEnterpriseConfig.CA_CERT_KEY))); 831 832 // Prepare the scan result. 833 final String header = "network id / ssid / bssid / flags"; 834 String networks = header + "\n" + Integer.toString(0) + "\t" + ssid + "\tany"; 835 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 836 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 837 838 // Load back the configuration. 839 mWifiConfigManager.loadConfiguredNetworks(); 840 List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks(); 841 assertEquals(1, configs.size()); 842 WifiConfiguration loadedConfig = configs.get(0); 843 assertEquals(ssid, unquote(loadedConfig.SSID)); 844 BitSet keyMgmt = new BitSet(); 845 keyMgmt.set(KeyMgmt.WPA_EAP); 846 assertEquals(keyMgmt, loadedConfig.allowedKeyManagement); 847 assertEquals(eapConfig.enterpriseConfig.getEapMethod(), 848 loadedConfig.enterpriseConfig.getEapMethod()); 849 assertEquals(eapConfig.enterpriseConfig.getPhase2Method(), 850 loadedConfig.enterpriseConfig.getPhase2Method()); 851 assertEquals(eapConfig.enterpriseConfig.getIdentity(), 852 loadedConfig.enterpriseConfig.getIdentity()); 853 assertEquals(eapConfig.enterpriseConfig.getPassword(), 854 loadedConfig.enterpriseConfig.getPassword()); 855 asserCaCertsAliasesMatch(eapConfig.caCerts, 856 loadedConfig.enterpriseConfig.getCaCertificateAliases()); 857 } 858 859 private String unquote(String value) { 860 if (value == null) { 861 return null; 862 } 863 int length = value.length(); 864 if ((length > 1) && (value.charAt(0) == '"') 865 && (value.charAt(length - 1) == '"')) { 866 return value.substring(1, length - 1); 867 } else { 868 return value; 869 } 870 } 871 872 private void asserCaCertsAliasesMatch(X509Certificate[] certs, String[] aliases) { 873 assertEquals(certs.length, aliases.length); 874 List<String> aliasList = new ArrayList<String>(Arrays.asList(aliases)); 875 try { 876 for (int i = 0; i < certs.length; i++) { 877 byte[] certPem = Credentials.convertToPem(certs[i]); 878 boolean found = false; 879 for (int j = 0; j < aliasList.size(); j++) { 880 byte[] keystoreCert = mMockKeyStore.getKeyBlob(Process.WIFI_UID, 881 Credentials.CA_CERTIFICATE + aliasList.get(j)).blob; 882 if (Arrays.equals(keystoreCert, certPem)) { 883 found = true; 884 aliasList.remove(j); 885 break; 886 } 887 } 888 assertTrue(found); 889 } 890 } catch (CertificateEncodingException | IOException e) { 891 fail("Cannot convert CA certificate to encoded form."); 892 } 893 } 894 895 private void assertSavedCaCerts(EnterpriseConfig eapConfig, String caCertVariable) { 896 ArrayList<String> aliases = new ArrayList<String>(); 897 if (TextUtils.isEmpty(caCertVariable)) { 898 // Do nothing. 899 } else if (caCertVariable.startsWith(WifiEnterpriseConfig.CA_CERT_PREFIX)) { 900 aliases.add(caCertVariable.substring(WifiEnterpriseConfig.CA_CERT_PREFIX.length())); 901 } else if (caCertVariable.startsWith(WifiEnterpriseConfig.KEYSTORES_URI)) { 902 String[] encodedAliases = TextUtils.split( 903 caCertVariable.substring(WifiEnterpriseConfig.KEYSTORES_URI.length()), 904 WifiEnterpriseConfig.CA_CERT_ALIAS_DELIMITER); 905 for (String encodedAlias : encodedAliases) { 906 String alias = WifiEnterpriseConfig.decodeCaCertificateAlias(encodedAlias); 907 assertTrue(alias.startsWith(Credentials.CA_CERTIFICATE)); 908 aliases.add(alias.substring(Credentials.CA_CERTIFICATE.length())); 909 } 910 } else { 911 fail("Unrecognized ca_cert variable: " + caCertVariable); 912 } 913 asserCaCertsAliasesMatch(eapConfig.caCerts, aliases.toArray(new String[aliases.size()])); 914 } 915 916 private static class EnterpriseConfig { 917 public String eap; 918 public String phase2; 919 public String identity; 920 public String password; 921 public X509Certificate[] caCerts; 922 public WifiEnterpriseConfig enterpriseConfig; 923 924 public EnterpriseConfig(int eapMethod) { 925 enterpriseConfig = new WifiEnterpriseConfig(); 926 enterpriseConfig.setEapMethod(eapMethod); 927 eap = Eap.strings[eapMethod]; 928 } 929 public EnterpriseConfig setPhase2(int phase2Method) { 930 enterpriseConfig.setPhase2Method(phase2Method); 931 phase2 = "auth=" + Phase2.strings[phase2Method]; 932 return this; 933 } 934 public EnterpriseConfig setIdentity(String identity, String password) { 935 enterpriseConfig.setIdentity(identity); 936 enterpriseConfig.setPassword(password); 937 this.identity = identity; 938 this.password = password; 939 return this; 940 } 941 public EnterpriseConfig setCaCerts(X509Certificate[] certs) { 942 enterpriseConfig.setCaCertificates(certs); 943 caCerts = certs; 944 return this; 945 } 946 } 947 948 /** 949 * Generates an array of unique random numbers below the specified maxValue. 950 * Values range from 0 to maxValue-1. 951 */ 952 private static ArrayDeque<Integer> getUniqueRandomNumberValues( 953 int seed, 954 int maxValue, 955 int numValues) { 956 assertTrue(numValues <= maxValue); 957 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode() + seed); 958 ArrayDeque<Integer> randomNumberList = new ArrayDeque<>(); 959 for (int i = 0; i < numValues; i++) { 960 int num = rand.nextInt(maxValue); 961 while (randomNumberList.contains(num)) { 962 num = rand.nextInt(maxValue); 963 } 964 randomNumberList.push(num); 965 } 966 return randomNumberList; 967 } 968 969 /** 970 * Verifies that the networks in pnoNetworkList is sorted in the same order as the 971 * network in expectedNetworkIDOrder list. 972 */ 973 private static void verifyPnoNetworkListOrder( 974 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList, 975 ArrayList<Integer> expectedNetworkIdOrder) throws Exception { 976 int i = 0; 977 for (WifiScanner.PnoSettings.PnoNetwork pnoNetwork : pnoNetworkList) { 978 Log.i(TAG, "PNO Network List Index: " + i + ", networkID: " + pnoNetwork.networkId); 979 assertEquals("Expected network ID: " + pnoNetwork.networkId, 980 pnoNetwork.networkId, expectedNetworkIdOrder.get(i++).intValue()); 981 } 982 } 983 984 /** 985 * Verifies the retrieveDisconnectedPnoNetworkList API. The test verifies that the list 986 * returned from the API is sorted as expected. 987 */ 988 @Test 989 public void testDisconnectedPnoNetworkListCreation() throws Exception { 990 addNetworks(); 991 992 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode()); 993 994 // First assign random |numAssociation| values and verify that the list is sorted 995 // in descending order of |numAssociation| values. Keep NetworkSelectionStatus 996 // values constant. 997 for (int userId : USER_IDS) { 998 switchUser(userId); 999 TreeMap<Integer, Integer> numAssociationToNetworkIdMap = 1000 new TreeMap<>(Collections.reverseOrder()); 1001 ArrayDeque<Integer> numAssociationValues = 1002 getUniqueRandomNumberValues( 1003 1, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1004 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1005 config.numAssociation = numAssociationValues.pop(); 1006 config.priority = rand.nextInt(10000); 1007 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1008 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1009 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId); 1010 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: " 1011 + config.numAssociation); 1012 } 1013 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1014 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1015 verifyPnoNetworkListOrder(pnoNetworkList, 1016 new ArrayList(numAssociationToNetworkIdMap.values())); 1017 } 1018 1019 // Assign random |priority| values and verify that the list is sorted in descending order 1020 // of |priority| values. Keep numAssociation/NetworkSelectionStatus values constant. 1021 for (int userId : USER_IDS) { 1022 switchUser(userId); 1023 TreeMap<Integer, Integer> priorityToNetworkIdMap = 1024 new TreeMap<>(Collections.reverseOrder()); 1025 ArrayDeque<Integer> priorityValues = 1026 getUniqueRandomNumberValues( 1027 2, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1028 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1029 config.numAssociation = 0; 1030 config.priority = priorityValues.pop(); 1031 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1032 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1033 priorityToNetworkIdMap.put(config.priority, config.networkId); 1034 Log.i(TAG, "networkID: " + config.networkId + ", priority: " + config.priority); 1035 } 1036 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1037 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1038 verifyPnoNetworkListOrder(pnoNetworkList, 1039 new ArrayList(priorityToNetworkIdMap.values())); 1040 } 1041 1042 // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in 1043 // ascending order of |NetworkSelectionStatus| values. 1044 for (int userId : USER_IDS) { 1045 switchUser(userId); 1046 TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>(); 1047 ArrayDeque<Integer> networkSelectionStatusValues = 1048 getUniqueRandomNumberValues( 1049 3, 1050 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX, 1051 mConfiguredNetworks.valuesForCurrentUser().size()); 1052 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1053 config.numAssociation = rand.nextInt(10000); 1054 config.priority = rand.nextInt(10000); 1055 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1056 networkSelectionStatusValues.pop()); 1057 networkSelectionStatusToNetworkIdMap.put( 1058 config.getNetworkSelectionStatus().getNetworkSelectionStatus(), 1059 config.networkId); 1060 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: " 1061 + config.getNetworkSelectionStatus().getNetworkSelectionStatus()); 1062 } 1063 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1064 mWifiConfigManager.retrieveDisconnectedPnoNetworkList(); 1065 verifyPnoNetworkListOrder(pnoNetworkList, 1066 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1067 } 1068 } 1069 1070 /** 1071 * Verifies the retrieveConnectedPnoNetworkList API. The test verifies that the list 1072 * returned from the API is sorted as expected. 1073 */ 1074 @Test 1075 public void testConnectedPnoNetworkListCreation() throws Exception { 1076 addNetworks(); 1077 1078 Random rand = new Random(WifiTestUtil.getTestMethod().hashCode()); 1079 1080 // First assign |lastSeen| values and verify that the list is sorted 1081 // in descending order of |lastSeen| values. Keep NetworkSelectionStatus 1082 // values constant. 1083 for (int userId : USER_IDS) { 1084 switchUser(userId); 1085 TreeMap<Boolean, Integer> lastSeenToNetworkIdMap = 1086 new TreeMap<>(Collections.reverseOrder()); 1087 ArrayDeque<Integer> lastSeenValues = getUniqueRandomNumberValues(1, 2, 2); 1088 if (mConfiguredNetworks.valuesForCurrentUser().size() > 2) continue; 1089 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1090 config.numAssociation = rand.nextInt(10000); 1091 config.priority = rand.nextInt(10000); 1092 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1093 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1094 boolean lastSeenValue = (lastSeenValues.pop() == 1); 1095 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection( 1096 lastSeenValue); 1097 lastSeenToNetworkIdMap.put(lastSeenValue, config.networkId); 1098 Log.i(TAG, "networkID: " + config.networkId + ", lastSeen: " + lastSeenValue); 1099 } 1100 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1101 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1102 verifyPnoNetworkListOrder(pnoNetworkList, 1103 new ArrayList(lastSeenToNetworkIdMap.values())); 1104 } 1105 1106 // Assign random |numAssociation| values and verify that the list is sorted 1107 // in descending order of |numAssociation| values. Keep NetworkSelectionStatus/lastSeen 1108 // values constant. 1109 for (int userId : USER_IDS) { 1110 switchUser(userId); 1111 TreeMap<Integer, Integer> numAssociationToNetworkIdMap = 1112 new TreeMap<>(Collections.reverseOrder()); 1113 ArrayDeque<Integer> numAssociationValues = 1114 getUniqueRandomNumberValues( 1115 1, 10000, mConfiguredNetworks.valuesForCurrentUser().size()); 1116 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1117 config.numAssociation = numAssociationValues.pop(); 1118 config.priority = rand.nextInt(10000); 1119 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1120 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1121 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true); 1122 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId); 1123 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: " 1124 + config.numAssociation); 1125 } 1126 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1127 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1128 verifyPnoNetworkListOrder(pnoNetworkList, 1129 new ArrayList(numAssociationToNetworkIdMap.values())); 1130 } 1131 1132 // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in 1133 // ascending order of |NetworkSelectionStatus| values. 1134 for (int userId : USER_IDS) { 1135 switchUser(userId); 1136 TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>(); 1137 ArrayDeque<Integer> networkSelectionStatusValues = 1138 getUniqueRandomNumberValues( 1139 3, 1140 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX, 1141 mConfiguredNetworks.valuesForCurrentUser().size()); 1142 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1143 config.numAssociation = rand.nextInt(10000); 1144 config.priority = rand.nextInt(10000); 1145 config.getNetworkSelectionStatus().setNetworkSelectionStatus( 1146 networkSelectionStatusValues.pop()); 1147 networkSelectionStatusToNetworkIdMap.put( 1148 config.getNetworkSelectionStatus().getNetworkSelectionStatus(), 1149 config.networkId); 1150 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: " 1151 + config.getNetworkSelectionStatus().getNetworkSelectionStatus()); 1152 } 1153 ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList = 1154 mWifiConfigManager.retrieveConnectedPnoNetworkList(); 1155 verifyPnoNetworkListOrder(pnoNetworkList, 1156 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1157 } 1158 } 1159} 1160