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