• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi.hotspot2;
18 
19 import static android.app.AppOpsManager.MODE_IGNORED;
20 import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE;
21 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
22 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
23 import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS;
24 
25 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
26 
27 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertNotNull;
31 import static org.junit.Assert.assertNull;
32 import static org.junit.Assert.assertThat;
33 import static org.junit.Assert.assertTrue;
34 import static org.mockito.ArgumentMatchers.argThat;
35 import static org.mockito.ArgumentMatchers.isNull;
36 import static org.mockito.Mockito.any;
37 import static org.mockito.Mockito.anyBoolean;
38 import static org.mockito.Mockito.anyInt;
39 import static org.mockito.Mockito.anyLong;
40 import static org.mockito.Mockito.anyMap;
41 import static org.mockito.Mockito.atLeastOnce;
42 import static org.mockito.Mockito.doAnswer;
43 import static org.mockito.Mockito.eq;
44 import static org.mockito.Mockito.lenient;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.never;
47 import static org.mockito.Mockito.reset;
48 import static org.mockito.Mockito.spy;
49 import static org.mockito.Mockito.times;
50 import static org.mockito.Mockito.verify;
51 import static org.mockito.Mockito.when;
52 import static org.mockito.MockitoAnnotations.initMocks;
53 
54 import android.app.ActivityManager;
55 import android.app.AppOpsManager;
56 import android.content.Context;
57 import android.content.Intent;
58 import android.net.MacAddress;
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.WifiContext;
64 import android.net.wifi.WifiEnterpriseConfig;
65 import android.net.wifi.WifiManager;
66 import android.net.wifi.WifiSsid;
67 import android.net.wifi.hotspot2.IProvisioningCallback;
68 import android.net.wifi.hotspot2.OsuProvider;
69 import android.net.wifi.hotspot2.PasspointConfiguration;
70 import android.net.wifi.hotspot2.pps.Credential;
71 import android.net.wifi.hotspot2.pps.HomeSp;
72 import android.os.Handler;
73 import android.os.Looper;
74 import android.os.UserHandle;
75 import android.os.test.TestLooper;
76 import android.telephony.SubscriptionInfo;
77 import android.telephony.SubscriptionManager;
78 import android.telephony.TelephonyManager;
79 import android.util.Base64;
80 import android.util.Pair;
81 
82 import androidx.test.filters.SmallTest;
83 
84 import com.android.server.wifi.Clock;
85 import com.android.server.wifi.FakeKeys;
86 import com.android.server.wifi.FrameworkFacade;
87 import com.android.server.wifi.MacAddressUtil;
88 import com.android.server.wifi.NetworkUpdateResult;
89 import com.android.server.wifi.WifiBaseTest;
90 import com.android.server.wifi.WifiCarrierInfoManager;
91 import com.android.server.wifi.WifiConfigManager;
92 import com.android.server.wifi.WifiConfigStore;
93 import com.android.server.wifi.WifiConfigurationTestUtil;
94 import com.android.server.wifi.WifiInjector;
95 import com.android.server.wifi.WifiKeyStore;
96 import com.android.server.wifi.WifiMetrics;
97 import com.android.server.wifi.WifiNative;
98 import com.android.server.wifi.WifiNetworkSuggestionsManager;
99 import com.android.server.wifi.WifiSettingsStore;
100 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
101 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
102 import com.android.server.wifi.hotspot2.anqp.DomainNameElement;
103 import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement;
104 import com.android.server.wifi.hotspot2.anqp.I18Name;
105 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo;
106 import com.android.server.wifi.hotspot2.anqp.VenueNameElement;
107 import com.android.server.wifi.hotspot2.anqp.VenueUrlElement;
108 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
109 import com.android.server.wifi.util.InformationElementUtil;
110 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
111 import com.android.server.wifi.util.WifiPermissionsUtil;
112 
113 import org.junit.Before;
114 import org.junit.BeforeClass;
115 import org.junit.Test;
116 import org.mockito.ArgumentCaptor;
117 import org.mockito.Mock;
118 import org.mockito.MockitoSession;
119 
120 import java.net.URL;
121 import java.nio.charset.StandardCharsets;
122 import java.security.KeyStore;
123 import java.security.cert.Certificate;
124 import java.security.cert.PKIXParameters;
125 import java.security.cert.X509Certificate;
126 import java.util.ArrayList;
127 import java.util.Arrays;
128 import java.util.Collections;
129 import java.util.HashMap;
130 import java.util.HashSet;
131 import java.util.List;
132 import java.util.Locale;
133 import java.util.Map;
134 import java.util.Set;
135 import java.util.stream.Collectors;
136 
137 /**
138  * Unit tests for {@link PasspointManager}.
139  */
140 @SmallTest
141 public class PasspointManagerTest extends WifiBaseTest {
142     private static final long BSSID = 0x112233445566L;
143     private static final String TEST_PACKAGE = "com.android.test";
144     private static final String TEST_PACKAGE1 = "com.android.test1";
145     private static final String TEST_FQDN = "test1.test.com";
146     private static final String TEST_FQDN2 = "test2.test.com";
147     private static final String TEST_FRIENDLY_NAME = "friendly name";
148     private static final String TEST_FRIENDLY_NAME2 = "second friendly name";
149     private static final String TEST_REALM = "realm.test.com";
150     private static final String TEST_REALM2 = "realm.test2.com";
151     private static final String TEST_REALM3 = "realm.test3.com";
152     private static final String TEST_IMSI = "123456*";
153     private static final String FULL_IMSI = "123456789123456";
154     private static final int TEST_CARRIER_ID = 10;
155     private static final int TEST_SUBID = 1;
156     private static final String TEST_VENUE_URL_ENG = "https://www.google.com/";
157     private static final String TEST_VENUE_URL_HEB = "https://www.google.co.il/";
158     private static final String TEST_LOCALE_ENGLISH = "eng";
159     private static final String TEST_LOCALE_HEBREW = "heb";
160     private static final String TEST_LOCALE_SPANISH = "spa";
161     private static final String TEST_TERMS_AND_CONDITIONS_URL =
162             "https://policies.google.com/terms?hl=en-US";
163     private static final String TEST_TERMS_AND_CONDITIONS_URL_NON_HTTPS =
164             "http://policies.google.com/terms?hl=en-US";
165     private static final String TEST_TERMS_AND_CONDITIONS_URL_INVALID =
166             "httpps://policies.google.com/terms?hl=en-US";
167 
168     private static final long TEST_BSSID = 0x112233445566L;
169     private static final String TEST_SSID = "TestSSID";
170     private static final String TEST_BSSID_STRING = "11:22:33:44:55:66";
171     private static final String TEST_SSID2 = "TestSSID2";
172     private static final String TEST_BSSID_STRING2 = "11:22:33:44:55:77";
173     private static final String TEST_SSID3 = "TestSSID3";
174     private static final String TEST_BSSID_STRING3 = "11:22:33:44:55:88";
175     private static final String TEST_MCC_MNC = "123456";
176     private static final String TEST_3GPP_FQDN = String.format("wlan.mnc%s.mcc%s.3gppnetwork.org",
177             TEST_MCC_MNC.substring(3), TEST_MCC_MNC.substring(0, 3));
178 
179     private static final long TEST_HESSID = 0x5678L;
180     private static final int TEST_ANQP_DOMAIN_ID = 0;
181     private static final int TEST_ANQP_DOMAIN_ID2 = 1;
182     private static final ANQPNetworkKey TEST_ANQP_KEY = ANQPNetworkKey.buildKey(
183             TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID);
184     private static final ANQPNetworkKey TEST_ANQP_KEY2 = ANQPNetworkKey.buildKey(
185             TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID2);
186     private static final int TEST_CREATOR_UID = 1234;
187     private static final int TEST_CREATOR_UID1 = 1235;
188     private static final int TEST_UID = 1500;
189     private static final int TEST_NETWORK_ID = 2;
190     private static final String TEST_ANONYMOUS_IDENTITY = "AnonymousIdentity";
191     private static final String USER_CONNECT_CHOICE = "SomeNetworkProfileId";
192     private static final int TEST_RSSI = -50;
193     public static PKIXParameters TEST_PKIX_PARAMETERS;
194 
195     @Mock Context mContext;
196     @Mock WifiNative mWifiNative;
197     @Mock WifiKeyStore mWifiKeyStore;
198     @Mock Clock mClock;
199     @Mock PasspointObjectFactory mObjectFactory;
200     @Mock PasspointEventHandler.Callbacks mCallbacks;
201     @Mock AnqpCache mAnqpCache;
202     @Mock ANQPRequestManager mAnqpRequestManager;
203     @Mock WifiConfigManager mWifiConfigManager;
204     @Mock WifiConfigStore mWifiConfigStore;
205     @Mock WifiSettingsStore mWifiSettingsStore;
206     PasspointConfigSharedStoreData.DataSource mSharedDataSource;
207     PasspointConfigUserStoreData.DataSource mUserDataSource;
208     @Mock WifiMetrics mWifiMetrics;
209     @Mock OsuNetworkConnection mOsuNetworkConnection;
210     @Mock OsuServerConnection mOsuServerConnection;
211     @Mock PasspointProvisioner mPasspointProvisioner;
212     @Mock PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
213     @Mock IProvisioningCallback mCallback;
214     @Mock WfaKeyStore mWfaKeyStore;
215     @Mock KeyStore mKeyStore;
216     @Mock AppOpsManager mAppOpsManager;
217     @Mock WifiInjector mWifiInjector;
218     @Mock TelephonyManager mTelephonyManager;
219     @Mock SubscriptionManager mSubscriptionManager;
220     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
221     @Mock MacAddressUtil mMacAddressUtil;
222     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
223     @Mock ActivityManager mActivityManager;
224 
225     Handler mHandler;
226     TestLooper mLooper;
227     PasspointManager mManager;
228     boolean mConfigSettingsPasspointEnabled = true;
229     ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor =
230             ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class);
231     WifiCarrierInfoManager mWifiCarrierInfoManager;
232     ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mNetworkListenerCaptor =
233             ArgumentCaptor.forClass(WifiConfigManager.OnNetworkUpdateListener.class);
234     ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> mSubscriptionsCaptor =
235             ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
236 
237     @BeforeClass
setUpBeforeClass()238     public static void setUpBeforeClass() throws Exception {
239         KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
240         keyStore.load(null, null);
241         TEST_PKIX_PARAMETERS = new PKIXParameters(keyStore);
242         TEST_PKIX_PARAMETERS.setRevocationEnabled(false);
243     }
244 
245     /** Sets up test. */
246     @Before
setUp()247     public void setUp() throws Exception {
248         initMocks(this);
249         when(mObjectFactory.makeAnqpCache(mClock)).thenReturn(mAnqpCache);
250         when(mObjectFactory.makeANQPRequestManager(any(), eq(mClock)))
251                 .thenReturn(mAnqpRequestManager);
252         when(mObjectFactory.makeOsuNetworkConnection(any(Context.class)))
253                 .thenReturn(mOsuNetworkConnection);
254         when(mObjectFactory.makeOsuServerConnection())
255                 .thenReturn(mOsuServerConnection);
256         when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore);
257         when(mWfaKeyStore.get()).thenReturn(mKeyStore);
258         when(mObjectFactory.makePasspointProvisioner(any(Context.class), any(WifiNative.class),
259                 any(PasspointManager.class), any(WifiMetrics.class)))
260                 .thenReturn(mPasspointProvisioner);
261         when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
262         when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
263         when(mWifiInjector.getWifiNetworkSuggestionsManager())
264                 .thenReturn(mWifiNetworkSuggestionsManager);
265         when(mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(anyInt()))
266                 .thenReturn(true);
267         // Update mConfigSettingsPasspointEnabled when WifiSettingsStore#handleWifiPasspointEnabled
268         // is called.
269         doAnswer(invocation -> {
270             mConfigSettingsPasspointEnabled = (boolean) invocation.getArguments()[0];
271             // Return success
272             return true;
273         }).when(mWifiSettingsStore).handleWifiPasspointEnabled(anyBoolean());
274         when(mWifiSettingsStore.isWifiPasspointEnabled())
275                 .thenReturn(mConfigSettingsPasspointEnabled);
276         mLooper = new TestLooper();
277         mHandler = new Handler(mLooper.getLooper());
278         mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager,
279                 mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
280                 mock(WifiContext.class), mWifiConfigStore, mHandler, mWifiMetrics, mClock);
281         verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(),
282                 mSubscriptionsCaptor.capture());
283         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
284                 mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager,
285                 mWifiConfigStore, mWifiSettingsStore, mWifiMetrics, mWifiCarrierInfoManager,
286                 mMacAddressUtil, mWifiPermissionsUtil);
287         mManager.setPasspointNetworkNominateHelper(mPasspointNetworkNominateHelper);
288         // Verify Passpoint is enabled on creation.
289         assertTrue(mManager.isWifiPasspointEnabled());
290         mManager.setUseInjectedPKIX(true);
291         mManager.injectPKIXParameters(TEST_PKIX_PARAMETERS);
292 
293         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
294                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
295         verify(mObjectFactory).makePasspointEventHandler(any(WifiInjector.class),
296                                                          callbacks.capture());
297         ArgumentCaptor<PasspointConfigSharedStoreData.DataSource> sharedDataSource =
298                 ArgumentCaptor.forClass(PasspointConfigSharedStoreData.DataSource.class);
299         verify(mObjectFactory).makePasspointConfigSharedStoreData(sharedDataSource.capture());
300         ArgumentCaptor<PasspointConfigUserStoreData.DataSource> userDataSource =
301                 ArgumentCaptor.forClass(PasspointConfigUserStoreData.DataSource.class);
302         verify(mObjectFactory).makePasspointConfigUserStoreData(any(WifiKeyStore.class),
303                 any(WifiCarrierInfoManager.class), userDataSource.capture(), any(Clock.class));
304         mCallbacks = callbacks.getValue();
305         mSharedDataSource = sharedDataSource.getValue();
306         mUserDataSource = userDataSource.getValue();
307         // SIM is absent
308         when(mSubscriptionManager.getActiveSubscriptionInfoList())
309                 .thenReturn(Collections.emptyList());
310         mLooper.dispatchAll();
311         verify(mWifiConfigManager).addOnNetworkUpdateListener(mNetworkListenerCaptor.capture());
312     }
313 
314     /**
315      * Verify that the given Passpoint configuration matches the one that's added to
316      * the PasspointManager.
317      *
318      * @param expectedConfig The expected installed Passpoint configuration
319      */
verifyInstalledConfig(PasspointConfiguration expectedConfig)320     private void verifyInstalledConfig(PasspointConfiguration expectedConfig) {
321         List<PasspointConfiguration> installedConfigs =
322                 mManager.getProviderConfigs(TEST_CREATOR_UID, true);
323         assertEquals(1, installedConfigs.size());
324         assertEquals(expectedConfig, installedConfigs.get(0));
325     }
326 
createMockProvider(PasspointConfiguration config)327     private PasspointProvider createMockProvider(PasspointConfiguration config) {
328         WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(-1,
329                 TEST_UID, "\"PasspointTestSSID\"", true, true,
330                 config.getHomeSp().getFqdn(), TEST_FRIENDLY_NAME, SECURITY_EAP);
331         return createMockProvider(config, wifiConfig, false);
332     }
333 
334     /**
335      * Create a mock PasspointProvider with default expectations.
336      *
337      * @param config The configuration associated with the provider
338      * @return {@link com.android.server.wifi.hotspot2.PasspointProvider}
339      */
createMockProvider( PasspointConfiguration config, WifiConfiguration wifiConfig, boolean isSuggestion)340     private PasspointProvider createMockProvider(
341             PasspointConfiguration config, WifiConfiguration wifiConfig, boolean isSuggestion) {
342         PasspointProvider provider = mock(PasspointProvider.class);
343         when(provider.installCertsAndKeys()).thenReturn(true);
344         lenient().when(provider.getConfig()).thenReturn(config);
345         lenient().when(provider.getWifiConfig()).thenReturn(wifiConfig);
346         lenient().when(provider.getCreatorUid()).thenReturn(TEST_CREATOR_UID);
347         lenient().when(provider.isFromSuggestion()).thenReturn(isSuggestion);
348         lenient().when(provider.isAutojoinEnabled()).thenReturn(true);
349         return provider;
350     }
351 
352     /**
353      * Helper function for creating a test configuration with user credential.
354      *
355      * @return {@link PasspointConfiguration}
356      */
createTestConfigWithUserCredential(String fqdn, String friendlyName)357     private PasspointConfiguration createTestConfigWithUserCredential(String fqdn,
358             String friendlyName) {
359         return createTestConfigWithUserCredentialAndRealm(fqdn, friendlyName, TEST_REALM);
360     }
361 
362         /**
363          * Helper function for creating a test configuration with user credential
364          * and a unique realm.
365          *
366          * @return {@link PasspointConfiguration}
367          */
createTestConfigWithUserCredentialAndRealm(String fqdn, String friendlyName, String realm)368     private PasspointConfiguration createTestConfigWithUserCredentialAndRealm(String fqdn,
369             String friendlyName, String realm) {
370         PasspointConfiguration config = new PasspointConfiguration();
371         HomeSp homeSp = new HomeSp();
372         homeSp.setFqdn(fqdn);
373         homeSp.setFriendlyName(friendlyName);
374         config.setHomeSp(homeSp);
375         Credential credential = new Credential();
376         credential.setRealm(realm != null ? realm : TEST_REALM);
377         credential.setCaCertificate(FakeKeys.CA_CERT0);
378         Credential.UserCredential userCredential = new Credential.UserCredential();
379         userCredential.setUsername("username");
380         userCredential.setPassword("password");
381         userCredential.setEapType(EAPConstants.EAP_TTLS);
382         userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP);
383         credential.setUserCredential(userCredential);
384         config.setCredential(credential);
385         return config;
386     }
387 
388     /**
389      * Helper function for creating a test configuration with SIM credential.
390      *
391      * @return {@link PasspointConfiguration}
392      */
createTestConfigWithSimCredential(String fqdn, String imsi, String realm)393     private PasspointConfiguration createTestConfigWithSimCredential(String fqdn, String imsi,
394             String realm) {
395         PasspointConfiguration config = new PasspointConfiguration();
396         HomeSp homeSp = new HomeSp();
397         homeSp.setFqdn(fqdn);
398         homeSp.setFriendlyName(TEST_FRIENDLY_NAME);
399         config.setHomeSp(homeSp);
400         Credential credential = new Credential();
401         credential.setRealm(TEST_REALM);
402         Credential.SimCredential simCredential = new Credential.SimCredential();
403         simCredential.setImsi(imsi);
404         simCredential.setEapType(EAPConstants.EAP_SIM);
405         credential.setSimCredential(simCredential);
406         config.setCredential(credential);
407         return config;
408     }
409 
addTestProvider(String fqdn, String friendlyName, String packageName, boolean isSuggestion, String realm, boolean addServiceFriendlyNames)410     private PasspointProvider addTestProvider(String fqdn, String friendlyName,
411             String packageName, boolean isSuggestion, String realm,
412             boolean addServiceFriendlyNames) {
413         WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(-1, TEST_UID,
414                 "\"PasspointTestSSID\"", true, true,
415                 fqdn, friendlyName, SECURITY_EAP);
416 
417         return addTestProvider(fqdn, friendlyName, packageName, wifiConfig, isSuggestion, realm,
418                 addServiceFriendlyNames);
419     }
420 
421     /**
422      * Helper function for adding a test provider to the manager.  Return the mock
423      * provider that's added to the manager.
424      *
425      * @return {@link PasspointProvider}
426      */
addTestProvider(String fqdn, String friendlyName, String packageName, WifiConfiguration wifiConfig, boolean isSuggestion, String realm, boolean addServiceFriendlyNames)427     private PasspointProvider addTestProvider(String fqdn, String friendlyName,
428             String packageName, WifiConfiguration wifiConfig, boolean isSuggestion, String realm,
429             boolean addServiceFriendlyNames) {
430         PasspointConfiguration config =
431                 createTestConfigWithUserCredentialAndRealm(fqdn, friendlyName, realm);
432         wifiConfig.setPasspointUniqueId(config.getUniqueId());
433         if (addServiceFriendlyNames) {
434             Map<String, String> friendlyNames = new HashMap<>();
435             friendlyNames.put("en", friendlyName);
436             friendlyNames.put("kr", friendlyName + 1);
437             friendlyNames.put("jp", friendlyName + 2);
438             config.setServiceFriendlyNames(friendlyNames);
439         }
440         PasspointProvider provider = createMockProvider(config, wifiConfig, isSuggestion);
441         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
442                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
443                 eq(isSuggestion), eq(mClock))).thenReturn(provider);
444         when(provider.getPackageName()).thenReturn(packageName);
445         assertTrue(mManager.addOrUpdateProvider(
446                 config, TEST_CREATOR_UID, TEST_PACKAGE, isSuggestion, true));
447         verify(mPasspointNetworkNominateHelper, atLeastOnce())
448                 .updateBestMatchScanDetailForProviders();
449         return provider;
450     }
451 
452     /**
453      * Helper function for creating a ScanResult for testing.
454      *
455      * @return {@link ScanResult}
456      */
createTestScanResult()457     private ScanResult createTestScanResult() {
458         ScanResult scanResult = new ScanResult();
459         scanResult.SSID = TEST_SSID;
460         scanResult.BSSID = TEST_BSSID_STRING;
461         scanResult.hessid = TEST_HESSID;
462         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID;
463         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
464         return scanResult;
465     }
466 
467     /**
468      * Helper function for creating a ScanResult for testing.
469      *
470      * @return {@link ScanResult}
471      */
createTestScanResults()472     private List<ScanResult> createTestScanResults() {
473         List<ScanResult> scanResults = new ArrayList<>();
474 
475         // Passpoint AP
476         ScanResult scanResult = new ScanResult();
477         scanResult.SSID = TEST_SSID;
478         scanResult.BSSID = TEST_BSSID_STRING;
479         scanResult.hessid = TEST_HESSID;
480         scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
481         scanResult.anqpDomainId = TEST_ANQP_DOMAIN_ID2;
482         scanResults.add(scanResult);
483 
484         // Non-Passpoint AP
485         ScanResult scanResult2 = new ScanResult();
486         scanResult2.SSID = TEST_SSID2;
487         scanResult2.BSSID = TEST_BSSID_STRING2;
488         scanResult2.hessid = TEST_HESSID;
489         scanResult2.flags = 0;
490         scanResults.add(scanResult2);
491 
492         // Passpoint AP
493         ScanResult scanResult3 = new ScanResult();
494         scanResult3.SSID = TEST_SSID3;
495         scanResult3.BSSID = TEST_BSSID_STRING3;
496         scanResult3.hessid = TEST_HESSID;
497         scanResult3.flags = ScanResult.FLAG_PASSPOINT_NETWORK;
498         scanResult3.anqpDomainId = TEST_ANQP_DOMAIN_ID2;
499         scanResults.add(scanResult3);
500 
501         return scanResults;
502     }
503 
504     /**
505      * Verify that the ANQP elements will be added to the ANQP cache on receiving a successful
506      * response.
507      *
508      * @throws Exception
509      */
510     @Test
anqpResponseSuccess()511     public void anqpResponseSuccess() throws Exception {
512         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
513         anqpElementMap.put(ANQPElementType.ANQPDomName,
514                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
515 
516         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(TEST_ANQP_KEY);
517         mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap);
518         verify(mAnqpCache).addOrUpdateEntry(TEST_ANQP_KEY, anqpElementMap);
519         verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class),
520                 any(String.class));
521     }
522 
523     /**
524      * Verify that no ANQP elements will be added to the ANQP cache on receiving a successful
525      * response for a request that's not sent by us.
526      *
527      * @throws Exception
528      */
529     @Test
anqpResponseSuccessWithUnknownRequest()530     public void anqpResponseSuccessWithUnknownRequest() throws Exception {
531         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
532         anqpElementMap.put(ANQPElementType.ANQPDomName,
533                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
534 
535         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(null);
536         mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap);
537         verify(mAnqpCache, never()).addOrUpdateEntry(any(ANQPNetworkKey.class), anyMap());
538     }
539 
540     /**
541      * Verify that no ANQP elements will be added to the ANQP cache on receiving a failure response.
542      *
543      * @throws Exception
544      */
545     @Test
anqpResponseFailure()546     public void anqpResponseFailure() throws Exception {
547         when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, false)).thenReturn(TEST_ANQP_KEY);
548         mCallbacks.onANQPResponse(TEST_BSSID, null);
549         verify(mAnqpCache, never()).addOrUpdateEntry(any(ANQPNetworkKey.class), anyMap());
550 
551     }
552 
553     /**
554      * Verify that adding a provider with a null configuration will fail.
555      *
556      * @throws Exception
557      */
558     @Test
addProviderWithNullConfig()559     public void addProviderWithNullConfig() throws Exception {
560         assertFalse(mManager.addOrUpdateProvider(null, TEST_CREATOR_UID, TEST_PACKAGE,
561                 false, true));
562         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
563         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
564     }
565 
566     /**
567      * Verify that adding a provider with a empty configuration will fail.
568      *
569      * @throws Exception
570      */
571     @Test
addProviderWithEmptyConfig()572     public void addProviderWithEmptyConfig() throws Exception {
573         assertFalse(mManager.addOrUpdateProvider(new PasspointConfiguration(), TEST_CREATOR_UID,
574                 TEST_PACKAGE, false, true));
575         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
576         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
577     }
578 
579     /**
580      * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS
581      * for user credential).
582      *
583      * @throws Exception
584      */
585     @Test
addProviderWithInvalidCredential()586     public void addProviderWithInvalidCredential() throws Exception {
587         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
588                 TEST_FRIENDLY_NAME);
589         // EAP-TLS not allowed for user credential.
590         config.getCredential().getUserCredential().setEapType(EAPConstants.EAP_TLS);
591         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
592                 false, true));
593         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
594         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
595     }
596 
597     /**
598      * Verify that adding a provider from a background user will fail.
599      *
600      * @throws Exception
601      */
602     @Test
addProviderWithBackgroundUser()603     public void addProviderWithBackgroundUser() throws Exception {
604         when(mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(anyInt()))
605                 .thenReturn(false);
606 
607         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
608                 TEST_FRIENDLY_NAME);
609         PasspointProvider provider = createMockProvider(config);
610         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
611         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
612                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
613                 eq(false), eq(mClock))).thenReturn(provider);
614         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID,
615                 TEST_PACKAGE, false, true));
616 
617         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
618         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
619     }
620 
621     /**
622      * Verify that adding a user saved provider with a valid configuration and user credential will
623      * succeed.
624      *
625      * @throws Exception
626      */
addRemoveSavedProviderWithValidUserCredential(boolean useFqdn)627     private void addRemoveSavedProviderWithValidUserCredential(boolean useFqdn) throws Exception {
628         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
629                 TEST_FRIENDLY_NAME);
630         PasspointProvider provider = createMockProvider(config);
631         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
632         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
633                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
634                 eq(false), eq(mClock))).thenReturn(provider);
635         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
636                 false, true));
637         verifyInstalledConfig(config);
638         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
639         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
640         verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE),
641                 any(AppOpsManager.OnOpChangedListener.class));
642         reset(mWifiMetrics);
643         reset(mWifiConfigManager);
644 
645         // Verify content in the data source.
646         List<PasspointProvider> providers = mUserDataSource.getProviders();
647         assertEquals(1, providers.size());
648         assertEquals(config, providers.get(0).getConfig());
649 
650         // Verify calling |enableAutoJoin|, |enableMacRandomization|, and |setMeteredOverride|
651         verifyEnableAutojoin(providers.get(0), useFqdn);
652         verifyEnableMacRandomization(providers.get(0));
653         verifySetMeteredOverride(providers.get(0));
654 
655         // Provider index start with 0, should be 1 after adding a provider.
656         assertEquals(1, mSharedDataSource.getProviderIndex());
657 
658         // Remove the provider as the creator app.
659         if (useFqdn) {
660             assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN));
661         } else {
662             assertTrue(
663                     mManager.removeProvider(TEST_CREATOR_UID, false, config.getUniqueId(), null));
664         }
665 
666         verify(provider).uninstallCertsAndKeys();
667         verify(mWifiConfigManager, times(3)).removePasspointConfiguredNetwork(
668                 provider.getWifiConfig().getProfileKey());
669         /**
670          * 1 from |removeProvider| + 2 from |setAutojoinEnabled| + 2 from
671          * |enableMacRandomization| + 2 from |setMeteredOverride| = 7 calls to |saveToStore|
672          */
673         verify(mWifiConfigManager, times(7)).saveToStore(true);
674         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
675         verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess();
676         verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class));
677         assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty());
678         verify(mWifiConfigManager).removeConnectChoiceFromAllNetworks(config.getUniqueId());
679 
680         // Verify content in the data source.
681         assertTrue(mUserDataSource.getProviders().isEmpty());
682         // Removing a provider should not change the provider index.
683         assertEquals(1, mSharedDataSource.getProviderIndex());
684     }
685 
686     /**
687      * Verify that adding a user saved provider with a valid configuration and user credential will
688      * succeed. Remove provider using FQDN as key.
689      *
690      * @throws Exception
691      */
692     @Test
addRemoveByFqdnSavedProviderWithValidUserCredential()693     public void addRemoveByFqdnSavedProviderWithValidUserCredential() throws Exception {
694         addRemoveSavedProviderWithValidUserCredential(true);
695     }
696 
697     /**
698      * Verify that adding a user saved provider with a valid configuration and user credential will
699      * succeed. Remove provider using unique identifier as key.
700      *
701      * @throws Exception
702      */
703     @Test
addRemoveByUniqueIdSavedProviderWithValidUserCredential()704     public void addRemoveByUniqueIdSavedProviderWithValidUserCredential() throws Exception {
705         addRemoveSavedProviderWithValidUserCredential(false);
706     }
707 
708     /**
709      * Verify enable/disable autojoin on a provider.
710      * @param provider a mock provider that is already added into the PasspointManager
711      */
verifyEnableAutojoin(PasspointProvider provider, boolean useFqdn)712     private void verifyEnableAutojoin(PasspointProvider provider, boolean useFqdn) {
713         when(provider.setAutojoinEnabled(anyBoolean())).thenReturn(true);
714         if (useFqdn) {
715             assertTrue(mManager.enableAutojoin(null, provider.getConfig().getHomeSp().getFqdn(),
716                     false));
717             verify(provider).setAutojoinEnabled(false);
718             assertTrue(mManager.enableAutojoin(null, provider.getConfig().getHomeSp().getFqdn(),
719                     true));
720             verify(provider).setAutojoinEnabled(true);
721             assertFalse(mManager.enableAutojoin(null, provider.getConfig().getHomeSp()
722                     .getFqdn() + "-XXXX", true));
723         } else {
724             assertTrue(mManager.enableAutojoin(provider.getConfig().getUniqueId(), null,
725                     false));
726             verify(provider).setAutojoinEnabled(false);
727             assertTrue(mManager.enableAutojoin(provider.getConfig().getUniqueId(), null,
728                     true));
729             verify(provider).setAutojoinEnabled(true);
730             assertFalse(
731                     mManager.enableAutojoin(provider.getConfig().getHomeSp().getFqdn() + "-XXXX",
732                             null, true));
733         }
734         verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF,
735                 false, true);
736         verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON,
737                 false, true);
738     }
739 
740     /**
741      * Verify enable/disable mac randomization on a provider.
742      * @param provider a mock provider that is already added into the PasspointManager
743      */
verifyEnableMacRandomization(PasspointProvider provider)744     private void verifyEnableMacRandomization(PasspointProvider provider) {
745         when(provider.setMacRandomizationEnabled(anyBoolean())).thenReturn(true);
746         assertTrue(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn(),
747                 false));
748         verify(provider).setMacRandomizationEnabled(false);
749         verify(mWifiMetrics).logUserActionEvent(
750                 UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_OFF, false, true);
751         assertTrue(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn(),
752                 true));
753         verify(mWifiConfigManager, times(2)).removePasspointConfiguredNetwork(
754                 provider.getWifiConfig().getProfileKey());
755         verify(mWifiMetrics).logUserActionEvent(
756                 UserActionEvent.EVENT_CONFIGURE_MAC_RANDOMIZATION_ON, false, true);
757         verify(provider).setMacRandomizationEnabled(true);
758         assertFalse(mManager.enableMacRandomization(provider.getConfig().getHomeSp().getFqdn()
759                 + "-XXXX", false));
760     }
761 
verifySetMeteredOverride(PasspointProvider provider)762     private void verifySetMeteredOverride(PasspointProvider provider) {
763         when(provider.setMeteredOverride(anyInt())).thenReturn(true);
764         assertTrue(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn(),
765                 METERED_OVERRIDE_METERED));
766         verify(provider).setMeteredOverride(METERED_OVERRIDE_METERED);
767         verify(mWifiMetrics).logUserActionEvent(
768                 UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_METERED, false, true);
769         assertTrue(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn(),
770                 METERED_OVERRIDE_NOT_METERED));
771         verify(provider).setMeteredOverride(METERED_OVERRIDE_NOT_METERED);
772         verify(mWifiMetrics).logUserActionEvent(
773                 UserActionEvent.EVENT_CONFIGURE_METERED_STATUS_UNMETERED, false, true);
774         assertFalse(mManager.setMeteredOverride(provider.getConfig().getHomeSp().getFqdn()
775                 + "-XXXX", METERED_OVERRIDE_METERED));
776     }
777 
778     /**
779      * Verify that adding a user saved  provider with a valid configuration and SIM credential will
780      * succeed.
781      *
782      * @throws Exception
783      */
784     @Test
addRemoveSavedProviderWithValidSimCredential()785     public void addRemoveSavedProviderWithValidSimCredential() throws Exception {
786         PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
787                 TEST_REALM);
788         PasspointProvider provider = createMockProvider(config);
789         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
790                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
791                 eq(false), eq(mClock))).thenReturn(provider);
792         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
793                 false, true));
794         verifyInstalledConfig(config);
795         verify(mWifiConfigManager).saveToStore(true);
796         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
797         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
798         reset(mWifiMetrics);
799         reset(mWifiConfigManager);
800 
801         // Verify content in the data source.
802         List<PasspointProvider> providers = mUserDataSource.getProviders();
803         assertEquals(1, providers.size());
804         assertEquals(config, providers.get(0).getConfig());
805         // Provider index start with 0, should be 1 after adding a provider.
806         assertEquals(1, mSharedDataSource.getProviderIndex());
807 
808         // Remove the provider as a privileged non-creator app.
809         assertTrue(mManager.removeProvider(TEST_UID, true, null, TEST_FQDN));
810         verify(provider).uninstallCertsAndKeys();
811         verify(mWifiConfigManager).removePasspointConfiguredNetwork(
812                 provider.getWifiConfig().getProfileKey());
813         verify(mWifiConfigManager).saveToStore(true);
814         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
815         verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess();
816         assertTrue(mManager.getProviderConfigs(TEST_UID, true).isEmpty());
817         verify(mWifiConfigManager).removeConnectChoiceFromAllNetworks(config.getUniqueId());
818 
819         // Verify content in the data source.
820         assertTrue(mUserDataSource.getProviders().isEmpty());
821         // Removing a provider should not change the provider index.
822         assertEquals(1, mSharedDataSource.getProviderIndex());
823     }
824 
825     /**
826      * Verify that if the passpoint profile has full IMSI, the carrier ID should be updated when
827      * the matched SIM card is present.
828      * @throws Exception
829      */
830     @Test
addProviderWithValidFullImsiOfSimCredential()831     public void addProviderWithValidFullImsiOfSimCredential() throws Exception {
832         PasspointConfiguration config =
833                 createTestConfigWithSimCredential(TEST_FQDN, FULL_IMSI, TEST_REALM);
834         X509Certificate[] certArr = new X509Certificate[] {FakeKeys.CA_CERT0};
835         config.getCredential().setCaCertificates(certArr);
836         SubscriptionInfo subInfo = mock(SubscriptionInfo.class);
837         when(subInfo.getSubscriptionId()).thenReturn(TEST_SUBID);
838         when(subInfo.getCarrierId()).thenReturn(TEST_CARRIER_ID);
839         TelephonyManager specifiedTm = mock(TelephonyManager.class);
840         when(mTelephonyManager.createForSubscriptionId(eq(TEST_SUBID))).thenReturn(specifiedTm);
841         when(specifiedTm.getSubscriberId()).thenReturn(FULL_IMSI);
842         when(specifiedTm.getSimApplicationState()).thenReturn(TelephonyManager.SIM_STATE_LOADED);
843         List<SubscriptionInfo> subInfoList = new ArrayList<SubscriptionInfo>() {{
844                 add(subInfo);
845             }};
846         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subInfoList);
847         mSubscriptionsCaptor.getValue().onSubscriptionsChanged();
848         when(mWifiKeyStore.putCaCertInKeyStore(any(String.class), any(Certificate.class)))
849                 .thenReturn(true);
850         PasspointObjectFactory spyFactory = spy(new PasspointObjectFactory());
851         when(mWifiNetworkSuggestionsManager.isPasspointSuggestionSharedWithUser(any()))
852                 .thenReturn(true);
853         PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
854                 mWifiKeyStore, mClock, spyFactory, mWifiConfigManager,
855                 mWifiConfigStore, mWifiSettingsStore, mWifiMetrics, mWifiCarrierInfoManager,
856                 mMacAddressUtil, mWifiPermissionsUtil);
857 
858         assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
859                 true, true));
860 
861         assertEquals(TEST_CARRIER_ID, config.getCarrierId());
862     }
863 
864     /**
865      * Verify that adding a user saved provider with the same base domain as the existing provider
866      * will succeed, and verify that the new provider with the new configuration is added.
867      *
868      * @throws Exception
869      */
870     @Test
addSavedProviderWithExistingConfig()871     public void addSavedProviderWithExistingConfig() throws Exception {
872         // Add a provider with the original configuration.
873         PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
874                 TEST_REALM);
875         PasspointProvider origProvider = createMockProvider(origConfig);
876         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
877                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
878                 eq(false), eq(mClock))).thenReturn(origProvider);
879         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
880                 false, true));
881         verifyInstalledConfig(origConfig);
882         verify(mWifiConfigManager).saveToStore(true);
883         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
884         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
885         verify(origProvider, never()).setUserConnectChoice(any(), anyInt());
886         verify(origProvider, never()).setAutojoinEnabled(anyBoolean());
887         verify(origProvider, never()).setAnonymousIdentity(any());
888         reset(mWifiMetrics);
889         reset(mWifiConfigManager);
890 
891         // Verify data source content.
892         List<PasspointProvider> origProviders = mUserDataSource.getProviders();
893         assertEquals(1, origProviders.size());
894         assertEquals(origConfig, origProviders.get(0).getConfig());
895         assertEquals(1, mSharedDataSource.getProviderIndex());
896 
897         // Add same provider as existing suggestion provider
898         // This should be no WifiConfig deletion
899         WifiConfiguration origWifiConfig = origProvider.getWifiConfig();
900         when(mWifiConfigManager.getConfiguredNetwork(origWifiConfig.getProfileKey()))
901                 .thenReturn(origWifiConfig);
902         when(mWifiConfigManager.addOrUpdateNetwork(
903                 origWifiConfig, TEST_CREATOR_UID, TEST_PACKAGE, false))
904                 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
905         when(origProvider.getAnonymousIdentity()).thenReturn(TEST_ANONYMOUS_IDENTITY);
906         when(origProvider.getConnectChoice()).thenReturn(USER_CONNECT_CHOICE);
907         when(origProvider.getConnectChoiceRssi()).thenReturn(TEST_RSSI);
908         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
909                 false, true));
910         verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork(
911                 origWifiConfig.getProfileKey());
912         verify(mWifiConfigManager).addOrUpdateNetwork(
913                 argThat((c) -> c.FQDN.equals(TEST_FQDN)), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
914                 eq(false));
915         verify(mWifiConfigManager).allowAutojoin(TEST_NETWORK_ID, origWifiConfig.allowAutojoin);
916         verify(mWifiConfigManager).saveToStore(true);
917         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
918         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
919         assertEquals(2, mSharedDataSource.getProviderIndex());
920         // Update provider will keep the user settings from the existing provider.
921         verify(origProvider).setUserConnectChoice(eq(USER_CONNECT_CHOICE), eq(TEST_RSSI));
922         verify(origProvider).setAnonymousIdentity(eq(TEST_ANONYMOUS_IDENTITY));
923         reset(mWifiMetrics);
924         reset(mWifiConfigManager);
925 
926         // Add another provider with the same base domain as the existing provider.
927         // This should replace the existing provider with the new configuration.
928         PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN,
929                 TEST_FRIENDLY_NAME);
930         PasspointProvider newProvider = createMockProvider(newConfig);
931         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
932                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
933                 eq(false), eq(mClock))).thenReturn(newProvider);
934         when(mWifiConfigManager.getConfiguredNetwork(origProvider.getWifiConfig()
935                 .getProfileKey())).thenReturn(origWifiConfig);
936         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE,
937                 false, true));
938 
939         List<PasspointConfiguration> installedConfigs =
940                 mManager.getProviderConfigs(TEST_CREATOR_UID, true);
941         assertEquals(2, installedConfigs.size());
942         assertTrue(installedConfigs.contains(origConfig));
943         assertTrue(installedConfigs.contains(newConfig));
944 
945         verify(mWifiConfigManager).saveToStore(true);
946         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
947         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
948 
949         // Verify data source content.
950         List<PasspointProvider> newProviders = mUserDataSource.getProviders();
951         assertEquals(2, newProviders.size());
952         assertTrue(newConfig.equals(newProviders.get(0).getConfig())
953                 || newConfig.equals(newProviders.get(1).getConfig()));
954         assertEquals(3, mSharedDataSource.getProviderIndex());
955     }
956 
957     /**
958      * Verify that adding a provider will fail when failing to install certificates and
959      * key to the keystore.
960      *
961      * @throws Exception
962      */
963     @Test
addProviderOnKeyInstallationFailiure()964     public void addProviderOnKeyInstallationFailiure() throws Exception {
965         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
966                 TEST_FRIENDLY_NAME);
967         PasspointProvider provider = mock(PasspointProvider.class);
968         when(provider.installCertsAndKeys()).thenReturn(false);
969         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), eq(
970                 mWifiCarrierInfoManager),
971                 anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE), eq(false),
972                 eq(mClock))).thenReturn(provider);
973         assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
974                 false, true));
975         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
976         verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
977     }
978 
979     /**
980      * Verify that adding a provider with R1 configuration and a private self-signed CA certificate
981      * is installed correctly.
982      *
983      * @throws Exception
984      */
985     @Test
addProviderWithR1ConfigPrivateCaCert()986     public void addProviderWithR1ConfigPrivateCaCert() throws Exception {
987         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
988                 TEST_FRIENDLY_NAME);
989         PasspointProvider provider = createMockProvider(config);
990         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
991                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
992                 eq(false), eq(mClock))).thenReturn(provider);
993         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
994                 false, true));
995         verifyInstalledConfig(config);
996         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
997         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
998     }
999 
1000     /**
1001      * Verify that adding a provider with R2 configuration will not perform CA certificate
1002      * verification.
1003      *
1004      * @throws Exception
1005      */
1006     @Test
addProviderWithR2Config()1007     public void addProviderWithR2Config() throws Exception {
1008         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
1009                 TEST_FRIENDLY_NAME);
1010         config.setUpdateIdentifier(1);
1011         PasspointProvider provider = createMockProvider(config);
1012         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1013                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
1014                 eq(false), eq(mClock))).thenReturn(provider);
1015         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
1016                 false, true));
1017         verifyInstalledConfig(config);
1018         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
1019         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
1020     }
1021 
1022     /**
1023      * Verify that removing a non-existing provider will fail.
1024      *
1025      * @throws Exception
1026      */
1027     @Test
removeNonExistingProvider()1028     public void removeNonExistingProvider() throws Exception {
1029         assertFalse(mManager.removeProvider(TEST_CREATOR_UID, true, null, TEST_FQDN));
1030         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
1031         verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess();
1032     }
1033 
1034     /**
1035      * Verify that a empty list will be returned when no providers are installed.
1036      *
1037      * @throws Exception
1038      */
1039     @Test
matchProviderWithNoProvidersInstalled()1040     public void matchProviderWithNoProvidersInstalled() throws Exception {
1041         assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty());
1042     }
1043 
1044     /**
1045      * Verify that a {code null} be returned when ANQP entry doesn't exist in the cache.
1046      *
1047      * @throws Exception
1048      */
1049     @Test
matchProviderWithAnqpCacheMissed()1050     public void matchProviderWithAnqpCacheMissed() throws Exception {
1051         // static mocking
1052         MockitoSession session =
1053                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
1054                         InformationElementUtil.class).startMocking();
1055         try {
1056             addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1057 
1058             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
1059             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1060             vsa.hsRelease = NetworkDetail.HSRelease.R1;
1061             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1062             InformationElementUtil.RoamingConsortium roamingConsortium =
1063                     new InformationElementUtil.RoamingConsortium();
1064             roamingConsortium.anqpOICount = 0;
1065             when(InformationElementUtil.getRoamingConsortiumIE(isNull()))
1066                     .thenReturn(roamingConsortium);
1067             assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty());
1068             // Verify that a request for ANQP elements is initiated.
1069             verify(mAnqpRequestManager).requestANQPElements(eq(TEST_BSSID),
1070                     any(ANQPNetworkKey.class),
1071                     anyBoolean(), any(NetworkDetail.HSRelease.class));
1072         } finally {
1073             session.finishMocking();
1074         }
1075     }
1076 
1077     /**
1078      * Verify that the expected provider will be returned when a HomeProvider is matched.
1079      *
1080      * @throws Exception
1081      */
1082     @Test
matchProviderAsHomeProvider()1083     public void matchProviderAsHomeProvider() throws Exception {
1084         PasspointProvider provider =
1085                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1086         ANQPData entry = new ANQPData(mClock, null);
1087 
1088         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
1089         when(provider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
1090             .thenReturn(PasspointMatch.HomeProvider);
1091         List<Pair<PasspointProvider, PasspointMatch>> results =
1092                 mManager.matchProvider(createTestScanResult());
1093         Pair<PasspointProvider, PasspointMatch> result = results.get(0);
1094         assertEquals(PasspointMatch.HomeProvider, result.second);
1095         assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
1096     }
1097 
1098     /**
1099      * Verify that the expected provider will be returned when a RoamingProvider is matched.
1100      *
1101      * @throws Exception
1102      */
1103     @Test
matchProviderAsRoamingProvider()1104     public void matchProviderAsRoamingProvider() throws Exception {
1105         PasspointProvider provider =
1106                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1107         ANQPData entry = new ANQPData(mClock, null);
1108 
1109         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
1110         when(provider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
1111             .thenReturn(PasspointMatch.RoamingProvider);
1112         List<Pair<PasspointProvider, PasspointMatch>> results =
1113                 mManager.matchProvider(createTestScanResult());
1114         Pair<PasspointProvider, PasspointMatch> result = results.get(0);
1115         assertEquals(PasspointMatch.RoamingProvider, result.second);
1116         assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
1117     }
1118 
1119     /**
1120      * Verify that a {code null} will be returned when there is no matching provider.
1121      *
1122      * @throws Exception
1123      */
1124     @Test
matchProviderWithNoMatch()1125     public void matchProviderWithNoMatch() throws Exception {
1126         PasspointProvider provider =
1127                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1128         ANQPData entry = new ANQPData(mClock, null);
1129 
1130         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
1131         when(provider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
1132             .thenReturn(PasspointMatch.None);
1133         assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty());
1134     }
1135 
1136     /**
1137      * Verify the expectations for sweepCache.
1138      *
1139      * @throws Exception
1140      */
1141     @Test
sweepCache()1142     public void sweepCache() throws Exception {
1143         mManager.sweepCache();
1144         verify(mAnqpCache).sweep();
1145     }
1146 
1147     /**
1148      * Verify that an empty map will be returned if ANQP elements are not cached for the given AP.
1149      *
1150      * @throws Exception
1151      */
1152     @Test
getANQPElementsWithNoMatchFound()1153     public void getANQPElementsWithNoMatchFound() throws Exception {
1154         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
1155         assertTrue(mManager.getANQPElements(createTestScanResult()).isEmpty());
1156     }
1157 
1158     /**
1159      * Verify that an expected ANQP elements will be returned if ANQP elements are cached for the
1160      * given AP.
1161      *
1162      * @throws Exception
1163      */
1164     @Test
getANQPElementsWithMatchFound()1165     public void getANQPElementsWithMatchFound() throws Exception {
1166         Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
1167         anqpElementMap.put(ANQPElementType.ANQPDomName,
1168                 new DomainNameElement(Arrays.asList(new String[] {"test.com"})));
1169         ANQPData entry = new ANQPData(mClock, anqpElementMap);
1170 
1171         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
1172         assertEquals(anqpElementMap, mManager.getANQPElements(createTestScanResult()));
1173     }
1174 
1175     /**
1176      * Verify that if the Carrier ID is updated during match, the config should be persisted.
1177      */
1178     @Test
getAllMatchingProvidersUpdatedConfigWithFullImsiSimCredential()1179     public void getAllMatchingProvidersUpdatedConfigWithFullImsiSimCredential() {
1180         // static mocking
1181         MockitoSession session =
1182                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
1183                         InformationElementUtil.class).startMocking();
1184         try {
1185             PasspointProvider provider = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME,
1186                     TEST_PACKAGE, false, null, false);
1187             when(provider.tryUpdateCarrierId()).thenReturn(true);
1188             reset(mWifiConfigManager);
1189 
1190             ANQPData entry = new ANQPData(mClock, null);
1191             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1192             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
1193 
1194             when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry);
1195             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1196             when(provider.match(anyMap(), isNull(), any(ScanResult.class)))
1197                     .thenReturn(PasspointMatch.HomeProvider);
1198 
1199             List<Pair<PasspointProvider, PasspointMatch>> matchedProviders =
1200                     mManager.getAllMatchedProviders(createTestScanResult());
1201 
1202             verify(mWifiConfigManager).saveToStore(eq(true));
1203 
1204         } finally {
1205             session.finishMocking();
1206         }
1207     }
1208     /**
1209      * Verify that an expected map of FQDN and a list of ScanResult will be returned when provided
1210      * scanResults are matched to installed Passpoint profiles.
1211      */
1212     @Test
getAllMatchingFqdnsForScanResults()1213     public void getAllMatchingFqdnsForScanResults() {
1214         // static mocking
1215         MockitoSession session =
1216                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
1217                         InformationElementUtil.class).startMocking();
1218         try {
1219             PasspointProvider providerHome = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME,
1220                     TEST_PACKAGE, false, null, false);
1221             providerHome.getWifiConfig().isHomeProviderNetwork = true;
1222             PasspointProvider providerRoaming = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
1223                     TEST_PACKAGE, false, null, false);
1224             WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1,
1225                     TEST_UID, "\"PasspointTestSSID\"", true, true,
1226                     TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP);
1227             PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
1228                     TEST_PACKAGE, wifiConfiguration, false, null, false);
1229             ANQPData entry = new ANQPData(mClock, null);
1230             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1231             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
1232 
1233             when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(entry);
1234             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1235             when(providerHome.match(anyMap(), isNull(), any(ScanResult.class)))
1236                     .thenReturn(PasspointMatch.HomeProvider);
1237             when(providerRoaming.match(anyMap(), isNull(), any(ScanResult.class)))
1238                     .thenReturn(PasspointMatch.RoamingProvider);
1239             when(providerNone.match(anyMap(), isNull(), any(ScanResult.class)))
1240                     .thenReturn(PasspointMatch.None);
1241 
1242             Map<String, Map<Integer, List<ScanResult>>> configs =
1243                     mManager.getAllMatchingPasspointProfilesForScanResults(
1244                             createTestScanResults());
1245 
1246             // Expects to be matched with home Provider for each AP (two APs).
1247             assertEquals(2, configs.get(providerHome.getConfig().getUniqueId()).get(
1248                     WifiManager.PASSPOINT_HOME_NETWORK).size());
1249             assertFalse(configs.get(providerHome.getConfig().getUniqueId())
1250                             .containsKey(WifiManager.PASSPOINT_ROAMING_NETWORK));
1251 
1252             // Expects to be matched with roaming Provider for each AP (two APs).
1253             assertEquals(2, configs.get(providerRoaming.getConfig().getUniqueId()).get(
1254                     WifiManager.PASSPOINT_ROAMING_NETWORK).size());
1255             assertFalse(configs.get(providerRoaming.getConfig().getUniqueId())
1256                     .containsKey(WifiManager.PASSPOINT_HOME_NETWORK));
1257 
1258         } finally {
1259             session.finishMocking();
1260         }
1261     }
1262 
1263     /**
1264      * Verify that an expected list of {@link WifiConfiguration} will be returned when provided
1265      * a list of FQDN is matched to installed Passpoint profiles which is already added into the
1266      * WifiConfigManager. For suggestion passpoint network, will check if that suggestion share
1267      * credential with user to choose from wifi picker.
1268      * - Provider1 and Provider2 are saved passpoint, Provider1 is already added into the
1269      * WifiConfigManger
1270      * - Provider3 and Provider4 are suggestion passpoint, only Provider4 is shared with user. Both
1271      * providers are already added into the WifiConfigManager
1272      * - Expected result: Provider1 and Provider4 should be returned .
1273      */
1274     @Test
getWifiConfigsForPasspointProfiles()1275     public void getWifiConfigsForPasspointProfiles() {
1276         PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
1277                 TEST_PACKAGE, false, null, false);
1278         WifiConfiguration config1 = provider1.getWifiConfig();
1279         when(mWifiConfigManager.getConfiguredNetwork(provider1.getConfig().getUniqueId()))
1280                 .thenReturn(config1);
1281         PasspointProvider provider2 = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
1282                 TEST_PACKAGE, false, null, false);
1283         PasspointProvider provider3 = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
1284                 TEST_PACKAGE, true, null, false);
1285         when(mWifiNetworkSuggestionsManager
1286                 .isPasspointSuggestionSharedWithUser(provider3.getWifiConfig())).thenReturn(false);
1287         WifiConfiguration config3 = provider3.getWifiConfig();
1288         when(mWifiConfigManager.getConfiguredNetwork(provider3.getConfig().getUniqueId()))
1289                 .thenReturn(config3);
1290         PasspointProvider provider4 = addTestProvider(TEST_FQDN + 3, TEST_FRIENDLY_NAME,
1291                 TEST_PACKAGE, true, null, false);
1292         when(mWifiNetworkSuggestionsManager
1293                 .isPasspointSuggestionSharedWithUser(provider4.getWifiConfig())).thenReturn(true);
1294         WifiConfiguration config4 = provider4.getWifiConfig();
1295         when(mWifiConfigManager.getConfiguredNetwork(provider4.getConfig().getUniqueId()))
1296                 .thenReturn(config4);
1297 
1298         List<WifiConfiguration> wifiConfigurationList = mManager.getWifiConfigsForPasspointProfiles(
1299                 List.of(provider1.getConfig().getUniqueId(), provider2.getConfig().getUniqueId(),
1300                         provider3.getConfig().getUniqueId(), provider4.getConfig().getUniqueId(),
1301                         TEST_FQDN + "_353ab8c93", TEST_FQDN + "_83765319aca"));
1302         assertEquals(2, wifiConfigurationList.size());
1303         Set<String> uniqueIdSet = wifiConfigurationList
1304                 .stream()
1305                 .map(WifiConfiguration::getPasspointUniqueId)
1306                 .collect(Collectors.toSet());
1307         assertTrue(uniqueIdSet.contains(provider1.getConfig().getUniqueId()));
1308         assertTrue(uniqueIdSet.contains(provider4.getConfig().getUniqueId()));
1309     }
1310 
1311     /**
1312      * Verify that a {@link WifiConfiguration} will be returned with the correct value for the
1313      * randomized MAC address.
1314      */
1315     @Test
getWifiConfigsForPasspointProfilesWithoutNonPersistentMacRandomization()1316     public void getWifiConfigsForPasspointProfilesWithoutNonPersistentMacRandomization() {
1317         MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab");
1318         when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress);
1319         when(mWifiConfigManager.shouldUseNonPersistentRandomization(any())).thenReturn(false);
1320         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
1321                 TEST_PACKAGE, false, null, false);
1322         WifiConfiguration configuration = provider.getWifiConfig();
1323         when(mWifiConfigManager.getConfiguredNetwork(provider.getConfig().getUniqueId()))
1324                 .thenReturn(configuration);
1325         WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles(
1326                 Collections.singletonList(provider.getConfig().getUniqueId())).get(0);
1327         assertEquals(config.getRandomizedMacAddress(), randomizedMacAddress);
1328         verify(mMacAddressUtil).calculatePersistentMac(
1329                 eq(provider.getConfig().getUniqueId()), any());
1330     }
1331 
1332     /**
1333      * Verify that a {@link WifiConfiguration} will be returned with DEFAULT_MAC_ADDRESS for the
1334      * randomized MAC address if non-persistent mac randomization is enabled. This value will
1335      * display in the wifi picker's network details page as "Not available" if the network is
1336      * disconnected.
1337      */
1338     @Test
getWifiConfigsForPasspointProfilesWithNonPersistentMacRandomization()1339     public void getWifiConfigsForPasspointProfilesWithNonPersistentMacRandomization() {
1340         MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab");
1341         when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress);
1342         when(mWifiConfigManager.shouldUseNonPersistentRandomization(any())).thenReturn(true);
1343         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
1344                 TEST_PACKAGE, false, null, false);
1345         WifiConfiguration configuration = provider.getWifiConfig();
1346         when(mWifiConfigManager.getConfiguredNetwork(provider.getConfig().getUniqueId()))
1347                 .thenReturn(configuration);
1348         WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles(
1349                 Collections.singletonList(provider.getConfig().getUniqueId())).get(0);
1350         assertEquals(config.getRandomizedMacAddress(), MacAddress.fromString(DEFAULT_MAC_ADDRESS));
1351     }
1352 
1353     /**
1354      * Verify that an empty map will be returned when trying to get all matching FQDN for a {@code
1355      * null} {@link ScanResult}.
1356      */
1357     @Test
getAllMatchingFqdnsForScanResultsWithNullScanResult()1358     public void getAllMatchingFqdnsForScanResultsWithNullScanResult() throws Exception {
1359         assertEquals(0,
1360                 mManager.getAllMatchingPasspointProfilesForScanResults(null).size());
1361     }
1362 
1363     /**
1364      * Verify that an empty map will be returned when trying to get a all matching FQDN for a {@link
1365      * ScanResult} with a {@code null} BSSID.
1366      */
1367     @Test
getAllMatchingFqdnsForScanResultsWithNullBSSID()1368     public void getAllMatchingFqdnsForScanResultsWithNullBSSID() throws Exception {
1369         ScanResult scanResult = createTestScanResult();
1370         scanResult.BSSID = null;
1371 
1372         assertEquals(0,
1373                 mManager.getAllMatchingPasspointProfilesForScanResults(
1374                         Arrays.asList(scanResult)).size());
1375     }
1376 
1377     /**
1378      * Verify that an empty map will be returned when trying to get all matching FQDN for a {@link
1379      * ScanResult} with an invalid BSSID.
1380      */
1381     @Test
ggetAllMatchingFqdnsForScanResultsWithInvalidBSSID()1382     public void ggetAllMatchingFqdnsForScanResultsWithInvalidBSSID() throws Exception {
1383         ScanResult scanResult = createTestScanResult();
1384         scanResult.BSSID = "asdfdasfas";
1385 
1386         assertEquals(0,
1387                 mManager.getAllMatchingPasspointProfilesForScanResults(
1388                         Arrays.asList(scanResult)).size());
1389     }
1390 
1391     /**
1392      * Verify that an empty map will be returned when trying to get all matching FQDN for a
1393      * non-Passpoint AP.
1394      */
1395     @Test
getAllMatchingFqdnsForScanResultsForNonPasspointAP()1396     public void getAllMatchingFqdnsForScanResultsForNonPasspointAP() throws Exception {
1397         ScanResult scanResult = createTestScanResult();
1398         scanResult.flags = 0;
1399         assertEquals(0,
1400                 mManager.getAllMatchingPasspointProfilesForScanResults(
1401                         Arrays.asList(scanResult)).size());
1402     }
1403 
1404     /**
1405      * Verify that an empty list will be returned when retrieving OSU providers for an AP with
1406      * null scan result.
1407      *
1408      * @throws Exception
1409      */
1410     @Test
getMatchingOsuProvidersForNullScanResult()1411     public void getMatchingOsuProvidersForNullScanResult() throws Exception {
1412         assertTrue(mManager.getMatchingOsuProviders(null).isEmpty());
1413     }
1414 
1415     /**
1416      * Verify that an empty list will be returned when retrieving OSU providers for an AP with
1417      * invalid BSSID.
1418      *
1419      * @throws Exception
1420      */
1421     @Test
getMatchingOsuProvidersForInvalidBSSID()1422     public void getMatchingOsuProvidersForInvalidBSSID() throws Exception {
1423         ScanResult scanResult = createTestScanResult();
1424         scanResult.BSSID = "asdfdasfas";
1425         assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty());
1426     }
1427 
1428     /**
1429      * Verify that an empty list will be returned when retrieving OSU providers for a
1430      * non-Passpoint AP.
1431      *
1432      * @throws Exception
1433      */
1434     @Test
getMatchingOsuProvidersForNonPasspointAP()1435     public void getMatchingOsuProvidersForNonPasspointAP() throws Exception {
1436         ScanResult scanResult = createTestScanResult();
1437         scanResult.flags = 0;
1438         assertTrue(mManager.getMatchingOsuProviders(Arrays.asList(scanResult)).isEmpty());
1439     }
1440 
1441     /**
1442      * Verify that an empty list will be returned when no match is found from the ANQP cache.
1443      *
1444      * @throws Exception
1445      */
1446     @Test
getMatchingOsuProviderWithNoMatch()1447     public void getMatchingOsuProviderWithNoMatch() throws Exception {
1448         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
1449         assertTrue(
1450                 mManager.getMatchingOsuProviders(Arrays.asList(createTestScanResult())).isEmpty());
1451     }
1452 
1453     /**
1454      * Verify that an expected provider list will be returned when a match is found from
1455      * the ANQP cache with a given list of scanResult.
1456      *
1457      * @throws Exception
1458      */
1459     @Test
getMatchingOsuProvidersWithMatch()1460     public void getMatchingOsuProvidersWithMatch() throws Exception {
1461         // Setup OSU providers ANQP element for AP1.
1462         List<OsuProviderInfo> providerInfoListOfAp1 = new ArrayList<>();
1463         Map<ANQPElementType, ANQPElement> anqpElementMapOfAp1 = new HashMap<>();
1464         Set<OsuProvider> expectedOsuProvidersForDomainId = new HashSet<>();
1465 
1466         // Setup OSU providers ANQP element for AP2.
1467         List<OsuProviderInfo> providerInfoListOfAp2 = new ArrayList<>();
1468         Map<ANQPElementType, ANQPElement> anqpElementMapOfAp2 = new HashMap<>();
1469         Set<OsuProvider> expectedOsuProvidersForDomainId2 = new HashSet<>();
1470         int osuProviderCount = 4;
1471 
1472         // static mocking
1473         MockitoSession session =
1474                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
1475                         InformationElementUtil.class).startMocking();
1476         try {
1477             for (int i = 0; i < osuProviderCount; i++) {
1478                 // Test data.
1479                 String friendlyName = "Test Provider" + i;
1480                 String serviceDescription = "Dummy Service" + i;
1481                 Uri serverUri = Uri.parse("https://" + "test" + i + ".com");
1482                 String nai = "access.test.com";
1483                 List<Integer> methodList = Arrays.asList(1);
1484                 List<I18Name> friendlyNames = Arrays.asList(
1485                         new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, friendlyName));
1486                 List<I18Name> serviceDescriptions = Arrays.asList(
1487                         new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH,
1488                                 serviceDescription));
1489                 Map<String, String> friendlyNameMap = new HashMap<>();
1490                 friendlyNames.forEach(e -> friendlyNameMap.put(e.getLanguage(), e.getText()));
1491 
1492                 expectedOsuProvidersForDomainId.add(new OsuProvider(
1493                         (WifiSsid) null, friendlyNameMap, serviceDescription,
1494                         serverUri, nai, methodList));
1495 
1496                 // add All OSU Providers for AP1.
1497                 providerInfoListOfAp1.add(new OsuProviderInfo(
1498                         friendlyNames, serverUri, methodList, null, nai, serviceDescriptions));
1499 
1500                 // add only half of All OSU Providers for AP2.
1501                 if (i >= osuProviderCount / 2) {
1502                     providerInfoListOfAp2.add(new OsuProviderInfo(
1503                             friendlyNames, serverUri, methodList, null, nai, serviceDescriptions));
1504                     expectedOsuProvidersForDomainId2.add(new OsuProvider(
1505                             (WifiSsid) null, friendlyNameMap, serviceDescription,
1506                             serverUri, nai, methodList));
1507                 }
1508             }
1509             anqpElementMapOfAp1.put(ANQPElementType.HSOSUProviders,
1510                     new HSOsuProvidersElement(WifiSsid.fromUtf8Text("Test SSID"),
1511                             providerInfoListOfAp1));
1512             ANQPData anqpData = new ANQPData(mClock, anqpElementMapOfAp1);
1513             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(anqpData);
1514 
1515             anqpElementMapOfAp2.put(ANQPElementType.HSOSUProviders,
1516                     new HSOsuProvidersElement(WifiSsid.fromUtf8Text("Test SSID2"),
1517                             providerInfoListOfAp2));
1518             ANQPData anqpData2 = new ANQPData(mClock, anqpElementMapOfAp2);
1519             when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(anqpData2);
1520 
1521             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
1522 
1523             // ANQP_DOMAIN_ID(TEST_ANQP_KEY)
1524             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
1525             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1526             assertEquals(mManager.getMatchingOsuProviders(
1527                     Arrays.asList(createTestScanResult())).keySet(),
1528                     expectedOsuProvidersForDomainId);
1529 
1530             // ANQP_DOMAIN_ID2(TEST_ANQP_KEY2)
1531             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
1532             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
1533             assertEquals(mManager.getMatchingOsuProviders(
1534                     createTestScanResults()).keySet(), expectedOsuProvidersForDomainId2);
1535         } finally {
1536             session.finishMocking();
1537         }
1538     }
1539 
1540     /**
1541      * Verify that matching Passpoint configurations will be returned as map with corresponding
1542      * OSU providers.
1543      */
1544     @Test
getMatchingPasspointConfigsForOsuProvidersWithMatch()1545     public void getMatchingPasspointConfigsForOsuProvidersWithMatch() {
1546         PasspointProvider provider1 =
1547                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, true);
1548         PasspointProvider provider2 =
1549                 addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE, false, null, true);
1550 
1551         List<OsuProvider> osuProviders = new ArrayList<>();
1552         Map<String, String> friendlyNames = new HashMap<>();
1553         friendlyNames.put("en", "NO-MATCH-NAME");
1554         friendlyNames.put("kr", TEST_FRIENDLY_NAME + 1);
1555 
1556         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1557                 friendlyNames));
1558         friendlyNames = new HashMap<>();
1559         friendlyNames.put("en", TEST_FRIENDLY_NAME2);
1560         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1561                 friendlyNames));
1562 
1563         Map<OsuProvider, PasspointConfiguration> results =
1564                 mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders);
1565 
1566         assertEquals(2, results.size());
1567         assertThat(Arrays.asList(provider1.getConfig(), provider2.getConfig()),
1568                 containsInAnyOrder(results.values().toArray()));
1569     }
1570 
1571     /**
1572      * Verify that empty map will be returned when there is no matching Passpoint configuration.
1573      */
1574     @Test
getMatchingPasspointConfigsForOsuProvidersWitNoMatch()1575     public void getMatchingPasspointConfigsForOsuProvidersWitNoMatch() {
1576         addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1577         addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE, false, null, false);
1578 
1579         List<OsuProvider> osuProviders = new ArrayList<>();
1580 
1581         Map<String, String> friendlyNames = new HashMap<>();
1582         friendlyNames.put("en", "NO-MATCH-NAME");
1583         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1584                 friendlyNames));
1585         friendlyNames = new HashMap<>();
1586         friendlyNames.put("en", "NO-MATCH-NAME-2");
1587         osuProviders.add(PasspointProvisioningTestUtil.generateOsuProviderWithFriendlyName(true,
1588                 friendlyNames));
1589 
1590         assertEquals(0, mManager.getMatchingPasspointConfigsForOsuProviders(osuProviders).size());
1591     }
1592 
1593     /**
1594      * Verify that the provider list maintained by the PasspointManager after the list is updated
1595      * in the data source.
1596      *
1597      * @throws Exception
1598      */
1599     @Test
verifyProvidersAfterDataSourceUpdate()1600     public void verifyProvidersAfterDataSourceUpdate() throws Exception {
1601         // Update the provider list in the data source.
1602         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
1603                 TEST_FRIENDLY_NAME);
1604         PasspointProvider provider = createMockProvider(config);
1605         List<PasspointProvider> providers = new ArrayList<>();
1606         providers.add(provider);
1607         mUserDataSource.setProviders(providers);
1608 
1609         // Verify the providers maintained by PasspointManager.
1610         assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size());
1611         assertEquals(config, mManager.getProviderConfigs(TEST_CREATOR_UID, true).get(0));
1612     }
1613 
1614     /**
1615      * Verify that the provider index used by PasspointManager is updated after it is updated in
1616      * the data source.
1617      *
1618      * @throws Exception
1619      */
1620     @Test
verifyProviderIndexAfterDataSourceUpdate()1621     public void verifyProviderIndexAfterDataSourceUpdate() throws Exception {
1622         long providerIndex = 9;
1623         mSharedDataSource.setProviderIndex(providerIndex);
1624         assertEquals(providerIndex, mSharedDataSource.getProviderIndex());
1625 
1626         // Add a provider.
1627         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
1628                 TEST_FRIENDLY_NAME);
1629         PasspointProvider provider = createMockProvider(config);
1630         // Verify the provider ID used to create the new provider.
1631         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1632                 eq(mWifiCarrierInfoManager), eq(providerIndex), eq(TEST_CREATOR_UID),
1633                 eq(TEST_PACKAGE), eq(false), eq(mClock))).thenReturn(provider);
1634 
1635         assertTrue(
1636                 mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE, false, true));
1637         verifyInstalledConfig(config);
1638         reset(mWifiConfigManager);
1639     }
1640 
1641     /**
1642      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1643      * adding a legacy Passpoint configuration containing a valid user credential.
1644      *
1645      * @throws Exception
1646      */
1647     @Test
addLegacyPasspointConfigWithUserCredential()1648     public void addLegacyPasspointConfigWithUserCredential() throws Exception {
1649         // Test data.
1650         String fqdn = "test.com";
1651         String friendlyName = "Friendly Name";
1652         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1653         String realm = "realm.com";
1654         String username = "username";
1655         String password = "password";
1656         byte[] base64EncodedPw =
1657                 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
1658         String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
1659         String caCertificateAlias = "CaCert";
1660 
1661         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1662         WifiConfiguration wifiConfig = new WifiConfiguration();
1663         wifiConfig.FQDN = fqdn;
1664         wifiConfig.providerFriendlyName = friendlyName;
1665         wifiConfig.roamingConsortiumIds = rcOIs;
1666         wifiConfig.enterpriseConfig.setIdentity(username);
1667         wifiConfig.enterpriseConfig.setPassword(password);
1668         wifiConfig.enterpriseConfig.setRealm(realm);
1669         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1670         wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
1671         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1672 
1673         // Setup expected {@link PasspointConfiguration}
1674         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1675         HomeSp homeSp = new HomeSp();
1676         homeSp.setFqdn(fqdn);
1677         homeSp.setFriendlyName(friendlyName);
1678         homeSp.setRoamingConsortiumOis(rcOIs);
1679         passpointConfig.setHomeSp(homeSp);
1680         Credential credential = new Credential();
1681         Credential.UserCredential userCredential = new Credential.UserCredential();
1682         userCredential.setUsername(username);
1683         userCredential.setPassword(encodedPasswordStr);
1684         userCredential.setEapType(EAPConstants.EAP_TTLS);
1685         userCredential.setNonEapInnerMethod("PAP");
1686         credential.setUserCredential(userCredential);
1687         credential.setRealm(realm);
1688         passpointConfig.setCredential(credential);
1689 
1690         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1691         verifyInstalledConfig(passpointConfig);
1692     }
1693 
1694     /**
1695      * Verify that adding a legacy Passpoint configuration containing user credential will
1696      * fail when client certificate is not provided.
1697      *
1698      * @throws Exception
1699      */
1700     @Test
addLegacyPasspointConfigWithUserCredentialWithoutCaCert()1701     public void addLegacyPasspointConfigWithUserCredentialWithoutCaCert() throws Exception {
1702         // Test data.
1703         String fqdn = "test.com";
1704         String friendlyName = "Friendly Name";
1705         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1706         String realm = "realm.com";
1707         String username = "username";
1708         String password = "password";
1709         byte[] base64EncodedPw =
1710                 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
1711         String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8);
1712 
1713         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1714         WifiConfiguration wifiConfig = new WifiConfiguration();
1715         wifiConfig.FQDN = fqdn;
1716         wifiConfig.providerFriendlyName = friendlyName;
1717         wifiConfig.roamingConsortiumIds = rcOIs;
1718         wifiConfig.enterpriseConfig.setIdentity(username);
1719         wifiConfig.enterpriseConfig.setPassword(password);
1720         wifiConfig.enterpriseConfig.setRealm(realm);
1721         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
1722         wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
1723 
1724         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1725     }
1726 
1727     /**
1728      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1729      * adding a legacy Passpoint configuration containing a valid SIM credential.
1730      *
1731      * @throws Exception
1732      */
1733     @Test
addLegacyPasspointConfigWithSimCredential()1734     public void addLegacyPasspointConfigWithSimCredential() throws Exception {
1735         // Test data.
1736         String fqdn = "test.com";
1737         String friendlyName = "Friendly Name";
1738         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1739         String realm = "realm.com";
1740         String imsi = "1234";
1741 
1742         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1743         WifiConfiguration wifiConfig = new WifiConfiguration();
1744         wifiConfig.FQDN = fqdn;
1745         wifiConfig.providerFriendlyName = friendlyName;
1746         wifiConfig.roamingConsortiumIds = rcOIs;
1747         wifiConfig.enterpriseConfig.setRealm(realm);
1748         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
1749         wifiConfig.enterpriseConfig.setPlmn(imsi);
1750 
1751         // Setup expected {@link PasspointConfiguration}
1752         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1753         HomeSp homeSp = new HomeSp();
1754         homeSp.setFqdn(fqdn);
1755         homeSp.setFriendlyName(friendlyName);
1756         homeSp.setRoamingConsortiumOis(rcOIs);
1757         passpointConfig.setHomeSp(homeSp);
1758         Credential credential = new Credential();
1759         Credential.SimCredential simCredential = new Credential.SimCredential();
1760         simCredential.setEapType(EAPConstants.EAP_SIM);
1761         simCredential.setImsi(imsi);
1762         credential.setSimCredential(simCredential);
1763         credential.setRealm(realm);
1764         passpointConfig.setCredential(credential);
1765 
1766         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1767         verifyInstalledConfig(passpointConfig);
1768     }
1769 
1770     /**
1771      * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when
1772      * adding a legacy Passpoint configuration containing a valid certificate credential.
1773      *
1774      * @throws Exception
1775      */
1776     @Test
addLegacyPasspointConfigWithCertCredential()1777     public void addLegacyPasspointConfigWithCertCredential() throws Exception {
1778         // Test data.
1779         String fqdn = "test.com";
1780         String friendlyName = "Friendly Name";
1781         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1782         String realm = "realm.com";
1783         String caCertificateAlias = "CaCert";
1784         String clientCertificateAlias = "ClientCert";
1785 
1786         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1787         WifiConfiguration wifiConfig = new WifiConfiguration();
1788         wifiConfig.FQDN = fqdn;
1789         wifiConfig.providerFriendlyName = friendlyName;
1790         wifiConfig.roamingConsortiumIds = rcOIs;
1791         wifiConfig.enterpriseConfig.setRealm(realm);
1792         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1793         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1794         wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias);
1795 
1796         // Setup expected {@link PasspointConfiguration}
1797         PasspointConfiguration passpointConfig = new PasspointConfiguration();
1798         HomeSp homeSp = new HomeSp();
1799         homeSp.setFqdn(fqdn);
1800         homeSp.setFriendlyName(friendlyName);
1801         homeSp.setRoamingConsortiumOis(rcOIs);
1802         passpointConfig.setHomeSp(homeSp);
1803         Credential credential = new Credential();
1804         Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
1805         certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3);
1806         credential.setCertCredential(certCredential);
1807         credential.setRealm(realm);
1808         passpointConfig.setCredential(credential);
1809 
1810         assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1811         verifyInstalledConfig(passpointConfig);
1812     }
1813 
1814     /**
1815      * Verify that adding a legacy Passpoint configuration containing certificate credential will
1816      * fail when CA certificate is not provided.
1817      *
1818      * @throws Exception
1819      */
1820     @Test
addLegacyPasspointConfigWithCertCredentialWithoutCaCert()1821     public void addLegacyPasspointConfigWithCertCredentialWithoutCaCert() throws Exception {
1822         // Test data.
1823         String fqdn = "test.com";
1824         String friendlyName = "Friendly Name";
1825         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1826         String realm = "realm.com";
1827         String clientCertificateAlias = "ClientCert";
1828 
1829         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1830         WifiConfiguration wifiConfig = new WifiConfiguration();
1831         wifiConfig.FQDN = fqdn;
1832         wifiConfig.providerFriendlyName = friendlyName;
1833         wifiConfig.roamingConsortiumIds = rcOIs;
1834         wifiConfig.enterpriseConfig.setRealm(realm);
1835         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1836         wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias);
1837 
1838         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1839     }
1840 
1841     /**
1842      * Verify that adding a legacy Passpoint configuration containing certificate credential will
1843      * fail when client certificate is not provided.
1844      *
1845      * @throws Exception
1846      */
1847     @Test
addLegacyPasspointConfigWithCertCredentialWithoutClientCert()1848     public void addLegacyPasspointConfigWithCertCredentialWithoutClientCert() throws Exception {
1849         // Test data.
1850         String fqdn = "test.com";
1851         String friendlyName = "Friendly Name";
1852         long[] rcOIs = new long[] {0x1234L, 0x2345L};
1853         String realm = "realm.com";
1854         String caCertificateAlias = "CaCert";
1855 
1856         // Setup WifiConfiguration for legacy Passpoint configuraiton.
1857         WifiConfiguration wifiConfig = new WifiConfiguration();
1858         wifiConfig.FQDN = fqdn;
1859         wifiConfig.providerFriendlyName = friendlyName;
1860         wifiConfig.roamingConsortiumIds = rcOIs;
1861         wifiConfig.enterpriseConfig.setRealm(realm);
1862         wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1863         wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias);
1864 
1865         assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig));
1866     }
1867 
1868     /**
1869      * Verify that the provider's "hasEverConnected" flag will be set to true and the associated
1870      * metric is updated after the provider was used to successfully connect to a Passpoint
1871      * network for the first time.
1872      *
1873      * @throws Exception
1874      */
1875     @Test
providerNetworkConnectedFirstTime()1876     public void providerNetworkConnectedFirstTime() throws Exception {
1877         PasspointProvider provider =
1878                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1879         when(provider.getHasEverConnected()).thenReturn(false);
1880         mManager.onPasspointNetworkConnected(provider.getConfig().getUniqueId());
1881         verify(provider).setHasEverConnected(eq(true));
1882     }
1883 
1884     /**
1885      * Verify that the provider's "hasEverConnected" flag the associated metric is not updated
1886      * after the provider was used to successfully connect to a Passpoint network for non-first
1887      * time.
1888      *
1889      * @throws Exception
1890      */
1891     @Test
providerNetworkConnectedNotFirstTime()1892     public void providerNetworkConnectedNotFirstTime() throws Exception {
1893         PasspointProvider provider =
1894                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1895         when(provider.getHasEverConnected()).thenReturn(true);
1896         mManager.onPasspointNetworkConnected(TEST_FQDN);
1897         verify(provider, never()).setHasEverConnected(anyBoolean());
1898     }
1899 
1900     /**
1901      * Verify that the expected Passpoint metrics are updated when
1902      * {@link PasspointManager#updateMetrics} is invoked.
1903      *
1904      * @throws Exception
1905      */
1906     @Test
updateMetrics()1907     public void updateMetrics() {
1908         PasspointProvider provider =
1909                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1910         ArgumentCaptor<Map<String, PasspointProvider>> argCaptor = ArgumentCaptor.forClass(
1911                 Map.class);
1912         // Provider have not provided a successful network connection.
1913         int expectedInstalledProviders = 1;
1914         int expectedConnectedProviders = 0;
1915         when(provider.getHasEverConnected()).thenReturn(false);
1916         mManager.updateMetrics();
1917         verify(mWifiMetrics).updateSavedPasspointProfiles(
1918                 eq(expectedInstalledProviders), eq(expectedConnectedProviders));
1919 
1920         verify(mWifiMetrics).updateSavedPasspointProfilesInfo(argCaptor.capture());
1921         assertEquals(expectedInstalledProviders, argCaptor.getValue().size());
1922         assertEquals(provider, argCaptor.getValue().get(provider.getConfig().getUniqueId()));
1923         reset(mWifiMetrics);
1924 
1925         // Provider have provided a successful network connection.
1926         expectedConnectedProviders = 1;
1927         when(provider.getHasEverConnected()).thenReturn(true);
1928         mManager.updateMetrics();
1929         verify(mWifiMetrics).updateSavedPasspointProfiles(
1930                 eq(expectedInstalledProviders), eq(expectedConnectedProviders));
1931     }
1932 
1933     /**
1934      * Verify Passpoint Manager's provisioning APIs by invoking methods in PasspointProvisioner for
1935      * initiailization and provisioning a provider.
1936      */
1937     @Test
verifyPasspointProvisioner()1938     public void verifyPasspointProvisioner() {
1939         mManager.initializeProvisioner(mLooper.getLooper());
1940         verify(mPasspointProvisioner).init(any(Looper.class));
1941         when(mPasspointProvisioner.startSubscriptionProvisioning(anyInt(), any(OsuProvider.class),
1942                 any(IProvisioningCallback.class))).thenReturn(true);
1943         OsuProvider osuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
1944         assertEquals(true,
1945                 mManager.startSubscriptionProvisioning(TEST_UID, osuProvider, mCallback));
1946     }
1947 
1948     /**
1949      * Verify that the corresponding Passpoint provider is removed when the app is disabled.
1950      */
1951     @Test
verifyRemovingPasspointProfilesWhenAppIsDisabled()1952     public void verifyRemovingPasspointProfilesWhenAppIsDisabled() {
1953         WifiConfiguration currentConfiguration = WifiConfigurationTestUtil.createPasspointNetwork();
1954         currentConfiguration.FQDN = TEST_FQDN;
1955         PasspointProvider passpointProvider =
1956                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
1957         currentConfiguration.setPasspointUniqueId(passpointProvider.getConfig().getUniqueId());
1958         verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE),
1959                 mAppOpChangedListenerCaptor.capture());
1960         assertEquals(1, mManager.getProviderConfigs(TEST_CREATOR_UID, true).size());
1961         AppOpsManager.OnOpChangedListener listener = mAppOpChangedListenerCaptor.getValue();
1962         assertNotNull(listener);
1963 
1964         // Disallow change wifi state & ensure we remove the profiles from database.
1965         when(mAppOpsManager.unsafeCheckOpNoThrow(
1966                 OPSTR_CHANGE_WIFI_STATE, TEST_CREATOR_UID,
1967                 TEST_PACKAGE))
1968                 .thenReturn(MODE_IGNORED);
1969         listener.onOpChanged(OPSTR_CHANGE_WIFI_STATE, TEST_PACKAGE);
1970         mLooper.dispatchAll();
1971 
1972         verify(mAppOpsManager).stopWatchingMode(mAppOpChangedListenerCaptor.getValue());
1973         verify(mWifiConfigManager).removePasspointConfiguredNetwork(
1974                 passpointProvider.getWifiConfig().getProfileKey());
1975         assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, true).isEmpty());
1976     }
1977 
1978     /**
1979      * Verify that removing a provider with a different UID will not succeed.
1980      *
1981      * @throws Exception
1982      */
1983     @Test
removeGetProviderWithDifferentUid()1984     public void removeGetProviderWithDifferentUid() throws Exception {
1985         PasspointConfiguration config = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
1986                 TEST_REALM);
1987         PasspointProvider provider = createMockProvider(config);
1988         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
1989                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
1990                 eq(false), eq(mClock))).thenReturn(provider);
1991         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
1992                 false, true));
1993         verifyInstalledConfig(config);
1994         verify(mWifiConfigManager).saveToStore(true);
1995         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
1996         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
1997         reset(mWifiMetrics);
1998         reset(mWifiConfigManager);
1999 
2000         // no profiles available for TEST_UID
2001         assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty());
2002         // 1 profile available for TEST_CREATOR_UID
2003         assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty());
2004 
2005         // Remove the provider as a non-privileged non-creator app.
2006         assertFalse(mManager.removeProvider(TEST_UID, false, null, TEST_FQDN));
2007         verify(provider, never()).uninstallCertsAndKeys();
2008         verify(mWifiConfigManager, never()).saveToStore(true);
2009         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
2010         verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess();
2011 
2012         // no profiles available for TEST_UID
2013         assertTrue(mManager.getProviderConfigs(TEST_UID, false).isEmpty());
2014         // 1 profile available for TEST_CREATOR_UID
2015         assertFalse(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty());
2016     }
2017 
2018     /**
2019      * Verify that removing a provider from a background user will fail.
2020      *
2021      * @throws Exception
2022      */
2023     @Test
removeProviderWithBackgroundUser()2024     public void removeProviderWithBackgroundUser() throws Exception {
2025         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
2026                 TEST_FRIENDLY_NAME);
2027         PasspointProvider provider = createMockProvider(config);
2028         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2029                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2030                 eq(false), eq(mClock))).thenReturn(provider);
2031         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
2032                 false, true));
2033         verifyInstalledConfig(config);
2034         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2035         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2036 
2037         when(mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(anyInt()))
2038                 .thenReturn(false);
2039         assertFalse(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN));
2040     }
2041 
2042     /**
2043      * Verify that adding a suggestion provider with a valid configuration and user credential will
2044      * succeed.
2045      *
2046      * @throws Exception
2047      */
2048     @Test
addRemoveSuggestionProvider()2049     public void addRemoveSuggestionProvider() throws Exception {
2050         PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
2051                 TEST_FRIENDLY_NAME);
2052         PasspointProvider provider = createMockProvider(config);
2053         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2054         when(provider.isFromSuggestion()).thenReturn(true);
2055         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2056                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2057                 eq(true), eq(mClock))).thenReturn(provider);
2058         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
2059                 true, true));
2060         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2061         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2062         verify(mAppOpsManager, never()).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE),
2063                 eq(TEST_PACKAGE), any(AppOpsManager.OnOpChangedListener.class));
2064         assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty());
2065         reset(mWifiMetrics);
2066         reset(mWifiConfigManager);
2067 
2068         // Verify content in the data source.
2069         List<PasspointProvider> providers = mUserDataSource.getProviders();
2070         assertEquals(1, providers.size());
2071         assertEquals(config, providers.get(0).getConfig());
2072         // Provider index start with 0, should be 1 after adding a provider.
2073         assertEquals(1, mSharedDataSource.getProviderIndex());
2074 
2075         // Remove from another Suggestor app, should fail.
2076         assertFalse(mManager.removeProvider(TEST_UID, false, null, TEST_FQDN));
2077         verify(provider, never()).uninstallCertsAndKeys();
2078         verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork(
2079                 provider.getWifiConfig().getProfileKey());
2080         verify(mWifiConfigManager, never()).saveToStore(true);
2081         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
2082         verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess();
2083         verify(mAppOpsManager, never()).stopWatchingMode(
2084                 any(AppOpsManager.OnOpChangedListener.class));
2085         // Verify content in the data source.
2086         providers = mUserDataSource.getProviders();
2087         assertEquals(1, providers.size());
2088         assertEquals(config, providers.get(0).getConfig());
2089         // Provider index start with 0, should be 1 after adding a provider.
2090         assertEquals(1, mSharedDataSource.getProviderIndex());
2091         reset(mWifiMetrics);
2092         reset(mWifiConfigManager);
2093 
2094         // Remove the provider from same app.
2095         assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN));
2096         verify(provider).uninstallCertsAndKeys();
2097         verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork(
2098                 provider.getWifiConfig().getProfileKey());
2099         verify(mWifiConfigManager, never()).saveToStore(true);
2100         verify(mWifiMetrics).incrementNumPasspointProviderUninstallation();
2101         verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess();
2102         verify(mAppOpsManager, never()).stopWatchingMode(
2103                 any(AppOpsManager.OnOpChangedListener.class));
2104         verify(mWifiConfigManager).removeConnectChoiceFromAllNetworks(config.getUniqueId());
2105 
2106         // Verify content in the data source.
2107         assertTrue(mUserDataSource.getProviders().isEmpty());
2108         // Removing a provider should not change the provider index.
2109         assertEquals(1, mSharedDataSource.getProviderIndex());
2110     }
2111 
2112     /**
2113      * Verify that adding a suggestion  provider with the same base domain as the existing
2114      * suggestion provider from same app will succeed, and verify that the new provider is
2115      * added along with the existing provider.
2116      *
2117      * @throws Exception
2118      */
2119     @Test
addSuggestionProviderWithExistingConfig()2120     public void addSuggestionProviderWithExistingConfig() throws Exception {
2121         // Add a provider with the original configuration.
2122         PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
2123                 TEST_REALM);
2124         PasspointProvider origProvider = createMockProvider(origConfig);
2125         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
2126         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
2127                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2128                 eq(true), eq(mClock))).thenReturn(origProvider);
2129         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
2130                 true, true));
2131         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2132         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2133         reset(mWifiMetrics);
2134         reset(mWifiConfigManager);
2135 
2136         // Verify data source content.
2137         List<PasspointProvider> origProviders = mUserDataSource.getProviders();
2138         assertEquals(1, origProviders.size());
2139         assertEquals(origConfig, origProviders.get(0).getConfig());
2140         assertEquals(1, mSharedDataSource.getProviderIndex());
2141 
2142         // Add same provider as existing suggestion provider
2143         // This should be no WifiConfig deletion
2144         WifiConfiguration origWifiConfig = origProvider.getWifiConfig();
2145         origWifiConfig.fromWifiNetworkSuggestion = true;
2146         origWifiConfig.creatorUid = TEST_CREATOR_UID;
2147         origWifiConfig.creatorName = TEST_PACKAGE;
2148         when(mWifiConfigManager.getConfiguredNetwork(origWifiConfig.getProfileKey()))
2149                 .thenReturn(origWifiConfig);
2150         when(mWifiConfigManager.addOrUpdateNetwork(
2151                 origWifiConfig, TEST_CREATOR_UID, TEST_PACKAGE, false))
2152                 .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID));
2153         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
2154                 true, true));
2155         verify(mWifiConfigManager, never()).removePasspointConfiguredNetwork(
2156                 origWifiConfig.getProfileKey());
2157         verify(mWifiConfigManager).addOrUpdateNetwork(
2158                 argThat((c) -> c.FQDN.equals(TEST_FQDN)), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2159                 eq(false));
2160         verify(mWifiConfigManager).allowAutojoin(TEST_NETWORK_ID, origWifiConfig.allowAutojoin);
2161         verify(mWifiConfigManager, never()).saveToStore(true);
2162         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2163         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2164         assertEquals(2, mSharedDataSource.getProviderIndex());
2165         reset(mWifiMetrics);
2166         reset(mWifiConfigManager);
2167 
2168         // Add another provider with the same base domain as the existing saved provider.
2169         // This should replace the existing provider with the new configuration.
2170         PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN,
2171                 TEST_FRIENDLY_NAME);
2172         PasspointProvider newProvider = createMockProvider(newConfig);
2173         when(newProvider.isFromSuggestion()).thenReturn(true);
2174         when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE);
2175         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
2176                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2177                 eq(true), eq(mClock))).thenReturn(newProvider);
2178         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE,
2179                 true, true));
2180         verify(mWifiConfigManager, never()).saveToStore(true);
2181         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2182         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2183 
2184         // Verify data source content.
2185         List<PasspointProvider> newProviders = mUserDataSource.getProviders();
2186         assertEquals(2, newProviders.size());
2187         assertTrue(newConfig.equals(newProviders.get(0).getConfig())
2188                 || newConfig.equals(newProviders.get(1).getConfig()));
2189         assertTrue(origConfig.equals(newProviders.get(0).getConfig())
2190                 || origConfig.equals(newProviders.get(1).getConfig()));
2191         assertEquals(3, mSharedDataSource.getProviderIndex());
2192     }
2193 
2194     /**
2195      * Verify that adding a saved provider with the same base domain as the existing
2196      * suggestion provider will succeed, and verify that the new provider with the new configuration
2197      * is added along with the existing provider.
2198      *
2199      * @throws Exception
2200      */
2201     @Test
addSavedProviderWithExistingSuggestionConfig()2202     public void addSavedProviderWithExistingSuggestionConfig() throws Exception {
2203         // Add a provider with the original configuration.
2204         PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
2205                 TEST_REALM);
2206         PasspointProvider origProvider = createMockProvider(origConfig);
2207         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
2208         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
2209                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2210                 eq(true), eq(mClock))).thenReturn(origProvider);
2211         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
2212                 true, true));
2213         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2214         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2215         reset(mWifiMetrics);
2216         reset(mWifiConfigManager);
2217 
2218         // Verify data source content.
2219         List<PasspointProvider> origProviders = mUserDataSource.getProviders();
2220         assertEquals(1, origProviders.size());
2221         assertEquals(origConfig, origProviders.get(0).getConfig());
2222         assertEquals(1, mSharedDataSource.getProviderIndex());
2223 
2224         // Add another provider with the same base domain as the existing saved provider.
2225         // This should replace the existing provider with the new configuration.
2226         PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN,
2227                 TEST_FRIENDLY_NAME);
2228         PasspointProvider newProvider = createMockProvider(newConfig);
2229         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
2230                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2231                 eq(false), eq(mClock))).thenReturn(newProvider);
2232         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE,
2233                 false, true));
2234         verify(mWifiConfigManager).saveToStore(true);
2235         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2236         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2237 
2238         // Verify data source content.
2239         List<PasspointProvider> newProviders = mUserDataSource.getProviders();
2240         assertEquals(2, newProviders.size());
2241         assertTrue(newConfig.equals(newProviders.get(0).getConfig())
2242                 || newConfig.equals(newProviders.get(1).getConfig()));
2243         assertTrue(origConfig.equals(newProviders.get(0).getConfig())
2244                 || origConfig.equals(newProviders.get(1).getConfig()));
2245         assertEquals(2, mSharedDataSource.getProviderIndex());
2246     }
2247 
2248     /**
2249      * Verify that adding a suggestion provider with the same base domain as the existing provider
2250      * from different apps will add a new provider.
2251      *
2252      * @throws Exception
2253      */
2254     @Test
addSuggestionProviderWithExistingConfigFromDifferentSource()2255     public void addSuggestionProviderWithExistingConfigFromDifferentSource() throws Exception {
2256         // Add a provider with the original configuration.
2257         PasspointConfiguration origConfig = createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI,
2258                 TEST_REALM);
2259         PasspointProvider origProvider = createMockProvider(origConfig);
2260         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
2261         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
2262                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2263                 eq(false), eq(mClock))).thenReturn(origProvider);
2264         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, false,
2265                 true));
2266         verifyInstalledConfig(origConfig);
2267         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2268         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2269         reset(mWifiMetrics);
2270         reset(mWifiConfigManager);
2271 
2272         // Verify data source content.
2273         List<PasspointProvider> origProviders = mUserDataSource.getProviders();
2274         assertEquals(1, origProviders.size());
2275         assertEquals(origConfig, origProviders.get(0).getConfig());
2276         assertEquals(1, mSharedDataSource.getProviderIndex());
2277 
2278         // Add another provider with the same base domain as the existing saved provider but from
2279         // different app. This should not replace the existing provider with the new configuration
2280         // but add another one.
2281         PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN,
2282                 TEST_FRIENDLY_NAME);
2283         PasspointProvider newProvider = createMockProvider(newConfig);
2284         when(newProvider.isFromSuggestion()).thenReturn(true);
2285         when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE1);
2286         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
2287                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1),
2288                 eq(true), eq(mClock))).thenReturn(newProvider);
2289         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE1, true,
2290                 true));
2291         verify(mWifiConfigManager, never()).saveToStore(true);
2292         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2293         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2294 
2295         // Verify data source content.
2296         List<PasspointProvider> newProviders = mUserDataSource.getProviders();
2297         assertEquals(2, newProviders.size());
2298         assertTrue(origConfig.equals(newProviders.get(0).getConfig())
2299                 || origConfig.equals(newProviders.get(1).getConfig()));
2300 
2301         assertEquals(2, mSharedDataSource.getProviderIndex());
2302     }
2303 
2304     /**
2305      * Verify that the HomeProvider provider will be returned when a HomeProvider profile has
2306      * not expired and RoamingProvider expiration is unset (still valid).
2307      *
2308      * @throws Exception
2309      */
2310     @Test
matchHomeProviderWhenHomeProviderNotExpired()2311     public void matchHomeProviderWhenHomeProviderNotExpired() throws Exception {
2312         // static mocking
2313         MockitoSession session =
2314                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2315                         InformationElementUtil.class).startMocking();
2316         try {
2317             PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2318                     TEST_PACKAGE, false, null, false);
2319             providerHome.getConfig().setSubscriptionExpirationTimeInMillis(
2320                     System.currentTimeMillis() + 100000);
2321             providerHome.getWifiConfig().isHomeProviderNetwork = true;
2322             PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME,
2323                     TEST_PACKAGE, false, null, false);
2324             WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1,
2325                     TEST_UID, "\"PasspointTestSSID\"", true, true,
2326                     TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP);
2327             PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
2328                     TEST_PACKAGE, wifiConfiguration, false, null, false);
2329             ANQPData entry = new ANQPData(mClock, null);
2330             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2331             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
2332 
2333             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2334             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2335             when(providerHome.match(anyMap(), isNull(), any(ScanResult.class)))
2336                     .thenReturn(PasspointMatch.HomeProvider);
2337             when(providerRoaming.match(anyMap(), isNull(), any(ScanResult.class)))
2338                     .thenReturn(PasspointMatch.RoamingProvider);
2339             when(providerNone.match(anyMap(), isNull(), any(ScanResult.class)))
2340                     .thenReturn(PasspointMatch.None);
2341 
2342             List<Pair<PasspointProvider, PasspointMatch>> results =
2343                     mManager.matchProvider(createTestScanResult());
2344             Pair<PasspointProvider, PasspointMatch> result = results.get(0);
2345 
2346             assertEquals(PasspointMatch.HomeProvider, result.second);
2347             assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
2348 
2349         } finally {
2350             session.finishMocking();
2351         }
2352     }
2353 
2354     /**
2355      * Verify that the RoamingProvider provider will be returned when a HomeProvider profile has
2356      * expired and RoamingProvider expiration is unset (still valid).
2357      *
2358      * @throws Exception
2359      */
2360     @Test
matchRoamingProviderUnsetWhenHomeProviderExpired()2361     public void matchRoamingProviderUnsetWhenHomeProviderExpired() throws Exception {
2362         // static mocking
2363         MockitoSession session =
2364                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2365                         InformationElementUtil.class).startMocking();
2366         try {
2367             PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2368                     TEST_PACKAGE, false, null, false);
2369             providerHome.getConfig().setSubscriptionExpirationTimeInMillis(
2370                     System.currentTimeMillis() - 10000);
2371             providerHome.getWifiConfig().isHomeProviderNetwork = true;
2372             PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME,
2373                     TEST_PACKAGE, false, null, false);
2374             WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1,
2375                     TEST_UID, "\"PasspointTestSSID\"", true, true,
2376                     TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP);
2377             PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
2378                     TEST_PACKAGE, wifiConfiguration, false, null, false);
2379             ANQPData entry = new ANQPData(mClock, null);
2380             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2381             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
2382 
2383             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2384             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2385             when(providerHome.match(anyMap(), isNull(), any(ScanResult.class)))
2386                     .thenReturn(PasspointMatch.HomeProvider);
2387             when(providerRoaming.match(anyMap(), isNull(), any(ScanResult.class)))
2388                     .thenReturn(PasspointMatch.RoamingProvider);
2389             when(providerNone.match(anyMap(), isNull(), any(ScanResult.class)))
2390                     .thenReturn(PasspointMatch.None);
2391 
2392             List<Pair<PasspointProvider, PasspointMatch>> results =
2393                     mManager.matchProvider(createTestScanResult());
2394             Pair<PasspointProvider, PasspointMatch> result = results.get(0);
2395 
2396             assertEquals(PasspointMatch.RoamingProvider, result.second);
2397             assertEquals(TEST_FQDN2, result.first.getConfig().getHomeSp().getFqdn());
2398 
2399         } finally {
2400             session.finishMocking();
2401         }
2402     }
2403 
2404     /**
2405      * Verify that the RoamingProvider provider will be returned when a HomeProvider profile has
2406      * expired and RoamingProvider expiration is still valid.
2407      *
2408      * @throws Exception
2409      */
2410     @Test
matchRoamingProviderNonExpiredWhenHomeProviderExpired()2411     public void matchRoamingProviderNonExpiredWhenHomeProviderExpired() throws Exception {
2412         // static mocking
2413         MockitoSession session =
2414                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2415                         InformationElementUtil.class).startMocking();
2416         try {
2417             PasspointProvider providerHome = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2418                     TEST_PACKAGE, false, null, false);
2419             providerHome.getConfig().setSubscriptionExpirationTimeInMillis(
2420                     System.currentTimeMillis() - 10000);
2421             providerHome.getWifiConfig().isHomeProviderNetwork = true;
2422             PasspointProvider providerRoaming = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME,
2423                     TEST_PACKAGE, false, null, false);
2424             providerRoaming.getConfig().setSubscriptionExpirationTimeInMillis(
2425                     System.currentTimeMillis() + 100000);
2426             WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.generateWifiConfig(-1,
2427                     TEST_UID, "\"PasspointTestSSID\"", true, true,
2428                     TEST_FQDN + 2, TEST_FRIENDLY_NAME, SECURITY_EAP);
2429             PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
2430                     TEST_PACKAGE, wifiConfiguration, false, null, false);
2431             ANQPData entry = new ANQPData(mClock, null);
2432             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2433             vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID;
2434 
2435             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2436             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2437             when(providerHome.match(anyMap(), isNull(), any(ScanResult.class)))
2438                     .thenReturn(PasspointMatch.HomeProvider);
2439             when(providerRoaming.match(anyMap(), isNull(), any(ScanResult.class)))
2440                     .thenReturn(PasspointMatch.RoamingProvider);
2441             when(providerNone.match(anyMap(), isNull(), any(ScanResult.class)))
2442                     .thenReturn(PasspointMatch.None);
2443 
2444             List<Pair<PasspointProvider, PasspointMatch>> results =
2445                     mManager.matchProvider(createTestScanResult());
2446             Pair<PasspointProvider, PasspointMatch> result = results.get(0);
2447 
2448             assertEquals(PasspointMatch.RoamingProvider, result.second);
2449             assertEquals(TEST_FQDN2, result.first.getConfig().getHomeSp().getFqdn());
2450 
2451         } finally {
2452             session.finishMocking();
2453         }
2454     }
2455 
2456     /**
2457      * Verify add untrusted passpoint network from suggestion success.
2458      */
2459     @Test
testAddUntrustedPasspointNetworkFromSuggestion()2460     public void testAddUntrustedPasspointNetworkFromSuggestion() {
2461         WifiConfiguration wifiConfig = new WifiConfiguration();
2462         wifiConfig.FQDN = TEST_FQDN;
2463         PasspointConfiguration config =
2464                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
2465         PasspointProvider provider = createMockProvider(config, wifiConfig, true);
2466         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2467                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2468                 eq(true), eq(mClock))).thenReturn(provider);
2469         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2470         assertTrue(mManager.addOrUpdateProvider(
2471                 config, TEST_CREATOR_UID, TEST_PACKAGE, true, false));
2472         verify(provider).setTrusted(false);
2473     }
2474 
2475     /**
2476      * Verify add untrusted passpoint network not from suggestion fail.
2477      */
2478     @Test
testAddUntrustedPasspointNetworkNotFromSuggestion()2479     public void testAddUntrustedPasspointNetworkNotFromSuggestion() {
2480         WifiConfiguration wifiConfig = new WifiConfiguration();
2481         wifiConfig.FQDN = TEST_FQDN;
2482         PasspointConfiguration config =
2483                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
2484         PasspointProvider provider = createMockProvider(config, wifiConfig, false);
2485         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2486                 eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2487                 eq(true), eq(mClock))).thenReturn(provider);
2488         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2489         assertFalse(mManager.addOrUpdateProvider(
2490                 config, TEST_CREATOR_UID, TEST_PACKAGE, false, false));
2491         verify(provider, never()).setTrusted(false);
2492     }
2493 
2494     /**
2495      * Verify that the ScanResults(Access Points) are returned when it may be
2496      * authenticated with the provided passpoint configuration as roaming match.
2497      */
2498     @Test
getMatchingScanResultsTestWithRoamingMatch()2499     public void getMatchingScanResultsTestWithRoamingMatch() {
2500         PasspointConfiguration config = mock(PasspointConfiguration.class);
2501         PasspointProvider mockProvider = mock(PasspointProvider.class);
2502         when(mObjectFactory.makePasspointProvider(config, null,
2503                 mWifiCarrierInfoManager, 0, 0, null, false, mClock))
2504                 .thenReturn(mockProvider);
2505         List<ScanResult> scanResults = new ArrayList<>() {{
2506                 add(mock(ScanResult.class));
2507             }};
2508         when(mockProvider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
2509                 .thenReturn(PasspointMatch.RoamingProvider);
2510 
2511         List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults);
2512 
2513         assertEquals(1, testResults.size());
2514     }
2515 
2516     /**
2517      * Verify that the ScanResults(Access Points) are returned when it may be
2518      * authenticated with the provided passpoint configuration as home match.
2519      */
2520     @Test
getMatchingScanResultsTestWithHomeMatch()2521     public void getMatchingScanResultsTestWithHomeMatch() {
2522         PasspointConfiguration config = mock(PasspointConfiguration.class);
2523         PasspointProvider mockProvider = mock(PasspointProvider.class);
2524         when(mObjectFactory.makePasspointProvider(config, null,
2525                 mWifiCarrierInfoManager, 0, 0, null, false, mClock))
2526                 .thenReturn(mockProvider);
2527         List<ScanResult> scanResults = new ArrayList<>() {{
2528                 add(mock(ScanResult.class));
2529             }};
2530         when(mockProvider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
2531                 .thenReturn(PasspointMatch.HomeProvider);
2532 
2533         List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults);
2534 
2535         assertEquals(1, testResults.size());
2536     }
2537 
2538     /**
2539      * Verify that the ScanResults(Access Points) are not returned when it cannot be
2540      * authenticated with the provided passpoint configuration as none match.
2541      */
2542     @Test
getMatchingScanResultsTestWithNonMatch()2543     public void getMatchingScanResultsTestWithNonMatch() {
2544         PasspointConfiguration config = mock(PasspointConfiguration.class);
2545 
2546         PasspointProvider mockProvider = mock(PasspointProvider.class);
2547 
2548         when(mObjectFactory.makePasspointProvider(config, null,
2549                 mWifiCarrierInfoManager, 0, 0, null, false, mClock))
2550                 .thenReturn(mockProvider);
2551 
2552         List<ScanResult> scanResults = new ArrayList<>() {{
2553                 add(mock(ScanResult.class));
2554             }};
2555         when(mockProvider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
2556                 .thenReturn(PasspointMatch.None);
2557 
2558         List<ScanResult> testResults = mManager.getMatchingScanResults(config, scanResults);
2559 
2560         assertEquals(0, testResults.size());
2561     }
2562 
2563     /**
2564      * Verify that no ANQP queries are requested when not allowed (i.e. by WifiMetrics) when
2565      * there is a cache miss.
2566      */
2567     @Test
testAnqpRequestNotAllowed()2568     public void testAnqpRequestNotAllowed() {
2569         reset(mWifiConfigManager);
2570         when(mAnqpCache.getEntry(TEST_ANQP_KEY2)).thenReturn(null);
2571         verify(mAnqpRequestManager, never()).requestANQPElements(any(long.class),
2572                 any(ANQPNetworkKey.class), any(boolean.class), any(NetworkDetail.HSRelease.class));
2573     }
2574 
2575     /**
2576      * Verify that removing of multiple providers with the same FQDN is done correctly.
2577      */
2578     @Test
removeAllProvidersWithSameFqdn()2579     public void removeAllProvidersWithSameFqdn() {
2580         PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2581                 TEST_PACKAGE, false, TEST_REALM, false);
2582         PasspointProvider provider2 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2583                 TEST_PACKAGE, false, TEST_REALM2, false);
2584         PasspointProvider provider3 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2585                 TEST_PACKAGE, false, TEST_REALM3, false);
2586 
2587         List<PasspointProvider> providers = mUserDataSource.getProviders();
2588         assertEquals(3, providers.size());
2589         verify(mWifiMetrics, times(3)).incrementNumPasspointProviderInstallation();
2590         verify(mWifiMetrics, times(3)).incrementNumPasspointProviderInstallSuccess();
2591 
2592         // Remove the provider as the creator app.
2593         assertTrue(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN));
2594 
2595         verify(provider1).uninstallCertsAndKeys();
2596         verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork(
2597                 provider1.getWifiConfig().getProfileKey());
2598         verify(provider2).uninstallCertsAndKeys();
2599         verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork(
2600                 provider2.getWifiConfig().getProfileKey());
2601         verify(provider3).uninstallCertsAndKeys();
2602         verify(mWifiConfigManager, times(1)).removePasspointConfiguredNetwork(
2603                 provider3.getWifiConfig().getProfileKey());
2604 
2605         verify(mWifiMetrics, times(3)).incrementNumPasspointProviderUninstallation();
2606         verify(mWifiMetrics, times(3)).incrementNumPasspointProviderUninstallSuccess();
2607         verify(mAppOpsManager).stopWatchingMode(any(AppOpsManager.OnOpChangedListener.class));
2608         assertTrue(mManager.getProviderConfigs(TEST_CREATOR_UID, false).isEmpty());
2609         verify(mWifiConfigManager, times(3)).removeConnectChoiceFromAllNetworks(any());
2610 
2611         // Verify content in the data source.
2612         assertTrue(mUserDataSource.getProviders().isEmpty());
2613     }
2614 
2615     /**
2616      * Verify that adding a provider with a self signed root CA increments the metrics correctly.
2617      *
2618      * @throws Exception
2619      */
2620     @Test
verifySelfSignRootCaMetrics()2621     public void verifySelfSignRootCaMetrics() throws Exception {
2622         WifiConfiguration wifiConfig = new WifiConfiguration();
2623         wifiConfig.FQDN = TEST_FQDN;
2624         PasspointConfiguration config =
2625                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
2626         PasspointProvider provider = createMockProvider(config, wifiConfig, true);
2627         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2628             eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2629             eq(true), eq(mClock))).thenReturn(provider);
2630         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2631         assertTrue(mManager.addOrUpdateProvider(
2632                 config, TEST_CREATOR_UID, TEST_PACKAGE, true, false));
2633         verify(mWifiMetrics).incrementNumPasspointProviderWithSelfSignedRootCa();
2634         verify(mWifiMetrics, never()).incrementNumPasspointProviderWithNoRootCa();
2635         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2636         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2637     }
2638 
2639     /**
2640      * Verify that adding a provider with no root CA increments the metrics correctly.
2641      *
2642      * @throws Exception
2643      */
2644     @Test
verifyNoRootCaMetrics()2645     public void verifyNoRootCaMetrics() throws Exception {
2646         WifiConfiguration wifiConfig = new WifiConfiguration();
2647         wifiConfig.FQDN = TEST_FQDN;
2648         PasspointConfiguration config =
2649                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
2650         config.getCredential().setCaCertificate(null);
2651         PasspointProvider provider = createMockProvider(config, wifiConfig, true);
2652         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2653             eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2654             eq(true), eq(mClock))).thenReturn(provider);
2655         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2656         assertTrue(mManager.addOrUpdateProvider(
2657                 config, TEST_CREATOR_UID, TEST_PACKAGE, true, false));
2658         verify(mWifiMetrics).incrementNumPasspointProviderWithNoRootCa();
2659         verify(mWifiMetrics, never()).incrementNumPasspointProviderWithSelfSignedRootCa();
2660         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2661         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2662     }
2663 
2664     /**
2665      * Verify that adding a provider with subscription expiration increments the metrics correctly.
2666      *
2667      * @throws Exception
2668      */
2669     @Test
verifySubscriptionExpirationMetrics()2670     public void verifySubscriptionExpirationMetrics() throws Exception {
2671         WifiConfiguration wifiConfig = new WifiConfiguration();
2672         wifiConfig.FQDN = TEST_FQDN;
2673         PasspointConfiguration config =
2674                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
2675         config.setSubscriptionExpirationTimeInMillis(1586228641000L);
2676         PasspointProvider provider = createMockProvider(config, wifiConfig, true);
2677         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
2678             eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
2679             eq(true), eq(mClock))).thenReturn(provider);
2680         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
2681         assertTrue(mManager.addOrUpdateProvider(
2682                 config, TEST_CREATOR_UID, TEST_PACKAGE, true, false));
2683         verify(mWifiMetrics).incrementNumPasspointProviderWithSubscriptionExpiration();
2684         verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
2685         verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
2686     }
2687 
2688     /**
2689      * Verify that venue URL ANQP request is sent correctly.
2690      *
2691      * @throws Exception
2692      */
2693     @Test
verifyRequestVenueUrlAnqpElement()2694     public void verifyRequestVenueUrlAnqpElement() throws Exception {
2695         // static mocking
2696         MockitoSession session =
2697                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2698                         InformationElementUtil.class).startMocking();
2699         try {
2700             ScanResult scanResult = createTestScanResult();
2701             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2702             vsa.anqpDomainID = scanResult.anqpDomainId;
2703             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2704             long bssid = Utils.parseMac(scanResult.BSSID);
2705             mManager.requestVenueUrlAnqpElement(scanResult);
2706             verify(mAnqpRequestManager).requestVenueUrlAnqpElement(eq(bssid), any());
2707         } finally {
2708             session.finishMocking();
2709         }
2710     }
2711 
2712     /**
2713      * Verify blocking a matched provider following a Deauthentication-imminent WNM-notification
2714      */
2715     @Test
testBlockingProvider()2716     public void testBlockingProvider() {
2717         WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(10, TEST_UID,
2718                 "\"PasspointTestSSID\"", true, true, TEST_FQDN,
2719                 TEST_FRIENDLY_NAME, SECURITY_EAP);
2720         wifiConfig.BSSID = TEST_BSSID_STRING;
2721 
2722         PasspointProvider provider =
2723                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, wifiConfig, false,
2724                         null, false);
2725         WnmData event = WnmData.createDeauthImminentEvent(Utils.parseMac(TEST_BSSID_STRING), "",
2726                 true, 30);
2727 
2728         mManager.handleDeauthImminentEvent(event, wifiConfig);
2729         verify(provider).blockBssOrEss(eq(event.getBssid()), eq(event.isEss()),
2730                 eq(event.getDelay()));
2731     }
2732 
2733     /**
2734      * Verify set Anonymous Identity to the right passpoint provider.
2735      */
2736     @Test
testSetAnonymousIdentity()2737     public void testSetAnonymousIdentity() {
2738         WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(10, TEST_UID,
2739                 "\"PasspointTestSSID\"", true, true, TEST_FQDN,
2740                 TEST_FRIENDLY_NAME, SECURITY_EAP);
2741 
2742         PasspointProvider provider =
2743                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, wifiConfig, false,
2744                         null, false);
2745 
2746         wifiConfig.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY);
2747         mManager.setAnonymousIdentity(wifiConfig);
2748         verify(provider).setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY);
2749 
2750 
2751         mManager.resetSimPasspointNetwork();
2752         verify(provider).setAnonymousIdentity(null);
2753         verify(mWifiConfigManager, times(3)).saveToStore(true);
2754     }
2755 
2756     /**
2757      * Test set and remove user connect choice.
2758      */
2759     @Test
testSetUserConnectChoice()2760     public void testSetUserConnectChoice() {
2761         WifiConfiguration wifiConfig = WifiConfigurationTestUtil.generateWifiConfig(10, TEST_UID,
2762                 "\"PasspointTestSSID\"", true, true, TEST_FQDN,
2763                 TEST_FRIENDLY_NAME, SECURITY_EAP);
2764 
2765         PasspointProvider provider =
2766                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, wifiConfig, false,
2767                         null, false);
2768 
2769         WifiConfiguration wifiConfig2 = WifiConfigurationTestUtil.generateWifiConfig(11, TEST_UID,
2770                 "\"PasspointTestSSID\"", true, true, TEST_FQDN2,
2771                 TEST_FRIENDLY_NAME, SECURITY_EAP);
2772 
2773         PasspointProvider provider2 =
2774                 addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME, TEST_PACKAGE, wifiConfig2, false,
2775                         null, false);
2776 
2777         WifiConfigManager.OnNetworkUpdateListener listener = mNetworkListenerCaptor.getValue();
2778         reset(mWifiConfigManager);
2779 
2780         // Set user connect choice on this passpoint network
2781         listener.onConnectChoiceSet(Collections.singletonList(wifiConfig), USER_CONNECT_CHOICE,
2782                 TEST_RSSI);
2783         verify(provider).setUserConnectChoice(USER_CONNECT_CHOICE, TEST_RSSI);
2784 
2785         // The user connect choice is this psspoint network, its user connect choice should null
2786         listener.onConnectChoiceSet(Collections.emptyList(), wifiConfig.getPasspointUniqueId(),
2787                 TEST_RSSI);
2788         verify(provider).setUserConnectChoice(null, 0);
2789 
2790         // Remove the user connect choice, if equals, user connect choice should set to null
2791         when(provider.getConnectChoice()).thenReturn(USER_CONNECT_CHOICE);
2792         listener.onConnectChoiceRemoved(USER_CONNECT_CHOICE);
2793         verify(provider, times(2)).setUserConnectChoice(null, 0);
2794 
2795         verify(provider2, never()).setUserConnectChoice(any(), anyInt());
2796         verify(mWifiConfigManager, times(3)).saveToStore(true);
2797     }
2798 
2799     /*
2800      * Verify that Passpoint manager returns the correct venue URL.
2801      *
2802      * @throws Exception
2803      */
2804     @Test
testGetVenueUrl()2805     public void testGetVenueUrl() throws Exception {
2806         // static mocking
2807         MockitoSession session =
2808                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2809                         InformationElementUtil.class).startMocking();
2810         try {
2811             ScanResult scanResult = createTestScanResult();
2812             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2813             vsa.anqpDomainID = scanResult.anqpDomainId;
2814             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2815 
2816             Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
2817             anqpElementMap.put(ANQPElementType.ANQPDomName,
2818                     new DomainNameElement(Arrays.asList(new String[]{"test.com"})));
2819             List<I18Name> names = new ArrayList<>();
2820             names.add(new I18Name(TEST_LOCALE_ENGLISH,
2821                     new Locale.Builder().setLanguage(TEST_LOCALE_ENGLISH).build(),
2822                     "Passpoint Venue"));
2823             names.add(new I18Name(TEST_LOCALE_HEBREW,
2824                     new Locale.Builder().setLanguage(TEST_LOCALE_HEBREW).build(), "רשת פאספוינט"));
2825             anqpElementMap.put(ANQPElementType.ANQPVenueName, new VenueNameElement(names));
2826 
2827             Map<Integer, URL> venueUrls = new HashMap<>();
2828             venueUrls.put(1, new URL(TEST_VENUE_URL_ENG));
2829             venueUrls.put(2, new URL(TEST_VENUE_URL_HEB));
2830             anqpElementMap.put(ANQPElementType.ANQPVenueUrl, new VenueUrlElement(venueUrls));
2831 
2832             mAnqpCache.addOrUpdateEntry(TEST_ANQP_KEY, anqpElementMap);
2833             ANQPData entry = new ANQPData(mClock, anqpElementMap);
2834             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2835 
2836             // Test language 1
2837             Locale.setDefault(new Locale(TEST_LOCALE_ENGLISH));
2838             URL venueUrl = mManager.getVenueUrl(scanResult);
2839             assertEquals(venueUrl.toString(), TEST_VENUE_URL_ENG);
2840 
2841             // Test language 2
2842             Locale.setDefault(new Locale(TEST_LOCALE_HEBREW));
2843             venueUrl = mManager.getVenueUrl(scanResult);
2844             assertEquals(venueUrl.toString(), TEST_VENUE_URL_HEB);
2845 
2846             // Test default language when no language match
2847             Locale.setDefault(new Locale(TEST_LOCALE_SPANISH));
2848             venueUrl = mManager.getVenueUrl(scanResult);
2849             assertEquals(venueUrl.toString(), TEST_VENUE_URL_ENG);
2850         } finally {
2851             session.finishMocking();
2852         }
2853     }
2854 
2855     /**
2856      * Verify that Passpoint manager returns null when no ANQP entry is available.
2857      *
2858      * @throws Exception
2859      */
2860     @Test
testGetVenueUrlNoAnqpEntry()2861     public void testGetVenueUrlNoAnqpEntry() throws Exception {
2862         // static mocking
2863         MockitoSession session =
2864                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2865                         InformationElementUtil.class).startMocking();
2866         try {
2867             ScanResult scanResult = createTestScanResult();
2868             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2869             vsa.anqpDomainID = scanResult.anqpDomainId;
2870             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2871 
2872             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
2873 
2874             URL venueUrl = mManager.getVenueUrl(scanResult);
2875             assertNull(venueUrl);
2876         } finally {
2877             session.finishMocking();
2878         }
2879     }
2880 
2881     /**
2882      * Verify that Passpoint manager returns null when no Venue URL ANQP-element is available.
2883      *
2884      * @throws Exception
2885      */
2886     @Test
testGetVenueUrlNoVenueUrlAnqpElement()2887     public void testGetVenueUrlNoVenueUrlAnqpElement() throws Exception {
2888         // static mocking
2889         MockitoSession session =
2890                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2891                         InformationElementUtil.class).startMocking();
2892         try {
2893             ScanResult scanResult = createTestScanResult();
2894             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2895             vsa.anqpDomainID = scanResult.anqpDomainId;
2896             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2897 
2898             Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
2899             anqpElementMap.put(ANQPElementType.ANQPDomName,
2900                     new DomainNameElement(Arrays.asList(new String[]{"test.com"})));
2901             List<I18Name> names = new ArrayList<>();
2902             names.add(new I18Name(TEST_LOCALE_ENGLISH,
2903                     new Locale.Builder().setLanguage(TEST_LOCALE_ENGLISH).build(),
2904                     "Passpoint Venue"));
2905             names.add(new I18Name(TEST_LOCALE_HEBREW,
2906                     new Locale.Builder().setLanguage(TEST_LOCALE_HEBREW).build(), "רשת פאספוינט"));
2907             anqpElementMap.put(ANQPElementType.ANQPVenueName, new VenueNameElement(names));
2908 
2909             mAnqpCache.addOrUpdateEntry(TEST_ANQP_KEY, anqpElementMap);
2910             ANQPData entry = new ANQPData(mClock, anqpElementMap);
2911             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2912 
2913             URL venueUrl = mManager.getVenueUrl(scanResult);
2914             assertNull(venueUrl);
2915         } finally {
2916             session.finishMocking();
2917         }
2918     }
2919 
2920     /**
2921      * Verify that Passpoint manager returns null when no Venue Name ANQP-element is available.
2922      *
2923      * @throws Exception
2924      */
2925     @Test
testGetVenueUrlNoVenueNameAnqpElement()2926     public void testGetVenueUrlNoVenueNameAnqpElement() throws Exception {
2927         // static mocking
2928         MockitoSession session =
2929                 com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession().mockStatic(
2930                         InformationElementUtil.class).startMocking();
2931         try {
2932             ScanResult scanResult = createTestScanResult();
2933             InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
2934             vsa.anqpDomainID = scanResult.anqpDomainId;
2935             when(InformationElementUtil.getHS2VendorSpecificIE(isNull())).thenReturn(vsa);
2936 
2937             Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>();
2938             anqpElementMap.put(ANQPElementType.ANQPDomName,
2939                     new DomainNameElement(Arrays.asList(new String[]{"test.com"})));
2940 
2941             Map<Integer, URL> venueUrls = new HashMap<>();
2942             venueUrls.put(1, new URL(TEST_VENUE_URL_ENG));
2943             venueUrls.put(2, new URL(TEST_VENUE_URL_HEB));
2944             anqpElementMap.put(ANQPElementType.ANQPVenueUrl, new VenueUrlElement(venueUrls));
2945 
2946             mAnqpCache.addOrUpdateEntry(TEST_ANQP_KEY, anqpElementMap);
2947             ANQPData entry = new ANQPData(mClock, anqpElementMap);
2948             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2949 
2950             URL venueUrl = mManager.getVenueUrl(scanResult);
2951             assertNull(venueUrl);
2952 
2953             // Now try with an incomplete list of venue names
2954             List<I18Name> names = new ArrayList<>();
2955             names.add(new I18Name(TEST_LOCALE_ENGLISH,
2956                     new Locale.Builder().setLanguage(TEST_LOCALE_ENGLISH).build(),
2957                     "Passpoint Venue"));
2958             anqpElementMap.put(ANQPElementType.ANQPVenueName, new VenueNameElement(names));
2959             entry = new ANQPData(mClock, anqpElementMap);
2960             when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
2961 
2962             venueUrl = mManager.getVenueUrl(scanResult);
2963             assertNull(venueUrl);
2964         } finally {
2965             session.finishMocking();
2966         }
2967     }
2968 
2969     /**
2970      * Verify that Passpoint manager handles the terms and conditions URL correctly: Accepts only
2971      * HTTPS URLs, and rejects HTTP and invalid URLs.
2972      *
2973      * @throws Exception
2974      */
2975     @Test
testHandleTermsAndConditionsEvent()2976     public void testHandleTermsAndConditionsEvent() throws Exception {
2977         WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
2978         PasspointProvider passpointProvider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
2979                 TEST_PACKAGE, config, false, null, false);
2980         assertEquals(TEST_TERMS_AND_CONDITIONS_URL, mManager.handleTermsAndConditionsEvent(
2981                 WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
2982                         TEST_TERMS_AND_CONDITIONS_URL), config).toString());
2983 
2984         // Verify that this provider is never blocked
2985         verify(passpointProvider, never()).blockBssOrEss(anyLong(), anyBoolean(), anyInt());
2986 
2987         assertNull(mManager.handleTermsAndConditionsEvent(
2988                 WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
2989                         TEST_TERMS_AND_CONDITIONS_URL_NON_HTTPS), config));
2990 
2991         // Verify that the ESS is blocked for 24 hours, the URL is non-HTTPS and unlikely to change
2992         verify(passpointProvider).blockBssOrEss(eq(TEST_BSSID), eq(true), eq(24 * 60 * 60));
2993 
2994         assertNull(mManager.handleTermsAndConditionsEvent(
2995                 WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
2996                         TEST_TERMS_AND_CONDITIONS_URL_INVALID), config));
2997 
2998         // Verify that the ESS is blocked for an hour due to a temporary issue with the URL
2999         verify(passpointProvider).blockBssOrEss(eq(TEST_BSSID), eq(true), eq(60 * 60));
3000 
3001         // Now try with a non-Passpoint network
3002         config = WifiConfigurationTestUtil.createEapNetwork();
3003         assertNull(mManager.handleTermsAndConditionsEvent(
3004                 WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
3005                         TEST_TERMS_AND_CONDITIONS_URL), config));
3006         // and a null configuration
3007         assertNull(mManager.handleTermsAndConditionsEvent(
3008                 WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
3009                         TEST_TERMS_AND_CONDITIONS_URL), null));
3010     }
3011 
3012     /**
3013      * Verify that Passpoint manager clears states and flushes caches as expected.
3014      *
3015      * @throws Exception
3016      */
3017     @Test
testClearAnqpRequestsAndFlushCache()3018     public void testClearAnqpRequestsAndFlushCache() throws Exception {
3019         PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
3020                 TEST_PACKAGE, false, TEST_REALM, false);
3021 
3022         mManager.clearAnqpRequestsAndFlushCache();
3023         verify(mAnqpRequestManager).clear();
3024         verify(mAnqpCache).flush();
3025         verify(provider).clearProviderBlock();
3026     }
3027 
3028     /**
3029      * Verify that when Passpoint manager is enabled/disabled the WifiSettingsStore is updated
3030      * with correct value.
3031      *
3032      * @throws Exception
3033      */
3034     @Test
testPasspointEnableSettingsStore()3035     public void testPasspointEnableSettingsStore() throws Exception {
3036         // Disable the Wifi Passpoint, check return value and verify status.
3037         mManager.setWifiPasspointEnabled(false);
3038         assertFalse(mManager.isWifiPasspointEnabled());
3039         // Verify WifiSettingStore has been called to set Wifi Passpoint status.
3040         verify(mWifiSettingsStore).handleWifiPasspointEnabled(false);
3041         assertFalse(mConfigSettingsPasspointEnabled);
3042 
3043         // Enable the Wifi Passpoint, check return value and verify status.
3044         mManager.setWifiPasspointEnabled(true);
3045         assertTrue(mManager.isWifiPasspointEnabled());
3046         // Verify WifiSettingStore has been called to set Wifi Passpoint status.
3047         verify(mWifiSettingsStore).handleWifiPasspointEnabled(true);
3048         assertTrue(mConfigSettingsPasspointEnabled);
3049     }
3050 
3051     /**
3052      * Verify that Passpoint manager is enabled and disabled.
3053      *
3054      * @throws Exception
3055      */
3056     @Test
testPasspointEnableDisable()3057     public void testPasspointEnableDisable() throws Exception {
3058         PasspointProvider provider =
3059                 addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false, null, false);
3060         ANQPData entry = new ANQPData(mClock, null);
3061 
3062         when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
3063         when(provider.match(anyMap(), any(RoamingConsortium.class), any(ScanResult.class)))
3064                 .thenReturn(PasspointMatch.HomeProvider);
3065 
3066         // Disable the Wifi Passpoint and expect the matchProvider to return empty list.
3067         mManager.setWifiPasspointEnabled(false);
3068         assertFalse(mManager.isWifiPasspointEnabled());
3069         assertTrue(mManager.matchProvider(createTestScanResult()).isEmpty());
3070 
3071         // Enable the Wifi Passpoint and expect the matchProvider to return matched result.
3072         mManager.setWifiPasspointEnabled(true);
3073         assertTrue(mManager.isWifiPasspointEnabled());
3074         List<Pair<PasspointProvider, PasspointMatch>> results =
3075                 mManager.matchProvider(createTestScanResult());
3076         Pair<PasspointProvider, PasspointMatch> result = results.get(0);
3077         assertEquals(PasspointMatch.HomeProvider, result.second);
3078         assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn());
3079     }
3080 }
3081 
3082