WifiConfigManagerTest.java revision 2d65b9aaaa740ecf66bf4734c12aea3df88e352a
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.os.Process; 46import android.os.UserHandle; 47import android.os.UserManager; 48import android.security.Credentials; 49import android.support.test.InstrumentationRegistry; 50import android.test.suitebuilder.annotation.SmallTest; 51import android.text.TextUtils; 52import android.util.Log; 53import android.util.SparseArray; 54 55import com.android.server.net.DelayedDiskWrite; 56import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 57import com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager; 58import com.android.server.wifi.hotspot2.pps.Credential; 59import com.android.server.wifi.hotspot2.pps.HomeSP; 60 61import org.junit.Before; 62import org.junit.Test; 63import org.mockito.Mock; 64import org.mockito.MockitoAnnotations; 65 66import java.io.ByteArrayInputStream; 67import java.io.ByteArrayOutputStream; 68import java.io.DataInputStream; 69import java.io.DataOutputStream; 70import java.io.EOFException; 71import java.io.File; 72import java.io.FileOutputStream; 73import java.io.IOException; 74import java.lang.reflect.Field; 75import java.math.BigInteger; 76import java.security.cert.CertificateEncodingException; 77import java.security.cert.X509Certificate; 78import java.util.ArrayDeque; 79import java.util.ArrayList; 80import java.util.Arrays; 81import java.util.BitSet; 82import java.util.Collection; 83import java.util.Collections; 84import java.util.HashMap; 85import java.util.HashSet; 86import java.util.List; 87import java.util.Map; 88import java.util.Random; 89import java.util.Set; 90import java.util.TreeMap; 91 92/** 93 * Unit tests for {@link com.android.server.wifi.WifiConfigManager}. 94 */ 95@SmallTest 96public class WifiConfigManagerTest { 97 private static final List<WifiConfiguration> CONFIGS = Arrays.asList( 98 WifiConfigurationTestUtil.generateWifiConfig( 99 0, 1000000, "\"red\"", true, true, null, null), 100 WifiConfigurationTestUtil.generateWifiConfig( 101 1, 1000001, "\"green\"", true, true, "example.com", "Green"), 102 WifiConfigurationTestUtil.generateWifiConfig( 103 2, 1100000, "\"blue\"", false, true, "example.org", "Blue"), 104 WifiConfigurationTestUtil.generateWifiConfig( 105 3, 1200000, "\"cyan\"", false, true, null, null)); 106 107 private static final int[] USER_IDS = {0, 10, 11}; 108 private static final int MANAGED_PROFILE_USER_ID = 12; 109 private static final int MANAGED_PROFILE_PARENT_USER_ID = 0; 110 private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>(); 111 static { 112 USER_PROFILES.put(0, Arrays.asList(new UserInfo(0, "Owner", 0), 113 new UserInfo(12, "Managed Profile", 0))); 114 USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0))); 115 USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0))); 116 } 117 118 private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>(); 119 static { 120 for (int userId : USER_IDS) { 121 List<WifiConfiguration> configs = new ArrayList<>(); 122 for (int i = 0; i < CONFIGS.size(); ++i) { 123 if (WifiConfigurationUtil.isVisibleToAnyProfile(CONFIGS.get(i), 124 USER_PROFILES.get(userId))) { 125 configs.add(CONFIGS.get(i)); 126 } 127 } 128 VISIBLE_CONFIGS.put(userId, configs); 129 } 130 } 131 132 public static final String TAG = "WifiConfigManagerTest"; 133 @Mock private Context mContext; 134 @Mock private WifiStateMachine mWifiStateMachine; 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(mWifiStateMachine.getCurrentUserId()).thenReturn(UserHandle.USER_SYSTEM); 159 when(mWifiStateMachine.getCurrentUserProfiles()) 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(mWifiStateMachine.getCurrentUserId()).thenReturn(newUserId); 206 when(mWifiStateMachine.getCurrentUserProfiles()) 207 .thenReturn(USER_PROFILES.get(newUserId)); 208 mWifiConfigManager.handleUserSwitch(); 209 } 210 211 private void switchUserToCreatorOrParentOf(WifiConfiguration config) { 212 final int creatorUserId = UserHandle.getUserId(config.creatorUid); 213 if (creatorUserId == MANAGED_PROFILE_USER_ID) { 214 switchUser(MANAGED_PROFILE_PARENT_USER_ID); 215 } else { 216 switchUser(creatorUserId); 217 } 218 } 219 220 private void addNetworks() throws Exception { 221 final int originalUserId = mWifiStateMachine.getCurrentUserId(); 222 223 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); 224 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 225 .thenReturn(true); 226 for (int i = 0; i < CONFIGS.size(); ++i) { 227 assertEquals(i, CONFIGS.get(i).networkId); 228 switchUserToCreatorOrParentOf(CONFIGS.get(i)); 229 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i)); 230 config.networkId = -1; 231 when(mWifiNative.addNetwork()).thenReturn(i); 232 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 233 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 234 mWifiConfigManager.saveNetwork(config, config.creatorUid); 235 } 236 237 switchUser(originalUserId); 238 } 239 240 private String encodeConfigSSID(WifiConfiguration config) throws Exception { 241 return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1) 242 .getBytes("UTF-8")).toString(16); 243 } 244 245 /** 246 * Verifies that getConfiguredNetworksSize() returns the number of network configurations 247 * visible to the current user. 248 */ 249 @Test 250 public void testGetConfiguredNetworksSize() throws Exception { 251 addNetworks(); 252 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 253 switchUser(entry.getKey()); 254 assertEquals(entry.getValue().size(), mWifiConfigManager.getConfiguredNetworksSize()); 255 } 256 } 257 258 private void verifyNetworkConfig(WifiConfiguration expectedConfig, 259 WifiConfiguration actualConfig) { 260 assertNotNull(actualConfig); 261 assertEquals(expectedConfig.SSID, actualConfig.SSID); 262 assertEquals(expectedConfig.FQDN, actualConfig.FQDN); 263 assertEquals(expectedConfig.providerFriendlyName, 264 actualConfig.providerFriendlyName); 265 assertEquals(expectedConfig.configKey(), actualConfig.configKey(false)); 266 } 267 268 private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, 269 Collection<WifiConfiguration> actualConfigs) { 270 assertEquals(expectedConfigs.size(), actualConfigs.size()); 271 for (WifiConfiguration expectedConfig : expectedConfigs) { 272 WifiConfiguration actualConfig = null; 273 // Find the network configuration to test (assume that |actualConfigs| contains them in 274 // undefined order). 275 for (final WifiConfiguration candidate : actualConfigs) { 276 if (candidate.networkId == expectedConfig.networkId) { 277 actualConfig = candidate; 278 break; 279 } 280 } 281 verifyNetworkConfig(expectedConfig, actualConfig); 282 } 283 } 284 285 /** 286 * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the 287 * current user. 288 */ 289 @Test 290 public void testGetConfiguredNetworks() throws Exception { 291 addNetworks(); 292 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 293 switchUser(entry.getKey()); 294 verifyNetworkConfigs(entry.getValue(), mWifiConfigManager.getConfiguredNetworks()); 295 } 296 } 297 298 /** 299 * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to 300 * the current user. 301 */ 302 @Test 303 public void testGetPrivilegedConfiguredNetworks() throws Exception { 304 addNetworks(); 305 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 306 switchUser(entry.getKey()); 307 verifyNetworkConfigs(entry.getValue(), 308 mWifiConfigManager.getPrivilegedConfiguredNetworks()); 309 } 310 } 311 312 /** 313 * Verifies that getWifiConfiguration(int netId) can be used to access network configurations 314 * visible to the current user only. 315 */ 316 @Test 317 public void testGetWifiConfigurationByNetworkId() throws Exception { 318 addNetworks(); 319 for (int userId : USER_IDS) { 320 switchUser(userId); 321 for (WifiConfiguration expectedConfig: CONFIGS) { 322 final WifiConfiguration actualConfig = 323 mWifiConfigManager.getWifiConfiguration(expectedConfig.networkId); 324 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 325 USER_PROFILES.get(userId))) { 326 verifyNetworkConfig(expectedConfig, actualConfig); 327 } else { 328 assertNull(actualConfig); 329 } 330 } 331 } 332 } 333 334 /** 335 * Verifies that getWifiConfiguration(String key) can be used to access network configurations 336 * visible to the current user only. 337 */ 338 @Test 339 public void testGetWifiConfigurationByConfigKey() throws Exception { 340 addNetworks(); 341 for (int userId : USER_IDS) { 342 switchUser(userId); 343 for (WifiConfiguration expectedConfig: CONFIGS) { 344 final WifiConfiguration actualConfig = 345 mWifiConfigManager.getWifiConfiguration(expectedConfig.configKey()); 346 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 347 USER_PROFILES.get(userId))) { 348 verifyNetworkConfig(expectedConfig, actualConfig); 349 } else { 350 assertNull(actualConfig); 351 } 352 } 353 } 354 } 355 356 /** 357 * Verifies that enableAllNetworks() enables all temporarily disabled network configurations 358 * visible to the current user. 359 */ 360 @Test 361 public void testEnableAllNetworks() throws Exception { 362 addNetworks(); 363 for (int userId : USER_IDS) { 364 switchUser(userId); 365 366 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 367 final WifiConfiguration.NetworkSelectionStatus status = 368 config.getNetworkSelectionStatus(); 369 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus 370 .NETWORK_SELECTION_TEMPORARY_DISABLED); 371 status.setNetworkSelectionDisableReason( 372 WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE); 373 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000); 374 } 375 376 mWifiConfigManager.enableAllNetworks(); 377 378 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 379 assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config, 380 USER_PROFILES.get(userId)), 381 config.getNetworkSelectionStatus().isNetworkEnabled()); 382 } 383 } 384 } 385 386 /** 387 * Verifies that selectNetwork() disables all network configurations visible to the current user 388 * except the selected one. 389 */ 390 @Test 391 public void testSelectNetwork() throws Exception { 392 addNetworks(); 393 394 for (int userId : USER_IDS) { 395 switchUser(userId); 396 397 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 398 // Enable all network configurations. 399 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 400 config2.status = WifiConfiguration.Status.ENABLED; 401 } 402 403 // Try to select a network configuration. 404 reset(mWifiNative); 405 when(mWifiNative.selectNetwork(config.networkId)).thenReturn(true); 406 final boolean success = 407 mWifiConfigManager.selectNetwork(config, false, config.creatorUid); 408 if (!WifiConfigurationUtil.isVisibleToAnyProfile(config, 409 USER_PROFILES.get(userId))) { 410 // If the network configuration is not visible to the current user, verify that 411 // nothing changed. 412 assertFalse(success); 413 verify(mWifiNative, never()).selectNetwork(anyInt()); 414 verify(mWifiNative, never()).enableNetwork(anyInt()); 415 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 416 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 417 } 418 } else { 419 // If the network configuration is visible to the current user, verify that it 420 // was enabled and all other network configurations visible to the user were 421 // disabled. 422 assertTrue(success); 423 verify(mWifiNative).selectNetwork(config.networkId); 424 verify(mWifiNative, never()).selectNetwork(intThat(not(config.networkId))); 425 verify(mWifiNative, never()).enableNetwork(config.networkId); 426 verify(mWifiNative, never()).enableNetwork(intThat(not(config.networkId))); 427 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 428 if (WifiConfigurationUtil.isVisibleToAnyProfile(config2, 429 USER_PROFILES.get(userId)) 430 && config2.networkId != config.networkId) { 431 assertEquals(WifiConfiguration.Status.DISABLED, config2.status); 432 } else { 433 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 434 } 435 } 436 } 437 } 438 } 439 } 440 441 /** 442 * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant 443 * variables and the networkHistory.txt file. 444 * TODO: Test all variables. Currently, only the following variables are tested: 445 * - In the wpa_supplicant: "ssid", "id_str" 446 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 447 */ 448 private void verifySaveNetwork(int network) throws Exception { 449 // Switch to the correct user. 450 switchUserToCreatorOrParentOf(CONFIGS.get(network)); 451 452 // Set up wpa_supplicant. 453 when(mWifiNative.addNetwork()).thenReturn(0); 454 when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString())) 455 .thenReturn(true); 456 when(mWifiNative.setNetworkExtra(eq(network), anyString(), 457 (Map<String, String>) anyObject())).thenReturn(true); 458 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName)) 459 .thenReturn(encodeConfigSSID(CONFIGS.get(network))); 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 no wpa_supplicant variables were read or written for any other network 477 // configurations. 478 verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(), 479 (Map<String, String>) anyObject()); 480 verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(), 481 anyString()); 482 verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString()); 483 484 // Parse networkHistory.txt. 485 assertNotNull(mNetworkHistoryBytes); 486 final DataInputStream stream = 487 new DataInputStream(new ByteArrayInputStream(mNetworkHistoryBytes)); 488 List<String> keys = new ArrayList<>(); 489 List<String> values = new ArrayList<>(); 490 try { 491 while (true) { 492 final String[] tokens = stream.readUTF().split(":", 2); 493 if (tokens.length == 2) { 494 keys.add(tokens[0].trim()); 495 values.add(tokens[1].trim()); 496 } 497 } 498 } catch (EOFException e) { 499 // Ignore. This is expected. 500 } 501 502 // Verify that a networkHistory.txt entry was written correctly for the network 503 // configuration. 504 assertTrue(keys.size() >= 3); 505 assertEquals(WifiNetworkHistory.CONFIG_KEY, keys.get(0)); 506 assertEquals(CONFIGS.get(network).configKey(), values.get(0)); 507 final int creatorUidIndex = keys.indexOf(WifiNetworkHistory.CREATOR_UID_KEY); 508 assertTrue(creatorUidIndex != -1); 509 assertEquals(Integer.toString(CONFIGS.get(network).creatorUid), 510 values.get(creatorUidIndex)); 511 final int sharedIndex = keys.indexOf(WifiNetworkHistory.SHARED_KEY); 512 assertTrue(sharedIndex != -1); 513 assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex)); 514 515 // Verify that no networkHistory.txt entries were written for any other network 516 // configurations. 517 final int lastConfigIndex = keys.lastIndexOf(WifiNetworkHistory.CONFIG_KEY); 518 assertEquals(0, lastConfigIndex); 519 } 520 521 /** 522 * Verifies that saveNetwork() correctly stores a regular network configuration. 523 */ 524 @Test 525 public void testSaveNetworkRegular() throws Exception { 526 verifySaveNetwork(0); 527 } 528 529 /** 530 * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration. 531 */ 532 @Test 533 public void testSaveNetworkHotspot20() throws Exception { 534 verifySaveNetwork(1); 535 } 536 537 /** 538 * Verifies that saveNetwork() correctly stores a private network configuration. 539 */ 540 @Test 541 public void testSaveNetworkPrivate() throws Exception { 542 verifySaveNetwork(2); 543 } 544 545 /** 546 * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the 547 * networkHistory.txt file and the MOManager, correlating the three sources based on the 548 * configKey and the FQDN for HotSpot 2.0 networks. 549 * TODO: Test all variables. Currently, only the following variables are tested: 550 * - In the wpa_supplicant: "ssid", "id_str" 551 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 552 */ 553 @Test 554 public void testLoadConfiguredNetworks() throws Exception { 555 // Set up list of network configurations returned by wpa_supplicant. 556 final String header = "network id / ssid / bssid / flags"; 557 String networks = header; 558 for (WifiConfiguration config : CONFIGS) { 559 networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany"; 560 } 561 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 562 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 563 564 // Set up variables returned by wpa_supplicant for the individual network configurations. 565 for (int i = 0; i < CONFIGS.size(); ++i) { 566 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 567 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 568 } 569 // Legacy regular network configuration: No "id_str". 570 when(mWifiNative.getNetworkExtra(0, WifiConfigStore.ID_STRING_VAR_NAME)) 571 .thenReturn(null); 572 // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str". 573 when(mWifiNative.getNetworkExtra(1, WifiConfigStore.ID_STRING_VAR_NAME)) 574 .thenReturn(null); 575 when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME)) 576 .thenReturn('"' + CONFIGS.get(1).FQDN + '"'); 577 // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str". 578 Map<String, String> metadata = new HashMap<String, String>(); 579 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey()); 580 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 581 Integer.toString(CONFIGS.get(2).creatorUid)); 582 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN); 583 when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME)) 584 .thenReturn(metadata); 585 // Up-to-date regular network configuration: Metadata in "id_str". 586 metadata = new HashMap<String, String>(); 587 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey()); 588 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 589 Integer.toString(CONFIGS.get(3).creatorUid)); 590 when(mWifiNative.getNetworkExtra(3, WifiConfigStore.ID_STRING_VAR_NAME)) 591 .thenReturn(metadata); 592 593 // Set up networkHistory.txt file. 594 final File file = File.createTempFile("networkHistory.txt", null); 595 file.deleteOnExit(); 596 597 Field wifiNetworkHistoryConfigFile = 598 WifiNetworkHistory.class.getDeclaredField("NETWORK_HISTORY_CONFIG_FILE"); 599 wifiNetworkHistoryConfigFile.setAccessible(true); 600 wifiNetworkHistoryConfigFile.set(null, file.getAbsolutePath()); 601 602 final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); 603 for (WifiConfiguration config : CONFIGS) { 604 stream.writeUTF(WifiNetworkHistory.CONFIG_KEY + ": " + config.configKey() + '\n'); 605 stream.writeUTF(WifiNetworkHistory.CREATOR_UID_KEY + ": " 606 + Integer.toString(config.creatorUid) + '\n'); 607 stream.writeUTF(WifiNetworkHistory.SHARED_KEY + ": " 608 + Boolean.toString(config.shared) + '\n'); 609 } 610 stream.close(); 611 612 // Set up list of home service providers returned by MOManager. 613 final List<HomeSP> homeSPs = new ArrayList<HomeSP>(); 614 for (WifiConfiguration config : CONFIGS) { 615 if (config.FQDN != null) { 616 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(), 617 new HashSet<String>(), 618 new HashSet<Long>(), new ArrayList<Long>(), 619 config.providerFriendlyName, null, 620 new Credential(0, 0, null, false, null, null), 621 null, 0, null, null, null, 0)); 622 } 623 } 624 when(mMOManager.loadAllSPs()).thenReturn(homeSPs); 625 626 // Load network configurations. 627 mWifiConfigManager.loadConfiguredNetworks(); 628 629 // Verify that network configurations were loaded and correlated correctly across the three 630 // sources. 631 verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers()); 632 } 633 634 /** 635 * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network 636 * configurations from the wpa_supplicant: The second configuration overwrites the first. 637 */ 638 @Test 639 public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception { 640 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0)); 641 config.networkId = 1; 642 643 // Set up list of network configurations returned by wpa_supplicant. The two configurations 644 // are identical except for their network IDs. 645 final String header = "network id / ssid / bssid / flags"; 646 final String networks = 647 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany"; 648 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 649 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 650 651 // Set up variables returned by wpa_supplicant. 652 when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName))) 653 .thenReturn(encodeConfigSSID(config)); 654 final Map<String, String> metadata = new HashMap<String, String>(); 655 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, config.configKey()); 656 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 657 Integer.toString(config.creatorUid)); 658 when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigStore.ID_STRING_VAR_NAME))) 659 .thenReturn(metadata); 660 661 // Load network configurations. 662 mWifiConfigManager.loadConfiguredNetworks(); 663 664 // Verify that the second network configuration (network ID 1) overwrote the first (network 665 // ID 0). 666 verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers()); 667 } 668 669 /** 670 * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network 671 * configurations that should no longer be visible and enables network configurations that 672 * should become visible. 673 */ 674 private void verifyHandleUserSwitch(int oldUserId, int newUserId, 675 boolean makeOneConfigEphemeral) throws Exception { 676 addNetworks(); 677 switchUser(oldUserId); 678 679 reset(mWifiNative); 680 final Field lastSelectedConfigurationField = 681 WifiConfigManager.class.getDeclaredField("lastSelectedConfiguration"); 682 lastSelectedConfigurationField.setAccessible(true); 683 WifiConfiguration removedEphemeralConfig = null; 684 final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>(); 685 final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>(); 686 final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>(); 687 final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers(); 688 int expectedNumberOfConfigs = oldConfigs.size(); 689 for (WifiConfiguration config : oldConfigs) { 690 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) { 691 config.status = WifiConfiguration.Status.ENABLED; 692 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 693 USER_PROFILES.get(newUserId))) { 694 if (makeOneConfigEphemeral && removedEphemeralConfig == null) { 695 config.ephemeral = true; 696 lastSelectedConfigurationField.set(mWifiConfigManager, config.configKey()); 697 removedEphemeralConfig = config; 698 } 699 } else { 700 oldUserOnlyConfigs.add(config); 701 } 702 } else { 703 config.status = WifiConfiguration.Status.DISABLED; 704 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 705 USER_PROFILES.get(newUserId))) { 706 newUserOnlyConfigs.add(config); 707 } else { 708 neitherUserConfigs.add(config); 709 } 710 } 711 } 712 713 when(mWifiNative.disableNetwork(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<WifiNative.WifiPnoNetwork> pnoNetworkList, 971 ArrayList<Integer> expectedNetworkIdOrder) throws Exception { 972 int i = 0; 973 for (WifiNative.WifiPnoNetwork 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 retrieveDisconnectedWifiPnoNetworkList API. The test verifies that the list 982 * returned from the API is sorted as expected. 983 */ 984 @Test 985 public void testDisconnectedWifiPnoNetworkListCreation() 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1010 mWifiConfigManager.retrieveDisconnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1033 mWifiConfigManager.retrieveDisconnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1060 mWifiConfigManager.retrieveDisconnectedWifiPnoNetworkList(); 1061 verifyPnoNetworkListOrder(pnoNetworkList, 1062 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1063 } 1064 } 1065 1066 /** 1067 * Verifies the retrieveConnectedWifiPnoNetworkList API. The test verifies that the list 1068 * returned from the API is sorted as expected. 1069 */ 1070 @Test 1071 public void testConnectedWifiPnoNetworkListCreation() 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1097 mWifiConfigManager.retrieveConnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1123 mWifiConfigManager.retrieveConnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1150 mWifiConfigManager.retrieveConnectedWifiPnoNetworkList(); 1151 verifyPnoNetworkListOrder(pnoNetworkList, 1152 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1153 } 1154 } 1155} 1156