• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi.hotspot2;
18 
19 import static android.app.AppOpsManager.MODE_IGNORED;
20 import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE;
21 
22 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertThat;
28 import static org.junit.Assert.assertTrue;
29 import static org.mockito.ArgumentMatchers.isNull;
30 import static org.mockito.Mockito.any;
31 import static org.mockito.Mockito.anyBoolean;
32 import static org.mockito.Mockito.anyInt;
33 import static org.mockito.Mockito.anyLong;
34 import static org.mockito.Mockito.anyMap;
35 import static org.mockito.Mockito.doThrow;
36 import static org.mockito.Mockito.eq;
37 import static org.mockito.Mockito.lenient;
38 import static org.mockito.Mockito.mock;
39 import static org.mockito.Mockito.never;
40 import static org.mockito.Mockito.reset;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.when;
43 import static org.mockito.MockitoAnnotations.initMocks;
44 
45 import android.app.AppOpsManager;
46 import android.content.Context;
47 import android.content.Intent;
48 import android.net.Uri;
49 import android.net.wifi.EAPConstants;
50 import android.net.wifi.ScanResult;
51 import android.net.wifi.WifiConfiguration;
52 import android.net.wifi.WifiEnterpriseConfig;
53 import android.net.wifi.WifiManager;
54 import android.net.wifi.WifiSsid;
55 import android.net.wifi.hotspot2.IProvisioningCallback;
56 import android.net.wifi.hotspot2.OsuProvider;
57 import android.net.wifi.hotspot2.PasspointConfiguration;
58 import android.net.wifi.hotspot2.pps.Credential;
59 import android.net.wifi.hotspot2.pps.HomeSp;
60 import android.os.Handler;
61 import android.os.Looper;
62 import android.os.UserHandle;
63 import android.os.test.TestLooper;
64 import android.telephony.SubscriptionManager;
65 import android.telephony.TelephonyManager;
66 import android.util.Base64;
67 import android.util.Pair;
68 
69 import androidx.test.filters.SmallTest;
70 
71 import com.android.dx.mockito.inline.extended.ExtendedMockito;
72 import com.android.server.wifi.ClientModeImpl;
73 import com.android.server.wifi.Clock;
74 import com.android.server.wifi.FakeKeys;
75 import com.android.server.wifi.IMSIParameter;
76 import com.android.server.wifi.SIMAccessor;
77 import com.android.server.wifi.ScanDetail;
78 import com.android.server.wifi.WifiConfigManager;
79 import com.android.server.wifi.WifiConfigStore;
80 import com.android.server.wifi.WifiConfigurationTestUtil;
81 import com.android.server.wifi.WifiInjector;
82 import com.android.server.wifi.WifiKeyStore;
83 import com.android.server.wifi.WifiMetrics;
84 import com.android.server.wifi.WifiNative;
85 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
86 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
87 import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
88 import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement;
89 import com.android.server.wifi.hotspot2.anqp.I18Name;
90 import com.android.server.wifi.hotspot2.anqp.NAIRealmData;
91 import com.android.server.wifi.hotspot2.anqp.NAIRealmElement;
92 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo;
93 import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
94 import com.android.server.wifi.util.InformationElementUtil;
95 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
96 
97 import org.junit.Before;
98 import org.junit.Test;
99 import org.mockito.ArgumentCaptor;
100 import org.mockito.Mock;
101 import org.mockito.MockitoSession;
102 
103 import java.nio.charset.StandardCharsets;
104 import java.security.GeneralSecurityException;
105 import java.security.KeyStore;
106 import java.security.cert.X509Certificate;
107 import java.util.ArrayList;
108 import java.util.Arrays;
109 import java.util.HashMap;
110 import java.util.HashSet;
111 import java.util.List;
112 import java.util.Locale;
113 import java.util.Map;
114 import java.util.Set;
115 
116 /**
117  * Unit tests for {@link PasspointManager}.
118  */
119 @SmallTest
120 public class PasspointManagerTest {
121     private static final long BSSID = 0x112233445566L;
122     private static final String TEST_PACKAGE = "com.android.test";
123     private static final String TEST_FQDN = "test1.test.com";
124     private static final String TEST_FQDN2 = "test2.test.com";
125     private static final String TEST_FRIENDLY_NAME = "friendly name";
126     private static final String TEST_FRIENDLY_NAME2 = "second friendly name";
127     private static final String TEST_REALM = "realm.test.com";
128     private static final String TEST_IMSI = "123456*";
129     private static final IMSIParameter TEST_IMSI_PARAM = IMSIParameter.build(TEST_IMSI);
130 
131     private static final long TEST_BSSID = 0x112233445566L;
132     private static final String TEST_SSID = "TestSSID";
133     private static final String TEST_BSSID_STRING = "11:22:33:44:55:66";
134     private static final String TEST_SSID2 = "TestSSID2";
135     private static final String TEST_BSSID_STRING2 = "11:22:33:44:55:77";
136     private static final String TEST_SSID3 = "TestSSID3";
137     private static final String TEST_BSSID_STRING3 = "11:22:33:44:55:88";
138     private static final String TEST_MCC_MNC = "123456";
139     private static final String TEST_3GPP_FQDN = String.format("wlan.mnc%s.mcc%s.3gppnetwork.org",
140             TEST_MCC_MNC.substring(3), TEST_MCC_MNC.substring(0, 3));
141 
142     private static final long TEST_HESSID = 0x5678L;
143     private static final int TEST_ANQP_DOMAIN_ID = 0;
144     private static final int TEST_ANQP_DOMAIN_ID2 = 1;
145     private static final ANQPNetworkKey TEST_ANQP_KEY = ANQPNetworkKey.buildKey(
146             TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID);
147     private static final ANQPNetworkKey TEST_ANQP_KEY2 = ANQPNetworkKey.buildKey(
148             TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID2);
149     private static final int TEST_CREATOR_UID = 1234;
150     private static final int TEST_UID = 1500;
151 
152     @Mock Context mContext;
153     @Mock WifiNative mWifiNative;
154     @Mock WifiKeyStore mWifiKeyStore;
155     @Mock Clock mClock;
156     @Mock SIMAccessor mSimAccessor;
157     @Mock PasspointObjectFactory mObjectFactory;
158     @Mock PasspointEventHandler.Callbacks mCallbacks;
159     @Mock AnqpCache mAnqpCache;
160     @Mock ANQPRequestManager mAnqpRequestManager;
161     @Mock CertificateVerifier mCertVerifier;
162     @Mock WifiConfigManager mWifiConfigManager;
163     @Mock WifiConfigStore mWifiConfigStore;
164     @Mock PasspointConfigSharedStoreData.DataSource mSharedDataSource;
165     @Mock PasspointConfigUserStoreData.DataSource mUserDataSource;
166     @Mock WifiMetrics mWifiMetrics;
167     @Mock OsuNetworkConnection mOsuNetworkConnection;
168     @Mock OsuServerConnection mOsuServerConnection;
169     @Mock PasspointProvisioner mPasspointProvisioner;
170     @Mock IProvisioningCallback mCallback;
171     @Mock WfaKeyStore mWfaKeyStore;
172     @Mock KeyStore mKeyStore;
173     @Mock AppOpsManager mAppOpsManager;
174     @Mock WifiInjector mWifiInjector;
175     @Mock ClientModeImpl mClientModeImpl;
176     @Mock TelephonyManager mTelephonyManager;
177     @Mock TelephonyManager mDataTelephonyManager;
178     @Mock SubscriptionManager mSubscriptionManager;
179 
180     Handler mHandler;
181     TestLooper mLooper;
182     PasspointManager mManager;
183     ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor =
184             ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class);
185 
186     /** Sets up test. */
187     @Before
setUp()188     public void setUp() throws Exception {
189         initMocks(this);
190         when(mObjectFactory.makeAnqpCache(mClock)).thenReturn(mAnqpCache);
191         when(mObjectFactory.makeANQPRequestManager(any(), eq(mClock)))
192                 .thenReturn(mAnqpRequestManager);
193         when(mObjectFactory.makeCertificateVerifier()).thenReturn(mCertVerifier);
194         when(mObjectFactory.makeOsuNetworkConnection(any(Context.class)))
195                 .thenReturn(mOsuNetworkConnection);
196         when(mObjectFactory.makeOsuServerConnection())
197                 .thenReturn(mOsuServerConnection);
198         when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore);
199         when(mWfaKeyStore.get()).thenReturn(mKeyStore);
200         when(mObjectFactory.makePasspointProvisioner(any(Context.class), any(WifiNative.class),
201                 any(PasspointManager.class), any(WifiMetrics.class)))
202                 .thenReturn(mPasspointProvisioner);
203         when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
204         when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl);
205         mLooper = new TestLooper();
206         mHandler = new Handler(mLooper.getLooper());
207         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
208                 mWifiKeyStore, mClock, mSimAccessor, mObjectFactory, mWifiConfigManager,
209                 mWifiConfigStore, mWifiMetrics, mTelephonyManager, mSubscriptionManager);
210         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
211                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
212         verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class),
213                                                          callbacks.capture());
214         ArgumentCaptor<PasspointConfigSharedStoreData.DataSource> sharedDataSource =
215                 ArgumentCaptor.forClass(PasspointConfigSharedStoreData.DataSource.class);
216         verify(mObjectFactory).makePasspointConfigSharedStoreData(sharedDataSource.capture());
217         ArgumentCaptor<PasspointConfigUserStoreData.DataSource> userDataSource =
218                 ArgumentCaptor.forClass(PasspointConfigUserStoreData.DataSource.class);
219         verify(mObjectFactory).makePasspointConfigUserStoreData(
220                 any(WifiKeyStore.class), any(SIMAccessor.class), userDataSource.capture());
221         mCallbacks = callbacks.getValue();
222         mSharedDataSource = sharedDataSource.getValue();
223         mUserDataSource = userDataSource.getValue();
224         // SIM is absent
225         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[0]);
226     }
227 
228     /**
229      * Verify that the given Passpoint configuration matches the one that's added to
230      * the PasspointManager.
231      *
232      * @param expectedConfig The expected installed Passpoint configuration
233      */
verifyInstalledConfig(PasspointConfiguration expectedConfig)234     private void verifyInstalledConfig(PasspointConfiguration expectedConfig) {
235         List<PasspointConfiguration> installedConfigs = mManager.getProviderConfigs();
236         assertEquals(1, installedConfigs.size());
237         assertEquals(expectedConfig, installedConfigs.get(0));
238     }
239 
240     /**
241      * Create a mock PasspointProvider with default expectations.
242      *
243      * @param config The configuration associated with the provider
244      * @return {@link com.android.server.wifi.hotspot2.PasspointProvider}
245      */
createMockProvider(PasspointConfiguration config)246     private PasspointProvider createMockProvider(PasspointConfiguration config) {
247         PasspointProvider provider = mock(PasspointProvider.class);
248         when(provider.installCertsAndKeys()).thenReturn(true);
249         lenient().when(provider.getConfig()).thenReturn(config);
250         return provider;
251     }
252 
253     /**
254      * Helper function for creating a test configuration with user credential.
255      *
256      * @return {@link PasspointConfiguration}
257      */
createTestConfigWithUserCredential(String fqdn, String friendlyName)258     private PasspointConfiguration createTestConfigWithUserCredential(String fqdn,
259             String friendlyName) {
260         PasspointConfiguration config = new PasspointConfiguration();
261         HomeSp homeSp = new HomeSp();
262         homeSp.setFqdn(fqdn);
263         homeSp.setFriendlyName(friendlyName);
264         config.setHomeSp(homeSp);
265         Map<String, String> friendlyNames = new HashMap<>();
266         friendlyNames.put("en", friendlyName);
267         friendlyNames.put("kr", friendlyName + 1);
268         friendlyNames.put("jp", friendlyName + 2);
269         config.setServiceFriendlyNames(friendlyNames);
270         Credential credential = new Credential();
271         credential.setRealm(TEST_REALM);
272         credential.setCaCertificate(FakeKeys.CA_CERT0);
273         Credential.UserCredential userCredential = new Credential.UserCredential();
274         userCredential.setUsername("username");
275         userCredential.setPassword("password");
276         userCredential.setEapType(EAPConstants.EAP_TTLS);
277         userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP);
278         credential.setUserCredential(userCredential);
279         config.setCredential(credential);
280         return config;
281     }
282 
283     /**
284      * Helper function for creating a test configuration with SIM credential.
285      *
286      * @return {@link PasspointConfiguration}
287      */
createTestConfigWithSimCredential(String fqdn, String imsi, String realm)288     private PasspointConfiguration createTestConfigWithSimCredential(String fqdn, String imsi,
289             String realm) {
290         PasspointConfiguration config = new PasspointConfiguration();
291         HomeSp homeSp = new HomeSp();
292         homeSp.setFqdn(fqdn);
293         homeSp.setFriendlyName(TEST_FRIENDLY_NAME);
294         config.setHomeSp(homeSp);
295         Credential credential = new Credential();
296         credential.setRealm(TEST_REALM);
297         Credential.SimCredential simCredential = new Credential.SimCredential();
298         simCredential.setImsi(imsi);
299         simCredential.setEapType(EAPConstants.EAP_SIM);
300         credential.setSimCredential(simCredential);
301         config.setCredential(credential);
302         return config;
303     }
304 
305     /**
306      * Helper function for adding a test provider to the manager.  Return the mock
307      * provider that's added to the manager.
308      *
309      * @return {@link PasspointProvider}
310      */
addTestProvider(String fqdn, String friendlyName, String packageName)311     private PasspointProvider addTestProvider(String fqdn, String friendlyName,
312             String packageName) {
313         PasspointConfiguration config = createTestConfigWithUserCredential(fqdn, friendlyName);
314         PasspointProvider provider = createMockProvider(config);
315         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
316                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
317                 provider);
318         when(provider.getPackageName()).thenReturn(packageName);
319         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
320         return provider;
321     }
322 
323     /**
324      * Helper function for adding a test provider with SIM credentials to the manager.  Return the
325      * mock provider that's added to the manager.
326      *
327      * @return {@link PasspointProvider}
328      */
addTestCarrierProvider(String fqdn, String imsi, String realm)329     private PasspointProvider addTestCarrierProvider(String fqdn, String imsi, String realm) {
330         PasspointConfiguration config = createTestConfigWithSimCredential(fqdn, imsi, realm);
331         PasspointProvider provider = createMockProvider(config);
332         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
333                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
334                 provider);
335 
336         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
337 
338         return provider;
339     }
340 
341     /**
342      * Helper function for creating a ScanResult for testing.
343      *
344      * @return {@link ScanResult}
345      */
createTestScanResult()346     private ScanResult createTestScanResult() {
347         ScanResult scanResult = new ScanResult();
348         scanResult.SSID = TEST_SSID;
349         scanResult.BSSID = TEST_BSSID_STRING;
350         scanResult.hessid = TEST_HESSID;
351         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID;
352         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
353         return scanResult;
354     }
355 
356     /**
357      * Helper function for creating a ScanResult for testing.
358      *
359      * @return {@link ScanResult}
360      */
createTestScanResults()361     private List<ScanResult> createTestScanResults() {
362         List<ScanResult> scanResults = new ArrayList<>();
363 
364         // Passpoint AP
365         ScanResult scanResult = new ScanResult();
366         scanResult.SSID = TEST_SSID;
367         scanResult.BSSID = TEST_BSSID_STRING;
368         scanResult.hessid = TEST_HESSID;
369         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
370         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID2;
371         scanResults.add(scanResult);
372 
373         // Non-Passpoint AP
374         ScanResult scanResult2 = new ScanResult();
375         scanResult2.SSID = TEST_SSID2;
376         scanResult2.BSSID = TEST_BSSID_STRING2;
377         scanResult2.hessid = TEST_HESSID;
378         scanResult2.flags = 0;
379         scanResults.add(scanResult2);
380 
381         // Passpoint AP
382         ScanResult scanResult3 = new ScanResult();
383         scanResult3.SSID = TEST_SSID3;
384         scanResult3.BSSID = TEST_BSSID_STRING3;
385         scanResult3.hessid = TEST_HESSID;
386         scanResult3.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
387         scanResult3.anqpDomainId = TEST_ANQP_DOMAIN_ID2;
388         scanResults.add(scanResult3);
389 
390         return scanResults;
391     }
392 
393     /**
394      * Helper function for generating {@link ScanDetail} for testing.
395      */
generateScanDetail(String ssid, String bssid, long hessid, int anqpDomaiId, boolean isPasspoint)396     private ScanDetail generateScanDetail(String ssid, String bssid, long hessid, int anqpDomaiId,
397             boolean isPasspoint) {
398         NetworkDetail networkDetail = mock(NetworkDetail.class);
399 
400         ScanDetail scanDetail = mock(ScanDetail.class);
401         ScanResult scanResult = new ScanResult();
402         scanResult.SSID = ssid;
403         scanResult.BSSID = bssid;
404         scanResult.hessid = hessid;
405         scanResult.anqpDomainId = anqpDomaiId;
406         if (isPasspoint) {
407             lenient().when(networkDetail.isInterworking()).thenReturn(true);
408             scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
409         } else {
410             lenient().when(networkDetail.isInterworking()).thenReturn(false);
411         }
412 
413         lenient().when(scanDetail.getScanResult()).thenReturn(scanResult);
414         lenient().when(scanDetail.getNetworkDetail()).thenReturn(networkDetail);
415         return scanDetail;
416     }
417 
418     /**
419      * Verify that the ANQP elements will be added to the ANQP cache on receiving a successful
420      * response.
421      *
422      * @throws Exception
423      */
424     @Test
anqpResponseSuccess()425     public void anqpResponseSuccess() throws Exception {
426         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
427         anqpElementMap.put(ANQPElementType.ANQPDomName,
428                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
429 
430         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(TEST_ANQP_KEY);
431         mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap);
432         verify(mAnqpCache).addEntry(TEST_ANQP_KEY, anqpElementMap);
433         verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class),
434                 any(String.class));
435     }
436 
437     /**
438      * Verify that no ANQP elements will be added to the ANQP cache on receiving a successful
439      * response for a request that's not sent by us.
440      *
441      * @throws Exception
442      */
443     @Test
anqpResponseSuccessWithUnknownRequest()444     public void anqpResponseSuccessWithUnknownRequest() throws Exception {
445         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
446         anqpElementMap.put(ANQPElementType.ANQPDomName,
447                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
448 
449         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(null);
450         mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap);
451         verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap());
452     }
453 
454     /**
455      * Verify that no ANQP elements will be added to the ANQP cache on receiving a failure response.
456      *
457      * @throws Exception
458      */
459     @Test
anqpResponseFailure()460     public void anqpResponseFailure() throws Exception {
461         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, false)).thenReturn(TEST_ANQP_KEY);
462         mCallbacks.onANQPResponse(TEST_BSSID, null);
463         verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap());
464 
465     }
466 
467     /**
468      * Verify that adding a provider with a null configuration will fail.
469      *
470      * @throws Exception
471      */
472     @Test
addProviderWithNullConfig()473     public void addProviderWithNullConfig() throws Exception {
474         assertFalse(mManager.addOrUpdateProvider(null, TEST_CREATOR_UID, TEST_PACKAGE));
475         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
476         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
477     }
478 
479     /**
480      * Verify that adding a provider with a empty configuration will fail.
481      *
482      * @throws Exception
483      */
484     @Test
addProviderWithEmptyConfig()485     public void addProviderWithEmptyConfig() throws Exception {
486         assertFalse(mManager.addOrUpdateProvider(new PasspointConfiguration(), TEST_CREATOR_UID,
487                 TEST_PACKAGE));
488         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
489         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
490     }
491 
492     /**
493      * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS
494      * for user credential).
495      *
496      * @throws Exception
497      */
498     @Test
addProviderWithInvalidCredential()499     public void addProviderWithInvalidCredential() throws Exception {
500         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
501                 TEST_FRIENDLY_NAME);
502         // EAP-TLS not allowed for user credential.
503         config.getCredential().getUserCredential().setEapType(EAPConstants.EAP_TLS);
504         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
505         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
506         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
507     }
508 
509     /**
510      * Verify that adding a provider with a valid configuration and user credential will succeed.
511      *
512      * @throws Exception
513      */
514     @Test
addRemoveProviderWithValidUserCredential()515     public void addRemoveProviderWithValidUserCredential() throws Exception {
516         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
517                 TEST_FRIENDLY_NAME);
518         PasspointProvider provider = createMockProvider(config);
519         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
520         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
521                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
522                 provider);
523         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
524         verifyInstalledConfig(config);
525         verify(mWifiConfigManager).saveToStore(true);
526         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
527         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
528         verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE), any(
529                 AppOpsManager.OnOpChangedListener.class));
530         reset(mWifiMetrics);
531         reset(mWifiConfigManager);
532 
533         // Verify content in the data source.
534         List<PasspointProvider> providers = mUserDataSource.getProviders();
535         assertEquals(1, providers.size());
536         assertEquals(config, providers.get(0).getConfig());
537         // Provider index start with 0, should be 1 after adding a provider.
538         assertEquals(1, mSharedDataSource.getProviderIndex());
539 
540         // Remove the provider.
541         assertTrue(mManager.removeProvider(TEST_FQDN));
542         verify(provider).uninstallCertsAndKeys();
543         verify(mWifiConfigManager).saveToStore(true);
544         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
545         verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess();
546         verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class));
547         assertTrue(mManager.getProviderConfigs().isEmpty());
548 
549         // Verify content in the data source.
550         assertTrue(mUserDataSource.getProviders().isEmpty());
551         // Removing a provider should not change the provider index.
552         assertEquals(1, mSharedDataSource.getProviderIndex());
553     }
554 
555     /**
556      * Verify that adding a provider with a valid configuration and SIM credential will succeed.
557      *
558      * @throws Exception
559      */
560     @Test
addRemoveProviderWithValidSimCredential()561     public void addRemoveProviderWithValidSimCredential() throws Exception {
562         PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
563                 TEST_REALM);
564         PasspointProvider provider = createMockProvider(config);
565         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
566                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
567                 provider);
568         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
569         verifyInstalledConfig(config);
570         verify(mWifiConfigManager).saveToStore(true);
571         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
572         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
573         reset(mWifiMetrics);
574         reset(mWifiConfigManager);
575 
576         // Verify content in the data source.
577         List<PasspointProvider> providers = mUserDataSource.getProviders();
578         assertEquals(1, providers.size());
579         assertEquals(config, providers.get(0).getConfig());
580         // Provider index start with 0, should be 1 after adding a provider.
581         assertEquals(1, mSharedDataSource.getProviderIndex());
582 
583         // Remove the provider.
584         assertTrue(mManager.removeProvider(TEST_FQDN));
585         verify(provider).uninstallCertsAndKeys();
586         verify(mWifiConfigManager).saveToStore(true);
587         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
588         verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess();
589         assertTrue(mManager.getProviderConfigs().isEmpty());
590 
591         // Verify content in the data source.
592         assertTrue(mUserDataSource.getProviders().isEmpty());
593         // Removing a provider should not change the provider index.
594         assertEquals(1, mSharedDataSource.getProviderIndex());
595     }
596 
597     /**
598      * Verify that adding a provider with the same base domain as the existing provider will
599      * succeed, and verify that the existing provider is replaced by the new provider with
600      * the new configuration.
601      *
602      * @throws Exception
603      */
604     @Test
addProviderWithExistingConfig()605     public void addProviderWithExistingConfig() throws Exception {
606         // Add a provider with the original configuration.
607         PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
608                 TEST_REALM);
609         PasspointProvider origProvider = createMockProvider(origConfig);
610         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
611                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
612                 origProvider);
613         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE));
614         verifyInstalledConfig(origConfig);
615         verify(mWifiConfigManager).saveToStore(true);
616         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
617         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
618         reset(mWifiMetrics);
619         reset(mWifiConfigManager);
620 
621         // Verify data source content.
622         List<PasspointProvider> origProviders = mUserDataSource.getProviders();
623         assertEquals(1, origProviders.size());
624         assertEquals(origConfig, origProviders.get(0).getConfig());
625         assertEquals(1, mSharedDataSource.getProviderIndex());
626 
627         // Add another provider with the same base domain as the existing provider.
628         // This should replace the existing provider with the new configuration.
629         PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN,
630                 TEST_FRIENDLY_NAME);
631         PasspointProvider newProvider = createMockProvider(newConfig);
632         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
633                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
634                 newProvider);
635         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE));
636         verifyInstalledConfig(newConfig);
637         verify(mWifiConfigManager).saveToStore(true);
638         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
639         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
640 
641         // Verify data source content.
642         List<PasspointProvider> newProviders = mUserDataSource.getProviders();
643         assertEquals(1, newProviders.size());
644         assertEquals(newConfig, newProviders.get(0).getConfig());
645         assertEquals(2, mSharedDataSource.getProviderIndex());
646     }
647 
648     /**
649      * Verify that adding a provider will fail when failing to install certificates and
650      * key to the keystore.
651      *
652      * @throws Exception
653      */
654     @Test
addProviderOnKeyInstallationFailiure()655     public void addProviderOnKeyInstallationFailiure() throws Exception {
656         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
657                 TEST_FRIENDLY_NAME);
658         PasspointProvider provider = mock(PasspointProvider.class);
659         when(provider.installCertsAndKeys()).thenReturn(false);
660         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
661                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
662                 provider);
663         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
664         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
665         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
666     }
667 
668     /**
669      * Verify that adding a provider with an invalid CA certificate will fail.
670      *
671      * @throws Exception
672      */
673     @Test
addProviderWithInvalidCaCert()674     public void addProviderWithInvalidCaCert() throws Exception {
675         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
676                 TEST_FRIENDLY_NAME);
677         doThrow(new GeneralSecurityException())
678                 .when(mCertVerifier).verifyCaCert(any(X509Certificate.class));
679         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
680         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
681         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
682     }
683 
684     /**
685      * Verify that adding a provider with R2 configuration will not perform CA certificate
686      * verification.
687      *
688      * @throws Exception
689      */
690     @Test
addProviderWithR2Config()691     public void addProviderWithR2Config() throws Exception {
692         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
693                 TEST_FRIENDLY_NAME);
694         config.setUpdateIdentifier(1);
695         PasspointProvider provider = createMockProvider(config);
696         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
697                 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
698                 provider);
699         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
700         verify(mCertVerifier, never()).verifyCaCert(any(X509Certificate.class));
701         verifyInstalledConfig(config);
702         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
703         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
704     }
705 
706     /**
707      * Verify that removing a non-existing provider will fail.
708      *
709      * @throws Exception
710      */
711     @Test
removeNonExistingProvider()712     public void removeNonExistingProvider() throws Exception {
713         assertFalse(mManager.removeProvider(TEST_FQDN));
714         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
715         verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess();
716     }
717 
718     /**
719      * Verify that a {code null} will be returned when no providers are installed.
720      *
721      * @throws Exception
722      */
723     @Test
matchProviderWithNoProvidersInstalled()724     public void matchProviderWithNoProvidersInstalled() throws Exception {
725         assertNull(mManager.matchProvider(createTestScanResult()));
726     }
727 
728     /**
729      * Verify that a {code null} be returned when ANQP entry doesn't exist in the cache.
730      *
731      * @throws Exception
732      */
733     @Test
matchProviderWithAnqpCacheMissed()734     public void matchProviderWithAnqpCacheMissed() throws Exception {
735         addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
736 
737         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
738         assertNull(mManager.matchProvider(createTestScanResult()));
739         // Verify that a request for ANQP elements is initiated.
740         verify(mAnqpRequestManager).requestANQPElements(eq(TEST_BSSID), any(ANQPNetworkKey.class),
741                 anyBoolean(), anyBoolean());
742     }
743 
744     /**
745      * Verify that the expected provider will be returned when a HomeProvider is matched.
746      *
747      * @throws Exception
748      */
749     @Test
matchProviderAsHomeProvider()750     public void matchProviderAsHomeProvider() throws Exception {
751         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
752         ANQPData entry = new ANQPData(mClock, null);
753 
754         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
755         when(provider.match(anyMap(), any(RoamingConsortium.class)))
756             .thenReturn(PasspointMatch.HomeProvider);
757         Pair<PasspointProvider, PasspointMatch> result =
758                 mManager.matchProvider(createTestScanResult());
759         assertEquals(PasspointMatch.HomeProvider, result.second);
760         assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
761     }
762 
763     /**
764      * Verify that the expected provider will be returned when a RoamingProvider is matched.
765      *
766      * @throws Exception
767      */
768     @Test
matchProviderAsRoamingProvider()769     public void matchProviderAsRoamingProvider() throws Exception {
770         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
771         ANQPData entry = new ANQPData(mClock, null);
772 
773         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
774         when(provider.match(anyMap(), any(RoamingConsortium.class)))
775             .thenReturn(PasspointMatch.RoamingProvider);
776         Pair<PasspointProvider, PasspointMatch> result =
777                 mManager.matchProvider(createTestScanResult());
778         assertEquals(PasspointMatch.RoamingProvider, result.second);
779         assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
780     }
781 
782     /**
783      * Verify that a {code null} will be returned when there is no matching provider.
784      *
785      * @throws Exception
786      */
787     @Test
matchProviderWithNoMatch()788     public void matchProviderWithNoMatch() throws Exception {
789         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
790         ANQPData entry = new ANQPData(mClock, null);
791 
792         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
793         when(provider.match(anyMap(), any(RoamingConsortium.class)))
794             .thenReturn(PasspointMatch.None);
795         assertNull(mManager.matchProvider(createTestScanResult()));
796     }
797 
798     /**
799      * Verify the expectations for sweepCache.
800      *
801      * @throws Exception
802      */
803     @Test
sweepCache()804     public void sweepCache() throws Exception {
805         mManager.sweepCache();
806         verify(mAnqpCache).sweep();
807     }
808 
809     /**
810      * Verify that an empty map will be returned if ANQP elements are not cached for the given AP.
811      *
812      * @throws Exception
813      */
814     @Test
getANQPElementsWithNoMatchFound()815     public void getANQPElementsWithNoMatchFound() throws Exception {
816         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
817         assertTrue(mManager.getANQPElements(createTestScanResult()).isEmpty());
818     }
819 
820     /**
821      * Verify that an expected ANQP elements will be returned if ANQP elements are cached for the
822      * given AP.
823      *
824      * @throws Exception
825      */
826     @Test
getANQPElementsWithMatchFound()827     public void getANQPElementsWithMatchFound() throws Exception {
828         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
829         anqpElementMap.put(ANQPElementType.ANQPDomName,
830                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
831         ANQPData entry = new ANQPData(mClock, anqpElementMap);
832 
833         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
834         assertEquals(anqpElementMap, mManager.getANQPElements(createTestScanResult()));
835     }
836 
837     /**
838      * Verify that an expected map of FQDN and a list of ScanResult will be returned when provided
839      * scanResults are matched to installed Passpoint profiles.
840      */
841     @Test
getAllMatchingFqdnsForScanResults()842     public void getAllMatchingFqdnsForScanResults() {
843         // static mocking
844         MockitoSession session =
845                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
846                         InformationElementUtil.class).startMocking();
847         try {
848             PasspointProvider providerHome = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME,
849                     TEST_PACKAGE);
850             WifiConfiguration homeWifiConfiguration = new WifiConfiguration();
851             homeWifiConfiguration.FQDN = TEST_FQDN + 0;
852             homeWifiConfiguration.isHomeProviderNetwork = true;
853             PasspointProvider providerRoaming = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
854                     TEST_PACKAGE);
855             WifiConfiguration roamingWifiConfiguration = new WifiConfiguration();
856             roamingWifiConfiguration.FQDN = TEST_FQDN + 1;
857             PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
858                     TEST_PACKAGE);
859             ANQPData entry = new ANQPData(mClock, null);
860             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
861             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
862 
863             when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry);
864             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
865             when(providerHome.match(anyMap(), isNull()))
866                     .thenReturn(PasspointMatch.HomeProvider);
867             when(providerRoaming.match(anyMap(), isNull()))
868                     .thenReturn(PasspointMatch.RoamingProvider);
869             when(providerNone.match(anyMap(), isNull()))
870                     .thenReturn(PasspointMatch.None);
871 
872             lenient().when(providerHome.getWifiConfig()).thenReturn(homeWifiConfiguration);
873             lenient().when(providerRoaming.getWifiConfig()).thenReturn(roamingWifiConfiguration);
874             lenient().when(providerNone.getWifiConfig()).thenReturn(new WifiConfiguration());
875 
876             Map<String, Map<Integer, List<ScanResult>>> configs =
877                     mManager.getAllMatchingFqdnsForScanResults(
878                             createTestScanResults());
879 
880             // Expects to be matched with home Provider for each AP (two APs).
881             assertEquals(2, configs.get(TEST_FQDN + 0).get(
882                     WifiManager.PASSPOINT_HOME_NETWORK).size());
883             assertFalse(
884                     configs.get(TEST_FQDN + 0).containsKey(WifiManager.PASSPOINT_ROAMING_NETWORK));
885 
886             // Expects to be matched with roaming Provider for each AP (two APs).
887             assertEquals(2, configs.get(TEST_FQDN + 1).get(
888                     WifiManager.PASSPOINT_ROAMING_NETWORK).size());
889             assertFalse(configs.get(TEST_FQDN + 1).containsKey(WifiManager.PASSPOINT_HOME_NETWORK));
890 
891         } finally {
892             session.finishMocking();
893         }
894     }
895 
896     /**
897      * Verify that an expected list of {@link WifiConfiguration} will be returned when provided
898      * a list of FQDN is matched to installed Passpoint profiles.
899      */
900     @Test
getWifiConfigsForPasspointProfiles()901     public void getWifiConfigsForPasspointProfiles() {
902         PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
903         WifiConfiguration wifiConfiguration1 = new WifiConfiguration();
904         wifiConfiguration1.FQDN = TEST_FQDN;
905         PasspointProvider provider2 = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
906                 TEST_PACKAGE);
907         WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
908         wifiConfiguration2.FQDN = TEST_FQDN + 1;
909         PasspointProvider provider3 = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
910                 TEST_PACKAGE);
911         WifiConfiguration wifiConfiguration3 = new WifiConfiguration();
912         wifiConfiguration3.FQDN = TEST_FQDN + 2;
913         lenient().when(provider1.getWifiConfig()).thenReturn(wifiConfiguration1);
914         lenient().when(provider2.getWifiConfig()).thenReturn(wifiConfiguration2);
915         lenient().when(provider3.getWifiConfig()).thenReturn(wifiConfiguration3);
916 
917         assertEquals(3, mManager.getWifiConfigsForPasspointProfiles(
918                 Arrays.asList(TEST_FQDN, TEST_FQDN + 1, TEST_FQDN + 2)).size());
919     }
920 
921     /**
922      * Verify that an empty map will be returned when trying to get all matching FQDN for a {@code
923      * null} {@link ScanResult}.
924      */
925     @Test
getAllMatchingFqdnsForScanResultsWithNullScanResult()926     public void getAllMatchingFqdnsForScanResultsWithNullScanResult() throws Exception {
927         assertEquals(0, mManager.getAllMatchingFqdnsForScanResults(null).size());
928     }
929 
930     /**
931      * Verify that an empty map will be returned when trying to get a all matching FQDN for a {@link
932      * ScanResult} with a {@code null} BSSID.
933      */
934     @Test
getAllMatchingFqdnsForScanResultsWithNullBSSID()935     public void getAllMatchingFqdnsForScanResultsWithNullBSSID() throws Exception {
936         ScanResult scanResult = createTestScanResult();
937         scanResult.BSSID = null;
938 
939         assertEquals(0,
940                 mManager.getAllMatchingFqdnsForScanResults(Arrays.asList(scanResult)).size());
941     }
942 
943     /**
944      * Verify that an empty map will be returned when trying to get all matching FQDN for a {@link
945      * ScanResult} with an invalid BSSID.
946      */
947     @Test
ggetAllMatchingFqdnsForScanResultsWithInvalidBSSID()948     public void ggetAllMatchingFqdnsForScanResultsWithInvalidBSSID() throws Exception {
949         ScanResult scanResult = createTestScanResult();
950         scanResult.BSSID = "asdfdasfas";
951 
952         assertEquals(0,
953                 mManager.getAllMatchingFqdnsForScanResults(Arrays.asList(scanResult)).size());
954     }
955 
956     /**
957      * Verify that an empty map will be returned when trying to get all matching FQDN for a
958      * non-Passpoint AP.
959      */
960     @Test
getAllMatchingFqdnsForScanResultsForNonPasspointAP()961     public void getAllMatchingFqdnsForScanResultsForNonPasspointAP() throws Exception {
962         ScanResult scanResult = createTestScanResult();
963         scanResult.flags = 0;
964         assertEquals(0,
965                 mManager.getAllMatchingFqdnsForScanResults(Arrays.asList(scanResult)).size());
966     }
967 
968     /**
969      * Verify that an empty list will be returned when retrieving OSU providers for an AP with
970      * null scan result.
971      *
972      * @throws Exception
973      */
974     @Test
getMatchingOsuProvidersForNullScanResult()975     public void getMatchingOsuProvidersForNullScanResult() throws Exception {
976         assertTrue(mManager.getMatchingOsuProviders(null).isEmpty());
977     }
978 
979     /**
980      * Verify that an empty list will be returned when retrieving OSU providers for an AP with
981      * invalid BSSID.
982      *
983      * @throws Exception
984      */
985     @Test
getMatchingOsuProvidersForInvalidBSSID()986     public void getMatchingOsuProvidersForInvalidBSSID() throws Exception {
987         ScanResult scanResult = createTestScanResult();
988         scanResult.BSSID = "asdfdasfas";
989         assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty());
990     }
991 
992     /**
993      * Verify that an empty list will be returned when retrieving OSU providers for a
994      * non-Passpoint AP.
995      *
996      * @throws Exception
997      */
998     @Test
getMatchingOsuProvidersForNonPasspointAP()999     public void getMatchingOsuProvidersForNonPasspointAP() throws Exception {
1000         ScanResult scanResult = createTestScanResult();
1001         scanResult.flags = 0;
1002         assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty());
1003     }
1004 
1005     /**
1006      * Verify that an empty list will be returned when no match is found from the ANQP cache.
1007      *
1008      * @throws Exception
1009      */
1010     @Test
getMatchingOsuProviderWithNoMatch()1011     public void getMatchingOsuProviderWithNoMatch() throws Exception {
1012         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
1013         assertTrue(
1014                 mManager.getMatchingOsuProviders(Arrays.asList(createTestScanResult())).isEmpty());
1015     }
1016 
1017     /**
1018      * Verify that an expected provider list will be returned when a match is found from
1019      * the ANQP cache with a given list of scanResult.
1020      *
1021      * @throws Exception
1022      */
1023     @Test
getMatchingOsuProvidersWithMatch()1024     public void getMatchingOsuProvidersWithMatch() throws Exception {
1025         // Setup OSU providers ANQP element for AP1.
1026         List<OsuProviderInfo> providerInfoListOfAp1 = new ArrayList<>();
1027         Map<ANQPElementType, ANQPElement> anqpElementMapOfAp1 = new HashMap<>();
1028         Set<OsuProvider> expectedOsuProvidersForDomainId = new HashSet<>();
1029 
1030         // Setup OSU providers ANQP element for AP2.
1031         List<OsuProviderInfo> providerInfoListOfAp2 = new ArrayList<>();
1032         Map<ANQPElementType, ANQPElement> anqpElementMapOfAp2 = new HashMap<>();
1033         Set<OsuProvider> expectedOsuProvidersForDomainId2 = new HashSet<>();
1034         int osuProviderCount = 4;
1035 
1036         // static mocking
1037         MockitoSession session =
1038                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
1039                         InformationElementUtil.class).startMocking();
1040         try {
1041             for (int i = 0; i < osuProviderCount; i++) {
1042                 // Test data.
1043                 String friendlyName = "Test Provider" + i;
1044                 String serviceDescription = "Dummy Service" + i;
1045                 Uri serverUri = Uri.parse("https://" + "test" + i + ".com");
1046                 String nai = "access.test.com";
1047                 List<Integer> methodList = Arrays.asList(1);
1048                 List<I18Name> friendlyNames = Arrays.asList(
1049                         new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, friendlyName));
1050                 List<I18Name> serviceDescriptions = Arrays.asList(
1051                         new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH,
1052                                 serviceDescription));
1053                 Map<String, String> friendlyNameMap = new HashMap<>();
1054                 friendlyNames.forEach(e -> friendlyNameMap.put(e.getLanguage(), e.getText()));
1055 
1056                 expectedOsuProvidersForDomainId.add(new OsuProvider(
1057                         null, friendlyNameMap, serviceDescription,
1058                         serverUri, nai, methodList, null));
1059 
1060                 // add All OSU Providers for AP1.
1061                 providerInfoListOfAp1.add(new OsuProviderInfo(
1062                         friendlyNames, serverUri, methodList, null, nai, serviceDescriptions));
1063 
1064                 // add only half of All OSU Providers for AP2.
1065                 if (i >= osuProviderCount / 2) {
1066                     providerInfoListOfAp2.add(new OsuProviderInfo(
1067                             friendlyNames, serverUri, methodList, null, nai, serviceDescriptions));
1068                     expectedOsuProvidersForDomainId2.add(new OsuProvider(
1069                             null, friendlyNameMap, serviceDescription,
1070                             serverUri, nai, methodList,
1071                             null));
1072                 }
1073             }
1074             anqpElementMapOfAp1.put(ANQPElementType.HSOSUProviders,
1075                     new HSOsuProvidersElement(WifiSsid.createFromAsciiEncoded("Test SSID"),
1076                             providerInfoListOfAp1));
1077             ANQPData anqpData = new ANQPData(mClock, anqpElementMapOfAp1);
1078             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(anqpData);
1079 
1080             anqpElementMapOfAp2.put(ANQPElementType.HSOSUProviders,
1081                     new HSOsuProvidersElement(WifiSsid.createFromAsciiEncoded("Test SSID2"),
1082                             providerInfoListOfAp2));
1083             ANQPData anqpData2 = new ANQPData(mClock, anqpElementMapOfAp2);
1084             when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(anqpData2);
1085 
1086             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1087 
1088             // ANQP_DOMAIN_ID(TEST_ANQP_KEY)
1089             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
1090             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1091             assertEquals(mManager.getMatchingOsuProviders(
1092                     Arrays.asList(createTestScanResult())).keySet(),
1093                     expectedOsuProvidersForDomainId);
1094 
1095             // ANQP_DOMAIN_ID2(TEST_ANQP_KEY2)
1096             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
1097             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1098             assertEquals(mManager.getMatchingOsuProviders(
1099                     createTestScanResults()).keySet(), expectedOsuProvidersForDomainId2);
1100         } finally {
1101             session.finishMocking();
1102         }
1103     }
1104 
1105     /**
1106      * Verify that matching Passpoint configurations will be returned as map with corresponding
1107      * OSU providers.
1108      */
1109     @Test
getMatchingPasspointConfigsForOsuProvidersWithMatch()1110     public void getMatchingPasspointConfigsForOsuProvidersWithMatch() {
1111         PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1112         PasspointProvider provider2 = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2,
1113                 TEST_PACKAGE);
1114 
1115         List<OsuProvider> osuProviders = new ArrayList<>();
1116         Map<String, String> friendlyNames = new HashMap<>();
1117         friendlyNames.put("en", "NO-MATCH-NAME");
1118         friendlyNames.put("kr", TEST_FRIENDLY_NAME + 1);
1119 
1120         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1121                 friendlyNames));
1122         friendlyNames = new HashMap<>();
1123         friendlyNames.put("en", TEST_FRIENDLY_NAME2);
1124         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1125                 friendlyNames));
1126 
1127         Map<OsuProvider, PasspointConfiguration> results =
1128                 mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders);
1129 
1130         assertEquals(2, results.size());
1131         assertThat(Arrays.asList(provider1.getConfig(), provider2.getConfig()),
1132                 containsInAnyOrder(results.values().toArray()));
1133     }
1134 
1135     /**
1136      * Verify that empty map will be returned when there is no matching Passpoint configuration.
1137      */
1138     @Test
getMatchingPasspointConfigsForOsuProvidersWitNoMatch()1139     public void getMatchingPasspointConfigsForOsuProvidersWitNoMatch() {
1140         addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1141         addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE);
1142 
1143         List<OsuProvider> osuProviders = new ArrayList<>();
1144 
1145         Map<String, String> friendlyNames = new HashMap<>();
1146         friendlyNames.put("en", "NO-MATCH-NAME");
1147         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1148                 friendlyNames));
1149         friendlyNames = new HashMap<>();
1150         friendlyNames.put("en", "NO-MATCH-NAME-2");
1151         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1152                 friendlyNames));
1153 
1154         assertEquals(0, mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders).size());
1155     }
1156 
1157     /**
1158      * Verify that the provider list maintained by the PasspointManager after the list is updated
1159      * in the data source.
1160      *
1161      * @throws Exception
1162      */
1163     @Test
verifyProvidersAfterDataSourceUpdate()1164     public void verifyProvidersAfterDataSourceUpdate() throws Exception {
1165         // Update the provider list in the data source.
1166         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
1167                 TEST_FRIENDLY_NAME);
1168         PasspointProvider provider = createMockProvider(config);
1169         List<PasspointProvider> providers = new ArrayList<>();
1170         providers.add(provider);
1171         mUserDataSource.setProviders(providers);
1172 
1173         // Verify the providers maintained by PasspointManager.
1174         assertEquals(1, mManager.getProviderConfigs().size());
1175         assertEquals(config, mManager.getProviderConfigs().get(0));
1176     }
1177 
1178     /**
1179      * Verify that the provider index used by PasspointManager is updated after it is updated in
1180      * the data source.
1181      *
1182      * @throws Exception
1183      */
1184     @Test
verifyProviderIndexAfterDataSourceUpdate()1185     public void verifyProviderIndexAfterDataSourceUpdate() throws Exception {
1186         long providerIndex = 9;
1187         mSharedDataSource.setProviderIndex(providerIndex);
1188         assertEquals(providerIndex, mSharedDataSource.getProviderIndex());
1189 
1190         // Add a provider.
1191         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
1192                 TEST_FRIENDLY_NAME);
1193         PasspointProvider provider = createMockProvider(config);
1194         // Verify the provider ID used to create the new provider.
1195         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1196                 eq(mSimAccessor), eq(providerIndex), eq(TEST_CREATOR_UID),
1197                 eq(TEST_PACKAGE))).thenReturn(provider);
1198 
1199         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE));
1200         verifyInstalledConfig(config);
1201         verify(mWifiConfigManager).saveToStore(true);
1202         reset(mWifiConfigManager);
1203     }
1204 
1205     /**
1206      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1207      * adding a legacy Passpoint configuration containing a valid user credential.
1208      *
1209      * @throws Exception
1210      */
1211     @Test
addLegacyPasspointConfigWithUserCredential()1212     public void addLegacyPasspointConfigWithUserCredential() throws Exception {
1213         // Test data.
1214         String fqdn = "test.com";
1215         String friendlyName = "Friendly Name";
1216         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1217         String realm = "realm.com";
1218         String username = "username";
1219         String password = "password";
1220         byte[] base64EncodedPw =
1221                 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
1222         String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
1223         String caCertificateAlias = "CaCert";
1224 
1225         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1226         WifiConfiguration wifiConfig = new WifiConfiguration();
1227         wifiConfig.FQDN = fqdn;
1228         wifiConfig.providerFriendlyName = friendlyName;
1229         wifiConfig.roamingConsortiumIds = rcOIs;
1230         wifiConfig.enterpriseConfig.setIdentity(username);
1231         wifiConfig.enterpriseConfig.setPassword(password);
1232         wifiConfig.enterpriseConfig.setRealm(realm);
1233         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1234         wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
1235         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1236 
1237         // Setup expected {@link PasspointConfiguration}
1238         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1239         HomeSp homeSp = new HomeSp();
1240         homeSp.setFqdn(fqdn);
1241         homeSp.setFriendlyName(friendlyName);
1242         homeSp.setRoamingConsortiumOis(rcOIs);
1243         passpointConfig.setHomeSp(homeSp);
1244         Credential credential = new Credential();
1245         Credential.UserCredential userCredential = new Credential.UserCredential();
1246         userCredential.setUsername(username);
1247         userCredential.setPassword(encodedPasswordStr);
1248         userCredential.setEapType(EAPConstants.EAP_TTLS);
1249         userCredential.setNonEapInnerMethod("PAP");
1250         credential.setUserCredential(userCredential);
1251         credential.setRealm(realm);
1252         passpointConfig.setCredential(credential);
1253 
1254         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1255         verifyInstalledConfig(passpointConfig);
1256     }
1257 
1258     /**
1259      * Verify that adding a legacy Passpoint configuration containing user credential will
1260      * fail when client certificate is not provided.
1261      *
1262      * @throws Exception
1263      */
1264     @Test
addLegacyPasspointConfigWithUserCredentialWithoutCaCert()1265     public void addLegacyPasspointConfigWithUserCredentialWithoutCaCert() throws Exception {
1266         // Test data.
1267         String fqdn = "test.com";
1268         String friendlyName = "Friendly Name";
1269         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1270         String realm = "realm.com";
1271         String username = "username";
1272         String password = "password";
1273         byte[] base64EncodedPw =
1274                 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
1275         String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
1276 
1277         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1278         WifiConfiguration wifiConfig = new WifiConfiguration();
1279         wifiConfig.FQDN = fqdn;
1280         wifiConfig.providerFriendlyName = friendlyName;
1281         wifiConfig.roamingConsortiumIds = rcOIs;
1282         wifiConfig.enterpriseConfig.setIdentity(username);
1283         wifiConfig.enterpriseConfig.setPassword(password);
1284         wifiConfig.enterpriseConfig.setRealm(realm);
1285         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1286         wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
1287 
1288         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1289     }
1290 
1291     /**
1292      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1293      * adding a legacy Passpoint configuration containing a valid SIM credential.
1294      *
1295      * @throws Exception
1296      */
1297     @Test
addLegacyPasspointConfigWithSimCredential()1298     public void addLegacyPasspointConfigWithSimCredential() throws Exception {
1299         // Test data.
1300         String fqdn = "test.com";
1301         String friendlyName = "Friendly Name";
1302         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1303         String realm = "realm.com";
1304         String imsi = "1234";
1305 
1306         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1307         WifiConfiguration wifiConfig = new WifiConfiguration();
1308         wifiConfig.FQDN = fqdn;
1309         wifiConfig.providerFriendlyName = friendlyName;
1310         wifiConfig.roamingConsortiumIds = rcOIs;
1311         wifiConfig.enterpriseConfig.setRealm(realm);
1312         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
1313         wifiConfig.enterpriseConfig.setPlmn(imsi);
1314 
1315         // Setup expected {@link PasspointConfiguration}
1316         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1317         HomeSp homeSp = new HomeSp();
1318         homeSp.setFqdn(fqdn);
1319         homeSp.setFriendlyName(friendlyName);
1320         homeSp.setRoamingConsortiumOis(rcOIs);
1321         passpointConfig.setHomeSp(homeSp);
1322         Credential credential = new Credential();
1323         Credential.SimCredential simCredential = new Credential.SimCredential();
1324         simCredential.setEapType(EAPConstants.EAP_SIM);
1325         simCredential.setImsi(imsi);
1326         credential.setSimCredential(simCredential);
1327         credential.setRealm(realm);
1328         passpointConfig.setCredential(credential);
1329 
1330         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1331         verifyInstalledConfig(passpointConfig);
1332     }
1333 
1334     /**
1335      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1336      * adding a legacy Passpoint configuration containing a valid certificate credential.
1337      *
1338      * @throws Exception
1339      */
1340     @Test
addLegacyPasspointConfigWithCertCredential()1341     public void addLegacyPasspointConfigWithCertCredential() throws Exception {
1342         // Test data.
1343         String fqdn = "test.com";
1344         String friendlyName = "Friendly Name";
1345         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1346         String realm = "realm.com";
1347         String caCertificateAlias = "CaCert";
1348         String clientCertificateAlias = "ClientCert";
1349 
1350         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1351         WifiConfiguration wifiConfig = new WifiConfiguration();
1352         wifiConfig.FQDN = fqdn;
1353         wifiConfig.providerFriendlyName = friendlyName;
1354         wifiConfig.roamingConsortiumIds = rcOIs;
1355         wifiConfig.enterpriseConfig.setRealm(realm);
1356         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1357         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1358         wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias);
1359 
1360         // Setup expected {@link PasspointConfiguration}
1361         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1362         HomeSp homeSp = new HomeSp();
1363         homeSp.setFqdn(fqdn);
1364         homeSp.setFriendlyName(friendlyName);
1365         homeSp.setRoamingConsortiumOis(rcOIs);
1366         passpointConfig.setHomeSp(homeSp);
1367         Credential credential = new Credential();
1368         Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
1369         certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3);
1370         credential.setCertCredential(certCredential);
1371         credential.setRealm(realm);
1372         passpointConfig.setCredential(credential);
1373 
1374         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1375         verifyInstalledConfig(passpointConfig);
1376     }
1377 
1378     /**
1379      * Verify that adding a legacy Passpoint configuration containing certificate credential will
1380      * fail when CA certificate is not provided.
1381      *
1382      * @throws Exception
1383      */
1384     @Test
addLegacyPasspointConfigWithCertCredentialWithoutCaCert()1385     public void addLegacyPasspointConfigWithCertCredentialWithoutCaCert() throws Exception {
1386         // Test data.
1387         String fqdn = "test.com";
1388         String friendlyName = "Friendly Name";
1389         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1390         String realm = "realm.com";
1391         String clientCertificateAlias = "ClientCert";
1392 
1393         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1394         WifiConfiguration wifiConfig = new WifiConfiguration();
1395         wifiConfig.FQDN = fqdn;
1396         wifiConfig.providerFriendlyName = friendlyName;
1397         wifiConfig.roamingConsortiumIds = rcOIs;
1398         wifiConfig.enterpriseConfig.setRealm(realm);
1399         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1400         wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias);
1401 
1402         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1403     }
1404 
1405     /**
1406      * Verify that adding a legacy Passpoint configuration containing certificate credential will
1407      * fail when client certificate is not provided.
1408      *
1409      * @throws Exception
1410      */
1411     @Test
addLegacyPasspointConfigWithCertCredentialWithoutClientCert()1412     public void addLegacyPasspointConfigWithCertCredentialWithoutClientCert() throws Exception {
1413         // Test data.
1414         String fqdn = "test.com";
1415         String friendlyName = "Friendly Name";
1416         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1417         String realm = "realm.com";
1418         String caCertificateAlias = "CaCert";
1419 
1420         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1421         WifiConfiguration wifiConfig = new WifiConfiguration();
1422         wifiConfig.FQDN = fqdn;
1423         wifiConfig.providerFriendlyName = friendlyName;
1424         wifiConfig.roamingConsortiumIds = rcOIs;
1425         wifiConfig.enterpriseConfig.setRealm(realm);
1426         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1427         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1428 
1429         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1430     }
1431 
1432     /**
1433      * Verify that the provider's "hasEverConnected" flag will be set to true and the associated
1434      * metric is updated after the provider was used to successfully connect to a Passpoint
1435      * network for the first time.
1436      *
1437      * @throws Exception
1438      */
1439     @Test
providerNetworkConnectedFirstTime()1440     public void providerNetworkConnectedFirstTime() throws Exception {
1441         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1442         when(provider.getHasEverConnected()).thenReturn(false);
1443         mManager.onPasspointNetworkConnected(TEST_FQDN);
1444         verify(provider).setHasEverConnected(eq(true));
1445     }
1446 
1447     /**
1448      * Verify that the provider's "hasEverConnected" flag the associated metric is not updated
1449      * after the provider was used to successfully connect to a Passpoint network for non-first
1450      * time.
1451      *
1452      * @throws Exception
1453      */
1454     @Test
providerNetworkConnectedNotFirstTime()1455     public void providerNetworkConnectedNotFirstTime() throws Exception {
1456         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1457         when(provider.getHasEverConnected()).thenReturn(true);
1458         mManager.onPasspointNetworkConnected(TEST_FQDN);
1459         verify(provider, never()).setHasEverConnected(anyBoolean());
1460     }
1461 
1462     /**
1463      * Verify that the expected Passpoint metrics are updated when
1464      * {@link PasspointManager#updateMetrics} is invoked.
1465      *
1466      * @throws Exception
1467      */
1468     @Test
updateMetrics()1469     public void updateMetrics() {
1470         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1471         ArgumentCaptor<Map<String, PasspointProvider>> argCaptor = ArgumentCaptor.forClass(
1472                 Map.class);
1473         // Provider have not provided a successful network connection.
1474         int expectedInstalledProviders = 1;
1475         int expectedConnectedProviders = 0;
1476         when(provider.getHasEverConnected()).thenReturn(false);
1477         mManager.updateMetrics();
1478         verify(mWifiMetrics).updateSavedPasspointProfiles(
1479                 eq(expectedInstalledProviders), eq(expectedConnectedProviders));
1480 
1481         verify(mWifiMetrics).updateSavedPasspointProfilesInfo(argCaptor.capture());
1482         assertEquals(expectedInstalledProviders, argCaptor.getValue().size());
1483         assertEquals(provider, argCaptor.getValue().get(TEST_FQDN));
1484         reset(mWifiMetrics);
1485 
1486         // Provider have provided a successful network connection.
1487         expectedConnectedProviders = 1;
1488         when(provider.getHasEverConnected()).thenReturn(true);
1489         mManager.updateMetrics();
1490         verify(mWifiMetrics).updateSavedPasspointProfiles(
1491                 eq(expectedInstalledProviders), eq(expectedConnectedProviders));
1492     }
1493 
1494     /**
1495      * Verify Passpoint Manager's provisioning APIs by invoking methods in PasspointProvisioner for
1496      * initiailization and provisioning a provider.
1497      */
1498     @Test
verifyPasspointProvisioner()1499     public void verifyPasspointProvisioner() {
1500         mManager.initializeProvisioner(mLooper.getLooper());
1501         verify(mPasspointProvisioner).init(any(Looper.class));
1502         when(mPasspointProvisioner.startSubscriptionProvisioning(anyInt(), any(OsuProvider.class),
1503                 any(IProvisioningCallback.class))).thenReturn(true);
1504         OsuProvider osuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
1505         assertEquals(true,
1506                 mManager.startSubscriptionProvisioning(TEST_UID, osuProvider, mCallback));
1507     }
1508 
1509     /**
1510      * Verify that it will return {@code null} if the EAP-Method provided is not a carrier
1511      * EAP-Method.
1512      */
1513     @Test
verifyCreateEphemeralPasspointConfigurationWithNonCarrierEapMethod()1514     public void verifyCreateEphemeralPasspointConfigurationWithNonCarrierEapMethod() {
1515         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
1516         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
1517         PasspointManager passpointManager = new PasspointManager(mContext, mWifiInjector,
1518                 mHandler, mWifiNative, mWifiKeyStore, mClock, mSimAccessor, mObjectFactory,
1519                 mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyManager,
1520                 mSubscriptionManager);
1521 
1522         assertNull(passpointManager.createEphemeralPasspointConfigForCarrier(
1523                 EAPConstants.EAP_TLS));
1524     }
1525 
1526     /**
1527      * Verify that it creates an ephemeral Passpoint configuration for the carrier.
1528      */
1529     @Test
verifyCreateEphemeralPasspointConfigurationWithCarrierEapMethod()1530     public void verifyCreateEphemeralPasspointConfigurationWithCarrierEapMethod() {
1531         String mccmnc = "123456";
1532         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
1533         when(mDataTelephonyManager.getSimOperator()).thenReturn(mccmnc);
1534         when(mDataTelephonyManager.getSimOperatorName()).thenReturn("test");
1535         PasspointManager passpointManager = new PasspointManager(mContext, mWifiInjector,
1536                 mHandler, mWifiNative, mWifiKeyStore, mClock, mSimAccessor, mObjectFactory,
1537                 mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyManager,
1538                 mSubscriptionManager);
1539 
1540         PasspointConfiguration result =
1541                 passpointManager.createEphemeralPasspointConfigForCarrier(
1542                         EAPConstants.EAP_AKA);
1543 
1544         assertNotNull(result);
1545         assertTrue(result.validate());
1546         assertEquals(Utils.getRealmForMccMnc(mccmnc), result.getHomeSp().getFqdn());
1547         assertEquals(mccmnc + "*", result.getCredential().getSimCredential().getImsi());
1548     }
1549 
1550     /**
1551      * Verify that it will not install the Passpoint configuration with Non-Carrier EAP method.
1552      */
1553     @Test
verifyInstallEphemeralPasspointConfigurationWithNonCarrierEapMethod()1554     public void verifyInstallEphemeralPasspointConfigurationWithNonCarrierEapMethod() {
1555         // SIM is present
1556         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[1]);
1557         PasspointConfiguration config = createTestConfigWithUserCredential("abc.com", "test");
1558         PasspointProvider provider = createMockProvider(config);
1559         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1560                 eq(mSimAccessor), anyLong(), anyInt(), isNull())).thenReturn(provider);
1561 
1562         assertFalse(mManager.installEphemeralPasspointConfigForCarrier(config));
1563     }
1564 
1565     /**
1566      * Verify that it installs the carrier Passpoint configuration successfully.
1567      */
1568     @Test
verifyInstallEphemeralPasspointConfiguration()1569     public void verifyInstallEphemeralPasspointConfiguration() {
1570         // SIM is present
1571         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[1]);
1572         PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
1573                 TEST_REALM);
1574         PasspointProvider provider = createMockProvider(config);
1575         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1576                 eq(mSimAccessor), anyLong(), anyInt(), isNull())).thenReturn(provider);
1577 
1578         assertTrue(mManager.installEphemeralPasspointConfigForCarrier(config));
1579         verify(mAppOpsManager, never()).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE),
1580                 eq(TEST_PACKAGE), any(AppOpsManager.OnOpChangedListener.class));
1581     }
1582 
1583     /**
1584      * Verify that it returns {@code true} when it has Carrier Provider.
1585      */
1586     @Test
verifyHasProviderForCarrierWithMatch()1587     public void verifyHasProviderForCarrierWithMatch() {
1588         addTestCarrierProvider(TEST_3GPP_FQDN, TEST_MCC_MNC, TEST_3GPP_FQDN);
1589 
1590         assertTrue(mManager.hasCarrierProvider(TEST_MCC_MNC));
1591     }
1592 
1593     /**
1594      * Verify that it returns {@code false} when it does not have Carrier Provider.
1595      */
1596     @Test
verifyHasProviderForCarrierWithNoMatch()1597     public void verifyHasProviderForCarrierWithNoMatch() {
1598         addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1599 
1600         assertFalse(mManager.hasCarrierProvider(TEST_MCC_MNC));
1601     }
1602 
1603     /**
1604      * Verify that it returns a carrier EAP-method from NAI-Realm matched with the carrier.
1605      */
1606     @Test
verifyFindEapMethodFromNAIRealmMatchedWithCarrierWithMatch()1607     public void verifyFindEapMethodFromNAIRealmMatchedWithCarrierWithMatch() {
1608         // static mocking
1609         MockitoSession session = ExtendedMockito.mockitoSession()
1610                 .mockStatic(InformationElementUtil.class)
1611                 .startMocking();
1612         try {
1613             when(mTelephonyManager.createForSubscriptionId(anyInt()))
1614                     .thenReturn(mDataTelephonyManager);
1615             when(mDataTelephonyManager.getSimOperator()).thenReturn(TEST_MCC_MNC);
1616             // SIM is present
1617             when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[1]);
1618             List<ScanDetail> scanDetails = new ArrayList<>();
1619             scanDetails.add(generateScanDetail(TEST_SSID, TEST_BSSID_STRING, TEST_HESSID,
1620                     TEST_ANQP_DOMAIN_ID, true));
1621             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1622 
1623             // ANQP_DOMAIN_ID(TEST_ANQP_KEY)
1624             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
1625             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1626             Map<ANQPElementType, ANQPElement> anqpElementMapOfAp1 = new HashMap<>();
1627             List<NAIRealmData> realmDataList = new ArrayList<>();
1628             realmDataList.add(new NAIRealmData(Arrays.asList(TEST_3GPP_FQDN),
1629                     Arrays.asList(new EAPMethod(EAPConstants.EAP_AKA, null))));
1630             anqpElementMapOfAp1.put(ANQPElementType.ANQPNAIRealm,
1631                     new NAIRealmElement(realmDataList));
1632 
1633             ANQPData anqpData = new ANQPData(mClock, anqpElementMapOfAp1);
1634             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(anqpData);
1635 
1636             PasspointManager passpointManager = new PasspointManager(mContext, mWifiInjector,
1637                     mHandler, mWifiNative, mWifiKeyStore, mClock, mSimAccessor, mObjectFactory,
1638                     mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyManager,
1639                     mSubscriptionManager);
1640             assertEquals(EAPConstants.EAP_AKA,
1641                     passpointManager.findEapMethodFromNAIRealmMatchedWithCarrier(scanDetails));
1642         } finally {
1643             session.finishMocking();
1644         }
1645     }
1646 
1647     /**
1648      * Verify that it returns -1 when there is no NAI-Realm matched with the carrier.
1649      */
1650     @Test
verifyFindEapMethodFromNAIRealmMatchedWithCarrierWithNoMatch()1651     public void verifyFindEapMethodFromNAIRealmMatchedWithCarrierWithNoMatch() {
1652         // static mocking
1653         MockitoSession session = ExtendedMockito.mockitoSession()
1654                 .mockStatic(InformationElementUtil.class)
1655                 .startMocking();
1656         try {
1657             when(mTelephonyManager.createForSubscriptionId(anyInt()))
1658                     .thenReturn(mDataTelephonyManager);
1659             when(mDataTelephonyManager.getSimOperator()).thenReturn(TEST_MCC_MNC);
1660             // SIM is present
1661             when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[1]);
1662             List<ScanDetail> scanDetails = new ArrayList<>();
1663             scanDetails.add(generateScanDetail(TEST_SSID, TEST_BSSID_STRING, 0, 0, false));
1664 
1665             PasspointManager passpointManager = new PasspointManager(mContext, mWifiInjector,
1666                     mHandler, mWifiNative, mWifiKeyStore, mClock, mSimAccessor, mObjectFactory,
1667                     mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyManager,
1668                     mSubscriptionManager);
1669 
1670             assertEquals(-1,
1671                     passpointManager.findEapMethodFromNAIRealmMatchedWithCarrier(scanDetails));
1672         } finally {
1673             session.finishMocking();
1674         }
1675     }
1676 
1677     /**
1678      * Verify that the corresponding Passpoint provider is removed when the app is disabled.
1679      */
1680     @Test
verifyRemovingPasspointProfilesWhenAppIsDisabled()1681     public void verifyRemovingPasspointProfilesWhenAppIsDisabled() {
1682         WifiConfiguration currentConfiguration = WifiConfigurationTestUtil.createPasspointNetwork();
1683         currentConfiguration.FQDN = TEST_FQDN;
1684         when(mClientModeImpl.getCurrentWifiConfiguration()).thenReturn(currentConfiguration);
1685         addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
1686 
1687         verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE),
1688                 mAppOpChangedListenerCaptor.capture());
1689         assertEquals(1, mManager.getProviderConfigs().size());
1690         AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue();
1691         assertNotNull(listener);
1692 
1693         // Disallow change wifi state & ensure we remove the profiles from database.
1694         when(mAppOpsManager.unsafeCheckOpNoThrow(
1695                 OPSTR_CHANGE_WIFI_STATE, TEST_CREATOR_UID,
1696                 TEST_PACKAGE))
1697                 .thenReturn(MODE_IGNORED);
1698         listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE);
1699         mLooper.dispatchAll();
1700 
1701         verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue());
1702         verify(mClientModeImpl).disconnectCommand();
1703         assertTrue(mManager.getProviderConfigs().isEmpty());
1704     }
1705 }
1706