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