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 17 package com.android.server.wifi; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.mockito.Mockito.*; 25 26 import android.content.pm.UserInfo; 27 import android.net.wifi.ScanResult; 28 import android.net.wifi.WifiConfiguration; 29 import android.net.wifi.WifiManager; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.util.SparseArray; 33 34 import androidx.test.filters.SmallTest; 35 36 import org.junit.After; 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.mockito.Mock; 40 import org.mockito.MockitoAnnotations; 41 import org.mockito.MockitoSession; 42 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.Collection; 46 import java.util.HashSet; 47 import java.util.List; 48 import java.util.Set; 49 50 /** 51 * Unit tests for {@link com.android.server.wifi.ConfigurationMapTest}. 52 */ 53 @SmallTest 54 public class ConfigurationMapTest extends WifiBaseTest { 55 private static final int SYSTEM_MANAGE_PROFILE_USER_ID = 12; 56 private static final String TEST_BSSID = "0a:08:5c:67:89:01"; 57 private static final List<WifiConfiguration> CONFIGS = Arrays.asList( 58 WifiConfigurationTestUtil.generateWifiConfig( 59 0, 1000000, "\"red\"", true, true, null, null, 60 WifiConfigurationTestUtil.SECURITY_NONE), 61 WifiConfigurationTestUtil.generateWifiConfig( 62 1, 1000001, "\"green\"", true, false, "example.com", "Green", 63 WifiConfigurationTestUtil.SECURITY_NONE), 64 WifiConfigurationTestUtil.generateWifiConfig( 65 2, 1200000, "\"blue\"", false, true, null, null, 66 WifiConfigurationTestUtil.SECURITY_NONE), 67 WifiConfigurationTestUtil.generateWifiConfig( 68 3, 1100000, "\"cyan\"", true, true, null, null, 69 WifiConfigurationTestUtil.SECURITY_NONE), 70 WifiConfigurationTestUtil.generateWifiConfig( 71 4, 1100001, "\"yellow\"", true, true, "example.org", "Yellow", 72 WifiConfigurationTestUtil.SECURITY_NONE), 73 WifiConfigurationTestUtil.generateWifiConfig( 74 5, 1100002, "\"magenta\"", false, false, null, null, 75 WifiConfigurationTestUtil.SECURITY_NONE)); 76 77 private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>(); 78 static { USER_PROFILES.put(UserHandle.USER_SYSTEM, Arrays.asList( new UserInfo(UserHandle.USER_SYSTEM, R, 0), new UserInfo(SYSTEM_MANAGE_PROFILE_USER_ID, R, 0)))79 USER_PROFILES.put(UserHandle.USER_SYSTEM, Arrays.asList( 80 new UserInfo(UserHandle.USER_SYSTEM, "Owner", 0), 81 new UserInfo(SYSTEM_MANAGE_PROFILE_USER_ID, "Managed Profile", 0))); 82 USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0))); 83 USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0))); 84 } 85 86 @Mock UserManager mUserManager; 87 @Mock WifiInjector mWifiInjector; 88 @Mock ActiveModeWarden mActiveModeWarden; 89 @Mock ClientModeManager mPrimaryClientModeManager; 90 @Mock WifiGlobals mWifiGlobals; 91 private MockitoSession mStaticMockSession = null; 92 93 private int mCurrentUserId = UserHandle.USER_SYSTEM; 94 private ConfigurationMap mConfigs; 95 96 /** 97 * Sets up the test harness before running a test. 98 */ 99 @Before setUp()100 public void setUp() { 101 MockitoAnnotations.initMocks(this); 102 mStaticMockSession = mockitoSession() 103 .mockStatic(WifiInjector.class) 104 .startMocking(); 105 lenient().when(WifiInjector.getInstance()).thenReturn(mWifiInjector); 106 when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); 107 when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); 108 when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); 109 when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( 110 WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); 111 when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); 112 when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); 113 114 // by default, return false 115 when(mUserManager.isSameProfileGroup(any(), any())).thenReturn(false); 116 // return true for these 2 userids 117 when(mUserManager.isSameProfileGroup(UserHandle.SYSTEM, 118 UserHandle.of(SYSTEM_MANAGE_PROFILE_USER_ID))) 119 .thenReturn(true); 120 when(mUserManager.isSameProfileGroup(UserHandle.of(SYSTEM_MANAGE_PROFILE_USER_ID), 121 UserHandle.SYSTEM)) 122 .thenReturn(true); 123 mConfigs = new ConfigurationMap(mUserManager); 124 } 125 126 @After cleanUp()127 public void cleanUp() throws Exception { 128 if (null != mStaticMockSession) { 129 mStaticMockSession.finishMocking(); 130 } 131 } 132 switchUser(int newUserId)133 private void switchUser(int newUserId) { 134 mCurrentUserId = newUserId; 135 mConfigs.setNewUser(newUserId); 136 mConfigs.clear(); 137 } 138 getEnabledNetworksForCurrentUser()139 private Collection<WifiConfiguration> getEnabledNetworksForCurrentUser() { 140 List<WifiConfiguration> list = new ArrayList<>(); 141 for (WifiConfiguration config : mConfigs.valuesForCurrentUser()) { 142 if (config.status != WifiConfiguration.Status.DISABLED) { 143 list.add(config); 144 } 145 } 146 return list; 147 } 148 getEphemeralForCurrentUser(String ssid)149 private WifiConfiguration getEphemeralForCurrentUser(String ssid) { 150 for (WifiConfiguration config : mConfigs.valuesForCurrentUser()) { 151 if (ssid.equals(config.SSID) && config.ephemeral) { 152 return config; 153 } 154 } 155 return null; 156 } 157 addNetworks(List<WifiConfiguration> configs)158 private void addNetworks(List<WifiConfiguration> configs) { 159 for (WifiConfiguration config : configs) { 160 assertNull(mConfigs.put(config)); 161 } 162 } 163 verifyGetters(List<WifiConfiguration> configs)164 private void verifyGetters(List<WifiConfiguration> configs) { 165 final Set<WifiConfiguration> configsForCurrentUser = new HashSet<>(); 166 final Set<WifiConfiguration> enabledConfigsForCurrentUser = new HashSet<>(); 167 final List<WifiConfiguration> configsNotForCurrentUser = new ArrayList<>(); 168 169 // Find out which network configurations should be / should not be visible to the current 170 // user. Also, check that *ForAllUsers() methods can be used to access all network 171 // configurations, irrespective of their visibility to the current user. 172 for (WifiConfiguration config : configs) { 173 final UserHandle currentUser = UserHandle.of(mCurrentUserId); 174 final UserHandle creatorUser = UserHandle.getUserHandleForUid(config.creatorUid); 175 if (config.shared || currentUser.equals(creatorUser) 176 || mUserManager.isSameProfileGroup(currentUser, creatorUser)) { 177 configsForCurrentUser.add(config); 178 if (config.status != WifiConfiguration.Status.DISABLED) { 179 enabledConfigsForCurrentUser.add(config); 180 } 181 } else { 182 configsNotForCurrentUser.add(config); 183 } 184 185 assertEquals(config, mConfigs.getForAllUsers(config.networkId)); 186 } 187 188 // Verify that *ForCurrentUser() methods can be used to access network configurations 189 // visible to the current user. 190 for (WifiConfiguration config : configsForCurrentUser) { 191 assertEquals(config, mConfigs.getForCurrentUser(config.networkId)); 192 assertEquals(config, mConfigs.getByConfigKeyForCurrentUser( 193 config.getProfileKey())); 194 final boolean wasEphemeral = config.ephemeral; 195 config.ephemeral = false; 196 assertNull(getEphemeralForCurrentUser(config.SSID)); 197 config.ephemeral = true; 198 assertEquals(config, getEphemeralForCurrentUser(config.SSID)); 199 config.ephemeral = wasEphemeral; 200 } 201 202 // Verify that *ForCurrentUser() methods cannot be used to access network configurations not 203 // visible to the current user. 204 for (WifiConfiguration config : configsNotForCurrentUser) { 205 assertNull(mConfigs.getForCurrentUser(config.networkId)); 206 assertNull(mConfigs.getByConfigKeyForCurrentUser(config.getProfileKey())); 207 final boolean wasEphemeral = config.ephemeral; 208 config.ephemeral = false; 209 assertNull(getEphemeralForCurrentUser(config.SSID)); 210 config.ephemeral = true; 211 assertNull(getEphemeralForCurrentUser(config.SSID)); 212 config.ephemeral = wasEphemeral; 213 } 214 215 // Verify that the methods which refer to more than one network configuration return the 216 // correct sets of networks. 217 assertEquals(configs.size(), mConfigs.sizeForAllUsers()); 218 assertEquals(configsForCurrentUser.size(), mConfigs.sizeForCurrentUser()); 219 assertEquals(enabledConfigsForCurrentUser, 220 new HashSet<WifiConfiguration>(getEnabledNetworksForCurrentUser())); 221 assertEquals(new HashSet<>(configs), 222 new HashSet<WifiConfiguration>(mConfigs.valuesForAllUsers())); 223 } 224 createScanResultForNetwork(WifiConfiguration config)225 private ScanResult createScanResultForNetwork(WifiConfiguration config) { 226 return WifiConfigurationTestUtil.createScanDetailForNetwork(config, TEST_BSSID, 0, 0, 0, 0) 227 .getScanResult(); 228 } 229 230 /** 231 * Helper function to create a scan result matching the network and ensuring that 232 * {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} can match that network. 233 */ verifyScanResultMatchWithNetwork(WifiConfiguration config)234 private void verifyScanResultMatchWithNetwork(WifiConfiguration config) { 235 mConfigs.put(config); 236 ScanResult scanResult = createScanResultForNetwork(config); 237 WifiConfiguration retrievedConfig = 238 mConfigs.getByScanResultForCurrentUser(scanResult); 239 assertNotNull(retrievedConfig); 240 assertEquals(config.getProfileKey(), retrievedConfig.getProfileKey()); 241 } 242 243 /** 244 * Verifies that all getters return the correct network configurations, taking into account the 245 * current user. Also verifies that handleUserSwitch() returns the list of network 246 * configurations that are no longer visible. 247 */ 248 @Test testGettersAndHandleUserSwitch()249 public void testGettersAndHandleUserSwitch() { 250 addNetworks(CONFIGS); 251 verifyGetters(CONFIGS); 252 253 switchUser(10); 254 addNetworks(CONFIGS); 255 verifyGetters(CONFIGS); 256 257 switchUser(11); 258 addNetworks(CONFIGS); 259 verifyGetters(CONFIGS); 260 } 261 262 /** 263 * Verifies put(), remove() and clear(). 264 */ 265 @Test testPutRemoveClear()266 public void testPutRemoveClear() { 267 final List<WifiConfiguration> configs = new ArrayList<>(); 268 final WifiConfiguration config1 = CONFIGS.get(0); 269 270 // Verify that there are no network configurations to start with. 271 switchUser(UserHandle.getUserHandleForUid(config1.creatorUid).getIdentifier()); 272 verifyGetters(configs); 273 274 // Add |config1|. 275 assertNull(mConfigs.put(config1)); 276 // Verify that the getters return |config1|. 277 configs.add(config1); 278 verifyGetters(configs); 279 280 // Overwrite |config1| with |config2|. 281 final WifiConfiguration config2 = CONFIGS.get(1); 282 config2.networkId = config1.networkId; 283 assertEquals(config1, mConfigs.put(config2)); 284 // Verify that the getters return |config2| only. 285 configs.clear(); 286 configs.add(config2); 287 verifyGetters(configs); 288 289 // Add |config3|, which belongs to a managed profile of the current user. 290 final WifiConfiguration config3 = CONFIGS.get(2); 291 assertNull(mConfigs.put(config3)); 292 // Verify that the getters return |config2| and |config3|. 293 configs.add(config3); 294 verifyGetters(configs); 295 296 // Remove |config2|. 297 assertEquals(config2, mConfigs.remove(config2.networkId)); 298 // Verify that the getters return |config3| only. 299 configs.remove(config2); 300 verifyGetters(configs); 301 302 // Clear all network configurations. 303 mConfigs.clear(); 304 // Verify that the getters do not return any network configurations. 305 configs.clear(); 306 verifyGetters(configs); 307 } 308 309 /** 310 * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} can 311 * positively match the corresponding networks. 312 */ 313 @Test testScanResultDoesMatchCorrespondingNetworks()314 public void testScanResultDoesMatchCorrespondingNetworks() { 315 verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createOpenNetwork()); 316 verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createPskNetwork()); 317 verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createWepNetwork()); 318 verifyScanResultMatchWithNetwork(WifiConfigurationTestUtil.createEapNetwork()); 319 } 320 321 /** 322 * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not 323 * match other networks. 324 */ 325 @Test testScanResultDoesNotMatchWithOtherNetworks()326 public void testScanResultDoesNotMatchWithOtherNetworks() { 327 WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); 328 ScanResult scanResult = createScanResultForNetwork(config); 329 // Change the network security type and the old scan result should not match now. 330 config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); 331 mConfigs.put(config); 332 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 333 } 334 335 /** 336 * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not 337 * match networks which have been removed. 338 */ 339 @Test testScanResultDoesNotMatchAfterNetworkRemove()340 public void testScanResultDoesNotMatchAfterNetworkRemove() { 341 WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); 342 ScanResult scanResult = createScanResultForNetwork(config); 343 config.networkId = 5; 344 mConfigs.put(config); 345 // Create another network in the map. 346 mConfigs.put(WifiConfigurationTestUtil.createPskNetwork()); 347 assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 348 349 mConfigs.remove(config.networkId); 350 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 351 } 352 353 /** 354 * Verifies that {@link ConfigurationMap#getByScanResultForCurrentUser(ScanResult)} does not 355 * match networks after clear. 356 */ 357 @Test testScanResultDoesNotMatchAfterClear()358 public void testScanResultDoesNotMatchAfterClear() { 359 WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); 360 ScanResult scanResult = createScanResultForNetwork(config); 361 config.networkId = 5; 362 mConfigs.put(config); 363 // Create another network in the map. 364 mConfigs.put(WifiConfigurationTestUtil.createPskNetwork()); 365 assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 366 367 mConfigs.clear(); 368 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 369 } 370 371 @Test testScanResultDoesNotMatchForWifiNetworkSpecifier()372 public void testScanResultDoesNotMatchForWifiNetworkSpecifier() { 373 // Add regular saved network, this should create a scan result match info cache entry. 374 WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); 375 ScanResult scanResult = createScanResultForNetwork(config); 376 config.networkId = 5; 377 mConfigs.put(config); 378 assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 379 380 mConfigs.clear(); 381 382 // Create WifiNetworkSpecifier network, this should not create a scan result match info 383 // cache entry. 384 config.ephemeral = true; 385 config.fromWifiNetworkSpecifier = true; 386 mConfigs.put(config); 387 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 388 } 389 390 @Test testScanResultDoesNotMatchForWifiNetworkSuggestion()391 public void testScanResultDoesNotMatchForWifiNetworkSuggestion() { 392 // Add regular saved network, this should create a scan result match info cache entry. 393 WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); 394 ScanResult scanResult = createScanResultForNetwork(config); 395 config.networkId = 5; 396 mConfigs.put(config); 397 assertNotNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 398 399 mConfigs.clear(); 400 401 // Create WifiNetworkSuggestion network, this should not create a scan result match info 402 // cache entry. 403 config.ephemeral = true; 404 config.fromWifiNetworkSuggestion = true; 405 mConfigs.put(config); 406 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 407 } 408 409 @Test testScanResultDoesNotMatchForPasspoint()410 public void testScanResultDoesNotMatchForPasspoint() { 411 // Add passpoint network, this should not create a scan result match info cache entry. 412 WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork(); 413 ScanResult scanResult = createScanResultForNetwork(config); 414 config.networkId = 5; 415 mConfigs.put(config); 416 assertNull(mConfigs.getByScanResultForCurrentUser(scanResult)); 417 } 418 } 419