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