• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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