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