WifiConfigStoreTest.java revision 75a766bae85ee8e94fbaad8fb5214804e7ff97e4
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.mockito.Mockito.anyBoolean; 21import static org.mockito.Mockito.anyInt; 22import static org.mockito.Mockito.anyObject; 23import static org.mockito.Mockito.anyString; 24import static org.mockito.Mockito.doAnswer; 25import static org.mockito.Mockito.eq; 26import static org.mockito.Mockito.intThat; 27import static org.mockito.Mockito.mock; 28import static org.mockito.Mockito.never; 29import static org.mockito.Mockito.verify; 30import static org.mockito.Mockito.when; 31 32import android.content.Context; 33import android.net.wifi.WifiConfiguration; 34import android.os.UserHandle; 35import android.test.AndroidTestCase; 36 37import com.android.server.net.DelayedDiskWrite; 38import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 39import com.android.server.wifi.hotspot2.omadm.MOManager; 40import com.android.server.wifi.hotspot2.pps.Credential; 41import com.android.server.wifi.hotspot2.pps.HomeSP; 42 43import org.mockito.Mock; 44import org.mockito.MockitoAnnotations; 45 46import java.io.ByteArrayInputStream; 47import java.io.ByteArrayOutputStream; 48import java.io.DataInputStream; 49import java.io.DataOutputStream; 50import java.io.EOFException; 51import java.io.File; 52import java.io.FileOutputStream; 53import java.lang.reflect.Field; 54import java.math.BigInteger; 55import java.util.ArrayList; 56import java.util.Arrays; 57import java.util.Collection; 58import java.util.HashMap; 59import java.util.HashSet; 60import java.util.List; 61import java.util.Map; 62import java.util.Set; 63 64/** 65 * Unit tests for {@link com.android.server.wifi.WifiConfigStore}. 66 */ 67public class WifiConfigStoreTest extends AndroidTestCase { 68 private static final List<WifiConfiguration> CONFIGS = Arrays.asList( 69 WifiConfigurationUtil.generateWifiConfig( 70 0, 1000000, "\"red\"", true, true, null, null), 71 WifiConfigurationUtil.generateWifiConfig( 72 1, 1000001, "\"green\"", true, true, "example.com", "Green"), 73 WifiConfigurationUtil.generateWifiConfig( 74 2, 1100000, "\"blue\"", false, true, "example.org", "Blue")); 75 76 private static final int[] USER_IDS = {0, 10, 11}; 77 private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>(); 78 static { 79 for (int userId : USER_IDS) { 80 List<WifiConfiguration> configs = new ArrayList<>(); 81 for (int i = 0; i < CONFIGS.size(); ++i) { 82 if (CONFIGS.get(i).isVisibleToUser(userId)) { 83 configs.add(CONFIGS.get(i)); 84 } 85 } 86 VISIBLE_CONFIGS.put(userId, configs); 87 } 88 } 89 90 @Mock private Context mContext; 91 @Mock private WifiStateMachine mWifiStateMachine; 92 @Mock private WifiNative mWifiNative; 93 @Mock private FrameworkFacade mFrameworkFacade; 94 @Mock private DelayedDiskWrite mWriter; 95 @Mock private MOManager mMOManager; 96 private WifiConfigStore mConfigStore; 97 private ConfigurationMap mConfiguredNetworks; 98 public byte[] mNetworkHistory; 99 100 @Override 101 public void setUp() throws Exception { 102 MockitoAnnotations.initMocks(this); 103 104 final Context realContext = getContext(); 105 when(mContext.getPackageName()).thenReturn(realContext.getPackageName()); 106 when(mContext.getResources()).thenReturn(realContext.getResources()); 107 when(mContext.getPackageManager()).thenReturn(realContext.getPackageManager()); 108 109 when(mWifiStateMachine.getCurrentUserId()).thenReturn(UserHandle.USER_SYSTEM); 110 111 mConfigStore = new WifiConfigStore(mContext, mWifiStateMachine, mWifiNative, 112 mFrameworkFacade); 113 114 final Field configuredNetworksField = 115 WifiConfigStore.class.getDeclaredField("mConfiguredNetworks"); 116 configuredNetworksField.setAccessible(true); 117 mConfiguredNetworks = (ConfigurationMap) configuredNetworksField.get(mConfigStore); 118 119 // Intercept writes to networkHistory.txt. 120 doAnswer(new AnswerWithArguments<Void>() { 121 public void answer(String filePath, DelayedDiskWrite.Writer writer) throws Exception { 122 final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 123 final DataOutputStream stream = new DataOutputStream(buffer); 124 writer.onWriteCalled(stream); 125 stream.close(); 126 mNetworkHistory = buffer.toByteArray(); 127 }}).when(mWriter).write(anyString(), (DelayedDiskWrite.Writer) anyObject()); 128 final Field writerField = WifiConfigStore.class.getSuperclass().getDeclaredField("mWriter"); 129 writerField.setAccessible(true); 130 writerField.set(mConfigStore, mWriter); 131 132 when(mMOManager.isEnabled()).thenReturn(true); 133 final Field moManagerField = WifiConfigStore.class.getDeclaredField("mMOManager"); 134 moManagerField.setAccessible(true); 135 moManagerField.set(mConfigStore, mMOManager); 136 } 137 138 private void switchUser(int newUserId) { 139 when(mWifiStateMachine.getCurrentUserId()).thenReturn(newUserId); 140 mConfigStore.handleUserSwitch(); 141 } 142 143 private void switchUserToCreatorOf(WifiConfiguration config) { 144 switchUser(UserHandle.getUserId(config.creatorUid)); 145 } 146 147 private void addNetworks() throws Exception { 148 final int originalUserId = mWifiStateMachine.getCurrentUserId(); 149 150 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true); 151 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 152 .thenReturn(true); 153 for (int i = 0; i < CONFIGS.size(); ++i) { 154 assertEquals(i, CONFIGS.get(i).networkId); 155 switchUserToCreatorOf(CONFIGS.get(i)); 156 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i)); 157 config.networkId = -1; 158 when(mWifiNative.addNetwork()).thenReturn(i); 159 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 160 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 161 mConfigStore.saveNetwork(config, config.creatorUid); 162 } 163 164 switchUser(originalUserId); 165 } 166 167 private String encodeConfigSSID(WifiConfiguration config) throws Exception { 168 return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1) 169 .getBytes("UTF-8")).toString(16); 170 } 171 172 private WifiNative createNewWifiNativeMock() throws Exception { 173 final WifiNative wifiNative = mock(WifiNative.class); 174 final Field wifiNativeField = WifiConfigStore.class.getDeclaredField("mWifiNative"); 175 wifiNativeField.setAccessible(true); 176 wifiNativeField.set(mConfigStore, wifiNative); 177 return wifiNative; 178 } 179 180 /** 181 * Verifies that getConfiguredNetworksSize() returns the number of network configurations 182 * visible to the current user. 183 */ 184 public void testGetConfiguredNetworksSize() throws Exception { 185 addNetworks(); 186 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 187 switchUser(entry.getKey()); 188 assertEquals(entry.getValue().size(), mConfigStore.getConfiguredNetworksSize()); 189 } 190 } 191 192 private void verifyNetworkConfig(WifiConfiguration expectedConfig, 193 WifiConfiguration actualConfig) { 194 assertNotNull(actualConfig); 195 assertEquals(expectedConfig.SSID, actualConfig.SSID); 196 assertEquals(expectedConfig.FQDN, actualConfig.FQDN); 197 assertEquals(expectedConfig.providerFriendlyName, 198 actualConfig.providerFriendlyName); 199 assertEquals(expectedConfig.configKey(), actualConfig.configKey(false)); 200 } 201 202 private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, 203 Collection<WifiConfiguration> actualConfigs) { 204 assertEquals(expectedConfigs.size(), actualConfigs.size()); 205 for (WifiConfiguration expectedConfig : expectedConfigs) { 206 WifiConfiguration actualConfig = null; 207 // Find the network configuration to test (assume that |actualConfigs| contains them in 208 // undefined order). 209 for (final WifiConfiguration candidate : actualConfigs) { 210 if (candidate.networkId == expectedConfig.networkId) { 211 actualConfig = candidate; 212 break; 213 } 214 } 215 verifyNetworkConfig(expectedConfig, actualConfig); 216 } 217 } 218 219 /** 220 * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the 221 * current user. 222 */ 223 public void testGetConfiguredNetworks() throws Exception { 224 addNetworks(); 225 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 226 switchUser(entry.getKey()); 227 verifyNetworkConfigs(entry.getValue(), mConfigStore.getConfiguredNetworks()); 228 } 229 } 230 231 /** 232 * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to 233 * the current user. 234 */ 235 public void testGetPrivilegedConfiguredNetworks() throws Exception { 236 addNetworks(); 237 for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) { 238 switchUser(entry.getKey()); 239 verifyNetworkConfigs(entry.getValue(), mConfigStore.getPrivilegedConfiguredNetworks()); 240 } 241 } 242 243 /** 244 * Verifies that getWifiConfiguration(int netId) can be used to access network configurations 245 * visible to the current user only. 246 */ 247 public void testGetWifiConfigurationByNetworkId() throws Exception { 248 addNetworks(); 249 for (int userId : USER_IDS) { 250 switchUser(userId); 251 for (WifiConfiguration expectedConfig: CONFIGS) { 252 final WifiConfiguration actualConfig = 253 mConfigStore.getWifiConfiguration(expectedConfig.networkId); 254 if (expectedConfig.isVisibleToUser(userId)) { 255 verifyNetworkConfig(expectedConfig, actualConfig); 256 } else { 257 assertNull(actualConfig); 258 } 259 } 260 } 261 } 262 263 /** 264 * Verifies that getWifiConfiguration(String key) can be used to access network configurations 265 * visible to the current user only. 266 */ 267 public void testGetWifiConfigurationByConfigKey() throws Exception { 268 addNetworks(); 269 for (int userId : USER_IDS) { 270 switchUser(userId); 271 for (WifiConfiguration expectedConfig: CONFIGS) { 272 final WifiConfiguration actualConfig = 273 mConfigStore.getWifiConfiguration(expectedConfig.configKey()); 274 if (expectedConfig.isVisibleToUser(userId)) { 275 verifyNetworkConfig(expectedConfig, actualConfig); 276 } else { 277 assertNull(actualConfig); 278 } 279 } 280 } 281 } 282 283 /** 284 * Verifies that enableAllNetworks() enables all temporarily disabled network configurations 285 * visible to the current user. 286 */ 287 public void testEnableAllNetworks() throws Exception { 288 addNetworks(); 289 when(mWifiNative.enableNetwork(anyInt(), anyBoolean())).thenReturn(true); 290 for (int userId : USER_IDS) { 291 switchUser(userId); 292 293 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 294 final WifiConfiguration.NetworkSelectionStatus status = 295 config.getNetworkSelectionStatus(); 296 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus 297 .NETWORK_SELECTION_TEMPORARY_DISABLED); 298 status.setNetworkSelectionDisableReason( 299 WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE); 300 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000); 301 } 302 303 mConfigStore.enableAllNetworks(); 304 305 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 306 assertEquals(config.isVisibleToUser(userId), 307 config.getNetworkSelectionStatus().isNetworkEnabled()); 308 } 309 } 310 } 311 312 /** 313 * Verifies that selectNetwork() disables all network configurations visible to the current user 314 * except the selected one. 315 */ 316 public void testSelectNetwork() throws Exception { 317 addNetworks(); 318 319 for (int userId : USER_IDS) { 320 switchUser(userId); 321 322 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 323 // Enable all network configurations. 324 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 325 config2.status = WifiConfiguration.Status.ENABLED; 326 } 327 328 // Try to select a network configuration. 329 final WifiNative wifiNative = createNewWifiNativeMock(); 330 final boolean success = 331 mConfigStore.selectNetwork(config, false, config.creatorUid); 332 if (!config.isVisibleToUser(userId)) { 333 // If the network configuration is not visible to the current user, verify that 334 // nothing changed. 335 assertFalse(success); 336 verify(wifiNative, never()).selectNetwork(anyInt()); 337 verify(wifiNative, never()).enableNetwork(anyInt(), anyBoolean()); 338 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 339 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 340 } 341 } else { 342 // If the network configuration is visible to the current user, verify that it 343 // was enabled and all other network configurations visible to the user were 344 // disabled. 345 assertTrue(success); 346 verify(wifiNative).selectNetwork(config.networkId); 347 verify(wifiNative, never()).selectNetwork(intThat(not(config.networkId))); 348 verify(wifiNative).enableNetwork(config.networkId, true); 349 verify(wifiNative, never()).enableNetwork(config.networkId, false); 350 verify(wifiNative, never()).enableNetwork(intThat(not(config.networkId)), 351 anyBoolean()); 352 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) { 353 if (config2.isVisibleToUser(userId) 354 && config2.networkId != config.networkId) { 355 assertEquals(WifiConfiguration.Status.DISABLED, config2.status); 356 } else { 357 assertEquals(WifiConfiguration.Status.ENABLED, config2.status); 358 } 359 } 360 } 361 } 362 } 363 } 364 365 /** 366 * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant 367 * variables and the networkHistory.txt file. 368 * TODO: Test all variables. Currently, only the following variables are tested: 369 * - In the wpa_supplicant: "ssid", "id_str" 370 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 371 */ 372 private void verifySaveNetwork(int network) throws Exception { 373 // Switch to the correct user. 374 switchUserToCreatorOf(CONFIGS.get(network)); 375 376 // Set up wpa_supplicant. 377 when(mWifiNative.addNetwork()).thenReturn(0); 378 when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString())) 379 .thenReturn(true); 380 when(mWifiNative.setNetworkExtra(eq(network), anyString(), 381 (Map<String, String>) anyObject())).thenReturn(true); 382 when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName)) 383 .thenReturn(encodeConfigSSID(CONFIGS.get(network))); 384 385 // Store a network configuration. 386 mConfigStore.saveNetwork(CONFIGS.get(network), CONFIGS.get(network).creatorUid); 387 388 // Verify that wpa_supplicant variables were written correctly for the network 389 // configuration. 390 final Map<String, String> metadata = new HashMap<String, String>(); 391 if (CONFIGS.get(network).FQDN != null) { 392 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(network).FQDN); 393 } 394 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(network).configKey()); 395 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 396 Integer.toString(CONFIGS.get(network).creatorUid)); 397 verify(mWifiNative).setNetworkExtra(network, WifiConfigStore.ID_STRING_VAR_NAME, 398 metadata); 399 400 // Verify that no wpa_supplicant variables were read or written for any other network 401 // configurations. 402 verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(), 403 (Map<String, String>) anyObject()); 404 verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(), 405 anyString()); 406 verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString()); 407 408 // Parse networkHistory.txt. 409 assertNotNull(mNetworkHistory); 410 final DataInputStream stream = 411 new DataInputStream(new ByteArrayInputStream(mNetworkHistory)); 412 List<String> keys = new ArrayList<>(); 413 List<String> values = new ArrayList<>(); 414 try { 415 while (true) { 416 final String[] tokens = stream.readUTF().split(":", 2); 417 if (tokens.length == 2) { 418 keys.add(tokens[0].trim()); 419 values.add(tokens[1].trim()); 420 } 421 } 422 } catch (EOFException e) { 423 // Ignore. This is expected. 424 } 425 426 // Verify that a networkHistory.txt entry was written correctly for the network 427 // configuration. 428 assertTrue(keys.size() >= 3); 429 assertEquals(WifiConfigStore.CONFIG_KEY, keys.get(0)); 430 assertEquals(CONFIGS.get(network).configKey(), values.get(0)); 431 final int creatorUidIndex = keys.indexOf(WifiConfigStore.CREATOR_UID_KEY); 432 assertTrue(creatorUidIndex != -1); 433 assertEquals(Integer.toString(CONFIGS.get(network).creatorUid), 434 values.get(creatorUidIndex)); 435 final int sharedIndex = keys.indexOf(WifiConfigStore.SHARED_KEY); 436 assertTrue(sharedIndex != -1); 437 assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex)); 438 439 // Verify that no networkHistory.txt entries were written for any other network 440 // configurations. 441 final int lastConfigIndex = keys.lastIndexOf(WifiConfigStore.CONFIG_KEY); 442 assertEquals(0, lastConfigIndex); 443 } 444 445 /** 446 * Verifies that saveNetwork() correctly stores a regular network configuration. 447 */ 448 public void testSaveNetworkRegular() throws Exception { 449 verifySaveNetwork(0); 450 } 451 452 /** 453 * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration. 454 */ 455 public void testSaveNetworkHotspot20() throws Exception { 456 verifySaveNetwork(1); 457 } 458 459 /** 460 * Verifies that saveNetwork() correctly stores a private network configuration. 461 */ 462 public void testSaveNetworkPrivate() throws Exception { 463 verifySaveNetwork(2); 464 } 465 466 /** 467 * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the 468 * networkHistory.txt file and the MOManager, correlating the three sources based on the 469 * configKey and the FQDN for HotSpot 2.0 networks. 470 * TODO: Test all variables. Currently, only the following variables are tested: 471 * - In the wpa_supplicant: "ssid", "id_str" 472 * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED" 473 */ 474 public void testLoadConfiguredNetworks() throws Exception { 475 // Set up list of network configurations returned by wpa_supplicant. 476 final String header = "network id / ssid / bssid / flags"; 477 String networks = header; 478 for (WifiConfiguration config : CONFIGS) { 479 networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany"; 480 } 481 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 482 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 483 484 // Set up variables returned by wpa_supplicant for the individual network configurations. 485 for (int i = 0; i < CONFIGS.size(); ++i) { 486 when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName)) 487 .thenReturn(encodeConfigSSID(CONFIGS.get(i))); 488 } 489 // Legacy regular network configuration: No "id_str". 490 when(mWifiNative.getNetworkExtra(0, WifiConfigStore.ID_STRING_VAR_NAME)) 491 .thenReturn(null); 492 // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str". 493 when(mWifiNative.getNetworkExtra(1, WifiConfigStore.ID_STRING_VAR_NAME)) 494 .thenReturn(null); 495 when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME)) 496 .thenReturn('"' + CONFIGS.get(1).FQDN + '"'); 497 // Up-to-date configuration: Metadata in "id_str". 498 final Map<String, String> metadata = new HashMap<String, String>(); 499 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey()); 500 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 501 Integer.toString(CONFIGS.get(2).creatorUid)); 502 metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN); 503 when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME)) 504 .thenReturn(metadata); 505 506 // Set up networkHistory.txt file. 507 final File file = File.createTempFile("networkHistory.txt", null); 508 file.deleteOnExit(); 509 Field wifiConfigStoreNetworkHistoryConfigFile = 510 WifiConfigStore.class.getDeclaredField("networkHistoryConfigFile"); 511 wifiConfigStoreNetworkHistoryConfigFile.setAccessible(true); 512 wifiConfigStoreNetworkHistoryConfigFile.set(null, file.getAbsolutePath()); 513 final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)); 514 for (WifiConfiguration config : CONFIGS) { 515 stream.writeUTF(WifiConfigStore.CONFIG_KEY + ": " + config.configKey() + '\n'); 516 stream.writeUTF(WifiConfigStore.CREATOR_UID_KEY + ": " 517 + Integer.toString(config.creatorUid) + '\n'); 518 stream.writeUTF(WifiConfigStore.SHARED_KEY + ": " 519 + Boolean.toString(config.shared) + '\n'); 520 } 521 stream.close(); 522 523 // Set up list of home service providers returned by MOManager. 524 final List<HomeSP> homeSPs = new ArrayList<HomeSP>(); 525 for (WifiConfiguration config : CONFIGS) { 526 if (config.FQDN != null) { 527 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(), 528 new HashSet<String>(), new HashSet<Long>(), new ArrayList<Long>(), 529 config.providerFriendlyName, null, new Credential(0, 0, null, false, null, 530 null), null, 0, null, null, null)); 531 } 532 } 533 when(mMOManager.loadAllSPs()).thenReturn(homeSPs); 534 535 // Load network configurations. 536 mConfigStore.loadConfiguredNetworks(); 537 538 // Verify that network configurations were loaded and correlated correctly across the three 539 // sources. 540 verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers()); 541 } 542 543 /** 544 * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network 545 * configurations from the wpa_supplicant: The second configuration overwrites the first. 546 */ 547 public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception { 548 final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0)); 549 config.networkId = 1; 550 551 // Set up list of network configurations returned by wpa_supplicant. The two configurations 552 // are identical except for their network IDs. 553 final String header = "network id / ssid / bssid / flags"; 554 final String networks = 555 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany"; 556 when(mWifiNative.listNetworks(anyInt())).thenReturn(header); 557 when(mWifiNative.listNetworks(-1)).thenReturn(networks); 558 559 // Set up variables returned by wpa_supplicant. 560 when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName))) 561 .thenReturn(encodeConfigSSID(config)); 562 final Map<String, String> metadata = new HashMap<String, String>(); 563 metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, config.configKey()); 564 metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID, 565 Integer.toString(config.creatorUid)); 566 when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigStore.ID_STRING_VAR_NAME))) 567 .thenReturn(metadata); 568 569 // Load network configurations. 570 mConfigStore.loadConfiguredNetworks(); 571 572 // Verify that the second network configuration (network ID 1) overwrote the first (network 573 // ID 0). 574 verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers()); 575 } 576 577 /** 578 * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network 579 * configurations that should no longer be visible and enables network configurations that 580 * should become visible. 581 */ 582 private void verifyHandleUserSwitch(int oldUserId, int newUserId, 583 boolean makeOneConfigEphemeral) throws Exception { 584 addNetworks(); 585 switchUser(oldUserId); 586 587 final WifiNative wifiNative = createNewWifiNativeMock(); 588 final Field lastSelectedConfigurationField = 589 WifiConfigStore.class.getDeclaredField("lastSelectedConfiguration"); 590 lastSelectedConfigurationField.setAccessible(true); 591 WifiConfiguration removedEphemeralConfig = null; 592 final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>(); 593 final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>(); 594 final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>(); 595 final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers(); 596 int expectedNumberOfConfigs = oldConfigs.size(); 597 for (WifiConfiguration config : oldConfigs) { 598 if (config.isVisibleToUser(oldUserId)) { 599 config.status = WifiConfiguration.Status.ENABLED; 600 if (config.isVisibleToUser(newUserId)) { 601 if (makeOneConfigEphemeral && removedEphemeralConfig == null) { 602 config.ephemeral = true; 603 lastSelectedConfigurationField.set(mConfigStore, config.configKey()); 604 removedEphemeralConfig = config; 605 } 606 } else { 607 oldUserOnlyConfigs.add(config); 608 } 609 } else { 610 config.status = WifiConfiguration.Status.DISABLED; 611 if (config.isVisibleToUser(newUserId)) { 612 newUserOnlyConfigs.add(config); 613 } else { 614 neitherUserConfigs.add(config); 615 } 616 } 617 } 618 when(wifiNative.disableNetwork(anyInt())).thenReturn(true); 619 620 switchUser(newUserId); 621 if (makeOneConfigEphemeral) { 622 // Verify that the ephemeral network configuration was removed. 623 assertNotNull(removedEphemeralConfig); 624 assertNull(mConfiguredNetworks.getForAllUsers(removedEphemeralConfig.networkId)); 625 assertNull(lastSelectedConfigurationField.get(mConfigStore)); 626 verify(wifiNative).removeNetwork(removedEphemeralConfig.networkId); 627 --expectedNumberOfConfigs; 628 } else { 629 assertNull(removedEphemeralConfig); 630 } 631 632 // Verify that the other network configurations were revealed/hidden and enabled/disabled as 633 // appropriate. 634 final Collection<WifiConfiguration> newConfigs = mConfiguredNetworks.valuesForAllUsers(); 635 assertEquals(expectedNumberOfConfigs, newConfigs.size()); 636 for (WifiConfiguration config : newConfigs) { 637 if (oldUserOnlyConfigs.contains(config)) { 638 verify(wifiNative).disableNetwork(config.networkId); 639 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 640 } else { 641 verify(wifiNative, never()).disableNetwork(config.networkId); 642 if (neitherUserConfigs.contains(config)) { 643 assertEquals(WifiConfiguration.Status.DISABLED, config.status); 644 } else { 645 assertEquals(WifiConfiguration.Status.ENABLED, config.status); 646 } 647 } 648 } 649 } 650 651 /** 652 * Verifies that handleUserSwitch() behaves correctly when the user switch removes an ephemeral 653 * network configuration and reveals a private network configuration. 654 */ 655 public void testHandleUserSwitchWithEphemeral() throws Exception { 656 verifyHandleUserSwitch(USER_IDS[2], USER_IDS[0], true); 657 } 658 659 /** 660 * Verifies that handleUserSwitch() behaves correctly when the user switch hides a private 661 * network configuration. 662 */ 663 public void testHandleUserSwitchWithoutEphemeral() throws Exception { 664 verifyHandleUserSwitch(USER_IDS[0], USER_IDS[2], false); 665 } 666} 667