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