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