PasspointManagerTest.java revision ec28f863c5e46c0a75e8bdb92283304b875ee0f2
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 17package com.android.server.wifi.hotspot2; 18 19import static android.net.wifi.WifiManager.ACTION_PASSPOINT_DEAUTH_IMMINENT; 20import static android.net.wifi.WifiManager.ACTION_PASSPOINT_ICON; 21import static android.net.wifi.WifiManager.ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION; 22import static android.net.wifi.WifiManager.EXTRA_BSSID_LONG; 23import static android.net.wifi.WifiManager.EXTRA_DELAY; 24import static android.net.wifi.WifiManager.EXTRA_ESS; 25import static android.net.wifi.WifiManager.EXTRA_ICON_INFO; 26import static android.net.wifi.WifiManager.EXTRA_SUBSCRIPTION_REMEDIATION_METHOD; 27import static android.net.wifi.WifiManager.EXTRA_URL; 28 29import static org.junit.Assert.assertEquals; 30import static org.junit.Assert.assertFalse; 31import static org.junit.Assert.assertTrue; 32import static org.mockito.Mockito.any; 33import static org.mockito.Mockito.anyBoolean; 34import static org.mockito.Mockito.anyLong; 35import static org.mockito.Mockito.anyMap; 36import static org.mockito.Mockito.eq; 37import static org.mockito.Mockito.mock; 38import static org.mockito.Mockito.never; 39import static org.mockito.Mockito.reset; 40import static org.mockito.Mockito.verify; 41import static org.mockito.Mockito.when; 42import static org.mockito.MockitoAnnotations.initMocks; 43 44import android.content.Context; 45import android.content.Intent; 46import android.net.wifi.EAPConstants; 47import android.net.wifi.IconInfo; 48import android.net.wifi.ScanResult; 49import android.net.wifi.WifiConfiguration; 50import android.net.wifi.WifiEnterpriseConfig; 51import android.net.wifi.hotspot2.PasspointConfiguration; 52import android.net.wifi.hotspot2.pps.Credential; 53import android.net.wifi.hotspot2.pps.HomeSp; 54import android.os.UserHandle; 55import android.test.suitebuilder.annotation.SmallTest; 56import android.util.Base64; 57import android.util.Pair; 58 59import com.android.server.wifi.Clock; 60import com.android.server.wifi.FakeKeys; 61import com.android.server.wifi.IMSIParameter; 62import com.android.server.wifi.SIMAccessor; 63import com.android.server.wifi.WifiConfigManager; 64import com.android.server.wifi.WifiConfigStore; 65import com.android.server.wifi.WifiKeyStore; 66import com.android.server.wifi.WifiNative; 67import com.android.server.wifi.hotspot2.anqp.ANQPElement; 68import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; 69import com.android.server.wifi.hotspot2.anqp.DomainNameElement; 70 71import org.junit.Before; 72import org.junit.Test; 73import org.mockito.ArgumentCaptor; 74import org.mockito.Mock; 75 76import java.nio.charset.StandardCharsets; 77import java.util.ArrayList; 78import java.util.Arrays; 79import java.util.HashMap; 80import java.util.List; 81import java.util.Map; 82 83/** 84 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointManager}. 85 */ 86@SmallTest 87public class PasspointManagerTest { 88 private static final long BSSID = 0x112233445566L; 89 private static final String ICON_FILENAME = "test"; 90 private static final String TEST_FQDN = "test1.test.com"; 91 private static final String TEST_FRIENDLY_NAME = "friendly name"; 92 private static final String TEST_REALM = "realm.test.com"; 93 private static final String TEST_IMSI = "1234*"; 94 private static final IMSIParameter TEST_IMSI_PARAM = IMSIParameter.build(TEST_IMSI); 95 96 private static final String TEST_SSID = "TestSSID"; 97 private static final long TEST_BSSID = 0x112233445566L; 98 private static final String TEST_BSSID_STRING = "11:22:33:44:55:66"; 99 private static final long TEST_HESSID = 0x5678L; 100 private static final int TEST_ANQP_DOMAIN_ID = 0; 101 private static final ANQPNetworkKey TEST_ANQP_KEY = ANQPNetworkKey.buildKey( 102 TEST_SSID, TEST_BSSID, TEST_HESSID, TEST_ANQP_DOMAIN_ID); 103 104 @Mock Context mContext; 105 @Mock WifiNative mWifiNative; 106 @Mock WifiKeyStore mWifiKeyStore; 107 @Mock Clock mClock; 108 @Mock SIMAccessor mSimAccessor; 109 @Mock PasspointObjectFactory mObjectFactory; 110 @Mock PasspointEventHandler.Callbacks mCallbacks; 111 @Mock AnqpCache mAnqpCache; 112 @Mock ANQPRequestManager mAnqpRequestManager; 113 @Mock WifiConfigManager mWifiConfigManager; 114 @Mock WifiConfigStore mWifiConfigStore; 115 @Mock PasspointConfigStoreData.DataSource mDataSource; 116 PasspointManager mManager; 117 118 /** Sets up test. */ 119 @Before 120 public void setUp() throws Exception { 121 initMocks(this); 122 when(mObjectFactory.makeAnqpCache(mClock)).thenReturn(mAnqpCache); 123 when(mObjectFactory.makeANQPRequestManager(any(PasspointEventHandler.class), eq(mClock))) 124 .thenReturn(mAnqpRequestManager); 125 mManager = new PasspointManager(mContext, mWifiNative, mWifiKeyStore, mClock, 126 mSimAccessor, mObjectFactory, mWifiConfigManager, mWifiConfigStore); 127 ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks = 128 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class); 129 verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class), 130 callbacks.capture()); 131 ArgumentCaptor<PasspointConfigStoreData.DataSource> dataSource = 132 ArgumentCaptor.forClass(PasspointConfigStoreData.DataSource.class); 133 verify(mObjectFactory).makePasspointConfigStoreData( 134 any(WifiKeyStore.class), any(SIMAccessor.class), dataSource.capture()); 135 mCallbacks = callbacks.getValue(); 136 mDataSource = dataSource.getValue(); 137 } 138 139 /** 140 * Verify {@link WifiManager#ACTION_PASSPOINT_ICON} broadcast intent. 141 * @param bssid BSSID of the AP 142 * @param fileName Name of the icon file 143 * @param data icon data byte array 144 */ 145 private void verifyIconIntent(long bssid, String fileName, byte[] data) { 146 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 147 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 148 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 149 assertEquals(ACTION_PASSPOINT_ICON, intent.getValue().getAction()); 150 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 151 assertEquals(bssid, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 152 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_ICON_INFO)); 153 IconInfo expectedInfo = new IconInfo(fileName, data); 154 assertEquals(new IconInfo(fileName, data), 155 (IconInfo) intent.getValue().getExtras().getParcelable(EXTRA_ICON_INFO)); 156 } 157 158 /** 159 * Verify that the given Passpoint configuration matches the one that's added to 160 * the PasspointManager. 161 * 162 * @param expectedConfig The expected installed Passpoint configuration 163 */ 164 private void verifyInstalledConfig(PasspointConfiguration expectedConfig) { 165 List<PasspointConfiguration> installedConfigs = mManager.getProviderConfigs(); 166 assertEquals(1, installedConfigs.size()); 167 assertEquals(expectedConfig, installedConfigs.get(0)); 168 } 169 170 /** 171 * Create a mock PasspointProvider with default expectations. 172 * 173 * @param config The configuration associated with the provider 174 * @return {@link com.android.server.wifi.hotspot2.PasspointProvider} 175 */ 176 private PasspointProvider createMockProvider(PasspointConfiguration config) { 177 PasspointProvider provider = mock(PasspointProvider.class); 178 when(provider.installCertsAndKeys()).thenReturn(true); 179 when(provider.getConfig()).thenReturn(config); 180 return provider; 181 } 182 183 /** 184 * Helper function for creating a test configuration with user credential. 185 * 186 * @return {@link PasspointConfiguration} 187 */ 188 private PasspointConfiguration createTestConfigWithUserCredential() { 189 PasspointConfiguration config = new PasspointConfiguration(); 190 HomeSp homeSp = new HomeSp(); 191 homeSp.setFqdn(TEST_FQDN); 192 homeSp.setFriendlyName(TEST_FRIENDLY_NAME); 193 config.setHomeSp(homeSp); 194 Credential credential = new Credential(); 195 credential.setRealm(TEST_REALM); 196 credential.setCaCertificate(FakeKeys.CA_CERT0); 197 Credential.UserCredential userCredential = new Credential.UserCredential(); 198 userCredential.setUsername("username"); 199 userCredential.setPassword("password"); 200 userCredential.setEapType(EAPConstants.EAP_TTLS); 201 userCredential.setNonEapInnerMethod(Credential.UserCredential.AUTH_METHOD_MSCHAP); 202 credential.setUserCredential(userCredential); 203 config.setCredential(credential); 204 return config; 205 } 206 207 /** 208 * Helper function for creating a test configuration with SIM credential. 209 * 210 * @return {@link PasspointConfiguration} 211 */ 212 private PasspointConfiguration createTestConfigWithSimCredential() { 213 PasspointConfiguration config = new PasspointConfiguration(); 214 HomeSp homeSp = new HomeSp(); 215 homeSp.setFqdn(TEST_FQDN); 216 homeSp.setFriendlyName(TEST_FRIENDLY_NAME); 217 config.setHomeSp(homeSp); 218 Credential credential = new Credential(); 219 credential.setRealm(TEST_REALM); 220 Credential.SimCredential simCredential = new Credential.SimCredential(); 221 simCredential.setImsi(TEST_IMSI); 222 simCredential.setEapType(EAPConstants.EAP_SIM); 223 credential.setSimCredential(simCredential); 224 config.setCredential(credential); 225 return config; 226 } 227 228 /** 229 * Helper function for adding a test provider to the manager. Return the mock 230 * provider that's added to the manager. 231 * 232 * @return {@link PasspointProvider} 233 */ 234 private PasspointProvider addTestProvider() { 235 PasspointConfiguration config = createTestConfigWithUserCredential(); 236 PasspointProvider provider = createMockProvider(config); 237 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 238 eq(mSimAccessor), anyLong())).thenReturn(provider); 239 assertTrue(mManager.addOrUpdateProvider(config)); 240 241 return provider; 242 } 243 244 /** 245 * Helper function for creating a ScanResult for testing. 246 * 247 * @return {@link ScanResult} 248 */ 249 private ScanResult createTestScanResult() { 250 ScanResult scanResult = new ScanResult(); 251 scanResult.SSID = TEST_SSID; 252 scanResult.BSSID = TEST_BSSID_STRING; 253 scanResult.hessid = TEST_HESSID; 254 return scanResult; 255 } 256 257 /** 258 * Verify that the ANQP elements will be added to the ANQP cache on receiving a successful 259 * response. 260 * 261 * @throws Exception 262 */ 263 @Test 264 public void anqpResponseSuccess() throws Exception { 265 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 266 anqpElementMap.put(ANQPElementType.ANQPDomName, 267 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 268 269 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(TEST_ANQP_KEY); 270 mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); 271 verify(mAnqpCache).addEntry(TEST_ANQP_KEY, anqpElementMap); 272 } 273 274 /** 275 * Verify that no ANQP elements will be added to the ANQP cache on receiving a successful 276 * response for a request that's not sent by us. 277 * 278 * @throws Exception 279 */ 280 @Test 281 public void anqpResponseSuccessWithUnknownRequest() throws Exception { 282 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 283 anqpElementMap.put(ANQPElementType.ANQPDomName, 284 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 285 286 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, true)).thenReturn(null); 287 mCallbacks.onANQPResponse(TEST_BSSID, anqpElementMap); 288 verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); 289 } 290 291 /** 292 * Verify that no ANQP elements will be added to the ANQP cache on receiving a failure response. 293 * 294 * @throws Exception 295 */ 296 @Test 297 public void anqpResponseFailure() throws Exception { 298 when(mAnqpRequestManager.onRequestCompleted(TEST_BSSID, false)).thenReturn(TEST_ANQP_KEY); 299 mCallbacks.onANQPResponse(TEST_BSSID, null); 300 verify(mAnqpCache, never()).addEntry(any(ANQPNetworkKey.class), anyMap()); 301 302 } 303 304 /** 305 * Validate the broadcast intent when icon file retrieval succeeded. 306 * 307 * @throws Exception 308 */ 309 @Test 310 public void iconResponseSuccess() throws Exception { 311 byte[] iconData = new byte[] {0x00, 0x11}; 312 mCallbacks.onIconResponse(BSSID, ICON_FILENAME, iconData); 313 verifyIconIntent(BSSID, ICON_FILENAME, iconData); 314 } 315 316 /** 317 * Validate the broadcast intent when icon file retrieval failed. 318 * 319 * @throws Exception 320 */ 321 @Test 322 public void iconResponseFailure() throws Exception { 323 mCallbacks.onIconResponse(BSSID, ICON_FILENAME, null); 324 verifyIconIntent(BSSID, ICON_FILENAME, null); 325 } 326 327 /** 328 * Validate the broadcast intent {@link WifiManager#ACTION_PASSPOINT_DEAUTH_IMMINENT} when 329 * Deauth Imminent WNM frame is received. 330 * 331 * @throws Exception 332 */ 333 @Test 334 public void onDeauthImminentReceived() throws Exception { 335 String reasonUrl = "test.com"; 336 int delay = 123; 337 boolean ess = true; 338 339 mCallbacks.onWnmFrameReceived(new WnmData(BSSID, reasonUrl, ess, delay)); 340 // Verify the broadcast intent. 341 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 342 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 343 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 344 assertEquals(ACTION_PASSPOINT_DEAUTH_IMMINENT, intent.getValue().getAction()); 345 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 346 assertEquals(BSSID, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 347 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_ESS)); 348 assertEquals(ess, intent.getValue().getExtras().getBoolean(EXTRA_ESS)); 349 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_DELAY)); 350 assertEquals(delay, intent.getValue().getExtras().getInt(EXTRA_DELAY)); 351 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_URL)); 352 assertEquals(reasonUrl, intent.getValue().getExtras().getString(EXTRA_URL)); 353 } 354 355 /** 356 * Validate the broadcast intent {@link WifiManager#ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION} 357 * when Subscription Remediation WNM frame is received. 358 * 359 * @throws Exception 360 */ 361 @Test 362 public void onSubscriptionRemediationReceived() throws Exception { 363 int serverMethod = 1; 364 String serverUrl = "testUrl"; 365 366 mCallbacks.onWnmFrameReceived(new WnmData(BSSID, serverUrl, serverMethod)); 367 // Verify the broadcast intent. 368 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 369 verify(mContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL), 370 eq(android.Manifest.permission.ACCESS_WIFI_STATE)); 371 assertEquals(ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION, intent.getValue().getAction()); 372 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_BSSID_LONG)); 373 assertEquals(BSSID, intent.getValue().getExtras().getLong(EXTRA_BSSID_LONG)); 374 assertTrue(intent.getValue().getExtras().containsKey( 375 EXTRA_SUBSCRIPTION_REMEDIATION_METHOD)); 376 assertEquals(serverMethod, intent.getValue().getExtras().getInt( 377 EXTRA_SUBSCRIPTION_REMEDIATION_METHOD)); 378 assertTrue(intent.getValue().getExtras().containsKey(EXTRA_URL)); 379 assertEquals(serverUrl, intent.getValue().getExtras().getString(EXTRA_URL)); 380 } 381 382 /** 383 * Verify that adding a provider with a null configuration will fail. 384 * 385 * @throws Exception 386 */ 387 @Test 388 public void addProviderWithNullConfig() throws Exception { 389 assertFalse(mManager.addOrUpdateProvider(null)); 390 } 391 392 /** 393 * Verify that adding a provider with a empty configuration will fail. 394 * 395 * @throws Exception 396 */ 397 @Test 398 public void addProviderWithEmptyConfig() throws Exception { 399 assertFalse(mManager.addOrUpdateProvider(new PasspointConfiguration())); 400 } 401 402 /** 403 * Verify taht adding a provider with an invalid credential will fail (using EAP-TLS 404 * for user credential). 405 * 406 * @throws Exception 407 */ 408 @Test 409 public void addProviderWithInvalidCredential() throws Exception { 410 PasspointConfiguration config = createTestConfigWithUserCredential(); 411 // EAP-TLS not allowed for user credential. 412 config.getCredential().getUserCredential().setEapType(EAPConstants.EAP_TLS); 413 assertFalse(mManager.addOrUpdateProvider(config)); 414 } 415 416 /** 417 * Verify that adding a provider with a valid configuration and user credential will succeed. 418 * 419 * @throws Exception 420 */ 421 @Test 422 public void addRemoveProviderWithValidUserCredential() throws Exception { 423 PasspointConfiguration config = createTestConfigWithUserCredential(); 424 PasspointProvider provider = createMockProvider(config); 425 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 426 eq(mSimAccessor), anyLong())).thenReturn(provider); 427 assertTrue(mManager.addOrUpdateProvider(config)); 428 verifyInstalledConfig(config); 429 verify(mWifiConfigManager).saveToStore(true); 430 reset(mWifiConfigManager); 431 432 // Verify content in the data source. 433 List<PasspointProvider> providers = mDataSource.getProviders(); 434 assertEquals(1, providers.size()); 435 assertEquals(config, providers.get(0).getConfig()); 436 // Provider index start with 0, should be 1 after adding a provider. 437 assertEquals(1, mDataSource.getProviderIndex()); 438 439 // Remove the provider. 440 assertTrue(mManager.removeProvider(TEST_FQDN)); 441 verify(provider).uninstallCertsAndKeys(); 442 verify(mWifiConfigManager).saveToStore(true); 443 assertTrue(mManager.getProviderConfigs().isEmpty()); 444 445 // Verify content in the data source. 446 assertTrue(mDataSource.getProviders().isEmpty()); 447 // Removing a provider should not change the provider index. 448 assertEquals(1, mDataSource.getProviderIndex()); 449 } 450 451 /** 452 * Verify that adding a provider with a valid configuration and SIM credential will succeed. 453 * 454 * @throws Exception 455 */ 456 @Test 457 public void addRemoveProviderWithValidSimCredential() throws Exception { 458 PasspointConfiguration config = createTestConfigWithSimCredential(); 459 PasspointProvider provider = createMockProvider(config); 460 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 461 eq(mSimAccessor), anyLong())).thenReturn(provider); 462 assertTrue(mManager.addOrUpdateProvider(config)); 463 verifyInstalledConfig(config); 464 verify(mWifiConfigManager).saveToStore(true); 465 reset(mWifiConfigManager); 466 467 // Verify content in the data source. 468 List<PasspointProvider> providers = mDataSource.getProviders(); 469 assertEquals(1, providers.size()); 470 assertEquals(config, providers.get(0).getConfig()); 471 // Provider index start with 0, should be 1 after adding a provider. 472 assertEquals(1, mDataSource.getProviderIndex()); 473 474 // Remove the provider. 475 assertTrue(mManager.removeProvider(TEST_FQDN)); 476 verify(provider).uninstallCertsAndKeys(); 477 verify(mWifiConfigManager).saveToStore(true); 478 assertTrue(mManager.getProviderConfigs().isEmpty()); 479 480 // Verify content in the data source. 481 assertTrue(mDataSource.getProviders().isEmpty()); 482 // Removing a provider should not change the provider index. 483 assertEquals(1, mDataSource.getProviderIndex()); 484 } 485 486 /** 487 * Verify that adding a provider with the same base domain as the existing provider will 488 * succeed, and verify that the existing provider is replaced by the new provider with 489 * the new configuration. 490 * 491 * @throws Exception 492 */ 493 @Test 494 public void addProviderWithExistingConfig() throws Exception { 495 // Add a provider with the original configuration. 496 PasspointConfiguration origConfig = createTestConfigWithSimCredential(); 497 PasspointProvider origProvider = createMockProvider(origConfig); 498 when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore), 499 eq(mSimAccessor), anyLong())).thenReturn(origProvider); 500 assertTrue(mManager.addOrUpdateProvider(origConfig)); 501 verifyInstalledConfig(origConfig); 502 verify(mWifiConfigManager).saveToStore(true); 503 reset(mWifiConfigManager); 504 505 // Verify data source content. 506 List<PasspointProvider> origProviders = mDataSource.getProviders(); 507 assertEquals(1, origProviders.size()); 508 assertEquals(origConfig, origProviders.get(0).getConfig()); 509 assertEquals(1, mDataSource.getProviderIndex()); 510 511 // Add another provider with the same base domain as the existing provider. 512 // This should replace the existing provider with the new configuration. 513 PasspointConfiguration newConfig = createTestConfigWithUserCredential(); 514 PasspointProvider newProvider = createMockProvider(newConfig); 515 when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore), 516 eq(mSimAccessor), anyLong())).thenReturn(newProvider); 517 assertTrue(mManager.addOrUpdateProvider(newConfig)); 518 verifyInstalledConfig(newConfig); 519 verify(mWifiConfigManager).saveToStore(true); 520 521 // Verify data source content. 522 List<PasspointProvider> newProviders = mDataSource.getProviders(); 523 assertEquals(1, newProviders.size()); 524 assertEquals(newConfig, newProviders.get(0).getConfig()); 525 assertEquals(2, mDataSource.getProviderIndex()); 526 } 527 528 /** 529 * Verify that adding a provider will fail when failing to install certificates and 530 * key to the keystore. 531 * 532 * @throws Exception 533 */ 534 @Test 535 public void addProviderOnKeyInstallationFailiure() throws Exception { 536 PasspointConfiguration config = createTestConfigWithUserCredential(); 537 PasspointProvider provider = mock(PasspointProvider.class); 538 when(provider.installCertsAndKeys()).thenReturn(false); 539 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 540 eq(mSimAccessor), anyLong())).thenReturn(provider); 541 assertFalse(mManager.addOrUpdateProvider(config)); 542 } 543 544 /** 545 * Verify that removing a non-existing provider will fail. 546 * 547 * @throws Exception 548 */ 549 @Test 550 public void removeNonExistingProvider() throws Exception { 551 assertFalse(mManager.removeProvider(TEST_FQDN)); 552 } 553 554 /** 555 * Verify that an empty list will be returned when no providers are installed. 556 * 557 * @throws Exception 558 */ 559 @Test 560 public void matchProviderWithNoProvidersInstalled() throws Exception { 561 List<Pair<PasspointProvider, PasspointMatch>> result = 562 mManager.matchProvider(createTestScanResult()); 563 assertTrue(result.isEmpty()); 564 } 565 566 /** 567 * Verify that an empty list will be returned when ANQP entry doesn't exist in the cache. 568 * 569 * @throws Exception 570 */ 571 @Test 572 public void matchProviderWithAnqpCacheMissed() throws Exception { 573 addTestProvider(); 574 575 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); 576 List<Pair<PasspointProvider, PasspointMatch>> result = 577 mManager.matchProvider(createTestScanResult()); 578 // Verify that a request for ANQP elements is initiated. 579 verify(mAnqpRequestManager).requestANQPElements(eq(TEST_BSSID), any(ANQPNetworkKey.class), 580 anyBoolean(), anyBoolean()); 581 assertTrue(result.isEmpty()); 582 } 583 584 /** 585 * Verify that the returned list will contained an expected provider when a HomeProvider 586 * is matched. 587 * 588 * @throws Exception 589 */ 590 @Test 591 public void matchProviderAsHomeProvider() throws Exception { 592 PasspointProvider provider = addTestProvider(); 593 ANQPData entry = new ANQPData(mClock, null); 594 595 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 596 when(provider.match(anyMap())).thenReturn(PasspointMatch.HomeProvider); 597 List<Pair<PasspointProvider, PasspointMatch>> result = 598 mManager.matchProvider(createTestScanResult()); 599 assertEquals(1, result.size()); 600 assertEquals(PasspointMatch.HomeProvider, result.get(0).second); 601 } 602 603 /** 604 * Verify that the returned list will contained an expected provider when a RoamingProvider 605 * is matched. 606 * 607 * @throws Exception 608 */ 609 @Test 610 public void matchProviderAsRoamingProvider() throws Exception { 611 PasspointProvider provider = addTestProvider(); 612 ANQPData entry = new ANQPData(mClock, null); 613 614 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 615 when(provider.match(anyMap())).thenReturn(PasspointMatch.RoamingProvider); 616 List<Pair<PasspointProvider, PasspointMatch>> result = 617 mManager.matchProvider(createTestScanResult()); 618 assertEquals(1, result.size()); 619 assertEquals(PasspointMatch.RoamingProvider, result.get(0).second); 620 assertEquals(TEST_FQDN, provider.getConfig().getHomeSp().getFqdn()); 621 } 622 623 /** 624 * Verify that an empty list will be returned when there is no matching provider. 625 * 626 * @throws Exception 627 */ 628 @Test 629 public void matchProviderWithNoMatch() throws Exception { 630 PasspointProvider provider = addTestProvider(); 631 ANQPData entry = new ANQPData(mClock, null); 632 633 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 634 when(provider.match(anyMap())).thenReturn(PasspointMatch.None); 635 List<Pair<PasspointProvider, PasspointMatch>> result = 636 mManager.matchProvider(createTestScanResult()); 637 assertEquals(0, result.size()); 638 } 639 640 /** 641 * Verify the expectations for sweepCache. 642 * 643 * @throws Exception 644 */ 645 @Test 646 public void sweepCache() throws Exception { 647 mManager.sweepCache(); 648 verify(mAnqpCache).sweep(); 649 } 650 651 /** 652 * Verify that an empty map will be returned if ANQP elements are not cached for the given AP. 653 * 654 * @throws Exception 655 */ 656 @Test 657 public void getANQPElementsWithNoMatchFound() throws Exception { 658 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null); 659 assertTrue(mManager.getANQPElements(createTestScanResult()).isEmpty()); 660 } 661 662 /** 663 * Verify that an expected ANQP elements will be returned if ANQP elements are cached for the 664 * given AP. 665 * 666 * @throws Exception 667 */ 668 @Test 669 public void getANQPElementsWithMatchFound() throws Exception { 670 Map<ANQPElementType, ANQPElement> anqpElementMap = new HashMap<>(); 671 anqpElementMap.put(ANQPElementType.ANQPDomName, 672 new DomainNameElement(Arrays.asList(new String[] {"test.com"}))); 673 ANQPData entry = new ANQPData(mClock, anqpElementMap); 674 675 when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry); 676 assertEquals(anqpElementMap, mManager.getANQPElements(createTestScanResult())); 677 } 678 679 /** 680 * Verify that the provider list maintained by the PasspointManager after the list is updated 681 * in the data source. 682 * 683 * @throws Exception 684 */ 685 @Test 686 public void verifyProvidersAfterDataSourceUpdate() throws Exception { 687 // Update the provider list in the data source. 688 PasspointConfiguration config = createTestConfigWithUserCredential(); 689 PasspointProvider provider = createMockProvider(config); 690 List<PasspointProvider> providers = new ArrayList<>(); 691 providers.add(provider); 692 mDataSource.setProviders(providers); 693 694 // Verify the providers maintained by PasspointManager. 695 assertEquals(1, mManager.getProviderConfigs().size()); 696 assertEquals(config, mManager.getProviderConfigs().get(0)); 697 } 698 699 /** 700 * Verify that the provider index used by PasspointManager is updated after it is updated in 701 * the data source. 702 * 703 * @throws Exception 704 */ 705 @Test 706 public void verifyProviderIndexAfterDataSourceUpdate() throws Exception { 707 long providerIndex = 9; 708 mDataSource.setProviderIndex(providerIndex); 709 assertEquals(providerIndex, mDataSource.getProviderIndex()); 710 711 // Add a provider. 712 PasspointConfiguration config = createTestConfigWithUserCredential(); 713 PasspointProvider provider = createMockProvider(config); 714 // Verify the provider ID used to create the new provider. 715 when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), 716 eq(mSimAccessor), eq(providerIndex))).thenReturn(provider); 717 assertTrue(mManager.addOrUpdateProvider(config)); 718 verifyInstalledConfig(config); 719 verify(mWifiConfigManager).saveToStore(true); 720 reset(mWifiConfigManager); 721 } 722 723 /** 724 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 725 * adding a legacy Passpoint configuration containing a valid user credential. 726 * 727 * @throws Exception 728 */ 729 @Test 730 public void addLegacyPasspointConfigWithUserCredential() throws Exception { 731 // Test data. 732 String fqdn = "test.com"; 733 String friendlyName = "Friendly Name"; 734 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 735 String realm = "realm.com"; 736 String username = "username"; 737 String password = "password"; 738 byte[] base64EncodedPw = 739 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 740 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 741 String caCertificateAlias = "CaCert"; 742 743 // Setup WifiConfiguration for legacy Passpoint configuraiton. 744 WifiConfiguration wifiConfig = new WifiConfiguration(); 745 wifiConfig.FQDN = fqdn; 746 wifiConfig.providerFriendlyName = friendlyName; 747 wifiConfig.roamingConsortiumIds = rcOIs; 748 wifiConfig.enterpriseConfig.setIdentity(username); 749 wifiConfig.enterpriseConfig.setPassword(password); 750 wifiConfig.enterpriseConfig.setRealm(realm); 751 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 752 wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); 753 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 754 755 // Setup expected {@link PasspointConfiguration} 756 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 757 HomeSp homeSp = new HomeSp(); 758 homeSp.setFqdn(fqdn); 759 homeSp.setFriendlyName(friendlyName); 760 homeSp.setRoamingConsortiumOis(rcOIs); 761 passpointConfig.setHomeSp(homeSp); 762 Credential credential = new Credential(); 763 Credential.UserCredential userCredential = new Credential.UserCredential(); 764 userCredential.setUsername(username); 765 userCredential.setPassword(encodedPasswordStr); 766 userCredential.setEapType(EAPConstants.EAP_TTLS); 767 userCredential.setNonEapInnerMethod("PAP"); 768 credential.setUserCredential(userCredential); 769 credential.setRealm(realm); 770 passpointConfig.setCredential(credential); 771 772 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 773 verifyInstalledConfig(passpointConfig); 774 } 775 776 /** 777 * Verify that adding a legacy Passpoint configuration containing user credential will 778 * fail when client certificate is not provided. 779 * 780 * @throws Exception 781 */ 782 @Test 783 public void addLegacyPasspointConfigWithUserCredentialWithoutCaCert() throws Exception { 784 // Test data. 785 String fqdn = "test.com"; 786 String friendlyName = "Friendly Name"; 787 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 788 String realm = "realm.com"; 789 String username = "username"; 790 String password = "password"; 791 byte[] base64EncodedPw = 792 Base64.encode(password.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); 793 String encodedPasswordStr = new String(base64EncodedPw, StandardCharsets.UTF_8); 794 795 // Setup WifiConfiguration for legacy Passpoint configuraiton. 796 WifiConfiguration wifiConfig = new WifiConfiguration(); 797 wifiConfig.FQDN = fqdn; 798 wifiConfig.providerFriendlyName = friendlyName; 799 wifiConfig.roamingConsortiumIds = rcOIs; 800 wifiConfig.enterpriseConfig.setIdentity(username); 801 wifiConfig.enterpriseConfig.setPassword(password); 802 wifiConfig.enterpriseConfig.setRealm(realm); 803 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 804 wifiConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP); 805 806 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 807 } 808 809 /** 810 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 811 * adding a legacy Passpoint configuration containing a valid SIM credential. 812 * 813 * @throws Exception 814 */ 815 @Test 816 public void addLegacyPasspointConfigWithSimCredential() throws Exception { 817 // Test data. 818 String fqdn = "test.com"; 819 String friendlyName = "Friendly Name"; 820 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 821 String realm = "realm.com"; 822 String imsi = "1234"; 823 824 // Setup WifiConfiguration for legacy Passpoint configuraiton. 825 WifiConfiguration wifiConfig = new WifiConfiguration(); 826 wifiConfig.FQDN = fqdn; 827 wifiConfig.providerFriendlyName = friendlyName; 828 wifiConfig.roamingConsortiumIds = rcOIs; 829 wifiConfig.enterpriseConfig.setRealm(realm); 830 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); 831 wifiConfig.enterpriseConfig.setPlmn(imsi); 832 833 // Setup expected {@link PasspointConfiguration} 834 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 835 HomeSp homeSp = new HomeSp(); 836 homeSp.setFqdn(fqdn); 837 homeSp.setFriendlyName(friendlyName); 838 homeSp.setRoamingConsortiumOis(rcOIs); 839 passpointConfig.setHomeSp(homeSp); 840 Credential credential = new Credential(); 841 Credential.SimCredential simCredential = new Credential.SimCredential(); 842 simCredential.setEapType(EAPConstants.EAP_SIM); 843 simCredential.setImsi(imsi); 844 credential.setSimCredential(simCredential); 845 credential.setRealm(realm); 846 passpointConfig.setCredential(credential); 847 848 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 849 verifyInstalledConfig(passpointConfig); 850 } 851 852 /** 853 * Verify that a PasspointProvider with expected PasspointConfiguration will be installed when 854 * adding a legacy Passpoint configuration containing a valid certificate credential. 855 * 856 * @throws Exception 857 */ 858 @Test 859 public void addLegacyPasspointConfigWithCertCredential() throws Exception { 860 // Test data. 861 String fqdn = "test.com"; 862 String friendlyName = "Friendly Name"; 863 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 864 String realm = "realm.com"; 865 String caCertificateAlias = "CaCert"; 866 String clientCertificateAlias = "ClientCert"; 867 868 // Setup WifiConfiguration for legacy Passpoint configuraiton. 869 WifiConfiguration wifiConfig = new WifiConfiguration(); 870 wifiConfig.FQDN = fqdn; 871 wifiConfig.providerFriendlyName = friendlyName; 872 wifiConfig.roamingConsortiumIds = rcOIs; 873 wifiConfig.enterpriseConfig.setRealm(realm); 874 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 875 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 876 wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); 877 878 // Setup expected {@link PasspointConfiguration} 879 PasspointConfiguration passpointConfig = new PasspointConfiguration(); 880 HomeSp homeSp = new HomeSp(); 881 homeSp.setFqdn(fqdn); 882 homeSp.setFriendlyName(friendlyName); 883 homeSp.setRoamingConsortiumOis(rcOIs); 884 passpointConfig.setHomeSp(homeSp); 885 Credential credential = new Credential(); 886 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 887 certCredential.setCertType(Credential.CertificateCredential.CERT_TYPE_X509V3); 888 credential.setCertCredential(certCredential); 889 credential.setRealm(realm); 890 passpointConfig.setCredential(credential); 891 892 assertTrue(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 893 verifyInstalledConfig(passpointConfig); 894 } 895 896 /** 897 * Verify that adding a legacy Passpoint configuration containing certificate credential will 898 * fail when CA certificate is not provided. 899 * 900 * @throws Exception 901 */ 902 @Test 903 public void addLegacyPasspointConfigWithCertCredentialWithoutCaCert() throws Exception { 904 // Test data. 905 String fqdn = "test.com"; 906 String friendlyName = "Friendly Name"; 907 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 908 String realm = "realm.com"; 909 String clientCertificateAlias = "ClientCert"; 910 911 // Setup WifiConfiguration for legacy Passpoint configuraiton. 912 WifiConfiguration wifiConfig = new WifiConfiguration(); 913 wifiConfig.FQDN = fqdn; 914 wifiConfig.providerFriendlyName = friendlyName; 915 wifiConfig.roamingConsortiumIds = rcOIs; 916 wifiConfig.enterpriseConfig.setRealm(realm); 917 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 918 wifiConfig.enterpriseConfig.setClientCertificateAlias(clientCertificateAlias); 919 920 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 921 } 922 923 /** 924 * Verify that adding a legacy Passpoint configuration containing certificate credential will 925 * fail when client certificate is not provided. 926 * 927 * @throws Exception 928 */ 929 @Test 930 public void addLegacyPasspointConfigWithCertCredentialWithoutClientCert() throws Exception { 931 // Test data. 932 String fqdn = "test.com"; 933 String friendlyName = "Friendly Name"; 934 long[] rcOIs = new long[] {0x1234L, 0x2345L}; 935 String realm = "realm.com"; 936 String caCertificateAlias = "CaCert"; 937 938 // Setup WifiConfiguration for legacy Passpoint configuraiton. 939 WifiConfiguration wifiConfig = new WifiConfiguration(); 940 wifiConfig.FQDN = fqdn; 941 wifiConfig.providerFriendlyName = friendlyName; 942 wifiConfig.roamingConsortiumIds = rcOIs; 943 wifiConfig.enterpriseConfig.setRealm(realm); 944 wifiConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); 945 wifiConfig.enterpriseConfig.setCaCertificateAlias(caCertificateAlias); 946 947 assertFalse(PasspointManager.addLegacyPasspointConfig(wifiConfig)); 948 } 949} 950