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.hotspot2; 18 19 import static android.net.wifi.WifiConfiguration.RANDOMIZATION_NONE; 20 21 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.ArgumentMatchers.anyString; 28 import static org.mockito.Mockito.any; 29 import static org.mockito.Mockito.anyInt; 30 import static org.mockito.Mockito.eq; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.when; 36 import static org.mockito.MockitoAnnotations.initMocks; 37 38 import android.content.res.Resources; 39 import android.net.wifi.ScanResult; 40 import android.net.wifi.WifiConfiguration; 41 import android.net.wifi.WifiEnterpriseConfig; 42 import android.net.wifi.hotspot2.PasspointConfiguration; 43 import android.net.wifi.hotspot2.pps.HomeSp; 44 import android.net.wifi.util.ScanResultUtil; 45 import android.telephony.SubscriptionInfo; 46 import android.telephony.SubscriptionManager; 47 import android.util.LocalLog; 48 import android.util.Pair; 49 50 import androidx.test.filters.SmallTest; 51 52 import com.android.server.wifi.Clock; 53 import com.android.server.wifi.NetworkUpdateResult; 54 import com.android.server.wifi.ScanDetail; 55 import com.android.server.wifi.WifiBaseTest; 56 import com.android.server.wifi.WifiCarrierInfoManager; 57 import com.android.server.wifi.WifiConfigManager; 58 import com.android.server.wifi.WifiConfigurationTestUtil; 59 import com.android.server.wifi.hotspot2.anqp.ANQPElement; 60 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; 61 import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement; 62 import com.android.wifi.resources.R; 63 64 import org.junit.Before; 65 import org.junit.Test; 66 import org.mockito.ArgumentCaptor; 67 import org.mockito.Mock; 68 69 import java.nio.ByteBuffer; 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.Collections; 73 import java.util.HashMap; 74 import java.util.List; 75 import java.util.Map; 76 77 /** 78 * Unit tests for {@link PasspointNetworkNominateHelper}. 79 */ 80 @SmallTest 81 public class PasspointNetworkNominateHelperTest extends WifiBaseTest { 82 // TODO(b/140763176): should extend WifiBaseTest, but if it does then it fails with NPE 83 private static final int TEST_NETWORK_ID = 1; 84 private static final int TEST_NETWORK_ID2 = 2; 85 private static final String TEST_SSID1 = "ssid1"; 86 private static final String TEST_SSID2 = "ssid2"; 87 private static final String TEST_BSSID1 = "01:23:45:56:78:9a"; 88 private static final String TEST_BSSID2 = "23:12:34:90:81:12"; 89 private static final String TEST_FQDN1 = "test1.com"; 90 private static final String TEST_FQDN2 = "test2.com"; 91 private static final int TEST_UID = 5555; 92 private static final String TEST_PACKAGE = "test.package.com"; 93 private static final WifiConfiguration TEST_CONFIG1 = generateWifiConfig(TEST_FQDN1); 94 private static final WifiConfiguration TEST_CONFIG2 = generateWifiConfig(TEST_FQDN2); 95 private static PasspointProvider sTestProvider1; 96 private static PasspointProvider sTestProvider2; 97 private static final long TEST_START_TIME_MS = 0; 98 99 @Mock PasspointManager mPasspointManager; 100 @Mock WifiConfigManager mWifiConfigManager; 101 @Mock SubscriptionManager mSubscriptionManager; 102 @Mock LocalLog mLocalLog; 103 @Mock WifiCarrierInfoManager mWifiCarrierInfoManager; 104 @Mock Resources mResources; 105 @Mock Clock mClock; 106 PasspointNetworkNominateHelper mNominateHelper; 107 108 /** 109 * Helper function for generating {@link WifiConfiguration} for testing. 110 * 111 * @param fqdn The FQDN associated with the configuration 112 * @return {@link WifiConfiguration} 113 */ generateWifiConfig(String fqdn)114 private static WifiConfiguration generateWifiConfig(String fqdn) { 115 WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1, 116 TEST_UID, "\"PasspointTestSSID\"", true, true, 117 fqdn, fqdn, SECURITY_EAP); 118 119 return wifiConfiguration; 120 } 121 122 /** 123 * Helper function for generating {@link PasspointProvider} for testing. 124 * 125 * @param config The WifiConfiguration associated with the provider 126 * @return {@link PasspointProvider} 127 */ generateProvider(WifiConfiguration config)128 private static PasspointProvider generateProvider(WifiConfiguration config) { 129 PasspointProvider provider = mock(PasspointProvider.class); 130 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 131 HomeSp homeSp = new HomeSp(); 132 homeSp.setFqdn(config.FQDN); 133 passpointConfig.setHomeSp(homeSp); 134 when(provider.getConfig()).thenReturn(passpointConfig); 135 when(provider.getWifiConfig()).thenReturn(config); 136 when(provider.isFromSuggestion()).thenReturn(false); 137 when(provider.isAutojoinEnabled()).thenReturn(true); 138 return provider; 139 } 140 141 /** 142 * Helper function for generating {@link ScanDetail} for testing. 143 * 144 * @param ssid The SSID associated with the scan 145 * @param bssid The BSSID associated with the scan 146 * @return {@link ScanDetail} 147 */ generateScanDetail(String ssid, String bssid)148 private ScanDetail generateScanDetail(String ssid, String bssid) { 149 NetworkDetail networkDetail = mock(NetworkDetail.class); 150 when(networkDetail.isInterworking()).thenReturn(true); 151 when(networkDetail.getHSRelease()).thenReturn(NetworkDetail.HSRelease.R1); 152 when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.FreePublic); 153 when(networkDetail.isInternet()).thenReturn(true); 154 155 ScanDetail scanDetail = mock(ScanDetail.class); 156 ScanResult scanResult = new ScanResult(); 157 scanResult.SSID = ssid; 158 scanResult.BSSID = bssid; 159 when(scanDetail.getSSID()).thenReturn(ssid); 160 when(scanDetail.getBSSIDString()).thenReturn(bssid); 161 when(scanDetail.getScanResult()).thenReturn(scanResult); 162 when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); 163 long currentTime = mClock.getWallClockMillis(); 164 when(scanDetail.getSeen()).thenReturn(currentTime); 165 when(scanDetail.toKeyString()).thenReturn(bssid); 166 return scanDetail; 167 } 168 advanceClockMs(long millis)169 private void advanceClockMs(long millis) { 170 long currentTimeMs = mClock.getWallClockMillis(); 171 when(mClock.getWallClockMillis()).thenReturn(currentTimeMs + millis); 172 } 173 174 /** 175 * Test setup. 176 */ 177 @Before setUp()178 public void setUp() throws Exception { 179 initMocks(this); 180 sTestProvider1 = generateProvider(TEST_CONFIG1); 181 sTestProvider2 = generateProvider(TEST_CONFIG2); 182 when(mResources.getStringArray( 183 R.array.config_wifiPasspointUseApWanLinkStatusAnqpElementFqdnAllowlist)) 184 .thenReturn(new String[0]); 185 186 mNominateHelper = new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager, 187 mLocalLog, mWifiCarrierInfoManager, mResources, mClock); 188 // Always assume Passpoint is enabled as we don't disable it in the test. 189 when(mPasspointManager.isWifiPasspointEnabled()).thenReturn(true); 190 when(mClock.getWallClockMillis()).thenReturn(TEST_START_TIME_MS); 191 } 192 193 /** 194 * Verify that no candidate will be nominated when evaluating scans without any matching 195 * providers. 196 */ 197 @Test evaluateScansWithNoMatch()198 public void evaluateScansWithNoMatch() { 199 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 200 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 201 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(null); 202 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 203 .getPasspointNetworkCandidates(scanDetails, false); 204 assertTrue(candidates.isEmpty()); 205 } 206 207 /** 208 * Verify that provider matching will not be performed when evaluating scans with no 209 * interworking support, verify that no candidate will be nominated. 210 * 211 * @throws Exception 212 */ 213 @Test evaluateScansWithNoInterworkingAP()214 public void evaluateScansWithNoInterworkingAP() throws Exception { 215 NetworkDetail networkDetail = mock(NetworkDetail.class); 216 when(networkDetail.isInterworking()).thenReturn(false); 217 ScanDetail scanDetail = mock(ScanDetail.class); 218 when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); 219 220 List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {scanDetail}); 221 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 222 .getPasspointNetworkCandidates(scanDetails, false); 223 assertTrue(candidates.isEmpty()); 224 // Verify that no provider matching is performed. 225 verify(mPasspointManager, never()).matchProvider(any(ScanResult.class)); 226 } 227 228 /** 229 * Verify that when a network matches a home provider is found, the correct network 230 * information (WifiConfiguration) is setup and nominated. 231 * 232 * @throws Exception 233 */ 234 @Test evaluateScansWithNetworkMatchingHomeProvider()235 public void evaluateScansWithNetworkMatchingHomeProvider() throws Exception { 236 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 237 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 238 when(mWifiCarrierInfoManager.shouldDisableMacRandomization(anyString(), anyInt(), anyInt())) 239 .thenReturn(true); 240 241 // Setup matching providers for ScanDetail with TEST_SSID1. 242 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 243 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 244 245 // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for 246 // for the second (TEST_SSID2); 247 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) 248 .thenReturn(null); 249 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 250 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 251 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 252 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 253 .getPasspointNetworkCandidates(scanDetails, false); 254 assertEquals(1, candidates.size()); 255 256 // Verify the content of the WifiConfiguration that was added to WifiConfigManager. 257 ArgumentCaptor<WifiConfiguration> addedConfig = 258 ArgumentCaptor.forClass(WifiConfiguration.class); 259 verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any(), 260 eq(false)); 261 assertEquals(ScanResultUtil.createQuotedSsid(TEST_SSID1), addedConfig.getValue().SSID); 262 assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); 263 assertNotNull(addedConfig.getValue().enterpriseConfig); 264 assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); 265 assertTrue(addedConfig.getValue().isHomeProviderNetwork); 266 assertEquals(RANDOMIZATION_NONE, addedConfig.getValue().macRandomizationSetting); 267 verify(mWifiConfigManager).enableNetwork( 268 eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); 269 verify(mWifiConfigManager).setNetworkCandidateScanResult( 270 eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); 271 verify(mWifiConfigManager).updateScanDetailForNetwork( 272 eq(TEST_NETWORK_ID), any(ScanDetail.class)); 273 274 // When Scan results time out, should be not candidate return. 275 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 276 candidates = mNominateHelper 277 .getPasspointNetworkCandidates(Collections.emptyList(), false); 278 assertTrue(candidates.isEmpty()); 279 } 280 281 /** 282 * Verify that when a network matches a home provider is found, the correct network 283 * information (WifiConfiguration) is setup and nominated even if the scan result does not 284 * report internet connectivity. 285 * 286 * @throws Exception 287 */ 288 @Test evaluateScansWithNoInternetBit()289 public void evaluateScansWithNoInternetBit() throws Exception { 290 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 291 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 292 for (ScanDetail scanDetail : scanDetails) { 293 when(scanDetail.getNetworkDetail().isInternet()).thenReturn(false); 294 } 295 296 // Setup matching providers for ScanDetail with TEST_SSID1. 297 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 298 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 299 300 // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for 301 // for the second (TEST_SSID2); 302 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) 303 .thenReturn(null); 304 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 305 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 306 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 307 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 308 .getPasspointNetworkCandidates(scanDetails, false); 309 assertEquals(1, candidates.size()); 310 311 // Verify the content of the WifiConfiguration that was added to WifiConfigManager. 312 ArgumentCaptor<WifiConfiguration> addedConfig = 313 ArgumentCaptor.forClass(WifiConfiguration.class); 314 verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any(), 315 eq(false)); 316 assertEquals(ScanResultUtil.createQuotedSsid(TEST_SSID1), addedConfig.getValue().SSID); 317 assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); 318 assertNotNull(addedConfig.getValue().enterpriseConfig); 319 assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); 320 assertTrue(addedConfig.getValue().isHomeProviderNetwork); 321 verify(mWifiConfigManager).enableNetwork( 322 eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); 323 verify(mWifiConfigManager).setNetworkCandidateScanResult( 324 eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); 325 verify(mWifiConfigManager).updateScanDetailForNetwork( 326 eq(TEST_NETWORK_ID), any(ScanDetail.class)); 327 } 328 329 /** 330 * Verify that when a network matches a roaming provider is found, the correct network 331 * information (WifiConfiguration) is setup and nominated. 332 */ 333 @Test evaluateScansWithNetworkMatchingRoamingProvider()334 public void evaluateScansWithNetworkMatchingRoamingProvider() { 335 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 336 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 337 338 // Setup matching providers for ScanDetail with TEST_SSID1. 339 List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); 340 roamingProvider.add(Pair.create(sTestProvider1, PasspointMatch.RoamingProvider)); 341 342 // Return roamingProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for 343 // for the second (TEST_SSID2); 344 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(roamingProvider) 345 .thenReturn(null); 346 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), any(), 347 eq(false))) 348 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 349 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 350 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 351 .getPasspointNetworkCandidates(scanDetails, false); 352 assertEquals(1, candidates.size()); 353 354 // Verify the content of the WifiConfiguration that was added to WifiConfigManager. 355 ArgumentCaptor<WifiConfiguration> addedConfig = 356 ArgumentCaptor.forClass(WifiConfiguration.class); 357 verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any(), 358 eq(false)); 359 assertEquals(ScanResultUtil.createQuotedSsid(TEST_SSID1), addedConfig.getValue().SSID); 360 assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); 361 assertNotNull(addedConfig.getValue().enterpriseConfig); 362 assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); 363 assertFalse(addedConfig.getValue().isHomeProviderNetwork); 364 verify(mWifiConfigManager).enableNetwork( 365 eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); 366 verify(mWifiConfigManager).setNetworkCandidateScanResult( 367 eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); 368 verify(mWifiConfigManager).updateScanDetailForNetwork( 369 eq(TEST_NETWORK_ID), any(ScanDetail.class)); 370 } 371 372 /** 373 * Verify that when a network matches a roaming provider is found for different scanDetails, 374 * will nominate both as the candidates. 375 * 376 * @throws Exception 377 */ 378 @Test evaluateScansWithHomeProviderNetworkAndRoamingProviderNetwork()379 public void evaluateScansWithHomeProviderNetworkAndRoamingProviderNetwork() throws Exception { 380 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 381 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 382 383 // Setup matching providers for ScanDetail with TEST_SSID1. 384 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 385 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 386 List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); 387 roamingProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); 388 389 // Return homeProvider for the first ScanDetail (TEST_SSID1) and 390 // roamingProvider for the second (TEST_SSID2); 391 when(mPasspointManager.matchProvider(any(ScanResult.class))) 392 .thenReturn(homeProvider).thenReturn(roamingProvider); 393 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 394 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 395 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + 1)); 396 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 397 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID + 1)) 398 .thenReturn(TEST_CONFIG2); 399 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 400 .getPasspointNetworkCandidates(scanDetails, false); 401 assertEquals(2, candidates.size()); 402 403 verify(mWifiConfigManager, times(2)) 404 .addOrUpdateNetwork(any(), anyInt(), any(), eq(false)); 405 } 406 407 /** 408 * Verify that anonymous identity is empty when matching a SIM credential provider with a 409 * network that supports encrypted IMSI and anonymous identity. The anonymous identity will be 410 * populated with {@code anonymous@<realm>} by ClientModeImpl's handling of the 411 * CMD_START_CONNECT event. 412 */ 413 @Test evaluateSIMProviderWithNetworkSupportingEncryptedIMSI()414 public void evaluateSIMProviderWithNetworkSupportingEncryptedIMSI() { 415 // Setup ScanDetail and match providers. 416 List<ScanDetail> scanDetails = Collections.singletonList( 417 generateScanDetail(TEST_SSID1, TEST_BSSID1)); 418 WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork( 419 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); 420 config.networkId = TEST_NETWORK_ID; 421 PasspointProvider testProvider = generateProvider(config); 422 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 423 homeProvider.add(Pair.create(testProvider, PasspointMatch.HomeProvider)); 424 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 425 when(testProvider.isSimCredential()).thenReturn(true); 426 // SIM is present 427 when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()) 428 .thenReturn(Arrays.asList(mock(SubscriptionInfo.class))); 429 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 430 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 431 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config); 432 433 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 434 .getPasspointNetworkCandidates(scanDetails, false); 435 assertEquals(1, candidates.size()); 436 437 assertEquals("", candidates.get(0).second.enterpriseConfig.getAnonymousIdentity()); 438 assertTrue(candidates.get(0).second.enterpriseConfig.isAuthenticationSimBased()); 439 } 440 441 /** 442 * Verify that when the current active network is matched, the scan info associated with 443 * the network is updated. 444 */ 445 @Test evaluateScansMatchingActiveNetworkWithDifferentBSS()446 public void evaluateScansMatchingActiveNetworkWithDifferentBSS() { 447 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID2)); 448 // Setup matching provider. 449 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 450 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 451 452 // Setup currently connected network. 453 WifiConfiguration currentNetwork = new WifiConfiguration(); 454 currentNetwork.networkId = TEST_NETWORK_ID; 455 currentNetwork.SSID = ScanResultUtil.createQuotedSsid(TEST_SSID1); 456 String currentBssid = TEST_BSSID1; 457 458 // Match the current connected network to a home provider. 459 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 460 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 461 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 462 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(currentNetwork); 463 464 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 465 .getPasspointNetworkCandidates(scanDetails, false); 466 467 assertEquals(1, candidates.size()); 468 469 // Verify network candidate information is updated. 470 ArgumentCaptor<ScanResult> updatedCandidateScanResult = 471 ArgumentCaptor.forClass(ScanResult.class); 472 verify(mWifiConfigManager).setNetworkCandidateScanResult(eq(TEST_NETWORK_ID), 473 updatedCandidateScanResult.capture(), anyInt(), any()); 474 assertEquals(TEST_BSSID2, updatedCandidateScanResult.getValue().BSSID); 475 ArgumentCaptor<ScanDetail> updatedCandidateScanDetail = 476 ArgumentCaptor.forClass(ScanDetail.class); 477 verify(mWifiConfigManager).updateScanDetailForNetwork(eq(TEST_NETWORK_ID), 478 updatedCandidateScanDetail.capture()); 479 assertEquals(TEST_BSSID2, updatedCandidateScanDetail.getValue().getBSSIDString()); 480 } 481 482 /** 483 * Verify that the current configuration for the passpoint network is disabled, it will not 484 * nominated that network. 485 */ 486 @Test evaluateNetworkWithDisabledWifiConfig()487 public void evaluateNetworkWithDisabledWifiConfig() { 488 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 489 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 490 491 WifiConfiguration disableConfig = new WifiConfiguration(); 492 WifiConfiguration.NetworkSelectionStatus selectionStatus = 493 new WifiConfiguration.NetworkSelectionStatus(); 494 selectionStatus.setNetworkSelectionDisableReason( 495 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 496 selectionStatus.setNetworkSelectionStatus( 497 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); 498 disableConfig.setNetworkSelectionStatus(selectionStatus); 499 disableConfig.networkId = TEST_NETWORK_ID; 500 TEST_CONFIG1.networkId = TEST_NETWORK_ID; 501 502 // Setup matching providers for ScanDetail with TEST_SSID1. 503 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 504 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 505 506 // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for 507 // for the second (TEST_SSID2); 508 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) 509 .thenReturn(null); 510 when(mWifiConfigManager.getConfiguredNetwork(anyString())).thenReturn(disableConfig); 511 512 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 513 .getPasspointNetworkCandidates(scanDetails, false); 514 verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(WifiConfiguration.class), 515 anyInt(), any(), eq(false)); 516 assertTrue(candidates.isEmpty()); 517 } 518 519 /** 520 * Verify that when a network matching a home provider is found, but the network was 521 * disconnected previously by user, it will not nominated that network. 522 */ 523 @Test evaluateScanResultWithHomeMatchButPreviouslyUserDisconnected()524 public void evaluateScanResultWithHomeMatchButPreviouslyUserDisconnected() { 525 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 526 527 // Setup matching providers for ScanDetail with TEST_SSID1. 528 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 529 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 530 531 // Return homeProvider for the first ScanDetail (TEST_SSID1). 532 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 533 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 534 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 535 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 536 when(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(TEST_FQDN1)) 537 .thenReturn(true); 538 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 539 .getPasspointNetworkCandidates(scanDetails, false); 540 assertTrue(candidates.isEmpty()); 541 } 542 543 /** 544 * Verify that when the WAN metrics status is 'LINK_STATUS_DOWN', it will not return as 545 * candidate when use wan link status. 546 */ 547 @Test evaluateScansWithNetworkMatchingHomeProviderUseAnqpLinkDown()548 public void evaluateScansWithNetworkMatchingHomeProviderUseAnqpLinkDown() throws Exception { 549 when(mResources.getBoolean(R.bool.config_wifiPasspointUseApWanLinkStatusAnqpElement)) 550 .thenReturn(true); 551 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 552 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 553 // Setup matching providers for ScanDetail with TEST_SSID1. 554 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 555 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 556 557 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 558 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 559 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 560 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + 1)); 561 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(TEST_CONFIG1); 562 // Setup WAN metrics status is 'LINK_STATUS_DOWN' 563 HSWanMetricsElement wm = mock(HSWanMetricsElement.class); 564 Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); 565 anqpElements.put(ANQPElementType.HSWANMetrics, wm); 566 when(mPasspointManager.getANQPElements(scanDetails.get(0).getScanResult())) 567 .thenReturn(anqpElements); 568 when(wm.getStatus()).thenReturn(HSWanMetricsElement.LINK_STATUS_DOWN); 569 when(wm.isElementInitialized()).thenReturn(true); 570 571 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 572 .getPasspointNetworkCandidates(scanDetails, false); 573 assertEquals(1, candidates.size()); 574 } 575 576 /** 577 * Verify that when the WAN metrics status is 'LINK_STATUS_DOWN', it will return as 578 * candidate when not use wan link status. 579 */ 580 581 @Test evaluateScansWithNetworkMatchingHomeProviderNotUseAnqpLinkDown()582 public void evaluateScansWithNetworkMatchingHomeProviderNotUseAnqpLinkDown() throws Exception { 583 when(mResources.getBoolean(R.bool.config_wifiPasspointUseApWanLinkStatusAnqpElement)) 584 .thenReturn(false); 585 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 586 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 587 // Setup matching providers for ScanDetail with TEST_SSID1. 588 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 589 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 590 591 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 592 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 593 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 594 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + 1)); 595 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(TEST_CONFIG1); 596 // Setup WAN metrics status is 'LINK_STATUS_DOWN' 597 HSWanMetricsElement wm = mock(HSWanMetricsElement.class); 598 Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); 599 anqpElements.put(ANQPElementType.HSWANMetrics, wm); 600 when(mPasspointManager.getANQPElements(scanDetails.get(0).getScanResult())) 601 .thenReturn(anqpElements); 602 when(wm.getStatus()).thenReturn(HSWanMetricsElement.LINK_STATUS_DOWN); 603 when(wm.isElementInitialized()).thenReturn(true); 604 605 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 606 .getPasspointNetworkCandidates(scanDetails, false); 607 assertEquals(2, candidates.size()); 608 } 609 610 /** 611 * Verify that when the WAN metrics status is 'LINK_STATUS_DOWN', it will not return as 612 * candidate when not use wan link status but FQDN in the allow list 613 */ 614 615 @Test evaluateScansWithNetworkMatchingHomeProviderNotUseAnqpLinkDownInFqdnList()616 public void evaluateScansWithNetworkMatchingHomeProviderNotUseAnqpLinkDownInFqdnList() 617 throws Exception { 618 when(mResources.getBoolean(R.bool.config_wifiPasspointUseApWanLinkStatusAnqpElement)) 619 .thenReturn(false); 620 when(mResources.getStringArray( 621 R.array.config_wifiPasspointUseApWanLinkStatusAnqpElementFqdnAllowlist)) 622 .thenReturn(new String[]{TEST_FQDN1}); 623 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 624 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 625 // Setup matching providers for ScanDetail with TEST_SSID1. 626 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 627 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 628 629 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 630 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 631 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 632 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID + 1)); 633 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(TEST_CONFIG1); 634 // Setup WAN metrics status is 'LINK_STATUS_DOWN' 635 HSWanMetricsElement wm = mock(HSWanMetricsElement.class); 636 Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); 637 anqpElements.put(ANQPElementType.HSWANMetrics, wm); 638 when(mPasspointManager.getANQPElements(scanDetails.get(0).getScanResult())) 639 .thenReturn(anqpElements); 640 when(wm.getStatus()).thenReturn(HSWanMetricsElement.LINK_STATUS_DOWN); 641 when(wm.isElementInitialized()).thenReturn(true); 642 643 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 644 .getPasspointNetworkCandidates(scanDetails, false); 645 assertEquals(1, candidates.size()); 646 } 647 648 /** 649 * Verify that when same provider is match home and roaming for different scanDetail, 650 * the home provider matched scanDetail will be chosen. 651 */ 652 653 @Test evaluateScansWithNetworkMatchingBothHomeAndRoamingForSameProvider()654 public void evaluateScansWithNetworkMatchingBothHomeAndRoamingForSameProvider() { 655 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 656 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 657 658 // Setup matching providers for ScanDetail. 659 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 660 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 661 List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); 662 roamingProvider.add(Pair.create(sTestProvider1, PasspointMatch.RoamingProvider)); 663 // Return homeProvider for the first ScanDetail (TEST_SSID1) and 664 // roamingProvider for the second (TEST_SSID2); 665 when(mPasspointManager.matchProvider(any(ScanResult.class))) 666 .thenReturn(roamingProvider).thenReturn(homeProvider); 667 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 668 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 669 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 670 671 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 672 .getPasspointNetworkCandidates(scanDetails, false); 673 // verify Only home provider matched candidate will by chosen 674 assertEquals(1, candidates.size()); 675 assertTrue(candidates.get(0).second.isHomeProviderNetwork); 676 assertEquals(ScanResultUtil.createQuotedSsid(TEST_SSID2), candidates.get(0).second.SSID); 677 } 678 679 /** 680 * For multiple scanDetails with matched providers, for each scanDetail nominate the best 681 * providers: if home available, return all home providers; otherwise return all roaming 682 * providers. 683 * ScanDetail1 matches home providerA, scanDetail2 matches roaming providerB, will nominate both 684 * matched pairs. 685 */ 686 @Test evaluateScansWithNetworkMatchingBothHomeAndRoamingForDifferentProvider()687 public void evaluateScansWithNetworkMatchingBothHomeAndRoamingForDifferentProvider() { 688 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1), 689 generateScanDetail(TEST_SSID2, TEST_BSSID2)); 690 // Setup matching providers for ScanDetail. 691 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 692 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 693 List<Pair<PasspointProvider, PasspointMatch>> roamingProvider = new ArrayList<>(); 694 roamingProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); 695 // Return homeProvider for the first ScanDetail (TEST_SSID1) and 696 // roamingProvider for the second (TEST_SSID2); 697 when(mPasspointManager.matchProvider(any(ScanResult.class))) 698 .thenReturn(homeProvider).thenReturn(roamingProvider); 699 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 700 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 701 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); 702 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 703 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)).thenReturn(TEST_CONFIG2); 704 705 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 706 .getPasspointNetworkCandidates(scanDetails, false); 707 // Nominate matched home provider for first ScanDetail (TEST_SSID1) and roaming provider for 708 // the second (TEST_SSID2). 709 assertEquals(2, candidates.size()); 710 assertTrue(candidates.stream().anyMatch(c -> c.second.isHomeProviderNetwork 711 && c.second.SSID.equals(ScanResultUtil.createQuotedSsid(TEST_SSID1)))); 712 assertTrue(candidates.stream().anyMatch(c -> !c.second.isHomeProviderNetwork 713 && c.second.SSID.equals(ScanResultUtil.createQuotedSsid(TEST_SSID2)))); 714 } 715 716 /** 717 * For multiple matched providers from suggestion and user saved, return right ones according to 718 * the request. 719 */ 720 @Test evaluateScansWithNetworkMatchingProviderBothFromSavedAndSuggestion()721 public void evaluateScansWithNetworkMatchingProviderBothFromSavedAndSuggestion() { 722 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 723 // Setup matching providers for ScanDetail. One provider is saved, the other is suggestion. 724 WifiConfiguration suggestionConfig = generateWifiConfig(TEST_FQDN2); 725 suggestionConfig.creatorUid = TEST_UID; 726 suggestionConfig.creatorName = TEST_PACKAGE; 727 suggestionConfig.fromWifiNetworkSuggestion = true; 728 PasspointProvider suggestionProvider = generateProvider(suggestionConfig); 729 when(suggestionProvider.isFromSuggestion()).thenReturn(true); 730 731 List<Pair<PasspointProvider, PasspointMatch>> homeProviders = new ArrayList<>(); 732 homeProviders.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 733 homeProviders.add(Pair.create(suggestionProvider, PasspointMatch.HomeProvider)); 734 when(mPasspointManager.matchProvider(any(ScanResult.class))) 735 .thenReturn(homeProviders); 736 when(mWifiConfigManager.addOrUpdateNetwork(eq(TEST_CONFIG1), anyInt(), 737 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 738 when(mWifiConfigManager.addOrUpdateNetwork(eq(suggestionConfig), anyInt(), 739 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); 740 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 741 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)) 742 .thenReturn(suggestionConfig); 743 //Get saved passpoint network candidate 744 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 745 .getPasspointNetworkCandidates(scanDetails, false); 746 assertEquals(1, candidates.size()); 747 assertEquals(TEST_FQDN1, candidates.get(0).second.FQDN); 748 //Get suggestion passpoint network candidate 749 candidates = mNominateHelper 750 .getPasspointNetworkCandidates(scanDetails, true); 751 assertEquals(1, candidates.size()); 752 assertEquals(TEST_FQDN2, candidates.get(0).second.FQDN); 753 } 754 755 /** 756 * Verify that provider matching will not be performed when evaluating scans with interworking 757 * support, but no HS2.0 VSA element with release version, verify that no candidate will be 758 * nominated. 759 * 760 * @throws Exception 761 */ 762 @Test evaluateScansWithInterworkingAndNoHs20VsaAP()763 public void evaluateScansWithInterworkingAndNoHs20VsaAP() throws Exception { 764 NetworkDetail networkDetail = mock(NetworkDetail.class); 765 when(networkDetail.isInterworking()).thenReturn(true); 766 when(networkDetail.getHSRelease()).thenReturn(null); 767 when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.FreePublic); 768 when(networkDetail.isInternet()).thenReturn(true); 769 ScanDetail scanDetail = mock(ScanDetail.class); 770 when(scanDetail.getNetworkDetail()).thenReturn(networkDetail); 771 772 List<ScanDetail> scanDetails = Arrays.asList(new ScanDetail[] {scanDetail}); 773 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 774 .getPasspointNetworkCandidates(scanDetails, false); 775 assertTrue(candidates.isEmpty()); 776 // Verify that no provider matching is performed. 777 verify(mPasspointManager, never()).matchProvider(any(ScanResult.class)); 778 } 779 780 /** 781 * Verify matching passpoint provider with ChargeablePublic AP will nominate a metered 782 * candidate. 783 */ 784 @Test evaluateScansWithAntIsChargeablePublic()785 public void evaluateScansWithAntIsChargeablePublic() { 786 ScanDetail scanDetail = generateScanDetail(TEST_SSID1, TEST_BSSID1); 787 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 788 when(networkDetail.getAnt()).thenReturn(NetworkDetail.Ant.ChargeablePublic); 789 List<ScanDetail> scanDetails = Arrays.asList(scanDetail); 790 791 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 792 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 793 794 // Return homeProvider for the first ScanDetail (TEST_SSID1) and a null (no match) for 795 // for the second (TEST_SSID2); 796 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider) 797 .thenReturn(null); 798 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 799 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 800 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 801 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 802 .getPasspointNetworkCandidates(scanDetails, false); 803 assertEquals(1, candidates.size()); 804 assertTrue(WifiConfiguration.isMetered(candidates.get(0).second, null)); 805 } 806 807 /** 808 * Verify that when the WAN Metrics ANQP element is not initialized (all 0's), then the logic 809 * ignores this element. 810 */ 811 @Test evaluateScansWithNetworkMatchingHomeProviderWithUninitializedWanMetricsAnqpElement()812 public void evaluateScansWithNetworkMatchingHomeProviderWithUninitializedWanMetricsAnqpElement() 813 throws Exception { 814 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 815 // Setup matching providers for ScanDetail with TEST_SSID1. 816 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 817 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 818 819 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 820 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 821 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 822 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 823 824 // Setup an uninitialized WAN Metrics element (or initialized with 0's) 825 ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE); 826 buffer.put(new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE]); 827 buffer.position(0); 828 HSWanMetricsElement wanMetricsElement = HSWanMetricsElement.parse(buffer); 829 Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); 830 anqpElements.put(ANQPElementType.HSWANMetrics, wanMetricsElement); 831 when(mPasspointManager.getANQPElements(any(ScanResult.class))) 832 .thenReturn(anqpElements); 833 834 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 835 .getPasspointNetworkCandidates(scanDetails, false); 836 assertEquals(1, candidates.size()); 837 } 838 839 @Test testRefreshPasspointNetworkCandidatesUsesCachedScans()840 public void testRefreshPasspointNetworkCandidatesUsesCachedScans() { 841 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 842 843 // Setup matching providers for ScanDetail with TEST_SSID1. 844 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 845 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 846 847 // No profiles have been added, so expect the first candidate matching to return nothing. 848 assertEquals(mNominateHelper.getPasspointNetworkCandidates( 849 scanDetails, false).size(), 0); 850 verify(mPasspointManager, times(1)).matchProvider(any()); 851 852 // Add a homeProvider for the scan detail passed in earlier 853 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 854 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 855 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 856 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 857 858 // Refreshing the network candidates with the cached scans should now result in a match 859 mNominateHelper.refreshWifiConfigsForProviders(); 860 verify(mPasspointManager, times(2)).matchProvider(any()); 861 // Verify the content of the WifiConfiguration that was added to WifiConfigManager. 862 ArgumentCaptor<WifiConfiguration> addedConfig = 863 ArgumentCaptor.forClass(WifiConfiguration.class); 864 verify(mWifiConfigManager).addOrUpdateNetwork(addedConfig.capture(), anyInt(), any(), 865 eq(false)); 866 assertEquals(ScanResultUtil.createQuotedSsid(TEST_SSID1), addedConfig.getValue().SSID); 867 assertEquals(TEST_FQDN1, addedConfig.getValue().FQDN); 868 assertNotNull(addedConfig.getValue().enterpriseConfig); 869 assertEquals("", addedConfig.getValue().enterpriseConfig.getAnonymousIdentity()); 870 assertTrue(addedConfig.getValue().isHomeProviderNetwork); 871 verify(mWifiConfigManager).enableNetwork( 872 eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); 873 verify(mWifiConfigManager).setNetworkCandidateScanResult( 874 eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); 875 verify(mWifiConfigManager).updateScanDetailForNetwork( 876 eq(TEST_NETWORK_ID), any(ScanDetail.class)); 877 878 // Timeout the scan detail and verify we don't try to match the scan detail again. 879 advanceClockMs(PasspointNetworkNominateHelper.SCAN_DETAIL_EXPIRATION_MS); 880 mNominateHelper.refreshWifiConfigsForProviders(); 881 verify(mPasspointManager, times(2)).matchProvider(any()); 882 verify(mWifiConfigManager, times(1)).addOrUpdateNetwork(any(), anyInt(), 883 any(), eq(false)); 884 } 885 886 /** 887 * Verify that when the WAN metrics status is 'LINK_STATUS_DOWN', it should be added to the 888 * WifiConfigManager and NOT set No Internet. 889 */ 890 @Test updateScansWithNetworkMatchingHomeProviderWithAnqpLinkDown()891 public void updateScansWithNetworkMatchingHomeProviderWithAnqpLinkDown() { 892 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 893 // Setup matching providers for ScanDetail with TEST_SSID1. 894 List<Pair<PasspointProvider, PasspointMatch>> homeProvider = new ArrayList<>(); 895 homeProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 896 897 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(homeProvider); 898 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 899 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); 900 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(TEST_CONFIG1); 901 // Setup WAN metrics status is 'LINK_STATUS_DOWN' 902 HSWanMetricsElement wm = mock(HSWanMetricsElement.class); 903 Map<ANQPElementType, ANQPElement> anqpElements = new HashMap<>(); 904 anqpElements.put(ANQPElementType.HSWANMetrics, wm); 905 when(mPasspointManager.getANQPElements(any(ScanResult.class))) 906 .thenReturn(anqpElements); 907 when(wm.getStatus()).thenReturn(HSWanMetricsElement.LINK_STATUS_DOWN); 908 when(wm.isElementInitialized()).thenReturn(true); 909 910 mNominateHelper.updatePasspointConfig(scanDetails); 911 verify(mWifiConfigManager, never()) 912 .incrementNetworkNoInternetAccessReports(eq(TEST_NETWORK_ID)); 913 verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(eq(TEST_NETWORK_ID), 914 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT)); 915 } 916 917 /** 918 * Verify that both home and roaming providers for same scan detail will be added to 919 * WifiConfigManager. 920 */ 921 @Test updateScansWithBothHomeProviderAndRoamingProvider()922 public void updateScansWithBothHomeProviderAndRoamingProvider() { 923 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 924 // Setup matching providers for ScanDetail with TEST_SSID1. 925 List<Pair<PasspointProvider, PasspointMatch>> matchedProvider = new ArrayList<>(); 926 matchedProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 927 matchedProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); 928 929 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(matchedProvider); 930 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 931 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 932 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); 933 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 934 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)).thenReturn(TEST_CONFIG2); 935 mNominateHelper.updatePasspointConfig(scanDetails); 936 verify(mWifiConfigManager, times(2)) 937 .addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), any(), eq(false)); 938 verify(mWifiConfigManager) 939 .enableNetwork(eq(TEST_NETWORK_ID), eq(false), anyInt(), any()); 940 verify(mWifiConfigManager) 941 .enableNetwork(eq(TEST_NETWORK_ID2), eq(false), anyInt(), any()); 942 verify(mWifiConfigManager) 943 .setNetworkCandidateScanResult(eq(TEST_NETWORK_ID), any(), anyInt(), any()); 944 verify(mWifiConfigManager) 945 .setNetworkCandidateScanResult(eq(TEST_NETWORK_ID2), any(), anyInt(), any()); 946 verify(mWifiConfigManager) 947 .updateScanDetailForNetwork(eq(TEST_NETWORK_ID), eq(scanDetails.get(0))); 948 verify(mWifiConfigManager) 949 .updateScanDetailForNetwork(eq(TEST_NETWORK_ID2), eq(scanDetails.get(0))); 950 } 951 952 /** 953 * Verify when ScanDetails matches both home and roaming providers, only home provider will be 954 * return as candidate. 955 */ 956 @Test evaluateScansWithBothHomeProviderAndRoamingProvider()957 public void evaluateScansWithBothHomeProviderAndRoamingProvider() { 958 List<ScanDetail> scanDetails = Arrays.asList(generateScanDetail(TEST_SSID1, TEST_BSSID1)); 959 // Setup matching providers for ScanDetail with TEST_SSID1. 960 List<Pair<PasspointProvider, PasspointMatch>> matchedProvider = new ArrayList<>(); 961 matchedProvider.add(Pair.create(sTestProvider1, PasspointMatch.HomeProvider)); 962 matchedProvider.add(Pair.create(sTestProvider2, PasspointMatch.RoamingProvider)); 963 964 when(mPasspointManager.matchProvider(any(ScanResult.class))).thenReturn(matchedProvider); 965 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 966 any(), eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)) 967 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID2)); 968 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(TEST_CONFIG1); 969 when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID2)).thenReturn(TEST_CONFIG2); 970 List<Pair<ScanDetail, WifiConfiguration>> candidates = mNominateHelper 971 .getPasspointNetworkCandidates(scanDetails, false); 972 assertEquals(1, candidates.size()); 973 verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt(), 974 any(), eq(false)); 975 assertTrue(candidates.get(0).second.isHomeProviderNetwork); 976 } 977 } 978