WifiConfigManagerTest.java revision 9d7489491984e86915b2cf4fac38a882de1c8cdb
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.mock; 33import static org.mockito.Mockito.never; 34import static org.mockito.Mockito.reset; 35import static org.mockito.Mockito.verify; 36import static org.mockito.Mockito.when; 37 38import android.content.Context; 39import android.content.pm.UserInfo; 40import android.net.wifi.FakeKeys; 41import android.net.wifi.WifiConfiguration; 42import android.net.wifi.WifiConfiguration.KeyMgmt; 43import android.net.wifi.WifiEnterpriseConfig; 44import android.net.wifi.WifiEnterpriseConfig.Eap; 45import android.net.wifi.WifiEnterpriseConfig.Phase2; 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 mConfigStore; 143 private ConfigurationMap mConfiguredNetworks; 144 public byte[] mNetworkHistory; 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 mConfigStore = new WifiConfigManager(mContext, mWifiStateMachine, mWifiNative, 168 mFrameworkFacade, mClock, mUserManager); 169 170 final Field configuredNetworksField = 171 WifiConfigManager.class.getDeclaredField("mConfiguredNetworks"); 172 configuredNetworksField.setAccessible(true); 173 mConfiguredNetworks = (ConfigurationMap) configuredNetworksField.get(mConfigStore); 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 mNetworkHistory = 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(mConfigStore, mWriter); 187 188 when(mMOManager.isEnabled()).thenReturn(true); 189 final Field moManagerField = WifiConfigManager.class.getDeclaredField("mMOManager"); 190 moManagerField.setAccessible(true); 191 moManagerField.set(mConfigStore, mMOManager); 192 193 mMockKeyStore = new MockKeyStore(); 194 final Field mKeyStoreField = WifiConfigManager.class.getDeclaredField("mKeyStore"); 195 mKeyStoreField.setAccessible(true); 196 mKeyStoreField.set(mConfigStore, mMockKeyStore.createMock()); 197 } 198 199 private void switchUser(int newUserId) { 200 when(mWifiStateMachine.getCurrentUserId()).thenReturn(newUserId); 201 when(mWifiStateMachine.getCurrentUserProfiles()) 202 .thenReturn(USER_PROFILES.get(newUserId)); 203 mConfigStore.handleUserSwitch(); 204 } 205 206 private void switchUserToCreatorOrParentOf(WifiConfiguration config) { 207 final int creatorUserId = UserHandle.getUserId(config.creatorUid); 208 if (creatorUserId == MANAGED_PROFILE_USER_ID) { 209 switchUser(MANAGED_PROFILE_PARENT_USER_ID); 210 } else { 211 switchUser(creatorUserId); 212 } 213 } 214 215 private void addNetworks() throws Exception { 216 final int originalUserId = mWifiStateMachine.getCurrentUserId(); 217 218 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); 219 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 220 .thenReturn(true); 221 for (int i = 0; i < CONFIGS.size(); ++i) { 222 assertEquals(i, CONFIGS.get(i).networkId); 223 switchUserToCreatorOrParentOf(CONFIGS.get(i)); 224 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i)); 225 config.networkId = -1; 226 when(mWifiNative.addNetwork()).thenReturn(i); 227 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 228 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 229 mConfigStore.saveNetwork(config, config.creatorUid); 230 } 231 232 switchUser(originalUserId); 233 } 234 235 private String encodeConfigSSID(WifiConfiguration config) throws Exception { 236 return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1) 237 .getBytes("UTF-8")).toString(16); 238 } 239 240 private WifiNative createNewWifiNativeMock() throws Exception { 241 final WifiNative wifiNative = mock(WifiNative.class); 242 final Field wifiNativeField = WifiConfigManager.class.getDeclaredField("mWifiNative"); 243 wifiNativeField.setAccessible(true); 244 wifiNativeField.set(mConfigStore, wifiNative); 245 return wifiNative; 246 } 247 248 /** 249 * Verifies that getConfiguredNetworksSize() returns the number of network configurations 250 * visible to the current user. 251 */ 252 @Test 253 public void testGetConfiguredNetworksSize() throws Exception { 254 addNetworks(); 255 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 256 switchUser(entry.getKey()); 257 assertEquals(entry.getValue().size(), mConfigStore.getConfiguredNetworksSize()); 258 } 259 } 260 261 private void verifyNetworkConfig(WifiConfiguration expectedConfig, 262 WifiConfiguration actualConfig) { 263 assertNotNull(actualConfig); 264 assertEquals(expectedConfig.SSID, actualConfig.SSID); 265 assertEquals(expectedConfig.FQDN, actualConfig.FQDN); 266 assertEquals(expectedConfig.providerFriendlyName, 267 actualConfig.providerFriendlyName); 268 assertEquals(expectedConfig.configKey(), actualConfig.configKey(false)); 269 } 270 271 private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, 272 Collection<WifiConfiguration> actualConfigs) { 273 assertEquals(expectedConfigs.size(), actualConfigs.size()); 274 for (WifiConfiguration expectedConfig : expectedConfigs) { 275 WifiConfiguration actualConfig = null; 276 // Find the network configuration to test (assume that |actualConfigs| contains them in 277 // undefined order). 278 for (final WifiConfiguration candidate : actualConfigs) { 279 if (candidate.networkId == expectedConfig.networkId) { 280 actualConfig = candidate; 281 break; 282 } 283 } 284 verifyNetworkConfig(expectedConfig, actualConfig); 285 } 286 } 287 288 /** 289 * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the 290 * current user. 291 */ 292 @Test 293 public void testGetConfiguredNetworks() throws Exception { 294 addNetworks(); 295 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 296 switchUser(entry.getKey()); 297 verifyNetworkConfigs(entry.getValue(), mConfigStore.getConfiguredNetworks()); 298 } 299 } 300 301 /** 302 * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to 303 * the current user. 304 */ 305 @Test 306 public void testGetPrivilegedConfiguredNetworks() throws Exception { 307 addNetworks(); 308 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 309 switchUser(entry.getKey()); 310 verifyNetworkConfigs(entry.getValue(), mConfigStore.getPrivilegedConfiguredNetworks()); 311 } 312 } 313 314 /** 315 * Verifies that getWifiConfiguration(int netId) can be used to access network configurations 316 * visible to the current user only. 317 */ 318 @Test 319 public void testGetWifiConfigurationByNetworkId() throws Exception { 320 addNetworks(); 321 for (int userId : USER_IDS) { 322 switchUser(userId); 323 for (WifiConfiguration expectedConfig: CONFIGS) { 324 final WifiConfiguration actualConfig = 325 mConfigStore.getWifiConfiguration(expectedConfig.networkId); 326 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 327 USER_PROFILES.get(userId))) { 328 verifyNetworkConfig(expectedConfig, actualConfig); 329 } else { 330 assertNull(actualConfig); 331 } 332 } 333 } 334 } 335 336 /** 337 * Verifies that getWifiConfiguration(String key) can be used to access network configurations 338 * visible to the current user only. 339 */ 340 @Test 341 public void testGetWifiConfigurationByConfigKey() throws Exception { 342 addNetworks(); 343 for (int userId : USER_IDS) { 344 switchUser(userId); 345 for (WifiConfiguration expectedConfig: CONFIGS) { 346 final WifiConfiguration actualConfig = 347 mConfigStore.getWifiConfiguration(expectedConfig.configKey()); 348 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig, 349 USER_PROFILES.get(userId))) { 350 verifyNetworkConfig(expectedConfig, actualConfig); 351 } else { 352 assertNull(actualConfig); 353 } 354 } 355 } 356 } 357 358 /** 359 * Verifies that enableAllNetworks() enables all temporarily disabled network configurations 360 * visible to the current user. 361 */ 362 @Test 363 public void testEnableAllNetworks() throws Exception { 364 addNetworks(); 365 for (int userId : USER_IDS) { 366 switchUser(userId); 367 368 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 369 final WifiConfiguration.NetworkSelectionStatus status = 370 config.getNetworkSelectionStatus(); 371 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus 372 .NETWORK_SELECTION_TEMPORARY_DISABLED); 373 status.setNetworkSelectionDisableReason( 374 WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE); 375 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000); 376 } 377 378 mConfigStore.enableAllNetworks(); 379 380 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 381 assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config, 382 USER_PROFILES.get(userId)), 383 config.getNetworkSelectionStatus().isNetworkEnabled()); 384 } 385 } 386 } 387 388 /** 389 * Verifies that selectNetwork() disables all network configurations visible to the current user 390 * except the selected one. 391 */ 392 @Test 393 public void testSelectNetwork() throws Exception { 394 addNetworks(); 395 396 for (int userId : USER_IDS) { 397 switchUser(userId); 398 399 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 400 // Enable all network configurations. 401 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 402 config2.status = WifiConfiguration.Status.ENABLED; 403 } 404 405 // Try to select a network configuration. 406 final WifiNative wifiNative = createNewWifiNativeMock(); 407 when(wifiNative.selectNetwork(config.networkId)).thenReturn(true); 408 final boolean success = 409 mConfigStore.selectNetwork(config, false, config.creatorUid); 410 if (!WifiConfigurationUtil.isVisibleToAnyProfile(config, 411 USER_PROFILES.get(userId))) { 412 // If the network configuration is not visible to the current user, verify that 413 // nothing changed. 414 assertFalse(success); 415 verify(wifiNative, never()).selectNetwork(anyInt()); 416 verify(wifiNative, never()).enableNetwork(anyInt()); 417 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 418 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 419 } 420 } else { 421 // If the network configuration is visible to the current user, verify that it 422 // was enabled and all other network configurations visible to the user were 423 // disabled. 424 assertTrue(success); 425 verify(wifiNative).selectNetwork(config.networkId); 426 verify(wifiNative, never()).selectNetwork(intThat(not(config.networkId))); 427 verify(wifiNative, never()).enableNetwork(config.networkId); 428 verify(wifiNative, never()).enableNetwork(intThat(not(config.networkId))); 429 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 430 if (WifiConfigurationUtil.isVisibleToAnyProfile(config2, 431 USER_PROFILES.get(userId)) 432 && config2.networkId != config.networkId) { 433 assertEquals(WifiConfiguration.Status.DISABLED, config2.status); 434 } else { 435 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 436 } 437 } 438 } 439 } 440 } 441 } 442 443 /** 444 * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant 445 * variables and the networkHistory.txt file. 446 * TODO: Test all variables. Currently, only the following variables are tested: 447 * - In the wpa_supplicant: "ssid", "id_str" 448 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 449 */ 450 private void verifySaveNetwork(int network) throws Exception { 451 // Switch to the correct user. 452 switchUserToCreatorOrParentOf(CONFIGS.get(network)); 453 454 // Set up wpa_supplicant. 455 when(mWifiNative.addNetwork()).thenReturn(0); 456 when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString())) 457 .thenReturn(true); 458 when(mWifiNative.setNetworkExtra(eq(network), anyString(), 459 (Map<String, String>) anyObject())).thenReturn(true); 460 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName)) 461 .thenReturn(encodeConfigSSID(CONFIGS.get(network))); 462 463 // Store a network configuration. 464 mConfigStore.saveNetwork(CONFIGS.get(network), CONFIGS.get(network).creatorUid); 465 466 // Verify that wpa_supplicant variables were written correctly for the network 467 // configuration. 468 final Map<String, String> metadata = new HashMap<String, String>(); 469 if (CONFIGS.get(network).FQDN != null) { 470 metadata.put(WifiConfigManager.ID_STRING_KEY_FQDN, CONFIGS.get(network).FQDN); 471 } 472 metadata.put(WifiConfigManager.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(network).configKey()); 473 metadata.put(WifiConfigManager.ID_STRING_KEY_CREATOR_UID, 474 Integer.toString(CONFIGS.get(network).creatorUid)); 475 verify(mWifiNative).setNetworkExtra(network, WifiConfigManager.ID_STRING_VAR_NAME, 476 metadata); 477 478 // Verify that no wpa_supplicant variables were read or written for any other network 479 // configurations. 480 verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(), 481 (Map<String, String>) anyObject()); 482 verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(), 483 anyString()); 484 verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString()); 485 486 // Parse networkHistory.txt. 487 assertNotNull(mNetworkHistory); 488 final DataInputStream stream = 489 new DataInputStream(new ByteArrayInputStream(mNetworkHistory)); 490 List<String> keys = new ArrayList<>(); 491 List<String> values = new ArrayList<>(); 492 try { 493 while (true) { 494 final String[] tokens = stream.readUTF().split(":", 2); 495 if (tokens.length == 2) { 496 keys.add(tokens[0].trim()); 497 values.add(tokens[1].trim()); 498 } 499 } 500 } catch (EOFException e) { 501 // Ignore. This is expected. 502 } 503 504 // Verify that a networkHistory.txt entry was written correctly for the network 505 // configuration. 506 assertTrue(keys.size() >= 3); 507 assertEquals(WifiConfigManager.CONFIG_KEY, keys.get(0)); 508 assertEquals(CONFIGS.get(network).configKey(), values.get(0)); 509 final int creatorUidIndex = keys.indexOf(WifiConfigManager.CREATOR_UID_KEY); 510 assertTrue(creatorUidIndex != -1); 511 assertEquals(Integer.toString(CONFIGS.get(network).creatorUid), 512 values.get(creatorUidIndex)); 513 final int sharedIndex = keys.indexOf(WifiConfigManager.SHARED_KEY); 514 assertTrue(sharedIndex != -1); 515 assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex)); 516 517 // Verify that no networkHistory.txt entries were written for any other network 518 // configurations. 519 final int lastConfigIndex = keys.lastIndexOf(WifiConfigManager.CONFIG_KEY); 520 assertEquals(0, lastConfigIndex); 521 } 522 523 /** 524 * Verifies that saveNetwork() correctly stores a regular network configuration. 525 */ 526 @Test 527 public void testSaveNetworkRegular() throws Exception { 528 verifySaveNetwork(0); 529 } 530 531 /** 532 * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration. 533 */ 534 @Test 535 public void testSaveNetworkHotspot20() throws Exception { 536 verifySaveNetwork(1); 537 } 538 539 /** 540 * Verifies that saveNetwork() correctly stores a private network configuration. 541 */ 542 @Test 543 public void testSaveNetworkPrivate() throws Exception { 544 verifySaveNetwork(2); 545 } 546 547 /** 548 * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the 549 * networkHistory.txt file and the MOManager, correlating the three sources based on the 550 * configKey and the FQDN for HotSpot 2.0 networks. 551 * TODO: Test all variables. Currently, only the following variables are tested: 552 * - In the wpa_supplicant: "ssid", "id_str" 553 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 554 */ 555 @Test 556 public void testLoadConfiguredNetworks() throws Exception { 557 // Set up list of network configurations returned by wpa_supplicant. 558 final String header = "network id / ssid / bssid / flags"; 559 String networks = header; 560 for (WifiConfiguration config : CONFIGS) { 561 networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany"; 562 } 563 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 564 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 565 566 // Set up variables returned by wpa_supplicant for the individual network configurations. 567 for (int i = 0; i < CONFIGS.size(); ++i) { 568 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 569 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 570 } 571 // Legacy regular network configuration: No "id_str". 572 when(mWifiNative.getNetworkExtra(0, WifiConfigManager.ID_STRING_VAR_NAME)) 573 .thenReturn(null); 574 // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str". 575 when(mWifiNative.getNetworkExtra(1, WifiConfigManager.ID_STRING_VAR_NAME)) 576 .thenReturn(null); 577 when(mWifiNative.getNetworkVariable(1, WifiConfigManager.ID_STRING_VAR_NAME)) 578 .thenReturn('"' + CONFIGS.get(1).FQDN + '"'); 579 // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str". 580 Map<String, String> metadata = new HashMap<String, String>(); 581 metadata.put(WifiConfigManager.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey()); 582 metadata.put(WifiConfigManager.ID_STRING_KEY_CREATOR_UID, 583 Integer.toString(CONFIGS.get(2).creatorUid)); 584 metadata.put(WifiConfigManager.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN); 585 when(mWifiNative.getNetworkExtra(2, WifiConfigManager.ID_STRING_VAR_NAME)) 586 .thenReturn(metadata); 587 // Up-to-date regular network configuration: Metadata in "id_str". 588 metadata = new HashMap<String, String>(); 589 metadata.put(WifiConfigManager.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey()); 590 metadata.put(WifiConfigManager.ID_STRING_KEY_CREATOR_UID, 591 Integer.toString(CONFIGS.get(3).creatorUid)); 592 when(mWifiNative.getNetworkExtra(3, WifiConfigManager.ID_STRING_VAR_NAME)) 593 .thenReturn(metadata); 594 595 // Set up networkHistory.txt file. 596 final File file = File.createTempFile("networkHistory.txt", null); 597 file.deleteOnExit(); 598 Field wifiConfigManagerNetworkHistoryConfigFile = 599 WifiConfigManager.class.getDeclaredField("networkHistoryConfigFile"); 600 wifiConfigManagerNetworkHistoryConfigFile.setAccessible(true); 601 wifiConfigManagerNetworkHistoryConfigFile.set(null, file.getAbsolutePath()); 602 final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); 603 for (WifiConfiguration config : CONFIGS) { 604 stream.writeUTF(WifiConfigManager.CONFIG_KEY + ": " + config.configKey() + '\n'); 605 stream.writeUTF(WifiConfigManager.CREATOR_UID_KEY + ": " 606 + Integer.toString(config.creatorUid) + '\n'); 607 stream.writeUTF(WifiConfigManager.SHARED_KEY + ": " 608 + Boolean.toString(config.shared) + '\n'); 609 } 610 stream.close(); 611 612 // Set up list of home service providers returned by MOManager. 613 final List<HomeSP> homeSPs = new ArrayList<HomeSP>(); 614 for (WifiConfiguration config : CONFIGS) { 615 if (config.FQDN != null) { 616 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(), 617 new HashSet<String>(), 618 new HashSet<Long>(), new ArrayList<Long>(), 619 config.providerFriendlyName, null, 620 new Credential(0, 0, null, false, null, null), 621 null, 0, null, null, null, 0)); 622 } 623 } 624 when(mMOManager.loadAllSPs()).thenReturn(homeSPs); 625 626 // Load network configurations. 627 mConfigStore.loadConfiguredNetworks(); 628 629 // Verify that network configurations were loaded and correlated correctly across the three 630 // sources. 631 verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers()); 632 } 633 634 /** 635 * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network 636 * configurations from the wpa_supplicant: The second configuration overwrites the first. 637 */ 638 @Test 639 public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception { 640 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0)); 641 config.networkId = 1; 642 643 // Set up list of network configurations returned by wpa_supplicant. The two configurations 644 // are identical except for their network IDs. 645 final String header = "network id / ssid / bssid / flags"; 646 final String networks = 647 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany"; 648 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 649 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 650 651 // Set up variables returned by wpa_supplicant. 652 when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName))) 653 .thenReturn(encodeConfigSSID(config)); 654 final Map<String, String> metadata = new HashMap<String, String>(); 655 metadata.put(WifiConfigManager.ID_STRING_KEY_CONFIG_KEY, config.configKey()); 656 metadata.put(WifiConfigManager.ID_STRING_KEY_CREATOR_UID, 657 Integer.toString(config.creatorUid)); 658 when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigManager.ID_STRING_VAR_NAME))) 659 .thenReturn(metadata); 660 661 // Load network configurations. 662 mConfigStore.loadConfiguredNetworks(); 663 664 // Verify that the second network configuration (network ID 1) overwrote the first (network 665 // ID 0). 666 verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers()); 667 } 668 669 /** 670 * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network 671 * configurations that should no longer be visible and enables network configurations that 672 * should become visible. 673 */ 674 private void verifyHandleUserSwitch(int oldUserId, int newUserId, 675 boolean makeOneConfigEphemeral) throws Exception { 676 addNetworks(); 677 switchUser(oldUserId); 678 679 final WifiNative wifiNative = createNewWifiNativeMock(); 680 final Field lastSelectedConfigurationField = 681 WifiConfigManager.class.getDeclaredField("lastSelectedConfiguration"); 682 lastSelectedConfigurationField.setAccessible(true); 683 WifiConfiguration removedEphemeralConfig = null; 684 final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>(); 685 final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>(); 686 final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>(); 687 final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers(); 688 int expectedNumberOfConfigs = oldConfigs.size(); 689 for (WifiConfiguration config : oldConfigs) { 690 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) { 691 config.status = WifiConfiguration.Status.ENABLED; 692 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 693 USER_PROFILES.get(newUserId))) { 694 if (makeOneConfigEphemeral && removedEphemeralConfig == null) { 695 config.ephemeral = true; 696 lastSelectedConfigurationField.set(mConfigStore, config.configKey()); 697 removedEphemeralConfig = config; 698 } 699 } else { 700 oldUserOnlyConfigs.add(config); 701 } 702 } else { 703 config.status = WifiConfiguration.Status.DISABLED; 704 if (WifiConfigurationUtil.isVisibleToAnyProfile(config, 705 USER_PROFILES.get(newUserId))) { 706 newUserOnlyConfigs.add(config); 707 } else { 708 neitherUserConfigs.add(config); 709 } 710 } 711 } 712 when(wifiNative.disableNetwork(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(mConfigStore)); 720 verify(wifiNative).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(wifiNative).disableNetwork(config.networkId); 733 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 734 } else { 735 verify(wifiNative, 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 mConfigStore.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 mConfigStore.loadConfiguredNetworks(); 835 List<WifiConfiguration> configs = mConfigStore.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<WifiNative.WifiPnoNetwork> pnoNetworkList, 970 ArrayList<Integer> expectedNetworkIdOrder) throws Exception { 971 int i = 0; 972 for (WifiNative.WifiPnoNetwork 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 retrieveDisconnectedWifiPnoNetworkList API. The test verifies that the list 981 * returned from the API is sorted as expected. 982 */ 983 @Test 984 public void testDisconnectedWifiPnoNetworkListCreation() 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1009 mConfigStore.retrieveDisconnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1032 mConfigStore.retrieveDisconnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1059 mConfigStore.retrieveDisconnectedWifiPnoNetworkList(); 1060 verifyPnoNetworkListOrder(pnoNetworkList, 1061 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1062 } 1063 } 1064 1065 /** 1066 * Verifies the retrieveConnectedWifiPnoNetworkList API. The test verifies that the list 1067 * returned from the API is sorted as expected. 1068 */ 1069 @Test 1070 public void testConnectedWifiPnoNetworkListCreation() 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1096 mConfigStore.retrieveConnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1122 mConfigStore.retrieveConnectedWifiPnoNetworkList(); 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<WifiNative.WifiPnoNetwork> pnoNetworkList = 1149 mConfigStore.retrieveConnectedWifiPnoNetworkList(); 1150 verifyPnoNetworkListOrder(pnoNetworkList, 1151 new ArrayList(networkSelectionStatusToNetworkIdMap.values())); 1152 } 1153 } 1154} 1155