1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.hotspot2; 18 19 import static android.net.wifi.WifiManager.ACTION_PASSPOINT_DEAUTH_IMMINENT; 20 import static android.net.wifi.WifiManager.ACTION_PASSPOINT_ICON; 21 import static android.net.wifi.WifiManager.ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION; 22 import static android.net.wifi.WifiManager.EXTRA_BSSID_LONG; 23 import static android.net.wifi.WifiManager.EXTRA_DELAY; 24 import static android.net.wifi.WifiManager.EXTRA_ESS; 25 import static android.net.wifi.WifiManager.EXTRA_FILENAME; 26 import static android.net.wifi.WifiManager.EXTRA_ICON; 27 import static android.net.wifi.WifiManager.EXTRA_SUBSCRIPTION_REMEDIATION_METHOD; 28 import static android.net.wifi.WifiManager.EXTRA_URL; 29 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.assertFalse; 32 import static org.junit.Assert.assertNull; 33 import static org.junit.Assert.assertTrue; 34 import static org.mockito.Mockito.any; 35 import static org.mockito.Mockito.anyBoolean; 36 import static org.mockito.Mockito.anyInt; 37 import static org.mockito.Mockito.anyLong; 38 import static org.mockito.Mockito.anyMap; 39 import static org.mockito.Mockito.doThrow; 40 import static org.mockito.Mockito.eq; 41 import static org.mockito.Mockito.mock; 42 import static org.mockito.Mockito.never; 43 import static org.mockito.Mockito.reset; 44 import static org.mockito.Mockito.verify; 45 import static org.mockito.Mockito.when; 46 import static org.mockito.MockitoAnnotations.initMocks; 47 48 import android.content.Context; 49 import android.content.Intent; 50 import android.graphics.drawable.Icon; 51 import android.net.Uri; 52 import android.net.wifi.EAPConstants; 53 import android.net.wifi.ScanResult; 54 import android.net.wifi.WifiConfiguration; 55 import android.net.wifi.WifiEnterpriseConfig; 56 import android.net.wifi.WifiManager; 57 import android.net.wifi.WifiSsid; 58 import android.net.wifi.hotspot2.IProvisioningCallback; 59 import android.net.wifi.hotspot2.OsuProvider; 60 import android.net.wifi.hotspot2.PasspointConfiguration; 61 import android.net.wifi.hotspot2.pps.Credential; 62 import android.net.wifi.hotspot2.pps.HomeSp; 63 import android.os.Looper; 64 import android.os.UserHandle; 65 import android.os.test.TestLooper; 66 import android.support.test.filters.SmallTest; 67 import android.util.Base64; 68 import android.util.Pair; 69 70 import com.android.server.wifi.Clock; 71 import com.android.server.wifi.FakeKeys; 72 import com.android.server.wifi.IMSIParameter; 73 import com.android.server.wifi.SIMAccessor; 74 import com.android.server.wifi.WifiConfigManager; 75 import com.android.server.wifi.WifiConfigStore; 76 import com.android.server.wifi.WifiKeyStore; 77 import com.android.server.wifi.WifiMetrics; 78 import com.android.server.wifi.WifiNative; 79 import com.android.server.wifi.hotspot2.anqp.ANQPElement; 80 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; 81 import com.android.server.wifi.hotspot2.anqp.DomainNameElement; 82 import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; 83 import com.android.server.wifi.hotspot2.anqp.I18Name; 84 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; 85 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium; 86 import com.android.server.wifi.util.ScanResultUtil; 87 88 import org.junit.Before; 89 import org.junit.Test; 90 import org.mockito.ArgumentCaptor; 91 import org.mockito.Mock; 92 93 import java.nio.charset.StandardCharsets; 94 import java.security.GeneralSecurityException; 95 import java.security.KeyStore; 96 import java.security.cert.X509Certificate; 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.HashMap; 100 import java.util.List; 101 import java.util.Locale; 102 import java.util.Map; 103 104 /** 105 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointManager}. 106 */ 107 @SmallTest 108 public class PasspointManagerTest { 109 private static final long BSSID = 0x112233445566L; 110 private static final String ICON_FILENAME = "test"; 111 private static final String TEST_FQDN = "test1.test.com"; 112 private static final String TEST_FRIENDLY_NAME = "friendly name"; 113 private static final String TEST_REALM = "realm.test.com"; 114 private static final String TEST_IMSI = "1234*"; 115 private static final IMSIParameter TEST_IMSI_PARAM = IMSIParameter.build(TEST_IMSI); 116 117 private static final String TEST_SSID = "TestSSID"; 118 private static final long TEST_BSSID = 0x112233445566L; 119 private static final String TEST_BSSID_STRING = "11:22:33:44:55:66"; 120 private static final long TEST_HESSID = 0x5678L; 121 private static final int TEST_ANQP_DOMAIN_ID = 0; 122 private static final ANQPNetworkKey TEST_ANQP_KEY = ANQPNetworkKey.buildKey( 123 TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID); 124 private static final int TEST_CREATOR_UID = 1234; 125 private static final int TEST_UID = 1500; 126 127 @Mock Context mContext; 128 @Mock WifiNative mWifiNative; 129 @Mock WifiKeyStore mWifiKeyStore; 130 @Mock Clock mClock; 131 @Mock SIMAccessor mSimAccessor; 132 @Mock PasspointObjectFactory mObjectFactory; 133 @Mock PasspointEventHandler.Callbacks mCallbacks; 134 @Mock AnqpCache mAnqpCache; 135 @Mock ANQPRequestManager mAnqpRequestManager; 136 @Mock CertificateVerifier mCertVerifier; 137 @Mock WifiConfigManager mWifiConfigManager; 138 @Mock WifiConfigStore mWifiConfigStore; 139 @Mock PasspointConfigStoreData.DataSource mDataSource; 140 @Mock WifiMetrics mWifiMetrics; 141 @Mock OsuNetworkConnection mOsuNetworkConnection; 142 @Mock OsuServerConnection mOsuServerConnection; 143 @Mock PasspointProvisioner mPasspointProvisioner; 144 @Mock IProvisioningCallback mCallback; 145 @Mock WfaKeyStore mWfaKeyStore; 146 @Mock KeyStore mKeyStore; 147 148 TestLooper mLooper; 149 PasspointManager mManager; 150 151 /** Sets up test. */ 152 @Before 153 public void setUp() throws Exception { 154 initMocks(this); 155 when(mObjectFactory.makeAnqpCache(mClock)).thenReturn(mAnqpCache); 156 when(mObjectFactory.makeANQPRequestManager(any(), eq(mClock))) 157 .thenReturn(mAnqpRequestManager); 158 when(mObjectFactory.makeCertificateVerifier()).thenReturn(mCertVerifier); 159 when(mObjectFactory.makeOsuNetworkConnection(any(Context.class))) 160 .thenReturn(mOsuNetworkConnection); 161 when(mObjectFactory.makeOsuServerConnection()) 162 .thenReturn(mOsuServerConnection); 163 when(mObjectFactory.makeWfaKeyStore()).thenReturn(mWfaKeyStore); 164 when(mWfaKeyStore.get()).thenReturn(mKeyStore); 165 when(mObjectFactory.makePasspointProvisioner(any(Context.class))) 166 .thenReturn(mPasspointProvisioner); 167 mManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock, 168 mSimAccessor, mObjectFactory, mWifiConfigManager, mWifiConfigStore, mWifiMetrics); 169 ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks = 170 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class); 171 verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class), 172 callbacks.capture()); 173 ArgumentCaptor<PasspointConfigStoreData.DataSource> dataSource = 174 ArgumentCaptor.forClass(PasspointConfigStoreData.DataSource.class); 175 verify(mObjectFactory).makePasspointConfigStoreData( 176 any(WifiKeyStore.class), any(SIMAccessor.class), dataSource.capture()); 177 mCallbacks = callbacks.getValue(); 178 mDataSource = dataSource.getValue(); 179 mLooper = new TestLooper(); 180 } 181 182 /** 183 * Verify {@link WifiManager#ACTION_PASSPOINT_ICON} broadcast intent. 184 * @param bssid BSSID of the AP 185 * @param fileName Name of the icon file 186 * @param data icon data byte array 187 */ 188 private void verifyIconIntent(long bssid, String fileName, byte[] data) { 189 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 190 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 191 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 192 assertEquals(ACTION_PASSPOINT_ICON, intent.getValue().getAction()); 193 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 194 assertEquals(bssid, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 195 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_FILENAME)); 196 assertEquals(fileName, intent.getValue().getExtras().getString(EXTRA_FILENAME)); 197 if (data != null) { 198 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_ICON)); 199 Icon icon = (Icon) intent.getValue().getExtras().getParcelable(EXTRA_ICON); 200 assertTrue(Arrays.equals(data, icon.getDataBytes())); 201 } else { 202 assertFalse(intent.getValue().getExtras().containsKey(EXTRA_ICON)); 203 } 204 } 205 206 /** 207 * Verify that the given Passpoint configuration matches the one that's added to 208 * the PasspointManager. 209 * 210 * @param expectedConfig The expected installed Passpoint configuration 211 */ 212 private void verifyInstalledConfig(PasspointConfiguration expectedConfig) { 213 List<PasspointConfiguration> installedConfigs = mManager.getProviderConfigs(); 214 assertEquals(1, installedConfigs.size()); 215 assertEquals(expectedConfig, installedConfigs.get(0)); 216 } 217 218 /** 219 * Create a mock PasspointProvider with default expectations. 220 * 221 * @param config The configuration associated with the provider 222 * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} 223 */ 224 private PasspointProvider createMockProvider(PasspointConfiguration config) { 225 PasspointProvider provider = mock(PasspointProvider.class); 226 when(provider.installCertsAndKeys()).thenReturn(true); 227 when(provider.getConfig()).thenReturn(config); 228 return provider; 229 } 230 231 /** 232 * Helper function for creating a test configuration with user credential. 233 * 234 * @return {@link PasspointConfiguration} 235 */ 236 private PasspointConfiguration createTestConfigWithUserCredential(String fqdn) { 237 PasspointConfiguration config = new PasspointConfiguration(); 238 HomeSp homeSp = new HomeSp(); 239 homeSp.setFqdn(fqdn); 240 homeSp.setFriendlyName(TEST_FRIENDLY_NAME); 241 config.setHomeSp(homeSp); 242 Credential credential = new Credential(); 243 credential.setRealm(TEST_REALM); 244 credential.setCaCertificate(FakeKeys.CA_CERT0); 245 Credential.UserCredential userCredential = new Credential.UserCredential(); 246 userCredential.setUsername("username"); 247 userCredential.setPassword("password"); 248 userCredential.setEapType(EAPConstants.EAP_TTLS); 249 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); 250 credential.setUserCredential(userCredential); 251 config.setCredential(credential); 252 return config; 253 } 254 255 /** 256 * Helper function for creating a test configuration with SIM credential. 257 * 258 * @return {@link PasspointConfiguration} 259 */ 260 private PasspointConfiguration createTestConfigWithSimCredential() { 261 PasspointConfiguration config = new PasspointConfiguration(); 262 HomeSp homeSp = new HomeSp(); 263 homeSp.setFqdn(TEST_FQDN); 264 homeSp.setFriendlyName(TEST_FRIENDLY_NAME); 265 config.setHomeSp(homeSp); 266 Credential credential = new Credential(); 267 credential.setRealm(TEST_REALM); 268 Credential.SimCredential simCredential = new Credential.SimCredential(); 269 simCredential.setImsi(TEST_IMSI); 270 simCredential.setEapType(EAPConstants.EAP_SIM); 271 credential.setSimCredential(simCredential); 272 config.setCredential(credential); 273 return config; 274 } 275 276 /** 277 * Helper function for adding a test provider to the manager. Return the mock 278 * provider that's added to the manager. 279 * 280 * @return {@link PasspointProvider} 281 */ 282 private PasspointProvider addTestProvider(String fqdn) { 283 PasspointConfiguration config = createTestConfigWithUserCredential(fqdn); 284 PasspointProvider provider = createMockProvider(config); 285 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 286 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(provider); 287 assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 288 289 return provider; 290 } 291 292 /** 293 * Helper function for creating a ScanResult for testing. 294 * 295 * @return {@link ScanResult} 296 */ 297 private ScanResult createTestScanResult() { 298 ScanResult scanResult = new ScanResult(); 299 scanResult.SSID = TEST_SSID; 300 scanResult.BSSID = TEST_BSSID_STRING; 301 scanResult.hessid = TEST_HESSID; 302 scanResult.flags = ScanResult.FLAG_PASSPOINT_NETWORK; 303 return scanResult; 304 } 305 306 /** 307 * Verify that the ANQP elements will be added to the ANQP cache on receiving a successful 308 * response. 309 * 310 * @throws Exception 311 */ 312 @Test 313 public void anqpResponseSuccess() throws Exception { 314 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 315 anqpElementMap.put(ANQPElementType.ANQPDomName, 316 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 317 318 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(TEST_ANQP_KEY); 319 mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); 320 verify(mAnqpCache).addEntry(TEST_ANQP_KEY, anqpElementMap); 321 verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class), 322 any(String.class)); 323 } 324 325 /** 326 * Verify that no ANQP elements will be added to the ANQP cache on receiving a successful 327 * response for a request that's not sent by us. 328 * 329 * @throws Exception 330 */ 331 @Test 332 public void anqpResponseSuccessWithUnknownRequest() throws Exception { 333 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 334 anqpElementMap.put(ANQPElementType.ANQPDomName, 335 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 336 337 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(null); 338 mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); 339 verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); 340 } 341 342 /** 343 * Verify that no ANQP elements will be added to the ANQP cache on receiving a failure response. 344 * 345 * @throws Exception 346 */ 347 @Test 348 public void anqpResponseFailure() throws Exception { 349 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, false)).thenReturn(TEST_ANQP_KEY); 350 mCallbacks.onANQPResponse(TEST_BSSID, null); 351 verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); 352 353 } 354 355 /** 356 * Validate the broadcast intent when icon file retrieval succeeded. 357 * 358 * @throws Exception 359 */ 360 @Test 361 public void iconResponseSuccess() throws Exception { 362 byte[] iconData = new byte[] {0x00, 0x11}; 363 mCallbacks.onIconResponse(BSSID, ICON_FILENAME, iconData); 364 verifyIconIntent(BSSID, ICON_FILENAME, iconData); 365 } 366 367 /** 368 * Validate the broadcast intent when icon file retrieval failed. 369 * 370 * @throws Exception 371 */ 372 @Test 373 public void iconResponseFailure() throws Exception { 374 mCallbacks.onIconResponse(BSSID, ICON_FILENAME, null); 375 verifyIconIntent(BSSID, ICON_FILENAME, null); 376 } 377 378 /** 379 * Validate the broadcast intent {@link WifiManager#ACTION_PASSPOINT_DEAUTH_IMMINENT} when 380 * Deauth Imminent WNM frame is received. 381 * 382 * @throws Exception 383 */ 384 @Test 385 public void onDeauthImminentReceived() throws Exception { 386 String reasonUrl = "test.com"; 387 int delay = 123; 388 boolean ess = true; 389 390 mCallbacks.onWnmFrameReceived(new WnmData(BSSID, reasonUrl, ess, delay)); 391 // Verify the broadcast intent. 392 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 393 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 394 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 395 assertEquals(ACTION_PASSPOINT_DEAUTH_IMMINENT, intent.getValue().getAction()); 396 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 397 assertEquals(BSSID, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 398 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_ESS)); 399 assertEquals(ess, intent.getValue().getExtras().getBoolean(EXTRA_ESS)); 400 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_DELAY)); 401 assertEquals(delay, intent.getValue().getExtras().getInt(EXTRA_DELAY)); 402 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_URL)); 403 assertEquals(reasonUrl, intent.getValue().getExtras().getString(EXTRA_URL)); 404 } 405 406 /** 407 * Validate the broadcast intent {@link WifiManager#ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION} 408 * when Subscription Remediation WNM frame is received. 409 * 410 * @throws Exception 411 */ 412 @Test 413 public void onSubscriptionRemediationReceived() throws Exception { 414 int serverMethod = 1; 415 String serverUrl = "testUrl"; 416 417 mCallbacks.onWnmFrameReceived(new WnmData(BSSID, serverUrl, serverMethod)); 418 // Verify the broadcast intent. 419 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 420 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 421 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 422 assertEquals(ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION, intent.getValue().getAction()); 423 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 424 assertEquals(BSSID, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 425 assertTrue(intent.getValue().getExtras().containsKey( 426 EXTRA_SUBSCRIPTION_REMEDIATION_METHOD)); 427 assertEquals(serverMethod, intent.getValue().getExtras().getInt( 428 EXTRA_SUBSCRIPTION_REMEDIATION_METHOD)); 429 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_URL)); 430 assertEquals(serverUrl, intent.getValue().getExtras().getString(EXTRA_URL)); 431 } 432 433 /** 434 * Verify that adding a provider with a null configuration will fail. 435 * 436 * @throws Exception 437 */ 438 @Test 439 public void addProviderWithNullConfig() throws Exception { 440 assertFalse(mManager.addOrUpdateProvider(null, TEST_CREATOR_UID)); 441 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 442 verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); 443 } 444 445 /** 446 * Verify that adding a provider with a empty configuration will fail. 447 * 448 * @throws Exception 449 */ 450 @Test 451 public void addProviderWithEmptyConfig() throws Exception { 452 assertFalse(mManager.addOrUpdateProvider(new PasspointConfiguration(), TEST_CREATOR_UID)); 453 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 454 verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); 455 } 456 457 /** 458 * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS 459 * for user credential). 460 * 461 * @throws Exception 462 */ 463 @Test 464 public void addProviderWithInvalidCredential() throws Exception { 465 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 466 // EAP-TLS not allowed for user credential. 467 config.getCredential().getUserCredential().setEapType(EAPConstants.EAP_TLS); 468 assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 469 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 470 verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); 471 } 472 473 /** 474 * Verify that adding a provider with a valid configuration and user credential will succeed. 475 * 476 * @throws Exception 477 */ 478 @Test 479 public void addRemoveProviderWithValidUserCredential() throws Exception { 480 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 481 PasspointProvider provider = createMockProvider(config); 482 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 483 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(provider); 484 assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 485 verifyInstalledConfig(config); 486 verify(mWifiConfigManager).saveToStore(true); 487 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 488 verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); 489 reset(mWifiMetrics); 490 reset(mWifiConfigManager); 491 492 // Verify content in the data source. 493 List<PasspointProvider> providers = mDataSource.getProviders(); 494 assertEquals(1, providers.size()); 495 assertEquals(config, providers.get(0).getConfig()); 496 // Provider index start with 0, should be 1 after adding a provider. 497 assertEquals(1, mDataSource.getProviderIndex()); 498 499 // Remove the provider. 500 assertTrue(mManager.removeProvider(TEST_FQDN)); 501 verify(provider).uninstallCertsAndKeys(); 502 verify(mWifiConfigManager).saveToStore(true); 503 verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); 504 verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); 505 assertTrue(mManager.getProviderConfigs().isEmpty()); 506 507 // Verify content in the data source. 508 assertTrue(mDataSource.getProviders().isEmpty()); 509 // Removing a provider should not change the provider index. 510 assertEquals(1, mDataSource.getProviderIndex()); 511 } 512 513 /** 514 * Verify that adding a provider with a valid configuration and SIM credential will succeed. 515 * 516 * @throws Exception 517 */ 518 @Test 519 public void addRemoveProviderWithValidSimCredential() throws Exception { 520 PasspointConfiguration config = createTestConfigWithSimCredential(); 521 PasspointProvider provider = createMockProvider(config); 522 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 523 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(provider); 524 assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 525 verifyInstalledConfig(config); 526 verify(mWifiConfigManager).saveToStore(true); 527 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 528 verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); 529 reset(mWifiMetrics); 530 reset(mWifiConfigManager); 531 532 // Verify content in the data source. 533 List<PasspointProvider> providers = mDataSource.getProviders(); 534 assertEquals(1, providers.size()); 535 assertEquals(config, providers.get(0).getConfig()); 536 // Provider index start with 0, should be 1 after adding a provider. 537 assertEquals(1, mDataSource.getProviderIndex()); 538 539 // Remove the provider. 540 assertTrue(mManager.removeProvider(TEST_FQDN)); 541 verify(provider).uninstallCertsAndKeys(); 542 verify(mWifiConfigManager).saveToStore(true); 543 verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); 544 verify(mWifiMetrics).incrementNumPasspointProviderUninstallSuccess(); 545 assertTrue(mManager.getProviderConfigs().isEmpty()); 546 547 // Verify content in the data source. 548 assertTrue(mDataSource.getProviders().isEmpty()); 549 // Removing a provider should not change the provider index. 550 assertEquals(1, mDataSource.getProviderIndex()); 551 } 552 553 /** 554 * Verify that adding a provider with the same base domain as the existing provider will 555 * succeed, and verify that the existing provider is replaced by the new provider with 556 * the new configuration. 557 * 558 * @throws Exception 559 */ 560 @Test 561 public void addProviderWithExistingConfig() throws Exception { 562 // Add a provider with the original configuration. 563 PasspointConfiguration origConfig = createTestConfigWithSimCredential(); 564 PasspointProvider origProvider = createMockProvider(origConfig); 565 when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), 566 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(origProvider); 567 assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID)); 568 verifyInstalledConfig(origConfig); 569 verify(mWifiConfigManager).saveToStore(true); 570 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 571 verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); 572 reset(mWifiMetrics); 573 reset(mWifiConfigManager); 574 575 // Verify data source content. 576 List<PasspointProvider> origProviders = mDataSource.getProviders(); 577 assertEquals(1, origProviders.size()); 578 assertEquals(origConfig, origProviders.get(0).getConfig()); 579 assertEquals(1, mDataSource.getProviderIndex()); 580 581 // Add another provider with the same base domain as the existing provider. 582 // This should replace the existing provider with the new configuration. 583 PasspointConfiguration newConfig = createTestConfigWithUserCredential(TEST_FQDN); 584 PasspointProvider newProvider = createMockProvider(newConfig); 585 when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), 586 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(newProvider); 587 assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID)); 588 verifyInstalledConfig(newConfig); 589 verify(mWifiConfigManager).saveToStore(true); 590 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 591 verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); 592 593 // Verify data source content. 594 List<PasspointProvider> newProviders = mDataSource.getProviders(); 595 assertEquals(1, newProviders.size()); 596 assertEquals(newConfig, newProviders.get(0).getConfig()); 597 assertEquals(2, mDataSource.getProviderIndex()); 598 } 599 600 /** 601 * Verify that adding a provider will fail when failing to install certificates and 602 * key to the keystore. 603 * 604 * @throws Exception 605 */ 606 @Test 607 public void addProviderOnKeyInstallationFailiure() throws Exception { 608 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 609 PasspointProvider provider = mock(PasspointProvider.class); 610 when(provider.installCertsAndKeys()).thenReturn(false); 611 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 612 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(provider); 613 assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 614 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 615 verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); 616 } 617 618 /** 619 * Verify that adding a provider with an invalid CA certificate will fail. 620 * 621 * @throws Exception 622 */ 623 @Test 624 public void addProviderWithInvalidCaCert() throws Exception { 625 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 626 doThrow(new GeneralSecurityException()) 627 .when(mCertVerifier).verifyCaCert(any(X509Certificate.class)); 628 assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 629 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 630 verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess(); 631 } 632 633 /** 634 * Verify that adding a provider with R2 configuration will not perform CA certificate 635 * verification. 636 * 637 * @throws Exception 638 */ 639 @Test 640 public void addProviderWithR2Config() throws Exception { 641 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 642 config.setUpdateIdentifier(1); 643 PasspointProvider provider = createMockProvider(config); 644 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 645 eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID))).thenReturn(provider); 646 assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 647 verify(mCertVerifier, never()).verifyCaCert(any(X509Certificate.class)); 648 verifyInstalledConfig(config); 649 verify(mWifiMetrics).incrementNumPasspointProviderInstallation(); 650 verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess(); 651 } 652 653 /** 654 * Verify that removing a non-existing provider will fail. 655 * 656 * @throws Exception 657 */ 658 @Test 659 public void removeNonExistingProvider() throws Exception { 660 assertFalse(mManager.removeProvider(TEST_FQDN)); 661 verify(mWifiMetrics).incrementNumPasspointProviderUninstallation(); 662 verify(mWifiMetrics, never()).incrementNumPasspointProviderUninstallSuccess(); 663 } 664 665 /** 666 * Verify that a {code null} will be returned when no providers are installed. 667 * 668 * @throws Exception 669 */ 670 @Test 671 public void matchProviderWithNoProvidersInstalled() throws Exception { 672 assertNull(mManager.matchProvider(createTestScanResult())); 673 } 674 675 /** 676 * Verify that a {code null} be returned when ANQP entry doesn't exist in the cache. 677 * 678 * @throws Exception 679 */ 680 @Test 681 public void matchProviderWithAnqpCacheMissed() throws Exception { 682 addTestProvider(TEST_FQDN); 683 684 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); 685 assertNull(mManager.matchProvider(createTestScanResult())); 686 // Verify that a request for ANQP elements is initiated. 687 verify(mAnqpRequestManager).requestANQPElements(eq(TEST_BSSID), any(ANQPNetworkKey.class), 688 anyBoolean(), anyBoolean()); 689 } 690 691 /** 692 * Verify that the expected provider will be returned when a HomeProvider is matched. 693 * 694 * @throws Exception 695 */ 696 @Test 697 public void matchProviderAsHomeProvider() throws Exception { 698 PasspointProvider provider = addTestProvider(TEST_FQDN); 699 ANQPData entry = new ANQPData(mClock, null); 700 701 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 702 when(provider.match(anyMap(), any(RoamingConsortium.class))) 703 .thenReturn(PasspointMatch.HomeProvider); 704 Pair<PasspointProvider, PasspointMatch> result = 705 mManager.matchProvider(createTestScanResult()); 706 assertEquals(PasspointMatch.HomeProvider, result.second); 707 assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn()); 708 } 709 710 /** 711 * Verify that the expected provider will be returned when a RoamingProvider is matched. 712 * 713 * @throws Exception 714 */ 715 @Test 716 public void matchProviderAsRoamingProvider() throws Exception { 717 PasspointProvider provider = addTestProvider(TEST_FQDN); 718 ANQPData entry = new ANQPData(mClock, null); 719 720 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 721 when(provider.match(anyMap(), any(RoamingConsortium.class))) 722 .thenReturn(PasspointMatch.RoamingProvider); 723 Pair<PasspointProvider, PasspointMatch> result = 724 mManager.matchProvider(createTestScanResult()); 725 assertEquals(PasspointMatch.RoamingProvider, result.second); 726 assertEquals(TEST_FQDN, result.first.getConfig().getHomeSp().getFqdn()); 727 } 728 729 /** 730 * Verify that a {code null} will be returned when there is no matching provider. 731 * 732 * @throws Exception 733 */ 734 @Test 735 public void matchProviderWithNoMatch() throws Exception { 736 PasspointProvider provider = addTestProvider(TEST_FQDN); 737 ANQPData entry = new ANQPData(mClock, null); 738 739 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 740 when(provider.match(anyMap(), any(RoamingConsortium.class))) 741 .thenReturn(PasspointMatch.None); 742 assertNull(mManager.matchProvider(createTestScanResult())); 743 } 744 745 /** 746 * Verify the expectations for sweepCache. 747 * 748 * @throws Exception 749 */ 750 @Test 751 public void sweepCache() throws Exception { 752 mManager.sweepCache(); 753 verify(mAnqpCache).sweep(); 754 } 755 756 /** 757 * Verify that an empty map will be returned if ANQP elements are not cached for the given AP. 758 * 759 * @throws Exception 760 */ 761 @Test 762 public void getANQPElementsWithNoMatchFound() throws Exception { 763 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); 764 assertTrue(mManager.getANQPElements(createTestScanResult()).isEmpty()); 765 } 766 767 /** 768 * Verify that an expected ANQP elements will be returned if ANQP elements are cached for the 769 * given AP. 770 * 771 * @throws Exception 772 */ 773 @Test 774 public void getANQPElementsWithMatchFound() throws Exception { 775 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 776 anqpElementMap.put(ANQPElementType.ANQPDomName, 777 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 778 ANQPData entry = new ANQPData(mClock, anqpElementMap); 779 780 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 781 assertEquals(anqpElementMap, mManager.getANQPElements(createTestScanResult())); 782 } 783 784 /** 785 * Verify that an expected {@link WifiConfiguration} will be returned when a {@link ScanResult} 786 * is matched to a home provider. 787 * 788 * @throws Exception 789 */ 790 @Test 791 public void getMatchingWifiConfigForHomeProviderAP() throws Exception { 792 PasspointProvider provider = addTestProvider(TEST_FQDN); 793 ANQPData entry = new ANQPData(mClock, null); 794 795 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 796 when(provider.match(anyMap(), any(RoamingConsortium.class))) 797 .thenReturn(PasspointMatch.HomeProvider); 798 when(provider.getWifiConfig()).thenReturn(new WifiConfiguration()); 799 WifiConfiguration config = mManager.getMatchingWifiConfig(createTestScanResult()); 800 assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID), config.SSID); 801 assertTrue(config.isHomeProviderNetwork); 802 } 803 804 /** 805 * Verify that an expected {@link WifiConfiguration} will be returned when a {@link ScanResult} 806 * is matched to a roaming provider. 807 * 808 * @throws Exception 809 */ 810 @Test 811 public void getMatchingWifiConfigForRoamingProviderAP() throws Exception { 812 PasspointProvider provider = addTestProvider(TEST_FQDN); 813 ANQPData entry = new ANQPData(mClock, null); 814 815 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 816 when(provider.match(anyMap(), any(RoamingConsortium.class))) 817 .thenReturn(PasspointMatch.RoamingProvider); 818 when(provider.getWifiConfig()).thenReturn(new WifiConfiguration()); 819 WifiConfiguration config = mManager.getMatchingWifiConfig(createTestScanResult()); 820 assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID), config.SSID); 821 assertFalse(config.isHomeProviderNetwork); 822 } 823 824 /** 825 * Verify that a {code null} will be returned when a {@link ScanResult} doesn't match any 826 * provider. 827 * 828 * @throws Exception 829 */ 830 @Test 831 public void getMatchingWifiConfigWithNoMatchingProvider() throws Exception { 832 PasspointProvider provider = addTestProvider(TEST_FQDN); 833 ANQPData entry = new ANQPData(mClock, null); 834 835 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 836 when(provider.match(anyMap(), any(RoamingConsortium.class))) 837 .thenReturn(PasspointMatch.None); 838 assertNull(mManager.getMatchingWifiConfig(createTestScanResult())); 839 verify(provider, never()).getWifiConfig(); 840 } 841 842 /** 843 * Verify that a {@code null} will be returned when trying to get a matching 844 * {@link WifiConfiguration} for a {@code null} {@link ScanResult}. 845 * 846 * @throws Exception 847 */ 848 @Test 849 public void getMatchingWifiConfigWithNullScanResult() throws Exception { 850 assertNull(mManager.getMatchingWifiConfig(null)); 851 } 852 853 /** 854 * Verify that a {@code null} will be returned when trying to get a matching 855 * {@link WifiConfiguration} for a {@link ScanResult} with a {@code null} BSSID. 856 * 857 * @throws Exception 858 */ 859 @Test 860 public void getMatchingWifiConfigWithNullBSSID() throws Exception { 861 ScanResult scanResult = createTestScanResult(); 862 scanResult.BSSID = null; 863 assertNull(mManager.getMatchingWifiConfig(scanResult)); 864 } 865 866 /** 867 * Verify that a {@code null} will be returned when trying to get a matching 868 * {@link WifiConfiguration} for a {@link ScanResult} with an invalid BSSID. 869 * 870 * @throws Exception 871 */ 872 @Test 873 public void getMatchingWifiConfigWithInvalidBSSID() throws Exception { 874 ScanResult scanResult = createTestScanResult(); 875 scanResult.BSSID = "asdfdasfas"; 876 assertNull(mManager.getMatchingWifiConfig(scanResult)); 877 } 878 879 /** 880 * Verify that a {@code null} will be returned when trying to get a matching 881 * {@link WifiConfiguration} for a non-Passpoint AP. 882 * 883 * @throws Exception 884 */ 885 @Test 886 public void getMatchingWifiConfigForNonPasspointAP() throws Exception { 887 ScanResult scanResult = createTestScanResult(); 888 scanResult.flags = 0; 889 assertNull(mManager.getMatchingWifiConfig(scanResult)); 890 } 891 892 /** 893 * Verify that an expected set of {@link WifiConfiguration} will be returned when a 894 * {@link ScanResult} is matched to a provider. 895 * 896 * @throws Exception 897 */ 898 @Test 899 public void getAllMatchingWifiConfigsForProviderAP() throws Exception { 900 PasspointProvider providerHome = addTestProvider(TEST_FQDN + 0); 901 PasspointProvider providerRoaming = addTestProvider(TEST_FQDN + 1); 902 PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2); 903 ANQPData entry = new ANQPData(mClock, null); 904 905 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 906 907 when(providerHome.match(anyMap(), any(RoamingConsortium.class))) 908 .thenReturn(PasspointMatch.HomeProvider); 909 when(providerRoaming.match(anyMap(), any(RoamingConsortium.class))) 910 .thenReturn(PasspointMatch.RoamingProvider); 911 when(providerNone.match(anyMap(), any(RoamingConsortium.class))) 912 .thenReturn(PasspointMatch.None); 913 914 when(providerHome.getWifiConfig()).thenReturn(new WifiConfiguration()); 915 when(providerRoaming.getWifiConfig()).thenReturn(new WifiConfiguration()); 916 when(providerNone.getWifiConfig()).thenReturn(new WifiConfiguration()); 917 918 List<WifiConfiguration> configs = mManager.getAllMatchingWifiConfigs( 919 createTestScanResult()); 920 921 assertEquals(2, configs.size()); 922 int observedHome = 0; 923 int observedRoaming = 0; 924 for (WifiConfiguration config : configs) { 925 assertEquals(ScanResultUtil.createQuotedSSID(TEST_SSID), config.SSID); 926 if (config.isHomeProviderNetwork) { 927 observedHome++; 928 } else { 929 observedRoaming++; 930 } 931 } 932 assertEquals(1, observedHome); 933 assertEquals(1, observedRoaming); 934 } 935 936 /** 937 * Verify that an empty list will be returned when trying to get all matching 938 * {@link WifiConfiguration} for a {@code null} {@link ScanResult}. 939 * 940 * @throws Exception 941 */ 942 @Test 943 public void getAllMatchingWifiConfigsWithNullScanResult() throws Exception { 944 assertEquals(0, mManager.getAllMatchingWifiConfigs(null).size()); 945 } 946 947 /** 948 * Verify that an empty list will be returned when trying to get a all matching 949 * {@link WifiConfiguration} for a {@link ScanResult} with a {@code null} BSSID. 950 * 951 * @throws Exception 952 */ 953 @Test 954 public void getAllMatchingWifiConfigWithNullBSSID() throws Exception { 955 ScanResult scanResult = createTestScanResult(); 956 scanResult.BSSID = null; 957 assertEquals(0, mManager.getAllMatchingWifiConfigs(scanResult).size()); 958 } 959 960 /** 961 * Verify that an empty list will be returned when trying to get all matching 962 * {@link WifiConfiguration} for a {@link ScanResult} with an invalid BSSID. 963 * 964 * @throws Exception 965 */ 966 @Test 967 public void getAllMatchingWifiConfigWithInvalidBSSID() throws Exception { 968 ScanResult scanResult = createTestScanResult(); 969 scanResult.BSSID = "asdfdasfas"; 970 assertEquals(0, mManager.getAllMatchingWifiConfigs(scanResult).size()); 971 } 972 973 /** 974 * Verify that an empty list will be returned when trying to get all matching 975 * {@link WifiConfiguration} for a non-Passpoint AP. 976 * 977 * @throws Exception 978 */ 979 @Test 980 public void getAllMatchingWifiConfigForNonPasspointAP() throws Exception { 981 ScanResult scanResult = createTestScanResult(); 982 scanResult.flags = 0; 983 assertEquals(0, mManager.getAllMatchingWifiConfigs(scanResult).size()); 984 } 985 986 /** 987 * Verify that an empty list will be returned when retrieving OSU providers for an AP with 988 * null scan result. 989 * 990 * @throws Exception 991 */ 992 @Test 993 public void getMatchingOsuProvidersForNullScanResult() throws Exception { 994 assertTrue(mManager.getMatchingOsuProviders(null).isEmpty()); 995 } 996 997 /** 998 * Verify that an empty list will be returned when retrieving OSU providers for an AP with 999 * invalid BSSID. 1000 * 1001 * @throws Exception 1002 */ 1003 @Test 1004 public void getMatchingOsuProvidersForInvalidBSSID() throws Exception { 1005 ScanResult scanResult = createTestScanResult(); 1006 scanResult.BSSID = "asdfdasfas"; 1007 assertTrue(mManager.getMatchingOsuProviders(scanResult).isEmpty()); 1008 } 1009 1010 /** 1011 * Verify that an empty list will be returned when retrieving OSU providers for a 1012 * non-Passpoint AP. 1013 * 1014 * @throws Exception 1015 */ 1016 @Test 1017 public void getMatchingOsuProvidersForNonPasspointAP() throws Exception { 1018 ScanResult scanResult = createTestScanResult(); 1019 scanResult.flags = 0; 1020 assertTrue(mManager.getMatchingOsuProviders(scanResult).isEmpty()); 1021 } 1022 1023 /** 1024 * Verify that an empty list will be returned when no match is found from the ANQP cache. 1025 * 1026 * @throws Exception 1027 */ 1028 @Test 1029 public void getMatchingOsuProviderWithNoMatch() throws Exception { 1030 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); 1031 assertTrue(mManager.getMatchingOsuProviders(createTestScanResult()).isEmpty()); 1032 } 1033 1034 /** 1035 * Verify that an expected provider list will be returned when a match is found from 1036 * the ANQP cache. 1037 * 1038 * @throws Exception 1039 */ 1040 @Test 1041 public void getMatchingOsuProvidersWithMatch() throws Exception { 1042 // Test data. 1043 WifiSsid osuSsid = WifiSsid.createFromAsciiEncoded("Test SSID"); 1044 String friendlyName = "Test Provider"; 1045 String serviceDescription = "Dummy Service"; 1046 Uri serverUri = Uri.parse("https://test.com"); 1047 String nai = "access.test.com"; 1048 List<Integer> methodList = Arrays.asList(1); 1049 List<I18Name> friendlyNames = Arrays.asList( 1050 new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, friendlyName)); 1051 List<I18Name> serviceDescriptions = Arrays.asList( 1052 new I18Name(Locale.ENGLISH.getLanguage(), Locale.ENGLISH, serviceDescription)); 1053 1054 // Setup OSU providers ANQP element. 1055 List<OsuProviderInfo> providerInfoList = new ArrayList<>(); 1056 providerInfoList.add(new OsuProviderInfo( 1057 friendlyNames, serverUri, methodList, null, nai, serviceDescriptions)); 1058 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 1059 anqpElementMap.put(ANQPElementType.HSOSUProviders, 1060 new HSOsuProvidersElement(osuSsid, providerInfoList)); 1061 ANQPData entry = new ANQPData(mClock, anqpElementMap); 1062 1063 // Setup expectation. 1064 OsuProvider provider = new OsuProvider( 1065 osuSsid, friendlyName, serviceDescription, serverUri, nai, methodList, null); 1066 List<OsuProvider> expectedList = new ArrayList<>(); 1067 expectedList.add(provider); 1068 1069 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 1070 assertEquals(expectedList, mManager.getMatchingOsuProviders(createTestScanResult())); 1071 } 1072 1073 /** 1074 * Verify that the provider list maintained by the PasspointManager after the list is updated 1075 * in the data source. 1076 * 1077 * @throws Exception 1078 */ 1079 @Test 1080 public void verifyProvidersAfterDataSourceUpdate() throws Exception { 1081 // Update the provider list in the data source. 1082 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 1083 PasspointProvider provider = createMockProvider(config); 1084 List<PasspointProvider> providers = new ArrayList<>(); 1085 providers.add(provider); 1086 mDataSource.setProviders(providers); 1087 1088 // Verify the providers maintained by PasspointManager. 1089 assertEquals(1, mManager.getProviderConfigs().size()); 1090 assertEquals(config, mManager.getProviderConfigs().get(0)); 1091 } 1092 1093 /** 1094 * Verify that the provider index used by PasspointManager is updated after it is updated in 1095 * the data source. 1096 * 1097 * @throws Exception 1098 */ 1099 @Test 1100 public void verifyProviderIndexAfterDataSourceUpdate() throws Exception { 1101 long providerIndex = 9; 1102 mDataSource.setProviderIndex(providerIndex); 1103 assertEquals(providerIndex, mDataSource.getProviderIndex()); 1104 1105 // Add a provider. 1106 PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN); 1107 PasspointProvider provider = createMockProvider(config); 1108 // Verify the provider ID used to create the new provider. 1109 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 1110 eq(mSimAccessor), eq(providerIndex), eq(TEST_CREATOR_UID))).thenReturn(provider); 1111 assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID)); 1112 verifyInstalledConfig(config); 1113 verify(mWifiConfigManager).saveToStore(true); 1114 reset(mWifiConfigManager); 1115 } 1116 1117 /** 1118 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 1119 * adding a legacy Passpoint configuration containing a valid user credential. 1120 * 1121 * @throws Exception 1122 */ 1123 @Test 1124 public void addLegacyPasspointConfigWithUserCredential() throws Exception { 1125 // Test data. 1126 String fqdn = "test.com"; 1127 String friendlyName = "Friendly Name"; 1128 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1129 String realm = "realm.com"; 1130 String username = "username"; 1131 String password = "password"; 1132 byte[] base64EncodedPw = 1133 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 1134 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 1135 String caCertificateAlias = "CaCert"; 1136 1137 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1138 WifiConfiguration wifiConfig = new WifiConfiguration(); 1139 wifiConfig.FQDN = fqdn; 1140 wifiConfig.providerFriendlyName = friendlyName; 1141 wifiConfig.roamingConsortiumIds = rcOIs; 1142 wifiConfig.enterpriseConfig.setIdentity(username); 1143 wifiConfig.enterpriseConfig.setPassword(password); 1144 wifiConfig.enterpriseConfig.setRealm(realm); 1145 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 1146 wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); 1147 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 1148 1149 // Setup expected {@link PasspointConfiguration} 1150 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 1151 HomeSp homeSp = new HomeSp(); 1152 homeSp.setFqdn(fqdn); 1153 homeSp.setFriendlyName(friendlyName); 1154 homeSp.setRoamingConsortiumOis(rcOIs); 1155 passpointConfig.setHomeSp(homeSp); 1156 Credential credential = new Credential(); 1157 Credential.UserCredential userCredential = new Credential.UserCredential(); 1158 userCredential.setUsername(username); 1159 userCredential.setPassword(encodedPasswordStr); 1160 userCredential.setEapType(EAPConstants.EAP_TTLS); 1161 userCredential.setNonEapInnerMethod("PAP"); 1162 credential.setUserCredential(userCredential); 1163 credential.setRealm(realm); 1164 passpointConfig.setCredential(credential); 1165 1166 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1167 verifyInstalledConfig(passpointConfig); 1168 } 1169 1170 /** 1171 * Verify that adding a legacy Passpoint configuration containing user credential will 1172 * fail when client certificate is not provided. 1173 * 1174 * @throws Exception 1175 */ 1176 @Test 1177 public void addLegacyPasspointConfigWithUserCredentialWithoutCaCert() throws Exception { 1178 // Test data. 1179 String fqdn = "test.com"; 1180 String friendlyName = "Friendly Name"; 1181 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1182 String realm = "realm.com"; 1183 String username = "username"; 1184 String password = "password"; 1185 byte[] base64EncodedPw = 1186 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 1187 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 1188 1189 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1190 WifiConfiguration wifiConfig = new WifiConfiguration(); 1191 wifiConfig.FQDN = fqdn; 1192 wifiConfig.providerFriendlyName = friendlyName; 1193 wifiConfig.roamingConsortiumIds = rcOIs; 1194 wifiConfig.enterpriseConfig.setIdentity(username); 1195 wifiConfig.enterpriseConfig.setPassword(password); 1196 wifiConfig.enterpriseConfig.setRealm(realm); 1197 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 1198 wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); 1199 1200 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1201 } 1202 1203 /** 1204 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 1205 * adding a legacy Passpoint configuration containing a valid SIM credential. 1206 * 1207 * @throws Exception 1208 */ 1209 @Test 1210 public void addLegacyPasspointConfigWithSimCredential() throws Exception { 1211 // Test data. 1212 String fqdn = "test.com"; 1213 String friendlyName = "Friendly Name"; 1214 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1215 String realm = "realm.com"; 1216 String imsi = "1234"; 1217 1218 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1219 WifiConfiguration wifiConfig = new WifiConfiguration(); 1220 wifiConfig.FQDN = fqdn; 1221 wifiConfig.providerFriendlyName = friendlyName; 1222 wifiConfig.roamingConsortiumIds = rcOIs; 1223 wifiConfig.enterpriseConfig.setRealm(realm); 1224 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); 1225 wifiConfig.enterpriseConfig.setPlmn(imsi); 1226 1227 // Setup expected {@link PasspointConfiguration} 1228 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 1229 HomeSp homeSp = new HomeSp(); 1230 homeSp.setFqdn(fqdn); 1231 homeSp.setFriendlyName(friendlyName); 1232 homeSp.setRoamingConsortiumOis(rcOIs); 1233 passpointConfig.setHomeSp(homeSp); 1234 Credential credential = new Credential(); 1235 Credential.SimCredential simCredential = new Credential.SimCredential(); 1236 simCredential.setEapType(EAPConstants.EAP_SIM); 1237 simCredential.setImsi(imsi); 1238 credential.setSimCredential(simCredential); 1239 credential.setRealm(realm); 1240 passpointConfig.setCredential(credential); 1241 1242 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1243 verifyInstalledConfig(passpointConfig); 1244 } 1245 1246 /** 1247 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 1248 * adding a legacy Passpoint configuration containing a valid certificate credential. 1249 * 1250 * @throws Exception 1251 */ 1252 @Test 1253 public void addLegacyPasspointConfigWithCertCredential() throws Exception { 1254 // Test data. 1255 String fqdn = "test.com"; 1256 String friendlyName = "Friendly Name"; 1257 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1258 String realm = "realm.com"; 1259 String caCertificateAlias = "CaCert"; 1260 String clientCertificateAlias = "ClientCert"; 1261 1262 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1263 WifiConfiguration wifiConfig = new WifiConfiguration(); 1264 wifiConfig.FQDN = fqdn; 1265 wifiConfig.providerFriendlyName = friendlyName; 1266 wifiConfig.roamingConsortiumIds = rcOIs; 1267 wifiConfig.enterpriseConfig.setRealm(realm); 1268 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 1269 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 1270 wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); 1271 1272 // Setup expected {@link PasspointConfiguration} 1273 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 1274 HomeSp homeSp = new HomeSp(); 1275 homeSp.setFqdn(fqdn); 1276 homeSp.setFriendlyName(friendlyName); 1277 homeSp.setRoamingConsortiumOis(rcOIs); 1278 passpointConfig.setHomeSp(homeSp); 1279 Credential credential = new Credential(); 1280 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 1281 certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); 1282 credential.setCertCredential(certCredential); 1283 credential.setRealm(realm); 1284 passpointConfig.setCredential(credential); 1285 1286 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1287 verifyInstalledConfig(passpointConfig); 1288 } 1289 1290 /** 1291 * Verify that adding a legacy Passpoint configuration containing certificate credential will 1292 * fail when CA certificate is not provided. 1293 * 1294 * @throws Exception 1295 */ 1296 @Test 1297 public void addLegacyPasspointConfigWithCertCredentialWithoutCaCert() throws Exception { 1298 // Test data. 1299 String fqdn = "test.com"; 1300 String friendlyName = "Friendly Name"; 1301 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1302 String realm = "realm.com"; 1303 String clientCertificateAlias = "ClientCert"; 1304 1305 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1306 WifiConfiguration wifiConfig = new WifiConfiguration(); 1307 wifiConfig.FQDN = fqdn; 1308 wifiConfig.providerFriendlyName = friendlyName; 1309 wifiConfig.roamingConsortiumIds = rcOIs; 1310 wifiConfig.enterpriseConfig.setRealm(realm); 1311 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 1312 wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); 1313 1314 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1315 } 1316 1317 /** 1318 * Verify that adding a legacy Passpoint configuration containing certificate credential will 1319 * fail when client certificate is not provided. 1320 * 1321 * @throws Exception 1322 */ 1323 @Test 1324 public void addLegacyPasspointConfigWithCertCredentialWithoutClientCert() throws Exception { 1325 // Test data. 1326 String fqdn = "test.com"; 1327 String friendlyName = "Friendly Name"; 1328 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 1329 String realm = "realm.com"; 1330 String caCertificateAlias = "CaCert"; 1331 1332 // Setup WifiConfiguration for legacy Passpoint configuraiton. 1333 WifiConfiguration wifiConfig = new WifiConfiguration(); 1334 wifiConfig.FQDN = fqdn; 1335 wifiConfig.providerFriendlyName = friendlyName; 1336 wifiConfig.roamingConsortiumIds = rcOIs; 1337 wifiConfig.enterpriseConfig.setRealm(realm); 1338 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 1339 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 1340 1341 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 1342 } 1343 1344 /** 1345 * Verify that the provider's "hasEverConnected" flag will be set to true and the associated 1346 * metric is updated after the provider was used to successfully connect to a Passpoint 1347 * network for the first time. 1348 * 1349 * @throws Exception 1350 */ 1351 @Test 1352 public void providerNetworkConnectedFirstTime() throws Exception { 1353 PasspointProvider provider = addTestProvider(TEST_FQDN); 1354 when(provider.getHasEverConnected()).thenReturn(false); 1355 mManager.onPasspointNetworkConnected(TEST_FQDN); 1356 verify(provider).setHasEverConnected(eq(true)); 1357 } 1358 1359 /** 1360 * Verify that the provider's "hasEverConnected" flag the associated metric is not updated 1361 * after the provider was used to successfully connect to a Passpoint network for non-first 1362 * time. 1363 * 1364 * @throws Exception 1365 */ 1366 @Test 1367 public void providerNetworkConnectedNotFirstTime() throws Exception { 1368 PasspointProvider provider = addTestProvider(TEST_FQDN); 1369 when(provider.getHasEverConnected()).thenReturn(true); 1370 mManager.onPasspointNetworkConnected(TEST_FQDN); 1371 verify(provider, never()).setHasEverConnected(anyBoolean()); 1372 } 1373 1374 /** 1375 * Verify that the expected Passpoint metrics are updated when 1376 * {@link PasspointManager#updateMetrics} is invoked. 1377 * 1378 * @throws Exception 1379 */ 1380 @Test 1381 public void updateMetrics() throws Exception { 1382 PasspointProvider provider = addTestProvider(TEST_FQDN); 1383 1384 // Provider have not provided a successful network connection. 1385 int expectedInstalledProviders = 1; 1386 int expectedConnectedProviders = 0; 1387 when(provider.getHasEverConnected()).thenReturn(false); 1388 mManager.updateMetrics(); 1389 verify(mWifiMetrics).updateSavedPasspointProfiles( 1390 eq(expectedInstalledProviders), eq(expectedConnectedProviders)); 1391 reset(provider); 1392 reset(mWifiMetrics); 1393 1394 // Provider have provided a successful network connection. 1395 expectedConnectedProviders = 1; 1396 when(provider.getHasEverConnected()).thenReturn(true); 1397 mManager.updateMetrics(); 1398 verify(mWifiMetrics).updateSavedPasspointProfiles( 1399 eq(expectedInstalledProviders), eq(expectedConnectedProviders)); 1400 } 1401 /** 1402 * Verify Passpoint Manager's provisioning APIs by invoking methods in PasspointProvisioner for 1403 * initiailization and provisioning a provider. 1404 */ 1405 @Test 1406 public void verifyPasspointProvisioner() { 1407 mManager.initializeProvisioner(mLooper.getLooper()); 1408 verify(mPasspointProvisioner).init(any(Looper.class)); 1409 when(mPasspointProvisioner.startSubscriptionProvisioning(anyInt(), any(OsuProvider.class), 1410 any(IProvisioningCallback.class))).thenReturn(true); 1411 OsuProvider osuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true); 1412 assertEquals(true, 1413 mManager.startSubscriptionProvisioning(TEST_UID, osuProvider, mCallback)); 1414 } 1415 } 1416