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