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 org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assume.assumeTrue;
23 import static org.mockito.Mockito.eq;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.when;
26 import static org.mockito.MockitoAnnotations.initMocks;
27 
28 import android.net.wifi.EAPConstants;
29 import android.net.wifi.ScanResult;
30 import android.net.wifi.WifiConfiguration;
31 import android.net.wifi.WifiEnterpriseConfig;
32 import android.net.wifi.WifiSsid;
33 import android.net.wifi.hotspot2.PasspointConfiguration;
34 import android.net.wifi.hotspot2.pps.Credential;
35 import android.net.wifi.hotspot2.pps.HomeSp;
36 import android.net.wifi.hotspot2.pps.UpdateParameter;
37 import android.text.TextUtils;
38 import android.util.Base64;
39 import android.util.Pair;
40 
41 import androidx.test.filters.SmallTest;
42 
43 import com.android.modules.utils.build.SdkLevel;
44 import com.android.server.wifi.Clock;
45 import com.android.server.wifi.FakeKeys;
46 import com.android.server.wifi.MboOceConstants;
47 import com.android.server.wifi.WifiBaseTest;
48 import com.android.server.wifi.WifiCarrierInfoManager;
49 import com.android.server.wifi.WifiKeyStore;
50 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
51 import com.android.server.wifi.hotspot2.anqp.CellularNetwork;
52 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
53 import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
54 import com.android.server.wifi.hotspot2.anqp.NAIRealmData;
55 import com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
56 import com.android.server.wifi.hotspot2.anqp.RoamingConsortiumElement;
57 import com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement;
58 import com.android.server.wifi.hotspot2.anqp.eap.AuthParam;
59 import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
60 import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth;
61 import com.android.server.wifi.util.ArrayUtils;
62 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
63 
64 import org.junit.Before;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.junit.runners.Parameterized;
68 import org.mockito.Mock;
69 
70 import java.nio.charset.StandardCharsets;
71 import java.security.MessageDigest;
72 import java.security.cert.Certificate;
73 import java.security.cert.X509Certificate;
74 import java.util.Arrays;
75 import java.util.BitSet;
76 import java.util.Collection;
77 import java.util.Collections;
78 import java.util.HashMap;
79 import java.util.HashSet;
80 import java.util.List;
81 import java.util.Map;
82 import java.util.Set;
83 
84 /**
85  * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointProvider}.
86  */
87 @SmallTest
88 @RunWith(Parameterized.class)
89 public class PasspointProviderTest extends WifiBaseTest {
90     private static final long PROVIDER_ID = 12L;
91     private static final int CREATOR_UID = 1234;
92     private static final String CREATOR_PACKAGE = "com.android.test";
93     private static final String CA_CERTIFICATE_ALIAS = "HS2_12_0";
94     private static final String CA_CERTIFICATE_ALIAS_2 = "HS2_12_1";
95     private static final String CLIENT_CERTIFICATE_ALIAS = "HS2_12";
96     private static final String CLIENT_PRIVATE_KEY_AND_CERT_ALIAS = "HS2_12";
97     private static final String REMEDIATION_CA_CERTIFICATE_ALIAS = "HS2_REMEDIATION_12";
98     private static final String SYSTEM_CA_STORE_PATH = "/system/etc/security/cacerts";
99 
100     private static final int TEST_UPDATE_IDENTIFIER = 1234;
101     private static final int TEST_USAGE_LIMIT_DATA_LIMIT = 100;
102     private static final String TEST_FQDN = "test.com";
103     private static final String TEST_FQDN2 = "test2.com";
104     private static final String TEST_FQDN3 = "test3.com";
105     private static final String TEST_FRIENDLY_NAME = "Friendly Name";
106     private static final long[] TEST_RC_OIS = new long[]{0x1234L, 0x2345L};
107     private static final long[] TEST_IE_RC_OIS = new long[]{0x1234L, 0x2133L};
108     private static final long[] TEST_IE_NO_MATCHED_RC_OIS = new long[]{0x2255L, 0x2133L};
109     private static final Long[] TEST_ANQP_RC_OIS = new Long[]{0x1234L, 0x2133L};
110     private static final Long[] TEST_ANQP_RC_OIS_2 = new Long[]{0x4321L, 0x3321L};
111     private static final String TEST_REALM = "realm.com";
112     private static final String[] TEST_TRUSTED_NAME =
113             new String[]{"trusted.fqdn.com", "another.fqdn.com"};
114     // User credential data
115     private static final String TEST_USERNAME = "username";
116     private static final String TEST_PASSWORD = "password3";
117     // SIM credential data
118     private static final int TEST_EAP_TYPE = WifiEnterpriseConfig.Eap.SIM;
119     private static final int TEST_SIM_CREDENTIAL_TYPE = EAPConstants.EAP_SIM;
120     private static final String TEST_IMSI = "1234567890";
121     private static final int VALID_CARRIER_ID = 1;
122     private static final int VALID_SUBSCRIPTION_ID = 2;
123 
124     private static final String TEST_SSID = "TestSSID";
125     private static final String TEST_SSID_QUOTED = "\"TestSSID\"";
126     private static final String TEST_SSID_2 = "TestSSID2";
127     private static final String TEST_SSID_2_QUOTED = "\"TestSSID2\"";
128     private static final String TEST_BSSID_STRING = "11:22:33:44:55:66";
129     private static final String TEST_BSSID_STRING_2 = "11:22:33:44:55:67";
130     private static final long TEST_HESSID = 0x5678L;
131     private static final int TEST_ANQP_DOMAIN_ID = 0;
132     private static final long TEST_HESSID_2 = 0xaa0aL;
133     private static final int TEST_ANQP_DOMAIN_ID_2 = 1;
134     private static final long TEST_ELAPSED_TIME_SINCE_BOOT = 100000L;
135     private static final String TEST_ANONYMOUS_IDENTITY = "AnonymousIdentity";
136     private static final String USER_CONNECT_CHOICE = "SomeNetworkProfileId";
137     private static final int TEST_RSSI = -50;
138     private static final String TEST_DECORATED_IDENTITY_PREFIX = "androidwifi.dev!";
139 
140     private enum CredentialType {
141         USER,
142         CERT,
143         SIM
144     }
145 
146     @Mock
147     WifiKeyStore mKeyStore;
148     @Mock
149     WifiCarrierInfoManager mWifiCarrierInfoManager;
150     @Mock
151     RoamingConsortium mRoamingConsortium;
152     @Mock
153     Clock mClock;
154     PasspointProvider mProvider;
155     X509Certificate mRemediationCaCertificate;
156     String mExpectedResult;
157 
158     @Parameterized.Parameters
rootCAConfigsForRemediation()159     public static Collection rootCAConfigsForRemediation() {
160         return Arrays.asList(
161                 new Object[][]{
162                         {FakeKeys.CA_CERT0, REMEDIATION_CA_CERTIFICATE_ALIAS}, // For R2 config
163                         {null, null}, // For R1 config
164                 });
165     }
166 
PasspointProviderTest(X509Certificate remediationCaCertificate, String expectedResult)167     public PasspointProviderTest(X509Certificate remediationCaCertificate, String expectedResult) {
168         mRemediationCaCertificate = remediationCaCertificate;
169         mExpectedResult = expectedResult;
170     }
171 
172     /**
173      * Sets up test.
174      */
175     @Before
setUp()176     public void setUp() throws Exception {
177         initMocks(this);
178         when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(null);
179     }
180 
181     /**
182      * Helper function for creating a provider instance for testing.
183      *
184      * @param config The configuration associated with the provider
185      * @return {@link com.android.server.wifi.hotspot2.PasspointProvider}
186      */
createProvider(PasspointConfiguration config)187     private PasspointProvider createProvider(PasspointConfiguration config) {
188         return new PasspointProvider(config, mKeyStore, mWifiCarrierInfoManager, PROVIDER_ID,
189                 CREATOR_UID, CREATOR_PACKAGE, false, mClock);
190     }
191 
192     /**
193      * Verify that the configuration associated with the provider is the same or not the same as the
194      * expected configuration.
195      *
196      * @param expectedConfig The expected configuration
197      * @param equals         Flag indicating equality or inequality check
198      */
verifyInstalledConfig(PasspointConfiguration expectedConfig, boolean equals)199     private void verifyInstalledConfig(PasspointConfiguration expectedConfig, boolean equals) {
200         PasspointConfiguration actualConfig = mProvider.getConfig();
201         if (equals) {
202             assertTrue(actualConfig.equals(expectedConfig));
203         } else {
204             assertFalse(actualConfig.equals(expectedConfig));
205         }
206     }
207 
208     /**
209      * Helper function for creating a Domain Name ANQP element.
210      *
211      * @param domains List of domain names
212      * @return {@link DomainNameElement}
213      */
createDomainNameElement(String[] domains)214     private DomainNameElement createDomainNameElement(String[] domains) {
215         return new DomainNameElement(Arrays.asList(domains));
216     }
217 
218     /**
219      * Helper function for creating a NAI Realm ANQP element.
220      *
221      * @param realm       The realm of the network
222      * @param eapMethodID EAP Method ID
223      * @param authParam   Authentication parameter
224      * @return {@link NAIRealmElement}
225      */
createNAIRealmElement(String realm, int eapMethodID, AuthParam authParam)226     private NAIRealmElement createNAIRealmElement(String realm, int eapMethodID,
227             AuthParam authParam) {
228         Map<Integer, Set<AuthParam>> authParamMap = new HashMap<>();
229         if (authParam != null) {
230             Set<AuthParam> authSet = new HashSet<>();
231             authSet.add(authParam);
232             authParamMap.put(authParam.getAuthTypeID(), authSet);
233         }
234         EAPMethod eapMethod = new EAPMethod(eapMethodID, authParamMap);
235         NAIRealmData realmData = new NAIRealmData(Arrays.asList(new String[]{realm}),
236                 Arrays.asList(new EAPMethod[]{eapMethod}));
237         return new NAIRealmElement(Arrays.asList(new NAIRealmData[]{realmData}));
238     }
239 
240     /**
241      * Helper function for creating a Roaming Consortium ANQP element.
242      *
243      * @param rcOIs Roaming consortium OIs
244      * @return {@link RoamingConsortiumElement}
245      */
createRoamingConsortiumElement(Long[] rcOIs)246     private RoamingConsortiumElement createRoamingConsortiumElement(Long[] rcOIs) {
247         return new RoamingConsortiumElement(Arrays.asList(rcOIs));
248     }
249 
250     /**
251      * Helper function for creating a 3GPP Network ANQP element.
252      *
253      * @param imsiList List of IMSI to be included in a 3GPP Network
254      * @return {@link ThreeGPPNetworkElement}
255      */
createThreeGPPNetworkElement(String[] imsiList)256     private ThreeGPPNetworkElement createThreeGPPNetworkElement(String[] imsiList) {
257         CellularNetwork network = new CellularNetwork(Arrays.asList(imsiList));
258         return new ThreeGPPNetworkElement(Arrays.asList(new CellularNetwork[]{network}));
259     }
260 
261     /**
262      * Helper function for generating test passpoint configuration for test cases
263      *
264      * @param credentialType which type credential is generated.
265      * @param isLegacy       if true, omit some passpoint fields to avoid breaking comparison
266      *                       between passpoint configuration converted from wifi configuration and
267      *                       generated passpoint configuration.
268      * @return a valid passpoint configuration
269      * @throws Exception
270      */
generateTestPasspointConfiguration( CredentialType credentialType, boolean isLegacy)271     private PasspointConfiguration generateTestPasspointConfiguration(
272             CredentialType credentialType, boolean isLegacy) throws Exception {
273         PasspointConfiguration config = new PasspointConfiguration();
274         if (!isLegacy) {
275             config.setUpdateIdentifier(TEST_UPDATE_IDENTIFIER);
276             config.setUsageLimitDataLimit(TEST_USAGE_LIMIT_DATA_LIMIT);
277         }
278         HomeSp homeSp = new HomeSp();
279         homeSp.setFqdn(TEST_FQDN);
280         homeSp.setFriendlyName(TEST_FRIENDLY_NAME);
281         homeSp.setRoamingConsortiumOis(TEST_RC_OIS);
282         config.setHomeSp(homeSp);
283         Credential credential = new Credential();
284         credential.setRealm(TEST_REALM);
285 
286         if (credentialType == CredentialType.USER) {
287             byte[] base64EncodedPw =
288                     Base64.encode(TEST_PASSWORD.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
289             String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
290             Credential.UserCredential userCredential = new Credential.UserCredential();
291             userCredential.setEapType(EAPConstants.EAP_TTLS);
292             userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAPV2);
293             userCredential.setUsername(TEST_USERNAME);
294             userCredential.setPassword(encodedPasswordStr);
295             if (!isLegacy) {
296                 credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0});
297             }
298             credential.setUserCredential(userCredential);
299         } else if (credentialType == CredentialType.CERT) {
300             Credential.CertificateCredential certCredential =
301                     new Credential.CertificateCredential();
302             if (!isLegacy) {
303                 certCredential.setCertSha256Fingerprint(
304                         MessageDigest.getInstance("SHA-256")
305                                 .digest(FakeKeys.CLIENT_CERT.getEncoded()));
306                 credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0});
307                 credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
308                 credential.setClientCertificateChain(new X509Certificate[]{FakeKeys.CLIENT_CERT});
309             } else {
310                 certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3);
311             }
312             credential.setCertCredential(certCredential);
313         } else if (credentialType == CredentialType.SIM) {
314             Credential.SimCredential simCredential = new Credential.SimCredential();
315             simCredential.setImsi(TEST_IMSI);
316             simCredential.setEapType(EAPConstants.EAP_SIM);
317             credential.setSimCredential(simCredential);
318         }
319         config.setCredential(credential);
320 
321         return config;
322     }
323 
324     /**
325      * Helper function for verifying wifi configuration based on Passpoint configuration
326      *
327      * @param passpointConfig the source of wifi configuration.
328      * @param wifiConfig      wifi configuration be verified.
329      * @throws Exception
330      */
verifyWifiConfigWithTestData( PasspointConfiguration passpointConfig, WifiConfiguration wifiConfig)331     private void verifyWifiConfigWithTestData(
332             PasspointConfiguration passpointConfig, WifiConfiguration wifiConfig) {
333         BitSet allowedProtocols = new BitSet();
334         allowedProtocols.set(WifiConfiguration.Protocol.RSN);
335 
336         HomeSp homeSp = passpointConfig.getHomeSp();
337         Credential credential = passpointConfig.getCredential();
338 
339         // Need to verify field by field since WifiConfiguration doesn't
340         // override equals() function.
341         WifiEnterpriseConfig wifiEnterpriseConfig = wifiConfig.enterpriseConfig;
342         assertEquals(homeSp.getFqdn(), wifiConfig.FQDN);
343         assertEquals(homeSp.getFriendlyName(), wifiConfig.providerFriendlyName);
344         assertTrue(Arrays.equals(homeSp.getRoamingConsortiumOis(),
345                 wifiConfig.roamingConsortiumIds));
346 
347         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
348         assertTrue(wifiConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
349         assertEquals(wifiConfig.updateIdentifier,
350                 Integer.toString(passpointConfig.getUpdateIdentifier()));
351         assertEquals(allowedProtocols, wifiConfig.allowedProtocols);
352         assertEquals(Integer.toString(passpointConfig.getUpdateIdentifier()),
353                 wifiConfig.updateIdentifier);
354         assertFalse(wifiConfig.shared);
355         assertEquals(credential.getRealm(), wifiEnterpriseConfig.getRealm());
356         if (passpointConfig.isMacRandomizationEnabled()) {
357             if (passpointConfig.isNonPersistentMacRandomizationEnabled()) {
358                 assertEquals(WifiConfiguration.RANDOMIZATION_NON_PERSISTENT,
359                         wifiConfig.macRandomizationSetting);
360             } else {
361                 assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT,
362                         wifiConfig.macRandomizationSetting);
363             }
364         } else {
365             assertEquals(WifiConfiguration.RANDOMIZATION_NONE, wifiConfig.macRandomizationSetting);
366         }
367 
368         if (credential.getUserCredential() != null) {
369             String decodedPassword;
370             Credential.UserCredential userCredential = credential.getUserCredential();
371             try {
372                 byte[] pwOctets = Base64.decode(userCredential.getPassword(), Base64.DEFAULT);
373                 decodedPassword = new String(pwOctets, StandardCharsets.UTF_8);
374             } catch (IllegalArgumentException e) {
375                 decodedPassword = userCredential.getPassword();
376             }
377 
378             assertEquals("anonymous@" + credential.getRealm(),
379                     wifiEnterpriseConfig.getAnonymousIdentity());
380             assertEquals(WifiEnterpriseConfig.Eap.TTLS, wifiEnterpriseConfig.getEapMethod());
381             switch (userCredential.getNonEapInnerMethod()) {
382                 case Credential.UserCredential.AUTH_METHOD_PAP:
383                     assertEquals(WifiEnterpriseConfig.Phase2.PAP,
384                             wifiEnterpriseConfig.getPhase2Method());
385                     break;
386                 case Credential.UserCredential.AUTH_METHOD_MSCHAP:
387                     assertEquals(WifiEnterpriseConfig.Phase2.MSCHAP,
388                             wifiEnterpriseConfig.getPhase2Method());
389                     break;
390                 case Credential.UserCredential.AUTH_METHOD_MSCHAPV2:
391                     assertEquals(WifiEnterpriseConfig.Phase2.MSCHAPV2,
392                             wifiEnterpriseConfig.getPhase2Method());
393                     break;
394             }
395             assertEquals(userCredential.getUsername(), wifiEnterpriseConfig.getIdentity());
396             assertEquals(decodedPassword, wifiEnterpriseConfig.getPassword());
397             assertEquals(decodedPassword, TEST_PASSWORD);
398             assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
399                     wifiConfig.meteredOverride);
400 
401             if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) {
402                 assertEquals(String.join(";", passpointConfig.getAaaServerTrustedNames()),
403                         wifiEnterpriseConfig.getDomainSuffixMatch());
404             } else {
405                 assertEquals(homeSp.getFqdn(), wifiEnterpriseConfig.getDomainSuffixMatch());
406             }
407 
408             if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) {
409                 assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath());
410             } else if (ArrayUtils.isEmpty(credential.getCaCertificates())) {
411                 assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath());
412             } else {
413                 assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias());
414             }
415             if (passpointConfig.getCredential().getCheckAaaServerCertStatus()) {
416                 assertEquals(wifiEnterpriseConfig.getOcsp(),
417                         WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS);
418             } else {
419                 assertEquals(wifiEnterpriseConfig.getOcsp(),
420                         WifiEnterpriseConfig.OCSP_NONE);
421             }
422         } else if (credential.getCertCredential() != null) {
423             Credential.CertificateCredential certCredential = credential.getCertCredential();
424             assertEquals("anonymous@" + credential.getRealm(),
425                     wifiEnterpriseConfig.getAnonymousIdentity());
426             assertEquals(WifiEnterpriseConfig.Eap.TLS, wifiEnterpriseConfig.getEapMethod());
427             assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE, wifiConfig.meteredOverride);
428             // Domain suffix match
429             if (ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) {
430                 assertEquals(homeSp.getFqdn(), wifiEnterpriseConfig.getDomainSuffixMatch());
431             } else {
432                 assertEquals(String.join(";", passpointConfig.getAaaServerTrustedNames()),
433                         wifiEnterpriseConfig.getDomainSuffixMatch());
434                 assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath());
435             }
436             // CA certificate
437             if (!ArrayUtils.isEmpty(passpointConfig.getAaaServerTrustedNames())) {
438                 assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath());
439             } else if (!ArrayUtils.isEmpty(credential.getCaCertificates())) {
440                 assertEquals(CA_CERTIFICATE_ALIAS, wifiEnterpriseConfig.getCaCertificateAlias());
441             } else {
442                 assertEquals(SYSTEM_CA_STORE_PATH, wifiEnterpriseConfig.getCaPath());
443             }
444             if (passpointConfig.getCredential().getCheckAaaServerCertStatus()) {
445                 assertEquals(wifiEnterpriseConfig.getOcsp(),
446                         WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS);
447             } else {
448                 assertEquals(wifiEnterpriseConfig.getOcsp(),
449                         WifiEnterpriseConfig.OCSP_NONE);
450             }
451         } else if (credential.getSimCredential() != null) {
452             Credential.SimCredential simCredential = credential.getSimCredential();
453             switch (simCredential.getEapType()) {
454                 case EAPConstants.EAP_SIM:
455                     assertEquals(WifiEnterpriseConfig.Eap.SIM,
456                             wifiEnterpriseConfig.getEapMethod());
457                     break;
458                 case EAPConstants.EAP_AKA:
459                     assertEquals(WifiEnterpriseConfig.Eap.AKA,
460                             wifiEnterpriseConfig.getEapMethod());
461                     break;
462                 case EAPConstants.EAP_AKA_PRIME:
463                     assertEquals(WifiEnterpriseConfig.Eap.AKA_PRIME,
464                             wifiEnterpriseConfig.getEapMethod());
465                     break;
466             }
467             assertEquals(simCredential.getImsi(), wifiEnterpriseConfig.getPlmn());
468         }
469     }
470 
471     /**
472      * Verify that modification to the configuration used for creating PasspointProvider will not
473      * change the configuration stored inside the PasspointProvider.
474      *
475      * @throws Exception
476      */
477     @Test
verifyModifyOriginalConfig()478     public void verifyModifyOriginalConfig() throws Exception {
479         // Create a placeholder PasspointConfiguration.
480         PasspointConfiguration config = generateTestPasspointConfiguration(
481                 CredentialType.USER, false);
482         mProvider = createProvider(config);
483         verifyInstalledConfig(config, true);
484 
485         // Modify the original configuration, the configuration maintained by the provider
486         // should be unchanged.
487         config.getHomeSp().setFqdn(TEST_FQDN2);
488         verifyInstalledConfig(config, false);
489     }
490 
491     /**
492      * Verify that modification to the configuration retrieved from the PasspointProvider will not
493      * change the configuration stored inside the PasspointProvider.
494      *
495      * @throws Exception
496      */
497     @Test
verifyModifyRetrievedConfig()498     public void verifyModifyRetrievedConfig() throws Exception {
499         // Create a placeholder PasspointConfiguration.
500         PasspointConfiguration config = generateTestPasspointConfiguration(
501                 CredentialType.USER, false);
502         mProvider = createProvider(config);
503         verifyInstalledConfig(config, true);
504 
505         // Modify the retrieved configuration, verify the configuration maintained by the
506         // provider should be unchanged.
507         PasspointConfiguration retrievedConfig = mProvider.getConfig();
508         retrievedConfig.getHomeSp().setFqdn(TEST_FQDN2);
509         verifyInstalledConfig(retrievedConfig, false);
510     }
511 
512     /**
513      * Verify a successful installation of certificates and key.
514      *
515      * @throws Exception
516      */
517     @Test
installCertsAndKeysSuccess()518     public void installCertsAndKeysSuccess() throws Exception {
519         // Create a placeholder configuration with certificate credential.
520         PasspointConfiguration config = generateTestPasspointConfiguration(
521                 CredentialType.CERT, false);
522         Credential credential = config.getCredential();
523         Credential.CertificateCredential certCredential = credential.getCertCredential();
524         credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
525         if (mRemediationCaCertificate != null) {
526             UpdateParameter updateParameter = new UpdateParameter();
527             updateParameter.setCaCertificate(mRemediationCaCertificate);
528             config.setSubscriptionUpdate(updateParameter);
529         }
530         mProvider = createProvider(config);
531 
532         // Install client certificate and key to the keystore successfully.
533         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
534                 .thenReturn(true);
535         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1))
536                 .thenReturn(true);
537         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
538                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
539                 new Certificate[]{FakeKeys.CLIENT_CERT}))
540                 .thenReturn(true);
541         when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
542                 .thenReturn(true);
543         assertTrue(mProvider.installCertsAndKeys());
544 
545         // Verify client certificate and key in the configuration gets cleared and aliases
546         // are set correctly.
547         PasspointConfiguration curConfig = mProvider.getConfig();
548         assertTrue(curConfig.getCredential().getCaCertificates() == null);
549         assertTrue(curConfig.getCredential().getClientPrivateKey() == null);
550         assertTrue(curConfig.getCredential().getClientCertificateChain() == null);
551         if (mRemediationCaCertificate != null) {
552             assertTrue(curConfig.getSubscriptionUpdate().getCaCertificate() == null);
553         }
554         assertTrue(mProvider.getCaCertificateAliases().equals(
555                 Arrays.asList(CA_CERTIFICATE_ALIAS, CA_CERTIFICATE_ALIAS_2)));
556         assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias()
557                 .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS));
558         assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias()
559                 .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS));
560         assertTrue(TextUtils.equals(mProvider.getRemediationCaCertificateAlias(), mExpectedResult));
561     }
562 
563     /**
564      * Verify a failure installation of certificates and key.
565      */
566     @Test
installCertsAndKeysFailure()567     public void installCertsAndKeysFailure() throws Exception {
568         // Create a placeholder configuration with certificate credential.
569         PasspointConfiguration config = generateTestPasspointConfiguration(
570                 CredentialType.CERT, false);
571         Credential credential = config.getCredential();
572         Credential.CertificateCredential certCredential = credential.getCertCredential();
573         credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
574         config.setCredential(credential);
575 
576         UpdateParameter updateParameter = new UpdateParameter();
577         updateParameter.setCaCertificate(mRemediationCaCertificate);
578         config.setSubscriptionUpdate(updateParameter);
579         mProvider = createProvider(config);
580 
581         // Failed to install client certificate to the keystore.
582         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
583                 .thenReturn(true);
584         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1))
585                 .thenReturn(false);
586         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
587                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
588                 new Certificate[]{FakeKeys.CLIENT_CERT}))
589                 .thenReturn(true);
590         when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
591                 .thenReturn(true);
592         assertFalse(mProvider.installCertsAndKeys());
593 
594         // Verify certificates and key in the configuration are not cleared and aliases
595         // are not set.
596         PasspointConfiguration curConfig = mProvider.getConfig();
597         assertTrue(curConfig.getCredential().getCaCertificates() != null);
598         assertTrue(curConfig.getCredential().getClientCertificateChain() != null);
599         assertTrue(curConfig.getCredential().getClientPrivateKey() != null);
600         if (mRemediationCaCertificate != null) {
601             assertTrue(curConfig.getSubscriptionUpdate().getCaCertificate() != null);
602         }
603         assertTrue(mProvider.getCaCertificateAliases() == null);
604         assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() == null);
605         assertTrue(mProvider.getRemediationCaCertificateAlias() == null);
606     }
607 
608     /**
609      * Verify a successful uninstallation of certificates and key.
610      */
611     @Test
uninstallCertsAndKeys()612     public void uninstallCertsAndKeys() throws Exception {
613         // Create a placeholder configuration with certificate credential.
614         PasspointConfiguration config = generateTestPasspointConfiguration(
615                 CredentialType.CERT, false);
616         Credential credential = config.getCredential();
617         Credential.CertificateCredential certCredential = credential.getCertCredential();
618         credential.setCaCertificates(new X509Certificate[]{FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
619         config.setCredential(credential);
620         if (mRemediationCaCertificate != null) {
621             UpdateParameter updateParameter = new UpdateParameter();
622             updateParameter.setCaCertificate(FakeKeys.CA_CERT0);
623             config.setSubscriptionUpdate(updateParameter);
624         }
625         mProvider = createProvider(config);
626 
627         // Install client certificate and key to the keystore successfully.
628         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
629                 .thenReturn(true);
630         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS_2, FakeKeys.CA_CERT1))
631                 .thenReturn(true);
632         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
633                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
634                 new Certificate[]{FakeKeys.CLIENT_CERT}))
635                 .thenReturn(true);
636         when(mKeyStore.putCaCertInKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
637                 .thenReturn(true);
638         assertTrue(mProvider.installCertsAndKeys());
639         assertTrue(mProvider.getCaCertificateAliases().equals(
640                 Arrays.asList(CA_CERTIFICATE_ALIAS, CA_CERTIFICATE_ALIAS_2)));
641         assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias()
642                 .equals(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS));
643         assertTrue(TextUtils.equals(mProvider.getRemediationCaCertificateAlias(), mExpectedResult));
644 
645         // Uninstall certificates and key from the keystore.
646         mProvider.uninstallCertsAndKeys();
647         verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_ALIAS);
648         verify(mKeyStore).removeEntryFromKeyStore(CA_CERTIFICATE_ALIAS_2);
649         verify(mKeyStore).removeEntryFromKeyStore(CLIENT_CERTIFICATE_ALIAS);
650         verify(mKeyStore).removeEntryFromKeyStore(CLIENT_PRIVATE_KEY_AND_CERT_ALIAS);
651         if (mRemediationCaCertificate != null) {
652             verify(mKeyStore).removeEntryFromKeyStore(REMEDIATION_CA_CERTIFICATE_ALIAS);
653         }
654 
655         assertTrue(mProvider.getCaCertificateAliases() == null);
656         assertTrue(mProvider.getClientPrivateKeyAndCertificateAlias() == null);
657         assertTrue(mProvider.getRemediationCaCertificateAlias() == null);
658     }
659 
660     /**
661      * Verify that a provider is a home provider when its FQDN matches a domain name in the Domain
662      * Name ANQP element and no NAI realm is provided.
663      *
664      * @throws Exception
665      */
666     @Test
matchFQDNWithoutNAIRealm()667     public void matchFQDNWithoutNAIRealm() throws Exception {
668         // Setup test provider.
669         PasspointConfiguration config = generateTestPasspointConfiguration(
670                 CredentialType.USER, false);
671         mProvider = createProvider(config);
672 
673         // Setup ANQP elements.
674         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
675         anqpElementMap.put(ANQPElementType.ANQPDomName,
676                 createDomainNameElement(new String[]{TEST_FQDN}));
677 
678         assertEquals(PasspointMatch.HomeProvider,
679                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
680     }
681 
682     /**
683      * Verify that a provider is a home provider when its FQDN matches a domain name in the Domain
684      * Name ANQP element and the provider's credential matches the NAI realm provided.
685      *
686      * @throws Exception
687      */
688     @Test
matchFQDNWithNAIRealmMatch()689     public void matchFQDNWithNAIRealmMatch() throws Exception {
690         // Setup test provider.
691         PasspointConfiguration config = generateTestPasspointConfiguration(
692                 CredentialType.USER, false);
693         mProvider = createProvider(config);
694 
695         // Setup Domain Name ANQP element.
696         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
697         anqpElementMap.put(ANQPElementType.ANQPDomName,
698                 createDomainNameElement(new String[]{TEST_FQDN}));
699         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
700                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
701                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
702 
703         assertEquals(PasspointMatch.HomeProvider,
704                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
705     }
706 
707     /**
708      * Verify that Home provider is matched even when the provider's FQDN matches a domain name in
709      * the Domain Name ANQP element but the provider's credential doesn't match the authentication
710      * method provided in the NAI realm. This can happen when the infrastructure provider is not the
711      * identity provider, and authentication method matching is not required in the spec.
712      *
713      * @throws Exception
714      */
715     @Test
matchFQDNWithNAIRealmMismatch()716     public void matchFQDNWithNAIRealmMismatch() throws Exception {
717         // Setup test provider.
718         PasspointConfiguration config = generateTestPasspointConfiguration(
719                 CredentialType.USER, false);
720         mProvider = createProvider(config);
721 
722         // Setup Domain Name ANQP element.
723         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
724         anqpElementMap.put(ANQPElementType.ANQPDomName,
725                 createDomainNameElement(new String[]{TEST_FQDN}));
726         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
727                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null));
728 
729         assertEquals(PasspointMatch.HomeProvider,
730                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
731     }
732 
733     /**
734      * Verify that a provider is a home provider when its SIM credential matches an 3GPP network
735      * domain name in the Domain Name ANQP element.
736      *
737      * @throws Exception
738      */
739     @Test
matchFQDNWith3GPPNetworkDomainName()740     public void matchFQDNWith3GPPNetworkDomainName() throws Exception {
741         // Setup test provider.
742         PasspointConfiguration config = generateTestPasspointConfiguration(
743                 CredentialType.SIM, false);
744         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
745                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
746         mProvider = createProvider(config);
747 
748         // Setup Domain Name ANQP element.
749         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
750         anqpElementMap.put(ANQPElementType.ANQPDomName,
751                 createDomainNameElement(new String[]{"wlan.mnc456.mcc123.3gppnetwork.org"}));
752 
753         assertEquals(PasspointMatch.HomeProvider,
754                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
755     }
756 
757     /**
758      * Verify that a provider is a home provider when its FQDN, roaming consortium OI, and IMSI all
759      * matched against the ANQP elements, since we prefer matching home provider over roaming
760      * provider.
761      *
762      * @throws Exception
763      */
764     @Test
matchFQDNOverRoamingProvider()765     public void matchFQDNOverRoamingProvider() throws Exception {
766         // Setup test provider.
767         PasspointConfiguration config = generateTestPasspointConfiguration(
768                 CredentialType.SIM, false);
769         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
770                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
771         mProvider = createProvider(config);
772 
773         // Setup ANQP elements.
774         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
775         anqpElementMap.put(ANQPElementType.ANQPDomName,
776                 createDomainNameElement(new String[]{TEST_FQDN}));
777         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
778                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS));
779         anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
780                 createThreeGPPNetworkElement(new String[]{"123456"}));
781 
782         assertEquals(PasspointMatch.HomeProvider,
783                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
784     }
785 
786     /**
787      * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI in
788      * the roaming consortium ANQP element and no NAI realm is provided.
789      *
790      * @throws Exception
791      */
792     @Test
matchRoamingConsortiumWithoutNAIRealm()793     public void matchRoamingConsortiumWithoutNAIRealm() throws Exception {
794         // Setup test provider.
795         PasspointConfiguration config = generateTestPasspointConfiguration(
796                 CredentialType.SIM, false);
797         mProvider = createProvider(config);
798         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(
799                 eq(config.getCredential().getSimCredential().getImsi())))
800                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
801 
802         // Setup Roaming Consortium ANQP element.
803         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
804         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
805                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS));
806 
807         assertEquals(PasspointMatch.RoamingProvider,
808                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
809 
810         // Confirm the selected RCOI matches the expected value
811         assertEquals(TEST_IE_RC_OIS[0],
812                 mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
813         // Confirm the value is cleared after it was fetched
814         assertEquals(0, mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
815     }
816 
817     /**
818      * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI in
819      * the roaming consortium ANQP element and the provider's credential matches the NAI realm
820      * provided.
821      *
822      * @throws Exception
823      */
824     @Test
matchRoamingConsortiumWithNAIRealmMatch()825     public void matchRoamingConsortiumWithNAIRealmMatch() throws Exception {
826 
827         // Setup test provider.
828         PasspointConfiguration config = generateTestPasspointConfiguration(
829                 CredentialType.USER, false);
830         mProvider = createProvider(config);
831 
832         // Setup Roaming Consortium ANQP element.
833         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
834         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
835                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS));
836         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
837                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
838                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
839 
840         assertEquals(PasspointMatch.RoamingProvider,
841                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
842     }
843 
844     /**
845      * Verify that there is Roaming provider match when a roaming consortium OI matches an OI in the
846      * roaming consortium ANQP element and regardless of NAI realm mismatch.
847      *
848      * @throws Exception
849      */
850     @Test
matchRoamingConsortiumWithNAIRealmMisMatch()851     public void matchRoamingConsortiumWithNAIRealmMisMatch() throws Exception {
852         // Setup test provider.
853         PasspointConfiguration config = generateTestPasspointConfiguration(
854                 CredentialType.USER, false);
855         mProvider = createProvider(config);
856 
857         // Setup Roaming Consortium ANQP element.
858         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
859         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
860                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS));
861         // Set up NAI with different EAP method
862         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
863                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null));
864 
865         assertEquals(PasspointMatch.RoamingProvider,
866                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
867     }
868 
869     /**
870      * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI in
871      * the roaming consortium information element and no NAI realm is provided.
872      *
873      * @throws Exception
874      */
875     @Test
matchRoamingConsortiumIeWithoutNAIRealm()876     public void matchRoamingConsortiumIeWithoutNAIRealm() throws Exception {
877         // Setup test provider.
878         PasspointConfiguration config = generateTestPasspointConfiguration(
879                 CredentialType.USER, false);
880         mProvider = createProvider(config);
881 
882         // Setup Roaming Consortium ANQP element.
883         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
884 
885         // Setup Roaming Consortium Information element.
886         when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS);
887 
888         assertEquals(PasspointMatch.RoamingProvider,
889                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
890     }
891 
892     /**
893      * Verify that a provider is a roaming provider when a roaming consortium OI matches an OI in
894      * the roaming consortium information element and the provider's credential matches the NAI
895      * realm provided.
896      *
897      * @throws Exception
898      */
899     @Test
matchRoamingConsortiumIeWithNAIRealmMatch()900     public void matchRoamingConsortiumIeWithNAIRealmMatch() throws Exception {
901         // Setup test provider.
902         PasspointConfiguration config = generateTestPasspointConfiguration(
903                 CredentialType.USER, false);
904         mProvider = createProvider(config);
905 
906         // Setup Roaming Consortium ANQP element.
907         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
908 
909         // Setup Roaming Consortium Information element.
910         when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS);
911         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
912                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
913                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
914 
915         assertEquals(PasspointMatch.RoamingProvider,
916                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
917     }
918 
919     /**
920      * Verify that there is Roaming provider match when a roaming consortium OI matches an OI in the
921      * roaming consortium information element, but NAI realm is not matched. This can happen in
922      * roaming federation where the infrastructure provider is not the identity provider. Page 133
923      * in the Hotspot2.0 specification states: Per subclause 11.25.8 of [2], if the value of HomeOI
924      * matches an OI in the Roaming Consortium advertised by a hotspot operator, successful
925      * authentication with that hotspot is possible.
926      *
927      * @throws Exception
928      */
929     @Test
matchRoamingConsortiumIeWithNAIRealmMismatch()930     public void matchRoamingConsortiumIeWithNAIRealmMismatch() throws Exception {
931         // Setup test provider.
932         PasspointConfiguration config = generateTestPasspointConfiguration(
933                 CredentialType.USER, false);
934         mProvider = createProvider(config);
935 
936         // Setup Roaming Consortium ANQP element.
937         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
938 
939         // Setup Roaming Consortium Information element.
940         when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_RC_OIS);
941         // Set up NAI with different EAP method
942         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
943                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TLS, null));
944 
945         assertEquals(PasspointMatch.RoamingProvider,
946                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
947 
948         // Confirm the selected RCOI matches the expected value
949         assertEquals(TEST_IE_RC_OIS[0],
950                 mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
951         // Confirm the value is cleared after it was fetched
952         assertEquals(0, mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
953     }
954 
955     /**
956      * Verify that none of matched providers are found when a roaming consortium OI doesn't matches
957      * an OI in the roaming consortium information element and none of NAI realms match each other.
958      *
959      * @throws Exception
960      */
961     @Test
misMatchForRoamingConsortiumIeAndNAIRealm()962     public void misMatchForRoamingConsortiumIeAndNAIRealm() throws Exception {
963         // Setup test provider.
964         PasspointConfiguration config = generateTestPasspointConfiguration(
965                 CredentialType.USER, false);
966         mProvider = createProvider(config);
967 
968         // Setup Roaming Consortium ANQP element.
969         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
970 
971         // Setup Roaming Consortium Information element.
972         when(mRoamingConsortium.getRoamingConsortiums()).thenReturn(TEST_IE_NO_MATCHED_RC_OIS);
973 
974         assertEquals(PasspointMatch.None,
975                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
976     }
977 
978     /**
979      * Verify that a provider is a roaming provider when the provider's IMSI parameter and an IMSI
980      * from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element regardless of NAI realm
981      * mismatch.
982      *
983      * @throws Exception
984      */
985     @Test
matchThreeGPPNetworkWithNAIRealmMismatch()986     public void matchThreeGPPNetworkWithNAIRealmMismatch() throws Exception {
987         // Setup test provider.
988         PasspointConfiguration config = generateTestPasspointConfiguration(
989                 CredentialType.SIM, false);
990         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
991                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
992         mProvider = createProvider(config);
993 
994         // Setup 3GPP Network ANQP element.
995         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
996         anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
997                 createThreeGPPNetworkElement(new String[]{"123456"}));
998 
999         // Setup NAI Realm ANQP element with different realm.
1000         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1001                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1002                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1003 
1004         assertEquals(PasspointMatch.RoamingProvider,
1005                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1006     }
1007 
1008     /**
1009      * Verify that a provider is a roaming provider when the provider's IMSI parameter and an IMSI
1010      * from the SIM card matches a MCC-MNC in the 3GPP Network ANQP element regardless of NAI realm
1011      * match.
1012      *
1013      * @throws Exception
1014      */
1015     @Test
matchThreeGPPNetworkWithNAIRealmMatch()1016     public void matchThreeGPPNetworkWithNAIRealmMatch() throws Exception {
1017         // Setup test provider.
1018         PasspointConfiguration config = generateTestPasspointConfiguration(
1019                 CredentialType.SIM, false);
1020         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
1021                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
1022         mProvider = createProvider(config);
1023 
1024         // Setup 3GPP Network ANQP element.
1025         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1026         anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
1027                 createThreeGPPNetworkElement(new String[]{"123456"}));
1028 
1029         // Setup NAI Realm ANQP element with same realm.
1030         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1031                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null));
1032 
1033         assertEquals(PasspointMatch.RoamingProvider,
1034                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1035         assertEquals(VALID_CARRIER_ID, mProvider.getWifiConfig().carrierId);
1036     }
1037 
1038     /**
1039      * Verify that when the SIM card matched by carrier ID of profile is absent, it shouldn't be
1040      * matched even the profile and ANQP elements are matched.
1041      *
1042      * @throws Exception
1043      */
1044     @Test
matchNothingIfSimMatchedByCarrierIdIsAbsent()1045     public void matchNothingIfSimMatchedByCarrierIdIsAbsent() throws Exception {
1046         // Setup test provider.
1047         PasspointConfiguration config = generateTestPasspointConfiguration(
1048                 CredentialType.SIM, false);
1049         config.setCarrierId(VALID_CARRIER_ID);
1050         when(mWifiCarrierInfoManager.getMatchingSubId(eq(VALID_CARRIER_ID)))
1051                 .thenReturn(VALID_SUBSCRIPTION_ID);
1052         when(mWifiCarrierInfoManager.getMatchingImsiBySubId(eq(VALID_SUBSCRIPTION_ID)))
1053                 .thenReturn(null);
1054         mProvider = createProvider(config);
1055 
1056         // Setup 3GPP Network ANQP element.
1057         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1058         anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
1059                 createThreeGPPNetworkElement(new String[]{"123456"}));
1060 
1061         // Setup NAI Realm ANQP element with same realm.
1062         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1063                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null));
1064 
1065         assertEquals(PasspointMatch.None,
1066                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1067     }
1068 
1069     /**
1070      * Verify that when the SIM card matched by IMSI of profile is absent, it shouldn't be matched
1071      * even the profile and ANQP elements are matched.
1072      *
1073      * @throws Exception
1074      */
1075     @Test
matchNothingIfSimMatchedByImsiIsAbsent()1076     public void matchNothingIfSimMatchedByImsiIsAbsent() throws Exception {
1077         // Setup test provider.
1078         PasspointConfiguration config = generateTestPasspointConfiguration(
1079                 CredentialType.SIM, false);
1080         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(eq(TEST_IMSI)))
1081                 .thenReturn(null);
1082         mProvider = createProvider(config);
1083 
1084         // Setup 3GPP Network ANQP element.
1085         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1086         anqpElementMap.put(ANQPElementType.ANQP3GPPNetwork,
1087                 createThreeGPPNetworkElement(new String[]{"123456"}));
1088 
1089         // Setup NAI Realm ANQP element with same realm.
1090         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1091                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_AKA, null));
1092 
1093         assertEquals(PasspointMatch.None,
1094                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1095     }
1096 
1097     /**
1098      * Verify that a provider is a roaming provider when its credential only matches a NAI realm in
1099      * the NAI Realm ANQP element and not match for Domain Name, RoamingConsortium and 3GPP.
1100      *
1101      * @throws Exception
1102      */
1103     @Test
matchOnlyNAIRealmWithOtherInformationMismatch()1104     public void matchOnlyNAIRealmWithOtherInformationMismatch() throws Exception {
1105         // Setup test provider.
1106         PasspointConfiguration config = generateTestPasspointConfiguration(
1107                 CredentialType.USER, false);
1108         mProvider = createProvider(config);
1109 
1110         // Setup NAI Realm ANQP element.
1111         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1112         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1113                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1114                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1115 
1116         assertEquals(PasspointMatch.RoamingProvider,
1117                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1118     }
1119 
1120     /**
1121      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1122      * user credential.
1123      *
1124      * @throws Exception
1125      */
1126     @Test
getWifiConfigWithUserCredential()1127     public void getWifiConfigWithUserCredential() throws Exception {
1128         // Create provider for R2.
1129         PasspointConfiguration config = generateTestPasspointConfiguration(
1130                 CredentialType.USER, false);
1131         mProvider = createProvider(config);
1132 
1133         // Install certificate.
1134         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
1135                 .thenReturn(true);
1136         assertTrue(mProvider.installCertsAndKeys());
1137 
1138         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1139         // the configuration.
1140         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1141 
1142         // Verify that AAA server trusted names are provisioned.
1143         config.setAaaServerTrustedNames(TEST_TRUSTED_NAME);
1144         mProvider = createProvider(config);
1145         verifyWifiConfigWithTestData(config,
1146                 createProvider(config).getWifiConfig());
1147     }
1148 
1149     /**
1150      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1151      * user credential which has AAA server trusted names provisioned.
1152      *
1153      * @throws Exception
1154      */
1155     @Test
getWifiConfigWithUserCredentialHasAaaServerTrustedNames()1156     public void getWifiConfigWithUserCredentialHasAaaServerTrustedNames() throws Exception {
1157         // Create provider for R2.
1158         PasspointConfiguration config = generateTestPasspointConfiguration(
1159                 CredentialType.USER, false);
1160         config.setAaaServerTrustedNames(TEST_TRUSTED_NAME);
1161         Credential credential = config.getCredential();
1162         // OCSP (Online Certificate Status Protocol) is required.
1163         credential.setCheckAaaServerCertStatus(true);
1164         mProvider = createProvider(config);
1165 
1166         // Install certificate.
1167         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
1168                 .thenReturn(true);
1169         assertTrue(mProvider.installCertsAndKeys());
1170 
1171         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1172         // the configuration.
1173         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1174 
1175         // Verify that AAA server trusted names are provisioned.
1176         config.setAaaServerTrustedNames(TEST_TRUSTED_NAME);
1177         mProvider = createProvider(config);
1178         verifyWifiConfigWithTestData(config,
1179                 createProvider(config).getWifiConfig());
1180     }
1181 
1182     /**
1183      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1184      * user credential which has no CA cert.
1185      *
1186      * @throws Exception
1187      */
1188     @Test
getWifiConfigWithUserCredentialNoCaCert()1189     public void getWifiConfigWithUserCredentialNoCaCert() throws Exception {
1190         // Create provider for R2.
1191         PasspointConfiguration config = generateTestPasspointConfiguration(
1192                 CredentialType.USER, false);
1193         config.getCredential().setCaCertificates(null);
1194         mProvider = createProvider(config);
1195 
1196         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1197         // the configuration.
1198         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1199     }
1200 
1201     /**
1202      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1203      * certificate credential.
1204      *
1205      * @throws Exception
1206      */
1207     @Test
getWifiConfigWithCertCredential()1208     public void getWifiConfigWithCertCredential() throws Exception {
1209         // Create provider.
1210         PasspointConfiguration config = generateTestPasspointConfiguration(
1211                 CredentialType.CERT, false);
1212         mProvider = createProvider(config);
1213 
1214         // Install certificate.
1215         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
1216                 .thenReturn(true);
1217         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
1218                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
1219                 new Certificate[]{FakeKeys.CLIENT_CERT}))
1220                 .thenReturn(true);
1221         assertTrue(mProvider.installCertsAndKeys());
1222 
1223         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1224         // the configuration.
1225         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1226     }
1227 
1228     /**
1229      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1230      * certificate credential which has AAA server trusted names provisioned.
1231      *
1232      * @throws Exception
1233      */
1234     @Test
getWifiConfigWithCertCredentialHasAaaServerTrustedNames()1235     public void getWifiConfigWithCertCredentialHasAaaServerTrustedNames() throws Exception {
1236         // Create provider.
1237         PasspointConfiguration config = generateTestPasspointConfiguration(
1238                 CredentialType.CERT, false);
1239         config.setAaaServerTrustedNames(TEST_TRUSTED_NAME);
1240         mProvider = createProvider(config);
1241 
1242         // Install certificate.
1243         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
1244                 .thenReturn(true);
1245         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
1246                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
1247                 new Certificate[]{FakeKeys.CLIENT_CERT}))
1248                 .thenReturn(true);
1249         assertTrue(mProvider.installCertsAndKeys());
1250 
1251         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1252         // the configuration.
1253         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1254     }
1255 
1256     /**
1257      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1258      * certificate credential which has no CA cert.
1259      *
1260      * @throws Exception
1261      */
1262     @Test
getWifiConfigWithCertCredentialNoCaCert()1263     public void getWifiConfigWithCertCredentialNoCaCert() throws Exception {
1264         // Create provider.
1265         PasspointConfiguration config = generateTestPasspointConfiguration(
1266                 CredentialType.CERT, false);
1267         config.getCredential().setCaCertificates(null);
1268         mProvider = createProvider(config);
1269 
1270         // Install certificate.
1271         when(mKeyStore.putUserPrivKeyAndCertsInKeyStore(
1272                 CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, FakeKeys.RSA_KEY1,
1273                 new Certificate[]{FakeKeys.CLIENT_CERT}))
1274                 .thenReturn(true);
1275         assertTrue(mProvider.installCertsAndKeys());
1276 
1277         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1278         // the configuration.
1279         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1280     }
1281 
1282     /**
1283      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1284      * SIM credential.
1285      *
1286      * @throws Exception
1287      */
1288     @Test
getWifiConfigWithSimCredential()1289     public void getWifiConfigWithSimCredential() throws Exception {
1290         // Create provider.
1291         PasspointConfiguration config = generateTestPasspointConfiguration(
1292                 CredentialType.SIM, false);
1293         mProvider = createProvider(config);
1294 
1295         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1296         // the configuration.
1297         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1298     }
1299 
1300     @Test
getWifiConfigWithAutojoinDisable()1301     public void getWifiConfigWithAutojoinDisable() throws Exception {
1302         PasspointConfiguration config = generateTestPasspointConfiguration(
1303                 CredentialType.USER, false);
1304         mProvider = createProvider(config);
1305 
1306         assertTrue(mProvider.getWifiConfig().allowAutojoin);
1307         mProvider.setAutojoinEnabled(false);
1308         assertFalse(mProvider.getWifiConfig().allowAutojoin);
1309     }
1310 
1311     @Test
getWifiConfigWithCarrierMerged()1312     public void getWifiConfigWithCarrierMerged() throws Exception {
1313         PasspointConfiguration config = generateTestPasspointConfiguration(
1314                 CredentialType.USER, false);
1315         config.setCarrierMerged(true);
1316         mProvider = createProvider(config);
1317         assertTrue(mProvider.getWifiConfig().carrierMerged);
1318     }
1319 
1320     @Test
getWifiConfigWithOemPaid()1321     public void getWifiConfigWithOemPaid() throws Exception {
1322         PasspointConfiguration config = generateTestPasspointConfiguration(
1323                 CredentialType.USER, false);
1324         config.setOemPaid(true);
1325         mProvider = createProvider(config);
1326         assertTrue(mProvider.getWifiConfig().oemPaid);
1327     }
1328 
1329     @Test
getWifiConfigWithOemPrivate()1330     public void getWifiConfigWithOemPrivate() throws Exception {
1331         PasspointConfiguration config = generateTestPasspointConfiguration(
1332                 CredentialType.USER, false);
1333         config.setOemPrivate(true);
1334         mProvider = createProvider(config);
1335         assertTrue(mProvider.getWifiConfig().oemPrivate);
1336     }
1337 
1338     /**
1339      * Verify that the mac randomization setting will be included in the generated
1340      * WifiConfiguration.
1341      */
1342     @Test
testSetMacRandomizationEnabledToFalse()1343     public void testSetMacRandomizationEnabledToFalse() throws Exception {
1344         // Create provider.
1345         PasspointConfiguration config = generateTestPasspointConfiguration(
1346                 CredentialType.SIM, false);
1347         mProvider = createProvider(config);
1348         mProvider.setMacRandomizationEnabled(false);
1349         verifyWifiConfigWithTestData(mProvider.getConfig(), mProvider.getWifiConfig());
1350     }
1351 
1352     /**
1353      * Verify the generated WifiConfiguration.macRandomizationSetting defaults to
1354      * RANDOMIZATION_PERSISTENT.
1355      */
1356     @Test
testMacRandomizationSettingDefaultIsPersistent()1357     public void testMacRandomizationSettingDefaultIsPersistent() throws Exception {
1358         PasspointConfiguration config = generateTestPasspointConfiguration(
1359                 CredentialType.SIM, false);
1360         mProvider = createProvider(config);
1361 
1362         assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT,
1363                 mProvider.getWifiConfig().macRandomizationSetting);
1364     }
1365 
1366     /**
1367      * Verify the WifiConfiguration is generated properly with settings to use non-persistent MAC
1368      * randomization.
1369      */
1370     @Test
testMacRandomizationSettingNonPersistent()1371     public void testMacRandomizationSettingNonPersistent() throws Exception {
1372         PasspointConfiguration config = generateTestPasspointConfiguration(
1373                 CredentialType.SIM, false);
1374         config.setNonPersistentMacRandomizationEnabled(true);
1375         mProvider = createProvider(config);
1376 
1377         assertEquals(WifiConfiguration.RANDOMIZATION_NON_PERSISTENT,
1378                 mProvider.getWifiConfig().macRandomizationSetting);
1379     }
1380 
1381     /**
1382      * Verify that an expected {@link PasspointConfiguration} will be returned when converting from
1383      * a {@link WifiConfiguration} containing a user credential.
1384      *
1385      * @throws Exception
1386      */
1387     @Test
convertFromWifiConfigWithUserCredential()1388     public void convertFromWifiConfigWithUserCredential() throws Exception {
1389         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1390         WifiConfiguration wifiConfig = new WifiConfiguration();
1391         wifiConfig.FQDN = TEST_FQDN;
1392         wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME;
1393         wifiConfig.roamingConsortiumIds = TEST_RC_OIS;
1394         wifiConfig.enterpriseConfig.setIdentity(TEST_USERNAME);
1395         wifiConfig.enterpriseConfig.setPassword(TEST_PASSWORD);
1396         wifiConfig.enterpriseConfig.setRealm(TEST_REALM);
1397         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1398         wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
1399 
1400         // Setup expected {@link PasspointConfiguration}
1401         PasspointConfiguration passpointConfig = generateTestPasspointConfiguration(
1402                 CredentialType.USER, true);
1403         Credential.UserCredential userCredential =
1404                 passpointConfig.getCredential().getUserCredential();
1405         userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_PAP);
1406 
1407         assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
1408     }
1409 
1410     /**
1411      * Verify that an expected {@link PasspointConfiguration} will be returned when converting from
1412      * a {@link WifiConfiguration} containing a SIM credential.
1413      *
1414      * @throws Exception
1415      */
1416     @Test
convertFromWifiConfigWithSimCredential()1417     public void convertFromWifiConfigWithSimCredential() throws Exception {
1418         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1419         WifiConfiguration wifiConfig = new WifiConfiguration();
1420         wifiConfig.FQDN = TEST_FQDN;
1421         wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME;
1422         wifiConfig.roamingConsortiumIds = TEST_RC_OIS;
1423         wifiConfig.enterpriseConfig.setRealm(TEST_REALM);
1424         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
1425         wifiConfig.enterpriseConfig.setPlmn(TEST_IMSI);
1426 
1427         // Setup expected {@link PasspointConfiguration}
1428         PasspointConfiguration passpointConfig = generateTestPasspointConfiguration(
1429                 CredentialType.SIM, true);
1430 
1431         assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
1432     }
1433 
1434     /**
1435      * Verify that an expected {@link PasspointConfiguration} will be returned when converting from
1436      * a {@link WifiConfiguration} containing a certificate credential.
1437      *
1438      * @throws Exception
1439      */
1440     @Test
convertFromWifiConfigWithCertCredential()1441     public void convertFromWifiConfigWithCertCredential() throws Exception {
1442         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1443         WifiConfiguration wifiConfig = new WifiConfiguration();
1444         wifiConfig.FQDN = TEST_FQDN;
1445         wifiConfig.providerFriendlyName = TEST_FRIENDLY_NAME;
1446         wifiConfig.roamingConsortiumIds = TEST_RC_OIS;
1447         wifiConfig.enterpriseConfig.setRealm(TEST_REALM);
1448         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1449 
1450         // Setup expected {@link PasspointConfiguration}
1451         PasspointConfiguration passpointConfig = generateTestPasspointConfiguration(
1452                 CredentialType.CERT, true);
1453 
1454         assertEquals(passpointConfig, PasspointProvider.convertFromWifiConfig(wifiConfig));
1455     }
1456 
1457     /**
1458      * Verify that {@link PasspointProvider#isSimCredential} will return true for provider that's
1459      * backed by a SIM credential.
1460      *
1461      * @throws Exception
1462      */
1463     @Test
providerBackedBySimCredential()1464     public void providerBackedBySimCredential() throws Exception {
1465         PasspointConfiguration config = generateTestPasspointConfiguration(
1466                 CredentialType.SIM, false);
1467         mProvider = createProvider(config);
1468 
1469         assertTrue(mProvider.isSimCredential());
1470     }
1471 
1472     /**
1473      * Verify that {@link PasspointProvider#isSimCredential} will return false for provider that's
1474      * not backed by a SIM credential.
1475      *
1476      * @throws Exception
1477      */
1478     @Test
providerNotBackedBySimCredential()1479     public void providerNotBackedBySimCredential() throws Exception {
1480         PasspointConfiguration config = generateTestPasspointConfiguration(
1481                 CredentialType.CERT, false);
1482         mProvider = createProvider(config);
1483 
1484         assertFalse(mProvider.isSimCredential());
1485     }
1486 
1487     /**
1488      * Verify that hasEverConnected flag is set correctly using {@link
1489      * PasspointProvider#setHasEverConnected}.
1490      *
1491      * @throws Exception
1492      */
1493     @Test
setHasEverConnected()1494     public void setHasEverConnected() throws Exception {
1495         PasspointConfiguration config = generateTestPasspointConfiguration(
1496                 CredentialType.USER, false);
1497         mProvider = createProvider(config);
1498         verifyInstalledConfig(config, true);
1499 
1500         assertFalse(mProvider.getHasEverConnected());
1501         mProvider.setHasEverConnected(true);
1502         assertTrue(mProvider.getHasEverConnected());
1503     }
1504 
1505     /**
1506      * Verify that a provider is a home provider when there is a match between Other Home Partners
1507      * in the profile and the Domain Name ANQP element.
1508      *
1509      * @throws Exception
1510      */
1511     @Test
getWifiConfigWithUserCredentialAndNonBase64Password()1512     public void getWifiConfigWithUserCredentialAndNonBase64Password() throws Exception {
1513         // Create provider for R2.
1514         PasspointConfiguration config = generateTestPasspointConfiguration(
1515                 CredentialType.USER, false);
1516 
1517         // Update the password to non-Base64
1518         Credential credential = config.getCredential();
1519         Credential.UserCredential userCredential = credential.getUserCredential();
1520         userCredential.setPassword(TEST_PASSWORD);
1521         credential.setUserCredential(userCredential);
1522         config.setCredential(credential);
1523 
1524         mProvider = createProvider(config);
1525 
1526         // Install certificate.
1527         when(mKeyStore.putCaCertInKeyStore(CA_CERTIFICATE_ALIAS, FakeKeys.CA_CERT0))
1528                 .thenReturn(true);
1529         assertTrue(mProvider.installCertsAndKeys());
1530 
1531         // Retrieve the WifiConfiguration associated with the provider, and verify the content of
1532         // the configuration.
1533         verifyWifiConfigWithTestData(config, mProvider.getWifiConfig());
1534 
1535         // Verify that AAA server trusted names are provisioned.
1536         config.setAaaServerTrustedNames(TEST_TRUSTED_NAME);
1537         mProvider = createProvider(config);
1538         verifyWifiConfigWithTestData(config,
1539                 createProvider(config).getWifiConfig());
1540     }
1541 
1542     /**
1543      * Verify that an expected WifiConfiguration will be returned for a Passpoint provider with a
1544      * user credential.
1545      *
1546      * @throws Exception
1547      */
1548     @Test
matchOtherPartnersDomainName()1549     public void matchOtherPartnersDomainName() throws Exception {
1550         // Setup test provider.
1551         PasspointConfiguration config = generateTestPasspointConfiguration(
1552                 CredentialType.USER, false);
1553 
1554         // Configuration was created with TEST_FQDN as the FQDN, add TEST_FQDN3 as other home
1555         // partner.
1556         HomeSp homeSp = config.getHomeSp();
1557         homeSp.setOtherHomePartners(new String[]{TEST_FQDN3});
1558         config.setHomeSp(homeSp);
1559         mProvider = createProvider(config);
1560 
1561         // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3
1562         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1563         anqpElementMap.put(ANQPElementType.ANQPDomName,
1564                 createDomainNameElement(new String[]{TEST_FQDN2, TEST_FQDN3}));
1565 
1566         assertEquals(PasspointMatch.HomeProvider,
1567                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1568     }
1569 
1570     /**
1571      * Verify that matching Any HomeOI results in a Home Provider match
1572      *
1573      * @throws Exception
1574      */
1575     @Test
matchAnyHomeOi()1576     public void matchAnyHomeOi() throws Exception {
1577         // Setup test provider.
1578         PasspointConfiguration config = generateTestPasspointConfiguration(
1579                 CredentialType.USER, false);
1580         Long[] anqpOis = new Long[]{0x1234L, 0xdeadL, 0xf0cdL};
1581 
1582         // Configuration was created with TEST_FQDN as the FQDN
1583         HomeSp homeSp = config.getHomeSp();
1584         homeSp.setMatchAnyOis(TEST_RC_OIS);
1585         homeSp.setRoamingConsortiumOis(null);
1586         config.setHomeSp(homeSp);
1587         mProvider = createProvider(config);
1588 
1589         // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3
1590         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1591         anqpElementMap.put(ANQPElementType.ANQPDomName,
1592                 createDomainNameElement(new String[]{TEST_FQDN2, TEST_FQDN3}));
1593         // Setup RCOIs advertised by the AP
1594         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
1595                 createRoamingConsortiumElement(anqpOis));
1596 
1597         assertEquals(PasspointMatch.HomeProvider,
1598                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1599     }
1600 
1601     /**
1602      * Verify that non-matching Any HomeOI results in a None Provider match
1603      *
1604      * @throws Exception
1605      */
1606     @Test
matchAnyHomeOiNegative()1607     public void matchAnyHomeOiNegative() throws Exception {
1608         // Setup test provider.
1609         PasspointConfiguration config = generateTestPasspointConfiguration(
1610                 CredentialType.USER, false);
1611         Long[] anqpOis = new Long[]{0x12a4L, 0xceadL, 0xf0cdL};
1612 
1613         // Configuration was created with TEST_FQDN as the FQDN
1614         HomeSp homeSp = config.getHomeSp();
1615         homeSp.setMatchAnyOis(TEST_RC_OIS);
1616         homeSp.setRoamingConsortiumOis(null);
1617         config.setHomeSp(homeSp);
1618         mProvider = createProvider(config);
1619 
1620         // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3
1621         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1622         anqpElementMap.put(ANQPElementType.ANQPDomName,
1623                 createDomainNameElement(new String[]{TEST_FQDN2, TEST_FQDN3}));
1624         // Setup RCOIs advertised by the AP
1625         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
1626                 createRoamingConsortiumElement(anqpOis));
1627 
1628         assertEquals(PasspointMatch.None,
1629                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1630     }
1631 
1632     /**
1633      * Verify that matching All HomeOI results in a Home Provider match
1634      *
1635      * @throws Exception
1636      */
1637     @Test
matchAllHomeOi()1638     public void matchAllHomeOi() throws Exception {
1639         // Setup test provider.
1640         PasspointConfiguration config = generateTestPasspointConfiguration(
1641                 CredentialType.USER, false);
1642         Long[] anqpOis = new Long[]{0x1234L, 0x2345L, 0xabcdL, 0xdeadL, 0xf0cdL};
1643 
1644         // Configuration was created with TEST_FQDN as the FQDN
1645         HomeSp homeSp = config.getHomeSp();
1646         homeSp.setMatchAllOis(TEST_RC_OIS);
1647         homeSp.setRoamingConsortiumOis(null);
1648         config.setHomeSp(homeSp);
1649         mProvider = createProvider(config);
1650 
1651         // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3
1652         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1653         anqpElementMap.put(ANQPElementType.ANQPDomName,
1654                 createDomainNameElement(new String[]{TEST_FQDN2, TEST_FQDN3}));
1655         // Setup RCOIs advertised by the AP
1656         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
1657                 createRoamingConsortiumElement(anqpOis));
1658 
1659         assertEquals(PasspointMatch.HomeProvider,
1660                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1661     }
1662 
1663     /**
1664      * Verify that non-matching All HomeOI results in a None Provider match
1665      *
1666      * @throws Exception
1667      */
1668     @Test
matchAllHomeOiNegative()1669     public void matchAllHomeOiNegative() throws Exception {
1670         // Setup test provider.
1671         PasspointConfiguration config = generateTestPasspointConfiguration(
1672                 CredentialType.USER, false);
1673         // 0x1234 matches, but 0x2345 does not
1674         Long[] anqpOis = new Long[]{0x1234L, 0x5678L, 0xdeadL, 0xf0cdL};
1675 
1676         // Configuration was created with TEST_FQDN as the FQDN
1677         HomeSp homeSp = config.getHomeSp();
1678         homeSp.setMatchAllOis(TEST_RC_OIS);
1679         homeSp.setRoamingConsortiumOis(null);
1680         config.setHomeSp(homeSp);
1681         mProvider = createProvider(config);
1682 
1683         // Setup Domain Name ANQP element to TEST_FQDN2 and TEST_FQDN3
1684         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1685         anqpElementMap.put(ANQPElementType.ANQPDomName,
1686                 createDomainNameElement(new String[]{TEST_FQDN2, TEST_FQDN3}));
1687         // Setup RCOIs advertised by the AP
1688         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
1689                 createRoamingConsortiumElement(anqpOis));
1690 
1691         assertEquals(PasspointMatch.None,
1692                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
1693         assertEquals(0, mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
1694     }
1695 
1696     /**
1697      * Helper function for creating a ScanResult for testing.
1698      *
1699      * @return {@link ScanResult}
1700      */
createTestScanResult()1701     private ScanResult createTestScanResult() {
1702         ScanResult scanResult = new ScanResult();
1703         scanResult.SSID = TEST_SSID;
1704         scanResult.BSSID = TEST_BSSID_STRING;
1705         scanResult.hessid = TEST_HESSID;
1706         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID;
1707         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
1708         scanResult.setWifiSsid(WifiSsid.fromString(TEST_SSID_QUOTED));
1709         return scanResult;
1710     }
1711 
1712     /**
1713      * Helper function for creating another ScanResult for testing.
1714      *
1715      * @return {@link ScanResult}
1716      */
createSecondaryTestScanResult()1717     private ScanResult createSecondaryTestScanResult() {
1718         ScanResult scanResult = new ScanResult();
1719         scanResult.SSID = TEST_SSID_2;
1720         scanResult.BSSID = TEST_BSSID_STRING_2;
1721         scanResult.hessid = TEST_HESSID_2;
1722         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID_2;
1723         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
1724         scanResult.setWifiSsid(WifiSsid.fromString(TEST_SSID_2_QUOTED));
1725         return scanResult;
1726     }
1727     /**
1728      * Verify that a home provider is not matched followed by a Deauthentication-imminent WNM
1729      * notification from the AP that covers a specific BSS.
1730      *
1731      * @throws Exception
1732      */
1733     @Test
noMatchWithBlockedBss()1734     public void noMatchWithBlockedBss() throws Exception {
1735         // Setup test provider.
1736         PasspointConfiguration config = generateTestPasspointConfiguration(
1737                 CredentialType.USER, false);
1738         mProvider = createProvider(config);
1739 
1740         // Setup Domain Name ANQP element.
1741         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1742         anqpElementMap.put(ANQPElementType.ANQPDomName,
1743                 createDomainNameElement(new String[]{TEST_FQDN}));
1744         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1745                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1746                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1747 
1748         ScanResult scanResult = createTestScanResult();
1749         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
1750 
1751         // Confirm this is a match under normal circumstances
1752         assertEquals(PasspointMatch.HomeProvider,
1753                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1754 
1755         // Now block the BSS (simulate Deauth-imminent notification)
1756         mProvider.blockBssOrEss(Utils.parseMac(scanResult.BSSID), false, 300 /* Seconds */);
1757 
1758         // Confirm there is no match
1759         assertEquals(PasspointMatch.None,
1760                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1761 
1762         // Now modify the BSSID
1763         scanResult.BSSID = TEST_BSSID_STRING_2;
1764 
1765         // Confirm there is a match
1766         assertEquals(PasspointMatch.HomeProvider,
1767                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1768 
1769         // Now clear the block
1770         mProvider.clearProviderBlock();
1771         scanResult.BSSID = TEST_BSSID_STRING;
1772 
1773         // Confirm this is a match under normal circumstances
1774         assertEquals(PasspointMatch.HomeProvider,
1775                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1776     }
1777 
1778     /**
1779      * Verify that a home provider is not matched followed by a Deauthentication-imminent WNM
1780      * notification from the AP that covers the entire ESS.
1781      *
1782      * @throws Exception
1783      */
1784     @Test
noMatchWithBlockedEss()1785     public void noMatchWithBlockedEss() throws Exception {
1786         // Setup test provider.
1787         PasspointConfiguration config = generateTestPasspointConfiguration(
1788                 CredentialType.USER, false);
1789         mProvider = createProvider(config);
1790 
1791         // Setup Domain Name ANQP element.
1792         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1793         anqpElementMap.put(ANQPElementType.ANQPDomName,
1794                 createDomainNameElement(new String[]{TEST_FQDN}));
1795         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1796                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1797                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1798 
1799         ScanResult scanResult = createTestScanResult();
1800         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
1801 
1802         // Confirm this is a match under normal circumstances
1803         assertEquals(PasspointMatch.HomeProvider,
1804                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1805 
1806         // Now block the BSS (simulate Deauth-imminent notification)
1807         mProvider.blockBssOrEss(Utils.parseMac(scanResult.BSSID), true, 300 /* Seconds */);
1808 
1809         // Confirm there is no match
1810         assertEquals(PasspointMatch.None,
1811                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1812 
1813         // Now modify the BSSID
1814         scanResult.BSSID = TEST_BSSID_STRING_2;
1815 
1816         // Confirm there is no match
1817         assertEquals(PasspointMatch.None,
1818                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1819     }
1820 
1821     /**
1822      * Verify that a home provider that was not matched followed by a Deauthentication-imminent WNM
1823      * notification from the AP is matched again after the reathentication delay expires.
1824      *
1825      * @throws Exception
1826      */
1827     @Test
blockedBssMatchRestoredAfterDelayExpires()1828     public void blockedBssMatchRestoredAfterDelayExpires() throws Exception {
1829         // Setup test provider.
1830         PasspointConfiguration config = generateTestPasspointConfiguration(
1831                 CredentialType.USER, false);
1832         mProvider = createProvider(config);
1833 
1834         // Setup Domain Name ANQP element.
1835         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1836         anqpElementMap.put(ANQPElementType.ANQPDomName,
1837                 createDomainNameElement(new String[]{TEST_FQDN}));
1838         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1839                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1840                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1841 
1842         ScanResult scanResult = createTestScanResult();
1843         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
1844 
1845         // Confirm this is a match under normal circumstances
1846         assertEquals(PasspointMatch.HomeProvider,
1847                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1848 
1849         // Now block the BSS (simulate Deauth-imminent notification)
1850         mProvider.blockBssOrEss(Utils.parseMac(scanResult.BSSID), false, 300 /* Seconds */);
1851 
1852         // Confirm there is no match
1853         assertEquals(PasspointMatch.None,
1854                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1855 
1856         // Now advance the time to some time in the future, after the delay expires
1857         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT
1858                 + (300 * 1000) + 5000);
1859 
1860         // Confirm there is a match now
1861         assertEquals(PasspointMatch.HomeProvider,
1862                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1863     }
1864 
1865 
1866     /**
1867      * Verify that a home provider that was not matched followed by a Deauthentication-imminent WNM
1868      * notification from the AP is matched again after the reathentication delay expires for WNM
1869      * notifications that do not specify an explicit delay (default is 5 minutes in AOSP).
1870      *
1871      * @throws Exception
1872      */
1873     @Test
blockedBssMatchRestoredAfterDelayExpiresNoDelaySpecified()1874     public void blockedBssMatchRestoredAfterDelayExpiresNoDelaySpecified() throws Exception {
1875         // Setup test provider.
1876         PasspointConfiguration config = generateTestPasspointConfiguration(
1877                 CredentialType.USER, false);
1878         mProvider = createProvider(config);
1879 
1880         // Setup Domain Name ANQP element.
1881         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1882         anqpElementMap.put(ANQPElementType.ANQPDomName,
1883                 createDomainNameElement(new String[]{TEST_FQDN}));
1884         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1885                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1886                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1887 
1888         ScanResult scanResult = createTestScanResult();
1889         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
1890 
1891         // Confirm this is a match under normal circumstances
1892         assertEquals(PasspointMatch.HomeProvider,
1893                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1894 
1895         // Now block the BSS (simulate Deauth-imminent notification)
1896         mProvider.blockBssOrEss(Utils.parseMac(scanResult.BSSID), false, 0 /* Seconds */);
1897 
1898         // Confirm there is no match
1899         assertEquals(PasspointMatch.None,
1900                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1901 
1902         // Now advance the time to some time in the future, after the delay expires
1903         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT
1904                 + (MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS));
1905 
1906         // Confirm there is a match now
1907         assertEquals(PasspointMatch.HomeProvider,
1908                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1909     }
1910 
1911     /**
1912      * Verify that a WNM-Notification with some invalid values is ignored and doesn't affect
1913      * the provider
1914      *
1915      * @throws Exception
1916      */
1917     @Test
testNoBlockingWithInvalidWnmData()1918     public void testNoBlockingWithInvalidWnmData() throws Exception {
1919         // Setup test provider.
1920         PasspointConfiguration config = generateTestPasspointConfiguration(
1921                 CredentialType.USER, false);
1922         mProvider = createProvider(config);
1923 
1924         // Setup Domain Name ANQP element.
1925         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1926         anqpElementMap.put(ANQPElementType.ANQPDomName,
1927                 createDomainNameElement(new String[]{TEST_FQDN}));
1928         anqpElementMap.put(ANQPElementType.ANQPNAIRealm,
1929                 createNAIRealmElement(TEST_REALM, EAPConstants.EAP_TTLS,
1930                         new NonEAPInnerAuth(NonEAPInnerAuth.AUTH_TYPE_MSCHAPV2)));
1931 
1932         ScanResult scanResult = createTestScanResult();
1933         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
1934 
1935         // Confirm this is a match under normal circumstances
1936         assertEquals(PasspointMatch.HomeProvider,
1937                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1938 
1939         // Test some invalid values
1940         mProvider.blockBssOrEss(Utils.parseMac(scanResult.BSSID), false, -40 /* Seconds */);
1941         assertEquals(PasspointMatch.HomeProvider,
1942                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1943 
1944         mProvider.blockBssOrEss(0, false, 300 /* Seconds */);
1945         assertEquals(PasspointMatch.HomeProvider,
1946                 mProvider.match(anqpElementMap, mRoamingConsortium, scanResult));
1947     }
1948 
1949     /**
1950      * Verify set and get Anonymous Identity on passpoint provider.
1951      */
1952     @Test
testSetAnonymousIdentity()1953     public void testSetAnonymousIdentity() throws Exception {
1954         PasspointConfiguration config = generateTestPasspointConfiguration(
1955                 CredentialType.SIM, false);
1956         mProvider = createProvider(config);
1957         mProvider.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY);
1958         assertEquals(TEST_ANONYMOUS_IDENTITY, mProvider.getAnonymousIdentity());
1959     }
1960 
1961     /**
1962      * Verify set and get connect choice on passpoint provider.
1963      */
1964     @Test
testSetUserConnectChoice()1965     public void testSetUserConnectChoice() throws Exception {
1966         PasspointConfiguration config = generateTestPasspointConfiguration(
1967                 CredentialType.SIM, false);
1968         mProvider = createProvider(config);
1969         mProvider.setUserConnectChoice(USER_CONNECT_CHOICE, TEST_RSSI);
1970         assertEquals(USER_CONNECT_CHOICE, mProvider.getConnectChoice());
1971         assertEquals(TEST_RSSI, mProvider.getConnectChoiceRssi());
1972         WifiConfiguration configuration = mProvider.getWifiConfig();
1973         assertEquals(USER_CONNECT_CHOICE,
1974                 configuration.getNetworkSelectionStatus().getConnectChoice());
1975         assertEquals(TEST_RSSI, configuration.getNetworkSelectionStatus().getConnectChoiceRssi());
1976     }
1977 
1978 
1979     /**
1980      * Verify that an expected decorated identity prefix is received from getWifiConfig()
1981      *
1982      * @throws Exception
1983      */
1984     @Test
testSetDecoratedIdentityPrefix()1985     public void testSetDecoratedIdentityPrefix() throws Exception {
1986         assumeTrue(SdkLevel.isAtLeastS());
1987         // Create provider for R2.
1988         PasspointConfiguration config = generateTestPasspointConfiguration(
1989                 CredentialType.USER, false);
1990         config.getCredential().setCaCertificates(null);
1991         config.setDecoratedIdentityPrefix(TEST_DECORATED_IDENTITY_PREFIX);
1992         mProvider = createProvider(config);
1993 
1994         assertEquals(TEST_DECORATED_IDENTITY_PREFIX,
1995                 mProvider.getWifiConfig().enterpriseConfig.getDecoratedIdentityPrefix());
1996     }
1997 
1998     @Test
testRcoiMatchMapAgeOut()1999     public void testRcoiMatchMapAgeOut() throws Exception {
2000         // Setup test provider.
2001         PasspointConfiguration config = generateTestPasspointConfiguration(
2002                 CredentialType.SIM, false);
2003         mProvider = createProvider(config);
2004         when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(
2005                 eq(config.getCredential().getSimCredential().getImsi())))
2006                 .thenReturn(new Pair<>(TEST_IMSI, VALID_CARRIER_ID));
2007 
2008         // Setup Roaming Consortium ANQP element.
2009         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
2010         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
2011                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS));
2012 
2013         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT);
2014 
2015         // Roaming provider with RCOI match adds a selected RCOI to the match map
2016         assertEquals(PasspointMatch.RoamingProvider,
2017                 mProvider.match(anqpElementMap, mRoamingConsortium, createTestScanResult()));
2018 
2019         when(mClock.getElapsedSinceBootMillis()).thenReturn(TEST_ELAPSED_TIME_SINCE_BOOT
2020                 + 700_000L);
2021 
2022         anqpElementMap.put(ANQPElementType.ANQPRoamingConsortium,
2023                 createRoamingConsortiumElement(TEST_ANQP_RC_OIS_2));
2024 
2025         // Now a new scan with another SSID and no match after a while
2026         assertEquals(PasspointMatch.None, mProvider.match(anqpElementMap, mRoamingConsortium,
2027                 createSecondaryTestScanResult()));
2028 
2029         // Confirm the selected roaming match map entry for the first SSID is cleared after it was
2030         // aged out
2031         assertEquals(0, mProvider.getAndRemoveMatchedRcoi(TEST_SSID_QUOTED));
2032     }
2033 
2034     /**
2035      * Verify that the {@link PasspointProvider.ConnectionTimeComparator} can be used to sort
2036      * providers in descending order of connection time.
2037      */
2038     @Test
testConnectionTimeComparator()2039     public void testConnectionTimeComparator() throws Exception {
2040         PasspointConfiguration config1 =
2041                 generateTestPasspointConfiguration(CredentialType.SIM, false);
2042         PasspointConfiguration config2 =
2043                 generateTestPasspointConfiguration(CredentialType.SIM, false);
2044         PasspointConfiguration config3 =
2045                 generateTestPasspointConfiguration(CredentialType.SIM, false);
2046         PasspointProvider leastRecentProvider = createProvider(config1);
2047         PasspointProvider recentProvider = createProvider(config2);
2048         PasspointProvider mostRecentProvider = createProvider(config3);
2049 
2050         when(mClock.getWallClockMillis())
2051                 .thenReturn((long) 10)
2052                 .thenReturn((long) 20)
2053                 .thenReturn((long) 30);
2054         leastRecentProvider.updateMostRecentConnectionTime();
2055         recentProvider.updateMostRecentConnectionTime();
2056         mostRecentProvider.updateMostRecentConnectionTime();
2057 
2058         // Initialize the list with providers in ascending order by connection time.
2059         List<PasspointProvider> providerList =
2060                 Arrays.asList(leastRecentProvider, recentProvider, mostRecentProvider);
2061 
2062         // Sort using the comparator. Expect the providers to be in descending order,
2063         // with the most recent provider at the beginning of the list.
2064         Collections.sort(providerList, new PasspointProvider.ConnectionTimeComparator());
2065         assertTrue(mostRecentProvider.equals(providerList.get(0)));
2066         assertTrue(recentProvider.equals(providerList.get(1)));
2067         assertTrue(leastRecentProvider.equals(providerList.get(2)));
2068     }
2069 }
2070