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