1 /* 2 * Copyright (C) 2009 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 android.net.wifi.cts; 18 19 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.pm.PackageManager; 25 import android.net.NetworkInfo; 26 import android.net.wifi.ScanResult; 27 import android.net.wifi.WifiConfiguration; 28 import android.net.wifi.WifiConfiguration.Status; 29 import android.net.wifi.WifiManager; 30 import android.net.wifi.WifiManager.TxPacketCountListener; 31 import android.net.wifi.WifiManager.WifiLock; 32 import android.net.wifi.hotspot2.PasspointConfiguration; 33 import android.net.wifi.hotspot2.pps.Credential; 34 import android.net.wifi.hotspot2.pps.HomeSp; 35 import android.os.SystemClock; 36 import android.provider.Settings; 37 import android.test.AndroidTestCase; 38 import android.util.Log; 39 40 import com.android.compatibility.common.util.WifiConfigCreator; 41 42 import java.net.HttpURLConnection; 43 import java.net.URL; 44 import java.security.MessageDigest; 45 import java.security.cert.X509Certificate; 46 import java.util.HashSet; 47 import java.util.List; 48 import java.util.Set; 49 import java.util.concurrent.TimeUnit; 50 import java.util.concurrent.atomic.AtomicInteger; 51 52 public class WifiManagerTest extends AndroidTestCase { 53 private static class MySync { 54 int expectedState = STATE_NULL; 55 } 56 57 private WifiManager mWifiManager; 58 private WifiLock mWifiLock; 59 private static MySync mMySync; 60 private List<ScanResult> mScanResults = null; 61 private NetworkInfo mNetworkInfo; 62 private Object mLOHSLock = new Object(); 63 64 // Please refer to WifiManager 65 private static final int MIN_RSSI = -100; 66 private static final int MAX_RSSI = -55; 67 68 private static final int STATE_NULL = 0; 69 private static final int STATE_WIFI_CHANGING = 1; 70 private static final int STATE_WIFI_ENABLED = 2; 71 private static final int STATE_WIFI_DISABLED = 3; 72 private static final int STATE_SCANNING = 4; 73 private static final int STATE_SCAN_DONE = 5; 74 75 private static final String TAG = "WifiManagerTest"; 76 private static final String SSID1 = "\"WifiManagerTest\""; 77 private static final String SSID2 = "\"WifiManagerTestModified\""; 78 private static final String PROXY_TEST_SSID = "SomeProxyAp"; 79 private static final String ADD_NETWORK_EXCEPTION_SUBSTR = "addNetwork"; 80 // A full single scan duration is about 6-7 seconds if country code is set 81 // to US. If country code is set to world mode (00), we would expect a scan 82 // duration of roughly 8 seconds. So we set scan timeout as 9 seconds here. 83 private static final int SCAN_TIMEOUT_MSEC = 9000; 84 private static final int TIMEOUT_MSEC = 6000; 85 private static final int WAIT_MSEC = 60; 86 private static final int DURATION = 10000; 87 private static final int WIFI_SCAN_TEST_INTERVAL_MILLIS = 60 * 1000; 88 private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000; 89 private static final int WIFI_SCAN_TEST_ITERATIONS = 5; 90 91 private static final String TEST_PAC_URL = "http://www.example.com/proxy.pac"; 92 93 private IntentFilter mIntentFilter; 94 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 95 @Override 96 public void onReceive(Context context, Intent intent) { 97 final String action = intent.getAction(); 98 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 99 100 synchronized (mMySync) { 101 if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) { 102 mScanResults = mWifiManager.getScanResults(); 103 } else { 104 mScanResults = null; 105 } 106 mMySync.expectedState = STATE_SCAN_DONE; 107 mMySync.notifyAll(); 108 } 109 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 110 int newState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 111 WifiManager.WIFI_STATE_UNKNOWN); 112 synchronized (mMySync) { 113 if (newState == WifiManager.WIFI_STATE_ENABLED) { 114 Log.d(TAG, "*** New WiFi state is ENABLED ***"); 115 mMySync.expectedState = STATE_WIFI_ENABLED; 116 mMySync.notifyAll(); 117 } else if (newState == WifiManager.WIFI_STATE_DISABLED) { 118 Log.d(TAG, "*** New WiFi state is DISABLED ***"); 119 mMySync.expectedState = STATE_WIFI_DISABLED; 120 mMySync.notifyAll(); 121 } 122 } 123 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 124 synchronized (mMySync) { 125 mNetworkInfo = 126 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 127 if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED) 128 mMySync.notifyAll(); 129 } 130 } 131 } 132 }; 133 134 @Override 135 protected void setUp() throws Exception { 136 super.setUp(); 137 if (!WifiFeature.isWifiSupported(getContext())) { 138 // skip the test if WiFi is not supported 139 return; 140 } 141 mMySync = new MySync(); 142 mIntentFilter = new IntentFilter(); 143 mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 144 mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 145 mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 146 mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 147 mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 148 mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 149 mIntentFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); 150 mIntentFilter.addAction(WifiManager.ACTION_PICK_WIFI_NETWORK); 151 152 mContext.registerReceiver(mReceiver, mIntentFilter); 153 mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 154 assertNotNull(mWifiManager); 155 mWifiLock = mWifiManager.createWifiLock(TAG); 156 mWifiLock.acquire(); 157 if (!mWifiManager.isWifiEnabled()) 158 setWifiEnabled(true); 159 Thread.sleep(DURATION); 160 assertTrue(mWifiManager.isWifiEnabled()); 161 synchronized (mMySync) { 162 mMySync.expectedState = STATE_NULL; 163 } 164 } 165 166 @Override 167 protected void tearDown() throws Exception { 168 if (!WifiFeature.isWifiSupported(getContext())) { 169 // skip the test if WiFi is not supported 170 super.tearDown(); 171 return; 172 } 173 if (!mWifiManager.isWifiEnabled()) 174 setWifiEnabled(true); 175 mWifiLock.release(); 176 mContext.unregisterReceiver(mReceiver); 177 Thread.sleep(DURATION); 178 super.tearDown(); 179 } 180 181 private void setWifiEnabled(boolean enable) throws Exception { 182 synchronized (mMySync) { 183 if (mWifiManager.isWifiEnabled() != enable) { 184 // the new state is different, we expect it to change 185 mMySync.expectedState = STATE_WIFI_CHANGING; 186 } else { 187 mMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 188 } 189 // now trigger the change 190 assertTrue(mWifiManager.setWifiEnabled(enable)); 191 waitForExpectedWifiState(enable); 192 } 193 } 194 195 private void waitForExpectedWifiState(boolean enabled) throws InterruptedException { 196 synchronized (mMySync) { 197 long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; 198 int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 199 while (System.currentTimeMillis() < timeout 200 && mMySync.expectedState != expected) { 201 mMySync.wait(WAIT_MSEC); 202 } 203 } 204 } 205 206 // Get the current scan status from sticky broadcast. 207 private boolean isScanCurrentlyAvailable() { 208 boolean isAvailable = false; 209 IntentFilter intentFilter = new IntentFilter(); 210 intentFilter.addAction(WifiManager.WIFI_SCAN_AVAILABLE); 211 Intent intent = mContext.registerReceiver(null, intentFilter); 212 assertNotNull(intent); 213 if (intent.getAction().equals(WifiManager.WIFI_SCAN_AVAILABLE)) { 214 int state = intent.getIntExtra( 215 WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_UNKNOWN); 216 if (state == WifiManager.WIFI_STATE_ENABLED) { 217 isAvailable = true; 218 } else if (state == WifiManager.WIFI_STATE_DISABLED) { 219 isAvailable = false; 220 } 221 } 222 return isAvailable; 223 } 224 225 private void startScan() throws Exception { 226 synchronized (mMySync) { 227 mMySync.expectedState = STATE_SCANNING; 228 mScanResults = null; 229 assertTrue(mWifiManager.startScan()); 230 long timeout = System.currentTimeMillis() + SCAN_TIMEOUT_MSEC; 231 while (System.currentTimeMillis() < timeout && mMySync.expectedState == STATE_SCANNING) 232 mMySync.wait(WAIT_MSEC); 233 } 234 } 235 236 private void connectWifi() throws Exception { 237 synchronized (mMySync) { 238 if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED) return; 239 assertTrue(mWifiManager.reconnect()); 240 long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; 241 while (System.currentTimeMillis() < timeout 242 && mNetworkInfo.getState() != NetworkInfo.State.CONNECTED) 243 mMySync.wait(WAIT_MSEC); 244 assertTrue(mNetworkInfo.getState() == NetworkInfo.State.CONNECTED); 245 } 246 } 247 248 private boolean existSSID(String ssid) { 249 for (final WifiConfiguration w : mWifiManager.getConfiguredNetworks()) { 250 if (w.SSID.equals(ssid)) 251 return true; 252 } 253 return false; 254 } 255 256 private int findConfiguredNetworks(String SSID, List<WifiConfiguration> networks) { 257 for (final WifiConfiguration w : networks) { 258 if (w.SSID.equals(SSID)) 259 return networks.indexOf(w); 260 } 261 return -1; 262 } 263 264 /** 265 * test point of wifiManager actions: 266 * 1.reconnect 267 * 2.reassociate 268 * 3.disconnect 269 * 4.createWifiLock 270 */ 271 public void testWifiManagerActions() throws Exception { 272 if (!WifiFeature.isWifiSupported(getContext())) { 273 // skip the test if WiFi is not supported 274 return; 275 } 276 assertTrue(mWifiManager.reconnect()); 277 assertTrue(mWifiManager.reassociate()); 278 assertTrue(mWifiManager.disconnect()); 279 final String TAG = "Test"; 280 assertNotNull(mWifiManager.createWifiLock(TAG)); 281 assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 282 } 283 284 /** 285 * Test wifi scanning when location scan is turned off. 286 */ 287 public void testWifiManagerScanWhenWifiOffLocationTurnedOn() throws Exception { 288 if (!WifiFeature.isWifiSupported(getContext())) { 289 // skip the test if WiFi is not supported 290 return; 291 } 292 if (!hasLocationFeature()) { 293 Log.d(TAG, "Skipping test as location is not supported"); 294 return; 295 } 296 if (!isLocationEnabled()) { 297 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 298 + " empty when location is disabled!"); 299 } 300 setWifiEnabled(false); 301 Thread.sleep(DURATION); 302 startScan(); 303 if (mWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) { 304 // Make sure at least one AP is found. 305 assertNotNull("mScanResult should not be null!", mScanResults); 306 assertFalse("empty scan results!", mScanResults.isEmpty()); 307 } else { 308 // Make sure no scan results are available. 309 assertNull("mScanResult should be null!", mScanResults); 310 } 311 final String TAG = "Test"; 312 assertNotNull(mWifiManager.createWifiLock(TAG)); 313 assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 314 } 315 316 /** 317 * test point of wifiManager properties: 318 * 1.enable properties 319 * 2.DhcpInfo properties 320 * 3.wifi state 321 * 4.ConnectionInfo 322 */ 323 public void testWifiManagerProperties() throws Exception { 324 if (!WifiFeature.isWifiSupported(getContext())) { 325 // skip the test if WiFi is not supported 326 return; 327 } 328 setWifiEnabled(true); 329 assertTrue(mWifiManager.isWifiEnabled()); 330 assertNotNull(mWifiManager.getDhcpInfo()); 331 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWifiManager.getWifiState()); 332 mWifiManager.getConnectionInfo(); 333 setWifiEnabled(false); 334 assertFalse(mWifiManager.isWifiEnabled()); 335 } 336 337 /** 338 * Test WiFi scan timestamp - fails when WiFi scan timestamps are inconsistent with 339 * {@link SystemClock#elapsedRealtime()} on device.<p> 340 * To run this test in cts-tradefed: 341 * run cts --class android.net.wifi.cts.WifiManagerTest --method testWifiScanTimestamp 342 */ 343 public void testWifiScanTimestamp() throws Exception { 344 if (!WifiFeature.isWifiSupported(getContext())) { 345 Log.d(TAG, "Skipping test as WiFi is not supported"); 346 return; 347 } 348 if (!hasLocationFeature()) { 349 Log.d(TAG, "Skipping test as location is not supported"); 350 return; 351 } 352 if (!isLocationEnabled()) { 353 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 354 + " empty when location is disabled!"); 355 } 356 if (!mWifiManager.isWifiEnabled()) { 357 setWifiEnabled(true); 358 } 359 // Scan multiple times to make sure scan timestamps increase with device timestamp. 360 for (int i = 0; i < WIFI_SCAN_TEST_ITERATIONS; ++i) { 361 startScan(); 362 // Make sure at least one AP is found. 363 assertTrue("mScanResult should not be null. This may be due to a scan timeout", 364 mScanResults != null); 365 assertFalse("empty scan results!", mScanResults.isEmpty()); 366 long nowMillis = SystemClock.elapsedRealtime(); 367 // Keep track of how many APs are fresh in one scan. 368 int numFreshAps = 0; 369 for (ScanResult result : mScanResults) { 370 long scanTimeMillis = TimeUnit.MICROSECONDS.toMillis(result.timestamp); 371 if (Math.abs(nowMillis - scanTimeMillis) < WIFI_SCAN_TEST_CACHE_DELAY_MILLIS) { 372 numFreshAps++; 373 } 374 } 375 // At least half of the APs in the scan should be fresh. 376 int numTotalAps = mScanResults.size(); 377 String msg = "Stale AP count: " + (numTotalAps - numFreshAps) + ", fresh AP count: " 378 + numFreshAps; 379 assertTrue(msg, numFreshAps * 2 >= mScanResults.size()); 380 if (i < WIFI_SCAN_TEST_ITERATIONS - 1) { 381 // Wait before running next iteration. 382 Thread.sleep(WIFI_SCAN_TEST_INTERVAL_MILLIS); 383 } 384 } 385 } 386 387 // Return true if location is enabled. 388 private boolean isLocationEnabled() { 389 return Settings.Secure.getInt(getContext().getContentResolver(), 390 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) != 391 Settings.Secure.LOCATION_MODE_OFF; 392 } 393 394 // Returns true if the device has location feature. 395 private boolean hasLocationFeature() { 396 return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION); 397 } 398 399 /** 400 * test point of wifiManager NetWork: 401 * 1.add NetWork 402 * 2.update NetWork 403 * 3.remove NetWork 404 * 4.enable NetWork 405 * 5.disable NetWork 406 * 6.configured Networks 407 * 7.save configure; 408 */ 409 public void testWifiManagerNetWork() throws Exception { 410 if (!WifiFeature.isWifiSupported(getContext())) { 411 // skip the test if WiFi is not supported 412 return; 413 } 414 415 // store the list of enabled networks, so they can be re-enabled after test completes 416 Set<String> enabledSsids = getEnabledNetworks(mWifiManager.getConfiguredNetworks()); 417 try { 418 WifiConfiguration wifiConfiguration; 419 // add a WifiConfig 420 final int notExist = -1; 421 List<WifiConfiguration> wifiConfiguredNetworks = mWifiManager.getConfiguredNetworks(); 422 int pos = findConfiguredNetworks(SSID1, wifiConfiguredNetworks); 423 if (notExist != pos) { 424 wifiConfiguration = wifiConfiguredNetworks.get(pos); 425 mWifiManager.removeNetwork(wifiConfiguration.networkId); 426 } 427 pos = findConfiguredNetworks(SSID1, wifiConfiguredNetworks); 428 assertEquals(notExist, pos); 429 final int size = wifiConfiguredNetworks.size(); 430 431 wifiConfiguration = new WifiConfiguration(); 432 wifiConfiguration.SSID = SSID1; 433 wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 434 int netId = mWifiManager.addNetwork(wifiConfiguration); 435 assertTrue(existSSID(SSID1)); 436 437 wifiConfiguredNetworks = mWifiManager.getConfiguredNetworks(); 438 assertEquals(size + 1, wifiConfiguredNetworks.size()); 439 pos = findConfiguredNetworks(SSID1, wifiConfiguredNetworks); 440 assertTrue(notExist != pos); 441 442 // Enable & disable network 443 boolean disableOthers = true; 444 assertTrue(mWifiManager.enableNetwork(netId, disableOthers)); 445 wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos); 446 assertEquals(Status.ENABLED, wifiConfiguration.status); 447 448 assertTrue(mWifiManager.disableNetwork(netId)); 449 wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos); 450 assertEquals(Status.DISABLED, wifiConfiguration.status); 451 452 // Update a WifiConfig 453 wifiConfiguration = wifiConfiguredNetworks.get(pos); 454 wifiConfiguration.SSID = SSID2; 455 netId = mWifiManager.updateNetwork(wifiConfiguration); 456 assertFalse(existSSID(SSID1)); 457 assertTrue(existSSID(SSID2)); 458 459 // Remove a WifiConfig 460 assertTrue(mWifiManager.removeNetwork(netId)); 461 assertFalse(mWifiManager.removeNetwork(notExist)); 462 assertFalse(existSSID(SSID1)); 463 assertFalse(existSSID(SSID2)); 464 465 assertTrue(mWifiManager.saveConfiguration()); 466 } finally { 467 reEnableNetworks(enabledSsids, mWifiManager.getConfiguredNetworks()); 468 mWifiManager.saveConfiguration(); 469 } 470 } 471 472 /** 473 * Verifies that addNetwork() fails for WifiConfigurations containing a non-null http proxy when 474 * the caller doesn't have OVERRIDE_WIFI_CONFIG permission, DeviceOwner or ProfileOwner device 475 * management policies 476 */ 477 public void testSetHttpProxy_PermissionFail() throws Exception { 478 if (!WifiFeature.isWifiSupported(getContext())) { 479 // skip the test if WiFi is not supported 480 return; 481 } 482 WifiConfigCreator configCreator = new WifiConfigCreator(getContext()); 483 boolean exceptionThrown = false; 484 try { 485 configCreator.addHttpProxyNetworkVerifyAndRemove( 486 PROXY_TEST_SSID, TEST_PAC_URL); 487 } catch (IllegalStateException e) { 488 // addHttpProxyNetworkVerifyAndRemove throws three IllegalStateException, 489 // expect it to throw for the addNetwork operation 490 if (e.getMessage().contains(ADD_NETWORK_EXCEPTION_SUBSTR)) { 491 exceptionThrown = true; 492 } 493 } 494 assertTrue(exceptionThrown); 495 } 496 497 private Set<String> getEnabledNetworks(List<WifiConfiguration> configuredNetworks) { 498 Set<String> ssids = new HashSet<String>(); 499 for (WifiConfiguration wifiConfig : configuredNetworks) { 500 if (Status.ENABLED == wifiConfig.status || Status.CURRENT == wifiConfig.status) { 501 ssids.add(wifiConfig.SSID); 502 Log.i(TAG, String.format("remembering enabled network %s", wifiConfig.SSID)); 503 } 504 } 505 return ssids; 506 } 507 508 private void reEnableNetworks(Set<String> enabledSsids, 509 List<WifiConfiguration> configuredNetworks) { 510 for (WifiConfiguration wifiConfig : configuredNetworks) { 511 if (enabledSsids.contains(wifiConfig.SSID)) { 512 mWifiManager.enableNetwork(wifiConfig.networkId, false); 513 Log.i(TAG, String.format("re-enabling network %s", wifiConfig.SSID)); 514 } 515 } 516 } 517 518 public void testSignal() { 519 if (!WifiFeature.isWifiSupported(getContext())) { 520 // skip the test if WiFi is not supported 521 return; 522 } 523 final int numLevels = 9; 524 int expectLevel = 0; 525 assertEquals(expectLevel, WifiManager.calculateSignalLevel(MIN_RSSI, numLevels)); 526 assertEquals(numLevels - 1, WifiManager.calculateSignalLevel(MAX_RSSI, numLevels)); 527 expectLevel = 4; 528 assertEquals(expectLevel, WifiManager.calculateSignalLevel((MIN_RSSI + MAX_RSSI) / 2, 529 numLevels)); 530 int rssiA = 4; 531 int rssiB = 5; 532 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) < 0); 533 rssiB = 4; 534 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) == 0); 535 rssiA = 5; 536 rssiB = 4; 537 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) > 0); 538 } 539 540 private int getTxPacketCount() throws Exception { 541 final AtomicInteger ret = new AtomicInteger(-1); 542 543 mWifiManager.getTxPacketCount(new TxPacketCountListener() { 544 @Override 545 public void onSuccess(int count) { 546 ret.set(count); 547 } 548 @Override 549 public void onFailure(int reason) { 550 ret.set(0); 551 } 552 }); 553 554 long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; 555 while (ret.get() < 0 && System.currentTimeMillis() < timeout) 556 Thread.sleep(WAIT_MSEC); 557 assertTrue(ret.get() >= 0); 558 return ret.get(); 559 } 560 561 /** 562 * The new WiFi watchdog requires kernel/driver to export some packet loss 563 * counters. This CTS tests whether those counters are correctly exported. 564 * To pass this CTS test, a connected WiFi link is required. 565 */ 566 public void testWifiWatchdog() throws Exception { 567 if (!WifiFeature.isWifiSupported(getContext())) { 568 // skip the test if WiFi is not supported 569 return; 570 } 571 // Make sure WiFi is enabled 572 if (!mWifiManager.isWifiEnabled()) { 573 setWifiEnabled(true); 574 Thread.sleep(DURATION); 575 } 576 assertTrue(mWifiManager.isWifiEnabled()); 577 578 // give the test a chance to autoconnect 579 Thread.sleep(DURATION); 580 if (mNetworkInfo.getState() != NetworkInfo.State.CONNECTED) { 581 // this test requires a connectable network be configured 582 fail("This test requires a wifi network connection."); 583 } 584 585 // This will generate a distinct stack trace if the initial connection fails. 586 connectWifi(); 587 588 int i = 0; 589 for (; i < 15; i++) { 590 // Wait for a WiFi connection 591 connectWifi(); 592 593 // Read TX packet counter 594 int txcount1 = getTxPacketCount(); 595 596 // Do some network operations 597 HttpURLConnection connection = null; 598 try { 599 URL url = new URL("http://www.google.com/"); 600 connection = (HttpURLConnection) url.openConnection(); 601 connection.setInstanceFollowRedirects(false); 602 connection.setConnectTimeout(TIMEOUT_MSEC); 603 connection.setReadTimeout(TIMEOUT_MSEC); 604 connection.setUseCaches(false); 605 connection.getInputStream(); 606 } catch (Exception e) { 607 // ignore 608 } finally { 609 if (connection != null) connection.disconnect(); 610 } 611 612 // Read TX packet counter again and make sure it increases 613 int txcount2 = getTxPacketCount(); 614 615 if (txcount2 > txcount1) { 616 break; 617 } else { 618 Thread.sleep(DURATION); 619 } 620 } 621 assertTrue(i < 15); 622 } 623 624 /** 625 * Verify Passpoint configuration management APIs (add, remove, get) for a Passpoint 626 * configuration with an user credential. 627 * 628 * @throws Exception 629 */ 630 public void testAddPasspointConfigWithUserCredential() throws Exception { 631 if (!WifiFeature.isWifiSupported(getContext())) { 632 // skip the test if WiFi is not supported 633 return; 634 } 635 testAddPasspointConfig(generatePasspointConfig(generateUserCredential())); 636 } 637 638 /** 639 * Verify Passpoint configuration management APIs (add, remove, get) for a Passpoint 640 * configuration with a certificate credential. 641 * 642 * @throws Exception 643 */ 644 public void testAddPasspointConfigWithCertCredential() throws Exception { 645 if (!WifiFeature.isWifiSupported(getContext())) { 646 // skip the test if WiFi is not supported 647 return; 648 } 649 testAddPasspointConfig(generatePasspointConfig(generateCertCredential())); 650 } 651 652 /** 653 * Verify Passpoint configuration management APIs (add, remove, get) for a Passpoint 654 * configuration with a SIm credential. 655 * 656 * @throws Exception 657 */ 658 public void testAddPasspointConfigWithSimCredential() throws Exception { 659 if (!WifiFeature.isWifiSupported(getContext())) { 660 // skip the test if WiFi is not supported 661 return; 662 } 663 testAddPasspointConfig(generatePasspointConfig(generateSimCredential())); 664 } 665 666 /** 667 * Helper function for generating a {@link PasspointConfiguration} for testing. 668 * 669 * @return {@link PasspointConfiguration} 670 */ 671 private PasspointConfiguration generatePasspointConfig(Credential credential) { 672 PasspointConfiguration config = new PasspointConfiguration(); 673 config.setCredential(credential); 674 675 // Setup HomeSp. 676 HomeSp homeSp = new HomeSp(); 677 homeSp.setFqdn("Test.com"); 678 homeSp.setFriendlyName("Test Provider"); 679 homeSp.setRoamingConsortiumOis(new long[] {0x11223344}); 680 config.setHomeSp(homeSp); 681 682 return config; 683 } 684 685 /** 686 * Helper function for generating an user credential for testing. 687 * 688 * @return {@link Credential} 689 */ 690 private Credential generateUserCredential() { 691 Credential credential = new Credential(); 692 credential.setRealm("test.net"); 693 Credential.UserCredential userCred = new Credential.UserCredential(); 694 userCred.setEapType(21 /* EAP_TTLS */); 695 userCred.setUsername("username"); 696 userCred.setPassword("password"); 697 userCred.setNonEapInnerMethod("PAP"); 698 credential.setUserCredential(userCred); 699 credential.setCaCertificate(FakeKeys.CA_PUBLIC_CERT); 700 return credential; 701 } 702 703 /** 704 * Helper function for generating a certificate credential for testing. 705 * 706 * @return {@link Credential} 707 */ 708 private Credential generateCertCredential() throws Exception { 709 Credential credential = new Credential(); 710 credential.setRealm("test.net"); 711 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 712 certCredential.setCertType("x509v3"); 713 certCredential.setCertSha256Fingerprint( 714 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); 715 credential.setCertCredential(certCredential); 716 credential.setCaCertificate(FakeKeys.CA_PUBLIC_CERT); 717 credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT}); 718 credential.setClientPrivateKey(FakeKeys.RSA_KEY1); 719 return credential; 720 } 721 722 /** 723 * Helper function for generating a SIM credential for testing. 724 * 725 * @return {@link Credential} 726 */ 727 private Credential generateSimCredential() throws Exception { 728 Credential credential = new Credential(); 729 credential.setRealm("test.net"); 730 Credential.SimCredential simCredential = new Credential.SimCredential(); 731 simCredential.setImsi("1234*"); 732 simCredential.setEapType(18 /* EAP_SIM */); 733 credential.setSimCredential(simCredential); 734 return credential; 735 } 736 737 /** 738 * Helper function verifying Passpoint configuration management APIs (add, remove, get) for 739 * a given configuration. 740 * 741 * @param config The configuration to test with 742 */ 743 private void testAddPasspointConfig(PasspointConfiguration config) throws Exception { 744 try { 745 746 // obtain number of passpoint networks already present in device (preloaded) 747 List<PasspointConfiguration> preConfigList = mWifiManager.getPasspointConfigurations(); 748 int numOfNetworks = preConfigList.size(); 749 750 // add new (test) configuration 751 mWifiManager.addOrUpdatePasspointConfiguration(config); 752 753 // Certificates and keys will be set to null after it is installed to the KeyStore by 754 // WifiManager. Reset them in the expected config so that it can be used to compare 755 // against the retrieved config. 756 config.getCredential().setCaCertificate(null); 757 config.getCredential().setClientCertificateChain(null); 758 config.getCredential().setClientPrivateKey(null); 759 760 // retrieve the configuration and verify it. The retrieved list may not be in order - 761 // check all configs to see if any match 762 List<PasspointConfiguration> configList = mWifiManager.getPasspointConfigurations(); 763 assertEquals(numOfNetworks + 1, configList.size()); 764 765 boolean anyMatch = false; 766 for (PasspointConfiguration passpointConfiguration : configList) { 767 if (passpointConfiguration.equals(config)) { 768 anyMatch = true; 769 break; 770 } 771 } 772 assertTrue(anyMatch); 773 774 // remove the (test) configuration and verify number of installed configurations 775 mWifiManager.removePasspointConfiguration(config.getHomeSp().getFqdn()); 776 assertEquals(mWifiManager.getPasspointConfigurations().size(), numOfNetworks); 777 } catch (UnsupportedOperationException e) { 778 // Passpoint build config |config_wifi_hotspot2_enabled| is disabled, so noop. 779 } 780 } 781 782 public class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback { 783 Object hotspotLock; 784 WifiManager.LocalOnlyHotspotReservation reservation = null; 785 boolean onStartedCalled = false; 786 boolean onStoppedCalled = false; 787 boolean onFailedCalled = false; 788 int failureReason = -1; 789 790 TestLocalOnlyHotspotCallback(Object lock) { 791 hotspotLock = lock; 792 } 793 794 @Override 795 public void onStarted(WifiManager.LocalOnlyHotspotReservation r) { 796 synchronized (hotspotLock) { 797 reservation = r; 798 onStartedCalled = true; 799 hotspotLock.notify(); 800 } 801 } 802 803 @Override 804 public void onStopped() { 805 synchronized (hotspotLock) { 806 onStoppedCalled = true; 807 hotspotLock.notify(); 808 } 809 } 810 811 @Override 812 public void onFailed(int reason) { 813 synchronized (hotspotLock) { 814 onFailedCalled = true; 815 failureReason = reason; 816 hotspotLock.notify(); 817 } 818 } 819 } 820 821 private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() { 822 // Location mode must be enabled for this test 823 if (!isLocationEnabled()) { 824 fail("Please enable location for this test"); 825 } 826 827 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock); 828 synchronized (mLOHSLock) { 829 try { 830 mWifiManager.startLocalOnlyHotspot(callback, null); 831 // now wait for callback 832 mLOHSLock.wait(DURATION); 833 } catch (InterruptedException e) { 834 } 835 // check if we got the callback 836 assertTrue(callback.onStartedCalled); 837 assertNotNull(callback.reservation.getWifiConfiguration()); 838 assertFalse(callback.onFailedCalled); 839 assertFalse(callback.onStoppedCalled); 840 } 841 return callback; 842 } 843 844 private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) { 845 synchronized (mMySync) { 846 // we are expecting a new state 847 mMySync.expectedState = STATE_WIFI_CHANGING; 848 849 // now shut down LocalOnlyHotspot 850 callback.reservation.close(); 851 852 try { 853 waitForExpectedWifiState(wifiEnabled); 854 } catch (InterruptedException e) {} 855 } 856 } 857 858 /** 859 * Verify that calls to startLocalOnlyHotspot succeed with proper permissions. 860 * 861 * Note: Location mode must be enabled for this test. 862 */ 863 public void testStartLocalOnlyHotspotSuccess() { 864 if (!WifiFeature.isWifiSupported(getContext())) { 865 // skip the test if WiFi is not supported 866 return; 867 } 868 // check that softap mode is supported by the device 869 if (!mWifiManager.isPortableHotspotSupported()) { 870 return; 871 } 872 873 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 874 875 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 876 877 stopLocalOnlyHotspot(callback, wifiEnabled); 878 879 // wifi should either stay on, or come back on 880 assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); 881 } 882 883 /** 884 * Verify calls to setWifiEnabled from a non-settings app while softap mode is active do not 885 * exit softap mode. 886 * 887 * This test uses the LocalOnlyHotspot API to enter softap mode. This should also be true when 888 * tethering is started. 889 * Note: Location mode must be enabled for this test. 890 */ 891 public void testSetWifiEnabledByAppDoesNotStopHotspot() throws Exception { 892 if (!WifiFeature.isWifiSupported(getContext())) { 893 // skip the test if WiFi is not supported 894 return; 895 } 896 // check that softap mode is supported by the device 897 if (!mWifiManager.isPortableHotspotSupported()) { 898 return; 899 } 900 901 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 902 903 if (wifiEnabled) { 904 // disable wifi so we have something to turn on (some devices may be able to run 905 // simultaneous modes) 906 setWifiEnabled(false); 907 } 908 909 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 910 911 // now we should fail to turn on wifi 912 assertFalse(mWifiManager.setWifiEnabled(true)); 913 914 stopLocalOnlyHotspot(callback, wifiEnabled); 915 } 916 917 /** 918 * Verify that applications can only have one registered LocalOnlyHotspot request at a time. 919 * 920 * Note: Location mode must be enabled for this test. 921 */ 922 public void testStartLocalOnlyHotspotSingleRequestByApps() { 923 if (!WifiFeature.isWifiSupported(getContext())) { 924 // skip the test if WiFi is not supported 925 return; 926 } 927 // check that softap mode is supported by the device 928 if (!mWifiManager.isPortableHotspotSupported()) { 929 return; 930 } 931 932 boolean caughtException = false; 933 934 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 935 936 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 937 938 // now make a second request - this should fail. 939 TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock); 940 try { 941 mWifiManager.startLocalOnlyHotspot(callback2, null); 942 } catch (IllegalStateException e) { 943 Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice"); 944 caughtException = true; 945 } 946 if (!caughtException) { 947 // second start did not fail, should clean up the hotspot. 948 stopLocalOnlyHotspot(callback2, wifiEnabled); 949 } 950 assertTrue(caughtException); 951 952 stopLocalOnlyHotspot(callback, wifiEnabled); 953 } 954 } 955