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 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 21 import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP; 22 import static android.net.wifi.WifiAvailableChannel.OP_MODE_STA; 23 import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; 24 import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP; 25 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE; 26 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT; 27 import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; 28 29 import static com.google.common.truth.Truth.assertThat; 30 import static com.google.common.truth.Truth.assertWithMessage; 31 32 import static org.junit.Assert.assertNotEquals; 33 34 import android.annotation.NonNull; 35 import android.app.UiAutomation; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.content.pm.PackageInfo; 41 import android.content.pm.PackageManager; 42 import android.content.pm.ResolveInfo; 43 import android.net.ConnectivityManager; 44 import android.net.MacAddress; 45 import android.net.Network; 46 import android.net.NetworkCapabilities; 47 import android.net.NetworkInfo; 48 import android.net.NetworkRequest; 49 import android.net.TetheringManager; 50 import android.net.Uri; 51 import android.net.wifi.CoexUnsafeChannel; 52 import android.net.wifi.ScanResult; 53 import android.net.wifi.SoftApCapability; 54 import android.net.wifi.SoftApConfiguration; 55 import android.net.wifi.SoftApInfo; 56 import android.net.wifi.WifiAvailableChannel; 57 import android.net.wifi.WifiClient; 58 import android.net.wifi.WifiConfiguration; 59 import android.net.wifi.WifiEnterpriseConfig; 60 import android.net.wifi.WifiInfo; 61 import android.net.wifi.WifiManager; 62 import android.net.wifi.WifiManager.SubsystemRestartTrackingCallback; 63 import android.net.wifi.WifiManager.WifiLock; 64 import android.net.wifi.WifiNetworkConnectionStatistics; 65 import android.net.wifi.WifiNetworkSuggestion; 66 import android.net.wifi.hotspot2.ConfigParser; 67 import android.net.wifi.hotspot2.OsuProvider; 68 import android.net.wifi.hotspot2.PasspointConfiguration; 69 import android.net.wifi.hotspot2.ProvisioningCallback; 70 import android.net.wifi.hotspot2.pps.Credential; 71 import android.net.wifi.hotspot2.pps.HomeSp; 72 import android.os.Build; 73 import android.os.Handler; 74 import android.os.HandlerExecutor; 75 import android.os.HandlerThread; 76 import android.os.Process; 77 import android.os.SystemClock; 78 import android.os.UserHandle; 79 import android.platform.test.annotations.AppModeFull; 80 import android.platform.test.annotations.AsbSecurityTest; 81 import android.provider.Settings; 82 import android.support.test.uiautomator.UiDevice; 83 import android.telephony.TelephonyManager; 84 import android.text.TextUtils; 85 import android.util.ArraySet; 86 import android.util.Log; 87 import android.util.SparseArray; 88 import android.util.SparseIntArray; 89 90 import androidx.test.filters.SdkSuppress; 91 import androidx.test.platform.app.InstrumentationRegistry; 92 93 import com.android.compatibility.common.util.ApiLevelUtil; 94 import com.android.compatibility.common.util.FeatureUtil; 95 import com.android.compatibility.common.util.PollingCheck; 96 import com.android.compatibility.common.util.PropertyUtil; 97 import com.android.compatibility.common.util.ShellIdentityUtils; 98 import com.android.compatibility.common.util.SystemUtil; 99 import com.android.compatibility.common.util.ThrowingRunnable; 100 import com.android.modules.utils.build.SdkLevel; 101 import com.android.net.module.util.MacAddressUtils; 102 103 import java.io.BufferedReader; 104 import java.io.IOException; 105 import java.io.InputStream; 106 import java.io.InputStreamReader; 107 import java.lang.reflect.Constructor; 108 import java.net.HttpURLConnection; 109 import java.net.InetAddress; 110 import java.net.URL; 111 import java.util.ArrayList; 112 import java.util.Arrays; 113 import java.util.Collections; 114 import java.util.HashMap; 115 import java.util.HashSet; 116 import java.util.List; 117 import java.util.Locale; 118 import java.util.Map; 119 import java.util.Objects; 120 import java.util.Set; 121 import java.util.concurrent.ConcurrentLinkedQueue; 122 import java.util.concurrent.CountDownLatch; 123 import java.util.concurrent.Executor; 124 import java.util.concurrent.Executors; 125 import java.util.concurrent.TimeUnit; 126 import java.util.stream.Collectors; 127 128 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 129 public class WifiManagerTest extends WifiJUnit3TestBase { 130 private static class MySync { 131 int expectedState = STATE_NULL; 132 } 133 134 private WifiManager mWifiManager; 135 private ConnectivityManager mConnectivityManager; 136 private TetheringManager mTetheringManager; 137 private WifiLock mWifiLock; 138 private static MySync mMySync; 139 private List<ScanResult> mScanResults = null; 140 private NetworkInfo mNetworkInfo = 141 new NetworkInfo(ConnectivityManager.TYPE_WIFI, TelephonyManager.NETWORK_TYPE_UNKNOWN, 142 "wifi", "unknown"); 143 private final Object mLock = new Object(); 144 private UiDevice mUiDevice; 145 private boolean mWasVerboseLoggingEnabled; 146 private boolean mWasScanThrottleEnabled; 147 private SoftApConfiguration mOriginalSoftApConfig = null; 148 149 // Please refer to WifiManager 150 private static final int MIN_RSSI = -100; 151 private static final int MAX_RSSI = -55; 152 153 private static final int STATE_NULL = 0; 154 private static final int STATE_WIFI_CHANGING = 1; 155 private static final int STATE_WIFI_ENABLED = 2; 156 private static final int STATE_WIFI_DISABLED = 3; 157 private static final int STATE_SCANNING = 4; 158 private static final int STATE_SCAN_DONE = 5; 159 160 private static final String TAG = "WifiManagerTest"; 161 private static final String SSID1 = "\"WifiManagerTest\""; 162 // A full single scan duration is typically about 6-7 seconds, but 163 // depending on devices it takes more time (9-11 seconds). For a 164 // safety margin, the test waits for 15 seconds. 165 private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000; 166 private static final int TEST_WAIT_DURATION_MS = 10_000; 167 private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000; 168 private static final int WAIT_MSEC = 60; 169 private static final int DURATION_SCREEN_TOGGLE = 2000; 170 private static final int DURATION_SETTINGS_TOGGLE = 1_000; 171 private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000; 172 173 private static final int ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP = 50; 174 175 private static final String TEST_PAC_URL = "http://www.example.com/proxy.pac"; 176 private static final String MANAGED_PROVISIONING_PACKAGE_NAME 177 = "com.android.managedprovisioning"; 178 179 private static final String TEST_SSID_UNQUOTED = "testSsid1"; 180 private static final String TEST_IP_ADDRESS = "192.168.5.5"; 181 private static final String TEST_MAC_ADDRESS = "aa:bb:cc:dd:ee:ff"; 182 private static final MacAddress TEST_MAC = MacAddress.fromString(TEST_MAC_ADDRESS); 183 private static final String TEST_PASSPHRASE = "passphrase"; 184 private static final String PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT = 185 "assets/ValidPasspointProfile.base64"; 186 private static final String TYPE_WIFI_CONFIG = "application/x-wifi-config"; 187 private static final String TEST_PSK_CAP = "[RSN-PSK-CCMP]"; 188 private static final String TEST_BSSID = "00:01:02:03:04:05"; 189 private static final String TEST_COUNTRY_CODE = "JP"; 190 private static final String TEST_DOM_SUBJECT_MATCH = "domSubjectMatch"; 191 private static final int TEST_SUB_ID = 2; 192 193 private IntentFilter mIntentFilter; 194 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 195 @Override 196 public void onReceive(Context context, Intent intent) { 197 final String action = intent.getAction(); 198 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 199 200 synchronized (mMySync) { 201 if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) { 202 mScanResults = mWifiManager.getScanResults(); 203 } else { 204 mScanResults = null; 205 } 206 mMySync.expectedState = STATE_SCAN_DONE; 207 mMySync.notifyAll(); 208 } 209 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 210 int newState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 211 WifiManager.WIFI_STATE_UNKNOWN); 212 synchronized (mMySync) { 213 if (newState == WifiManager.WIFI_STATE_ENABLED) { 214 Log.d(TAG, "*** New WiFi state is ENABLED ***"); 215 mMySync.expectedState = STATE_WIFI_ENABLED; 216 mMySync.notifyAll(); 217 } else if (newState == WifiManager.WIFI_STATE_DISABLED) { 218 Log.d(TAG, "*** New WiFi state is DISABLED ***"); 219 mMySync.expectedState = STATE_WIFI_DISABLED; 220 mMySync.notifyAll(); 221 } 222 } 223 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 224 synchronized (mMySync) { 225 mNetworkInfo = 226 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 227 if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED) 228 mMySync.notifyAll(); 229 } 230 } 231 } 232 }; 233 // Initialize with an invalid status value (0) 234 private int mProvisioningStatus = 0; 235 // Initialize with an invalid status value (0) 236 private int mProvisioningFailureStatus = 0; 237 private boolean mProvisioningComplete = false; 238 private ProvisioningCallback mProvisioningCallback = new ProvisioningCallback() { 239 @Override 240 public void onProvisioningFailure(int status) { 241 synchronized (mLock) { 242 mProvisioningFailureStatus = status; 243 mLock.notify(); 244 } 245 } 246 247 @Override 248 public void onProvisioningStatus(int status) { 249 synchronized (mLock) { 250 mProvisioningStatus = status; 251 mLock.notify(); 252 } 253 } 254 255 @Override 256 public void onProvisioningComplete() { 257 mProvisioningComplete = true; 258 } 259 }; 260 private int mSubsystemRestartStatus = 0; // 0: nada, 1: restarting, 2: restarted 261 private SubsystemRestartTrackingCallback mSubsystemRestartTrackingCallback = 262 new SubsystemRestartTrackingCallback() { 263 @Override 264 public void onSubsystemRestarting() { 265 synchronized (mLock) { 266 mSubsystemRestartStatus = 1; 267 mLock.notify(); 268 } 269 } 270 271 @Override 272 public void onSubsystemRestarted() { 273 synchronized (mLock) { 274 mSubsystemRestartStatus = 2; 275 mLock.notify(); 276 } 277 } 278 }; 279 private static final String TEST_SSID = "TEST SSID"; 280 private static final String TEST_FRIENDLY_NAME = "Friendly Name"; 281 private static final Map<String, String> TEST_FRIENDLY_NAMES = 282 new HashMap<String, String>() { 283 { 284 put("en", TEST_FRIENDLY_NAME); 285 put("kr", TEST_FRIENDLY_NAME + 2); 286 put("jp", TEST_FRIENDLY_NAME + 3); 287 } 288 }; 289 private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service"; 290 private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com"); 291 private static final String TEST_NAI = "test.access.com"; 292 private static final List<Integer> TEST_METHOD_LIST = 293 Arrays.asList(1 /* METHOD_SOAP_XML_SPP */); 294 private final HandlerThread mHandlerThread = new HandlerThread("WifiManagerTest"); 295 protected final Executor mExecutor; 296 { mHandlerThread.start()297 mHandlerThread.start(); 298 mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper())); 299 } 300 301 @Override setUp()302 protected void setUp() throws Exception { 303 super.setUp(); 304 if (!WifiFeature.isWifiSupported(getContext())) { 305 // skip the test if WiFi is not supported 306 return; 307 } 308 mMySync = new MySync(); 309 mIntentFilter = new IntentFilter(); 310 mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 311 mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 312 mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 313 mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 314 mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 315 mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 316 mIntentFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); 317 mIntentFilter.addAction(WifiManager.ACTION_PICK_WIFI_NETWORK); 318 319 mContext.registerReceiver(mReceiver, mIntentFilter); 320 mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 321 mConnectivityManager = getContext().getSystemService(ConnectivityManager.class); 322 mTetheringManager = getContext().getSystemService(TetheringManager.class); 323 assertNotNull(mWifiManager); 324 assertNotNull(mTetheringManager); 325 326 // turn on verbose logging for tests 327 mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions( 328 () -> mWifiManager.isVerboseLoggingEnabled()); 329 ShellIdentityUtils.invokeWithShellPermissions( 330 () -> mWifiManager.setVerboseLoggingEnabled(true)); 331 // Disable scan throttling for tests. 332 mWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions( 333 () -> mWifiManager.isScanThrottleEnabled()); 334 ShellIdentityUtils.invokeWithShellPermissions( 335 () -> mWifiManager.setScanThrottleEnabled(false)); 336 337 mWifiLock = mWifiManager.createWifiLock(TAG); 338 mWifiLock.acquire(); 339 // enable Wifi 340 if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true); 341 PollingCheck.check("Wifi not enabled", TEST_WAIT_DURATION_MS, 342 () -> mWifiManager.isWifiEnabled()); 343 344 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 345 turnScreenOnNoDelay(); 346 347 synchronized (mMySync) { 348 mMySync.expectedState = STATE_NULL; 349 } 350 351 List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 352 mWifiManager::getConfiguredNetworks); 353 assertFalse("Need at least one saved network", savedNetworks.isEmpty()); 354 355 // Get original config for restore 356 mOriginalSoftApConfig = ShellIdentityUtils.invokeWithShellPermissions( 357 mWifiManager::getSoftApConfiguration); 358 } 359 360 @Override tearDown()361 protected void tearDown() throws Exception { 362 if (!WifiFeature.isWifiSupported(getContext())) { 363 // skip the test if WiFi is not supported 364 super.tearDown(); 365 return; 366 } 367 if (!mWifiManager.isWifiEnabled()) 368 setWifiEnabled(true); 369 mWifiLock.release(); 370 mContext.unregisterReceiver(mReceiver); 371 ShellIdentityUtils.invokeWithShellPermissions( 372 () -> mWifiManager.setScanThrottleEnabled(mWasScanThrottleEnabled)); 373 ShellIdentityUtils.invokeWithShellPermissions( 374 () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled)); 375 // restore original softap config 376 ShellIdentityUtils.invokeWithShellPermissions( 377 () -> mWifiManager.setSoftApConfiguration(mOriginalSoftApConfig)); 378 Thread.sleep(TEST_WAIT_DURATION_MS); 379 super.tearDown(); 380 } 381 setWifiEnabled(boolean enable)382 private void setWifiEnabled(boolean enable) throws Exception { 383 synchronized (mMySync) { 384 if (mWifiManager.isWifiEnabled() != enable) { 385 // the new state is different, we expect it to change 386 mMySync.expectedState = STATE_WIFI_CHANGING; 387 } else { 388 mMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 389 } 390 // now trigger the change using shell commands. 391 SystemUtil.runShellCommand("svc wifi " + (enable ? "enable" : "disable")); 392 waitForExpectedWifiState(enable); 393 } 394 } 395 waitForExpectedWifiState(boolean enabled)396 private void waitForExpectedWifiState(boolean enabled) throws InterruptedException { 397 synchronized (mMySync) { 398 long timeout = System.currentTimeMillis() + TEST_WAIT_DURATION_MS; 399 int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 400 while (System.currentTimeMillis() < timeout 401 && mMySync.expectedState != expected) { 402 mMySync.wait(WAIT_MSEC); 403 } 404 } 405 } 406 407 // Get the current scan status from sticky broadcast. isScanCurrentlyAvailable()408 private boolean isScanCurrentlyAvailable() { 409 IntentFilter intentFilter = new IntentFilter(); 410 intentFilter.addAction(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED); 411 Intent intent = mContext.registerReceiver(null, intentFilter); 412 assertNotNull(intent); 413 if (intent.getAction().equals(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED)) { 414 return intent.getBooleanExtra(WifiManager.EXTRA_SCAN_AVAILABLE, false); 415 } 416 return false; 417 } 418 startScan()419 private void startScan() throws Exception { 420 synchronized (mMySync) { 421 mMySync.expectedState = STATE_SCANNING; 422 mScanResults = null; 423 assertTrue(mWifiManager.startScan()); 424 long timeout = System.currentTimeMillis() + SCAN_TEST_WAIT_DURATION_MS; 425 while (System.currentTimeMillis() < timeout && mMySync.expectedState == STATE_SCANNING) 426 mMySync.wait(WAIT_MSEC); 427 } 428 } 429 waitForNetworkInfoState(NetworkInfo.State state, int timeoutMillis)430 private void waitForNetworkInfoState(NetworkInfo.State state, int timeoutMillis) 431 throws Exception { 432 synchronized (mMySync) { 433 if (mNetworkInfo.getState() == state) return; 434 long timeout = System.currentTimeMillis() + timeoutMillis; 435 while (System.currentTimeMillis() < timeout 436 && mNetworkInfo.getState() != state) 437 mMySync.wait(WAIT_MSEC); 438 assertEquals(state, mNetworkInfo.getState()); 439 } 440 } 441 waitForConnection()442 private void waitForConnection() throws Exception { 443 waitForNetworkInfoState(NetworkInfo.State.CONNECTED, WIFI_CONNECT_TIMEOUT_MILLIS); 444 } 445 waitForDisconnection()446 private void waitForDisconnection() throws Exception { 447 waitForNetworkInfoState(NetworkInfo.State.DISCONNECTED, TEST_WAIT_DURATION_MS); 448 } 449 ensureNotNetworkInfoState(NetworkInfo.State state)450 private void ensureNotNetworkInfoState(NetworkInfo.State state) throws Exception { 451 synchronized (mMySync) { 452 long timeout = System.currentTimeMillis() + TEST_WAIT_DURATION_MS + WAIT_MSEC; 453 while (System.currentTimeMillis() < timeout) { 454 assertNotEquals(state, mNetworkInfo.getState()); 455 mMySync.wait(WAIT_MSEC); 456 } 457 } 458 } 459 ensureNotConnected()460 private void ensureNotConnected() throws Exception { 461 ensureNotNetworkInfoState(NetworkInfo.State.CONNECTED); 462 } 463 ensureNotDisconnected()464 private void ensureNotDisconnected() throws Exception { 465 ensureNotNetworkInfoState(NetworkInfo.State.DISCONNECTED); 466 } 467 existSSID(String ssid)468 private boolean existSSID(String ssid) { 469 for (final WifiConfiguration w : mWifiManager.getConfiguredNetworks()) { 470 if (w.SSID.equals(ssid)) 471 return true; 472 } 473 return false; 474 } 475 findConfiguredNetworks(String SSID, List<WifiConfiguration> networks)476 private int findConfiguredNetworks(String SSID, List<WifiConfiguration> networks) { 477 for (final WifiConfiguration w : networks) { 478 if (w.SSID.equals(SSID)) 479 return networks.indexOf(w); 480 } 481 return -1; 482 } 483 484 /** 485 * Test creation of WifiManager Lock. 486 */ testWifiManagerLock()487 public void testWifiManagerLock() throws Exception { 488 if (!WifiFeature.isWifiSupported(getContext())) { 489 // skip the test if WiFi is not supported 490 return; 491 } 492 final String TAG = "Test"; 493 assertNotNull(mWifiManager.createWifiLock(TAG)); 494 assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 495 } 496 497 /** 498 * Test wifi scanning when Wifi is off and location scanning is turned on. 499 */ testWifiManagerScanWhenWifiOffLocationTurnedOn()500 public void testWifiManagerScanWhenWifiOffLocationTurnedOn() throws Exception { 501 if (!WifiFeature.isWifiSupported(getContext())) { 502 // skip the test if WiFi is not supported 503 return; 504 } 505 if (!hasLocationFeature()) { 506 Log.d(TAG, "Skipping test as location is not supported"); 507 return; 508 } 509 if (!isLocationEnabled()) { 510 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 511 + " empty when location is disabled!"); 512 } 513 runWithScanningEnabled(() -> { 514 setWifiEnabled(false); 515 Thread.sleep(TEST_WAIT_DURATION_MS); 516 startScan(); 517 if (mWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) { 518 // Make sure at least one AP is found. 519 assertNotNull("mScanResult should not be null!", mScanResults); 520 assertFalse("empty scan results!", mScanResults.isEmpty()); 521 } else { 522 // Make sure no scan results are available. 523 assertNull("mScanResult should be null!", mScanResults); 524 } 525 final String TAG = "Test"; 526 assertNotNull(mWifiManager.createWifiLock(TAG)); 527 assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 528 }); 529 } 530 531 /** 532 * Restart WiFi subsystem - verify that privileged call fails. 533 */ 534 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testRestartWifiSubsystemShouldFailNoPermission()535 public void testRestartWifiSubsystemShouldFailNoPermission() throws Exception { 536 if (!WifiFeature.isWifiSupported(getContext())) { 537 // skip the test if WiFi is not supported 538 return; 539 } 540 try { 541 mWifiManager.restartWifiSubsystem(); 542 fail("The restartWifiSubsystem should not succeed - privileged call"); 543 } catch (SecurityException e) { 544 // expected 545 } 546 } 547 548 /** 549 * Restart WiFi subsystem and verify transition through states. 550 */ 551 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testRestartWifiSubsystem()552 public void testRestartWifiSubsystem() throws Exception { 553 if (!WifiFeature.isWifiSupported(getContext())) { 554 // skip the test if WiFi is not supported 555 return; 556 } 557 mSubsystemRestartStatus = 0; // 0: uninitialized 558 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 559 try { 560 uiAutomation.adoptShellPermissionIdentity(); 561 mWifiManager.registerSubsystemRestartTrackingCallback(mExecutor, 562 mSubsystemRestartTrackingCallback); 563 synchronized (mLock) { 564 mWifiManager.restartWifiSubsystem(); 565 mLock.wait(TEST_WAIT_DURATION_MS); 566 } 567 assertEquals(mSubsystemRestartStatus, 1); // 1: restarting 568 waitForExpectedWifiState(false); 569 assertFalse(mWifiManager.isWifiEnabled()); 570 synchronized (mLock) { 571 mLock.wait(TEST_WAIT_DURATION_MS); 572 assertEquals(mSubsystemRestartStatus, 2); // 2: restarted 573 } 574 waitForExpectedWifiState(true); 575 assertTrue(mWifiManager.isWifiEnabled()); 576 } finally { 577 // cleanup 578 mWifiManager.unregisterSubsystemRestartTrackingCallback( 579 mSubsystemRestartTrackingCallback); 580 uiAutomation.dropShellPermissionIdentity(); 581 } 582 } 583 584 /** 585 * test point of wifiManager properties: 586 * 1.enable properties 587 * 2.DhcpInfo properties 588 * 3.wifi state 589 * 4.ConnectionInfo 590 */ testWifiManagerProperties()591 public void testWifiManagerProperties() throws Exception { 592 if (!WifiFeature.isWifiSupported(getContext())) { 593 // skip the test if WiFi is not supported 594 return; 595 } 596 setWifiEnabled(true); 597 assertTrue(mWifiManager.isWifiEnabled()); 598 assertNotNull(mWifiManager.getDhcpInfo()); 599 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWifiManager.getWifiState()); 600 mWifiManager.getConnectionInfo(); 601 setWifiEnabled(false); 602 assertFalse(mWifiManager.isWifiEnabled()); 603 } 604 605 /** 606 * Test WiFi scan timestamp - fails when WiFi scan timestamps are inconsistent with 607 * {@link SystemClock#elapsedRealtime()} on device.<p> 608 * To run this test in cts-tradefed: 609 * run cts --class android.net.wifi.cts.WifiManagerTest --method testWifiScanTimestamp 610 */ 611 @VirtualDeviceNotSupported testWifiScanTimestamp()612 public void testWifiScanTimestamp() throws Exception { 613 if (!WifiFeature.isWifiSupported(getContext())) { 614 Log.d(TAG, "Skipping test as WiFi is not supported"); 615 return; 616 } 617 if (!hasLocationFeature()) { 618 Log.d(TAG, "Skipping test as location is not supported"); 619 return; 620 } 621 if (!isLocationEnabled()) { 622 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 623 + " empty when location is disabled!"); 624 } 625 if (!mWifiManager.isWifiEnabled()) { 626 setWifiEnabled(true); 627 } 628 // Make sure the scan timestamps are consistent with the device timestamp within the range 629 // of WIFI_SCAN_TEST_CACHE_DELAY_MILLIS. 630 startScan(); 631 // Make sure at least one AP is found. 632 assertTrue("mScanResult should not be null. This may be due to a scan timeout", 633 mScanResults != null); 634 assertFalse("empty scan results!", mScanResults.isEmpty()); 635 long nowMillis = SystemClock.elapsedRealtime(); 636 // Keep track of how many APs are fresh in one scan. 637 int numFreshAps = 0; 638 for (ScanResult result : mScanResults) { 639 long scanTimeMillis = TimeUnit.MICROSECONDS.toMillis(result.timestamp); 640 if (Math.abs(nowMillis - scanTimeMillis) < WIFI_SCAN_TEST_CACHE_DELAY_MILLIS) { 641 numFreshAps++; 642 } 643 } 644 // At least half of the APs in the scan should be fresh. 645 int numTotalAps = mScanResults.size(); 646 String msg = "Stale AP count: " + (numTotalAps - numFreshAps) + ", fresh AP count: " 647 + numFreshAps; 648 assertTrue(msg, numFreshAps * 2 >= mScanResults.size()); 649 } 650 testConvertBetweenChannelFrequencyMhz()651 public void testConvertBetweenChannelFrequencyMhz() throws Exception { 652 int[] testFrequency_2G = {2412, 2437, 2462, 2484}; 653 int[] testFrequency_5G = {5180, 5220, 5540, 5745}; 654 int[] testFrequency_6G = {5955, 6435, 6535, 7115}; 655 int[] testFrequency_60G = {58320, 64800}; 656 SparseArray<int[]> testData = new SparseArray<>() {{ 657 put(ScanResult.WIFI_BAND_24_GHZ, testFrequency_2G); 658 put(ScanResult.WIFI_BAND_5_GHZ, testFrequency_5G); 659 put(ScanResult.WIFI_BAND_6_GHZ, testFrequency_6G); 660 put(ScanResult.WIFI_BAND_60_GHZ, testFrequency_60G); 661 }}; 662 663 for (int i = 0; i < testData.size(); i++) { 664 for (int frequency : testData.valueAt(i)) { 665 assertEquals(frequency, ScanResult.convertChannelToFrequencyMhzIfSupported( 666 ScanResult.convertFrequencyMhzToChannelIfSupported(frequency), testData.keyAt(i))); 667 } 668 } 669 } 670 671 // Return true if location is enabled. isLocationEnabled()672 private boolean isLocationEnabled() { 673 return Settings.Secure.getInt(getContext().getContentResolver(), 674 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) != 675 Settings.Secure.LOCATION_MODE_OFF; 676 } 677 678 // Returns true if the device has location feature. hasLocationFeature()679 private boolean hasLocationFeature() { 680 return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION); 681 } 682 hasAutomotiveFeature()683 private boolean hasAutomotiveFeature() { 684 return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 685 } 686 testSignal()687 public void testSignal() { 688 if (!WifiFeature.isWifiSupported(getContext())) { 689 // skip the test if WiFi is not supported 690 return; 691 } 692 final int numLevels = 9; 693 int expectLevel = 0; 694 assertEquals(expectLevel, WifiManager.calculateSignalLevel(MIN_RSSI, numLevels)); 695 assertEquals(numLevels - 1, WifiManager.calculateSignalLevel(MAX_RSSI, numLevels)); 696 expectLevel = 4; 697 assertEquals(expectLevel, WifiManager.calculateSignalLevel((MIN_RSSI + MAX_RSSI) / 2, 698 numLevels)); 699 int rssiA = 4; 700 int rssiB = 5; 701 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) < 0); 702 rssiB = 4; 703 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) == 0); 704 rssiA = 5; 705 rssiB = 4; 706 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) > 0); 707 } 708 709 /** 710 * Test that {@link WifiManager#calculateSignalLevel(int)} returns a value in the range 711 * [0, {@link WifiManager#getMaxSignalLevel()}], and its value is monotonically increasing as 712 * the RSSI increases. 713 */ testCalculateSignalLevel()714 public void testCalculateSignalLevel() { 715 if (!WifiFeature.isWifiSupported(getContext())) { 716 // skip the test if WiFi is not supported 717 return; 718 } 719 720 int maxSignalLevel = mWifiManager.getMaxSignalLevel(); 721 722 int prevSignalLevel = 0; 723 for (int rssi = -150; rssi <= 50; rssi++) { 724 int signalLevel = mWifiManager.calculateSignalLevel(rssi); 725 726 // between [0, maxSignalLevel] 727 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(0); 728 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtMost(maxSignalLevel); 729 730 // calculateSignalLevel(rssi) <= calculateSignalLevel(rssi + 1) 731 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(prevSignalLevel); 732 prevSignalLevel = signalLevel; 733 } 734 } 735 736 public class TestWifiVerboseLoggingStatusChangedListener implements 737 WifiManager.WifiVerboseLoggingStatusChangedListener { 738 public int numCalls; 739 public boolean status; 740 741 @Override onWifiVerboseLoggingStatusChanged(boolean enabled)742 public void onWifiVerboseLoggingStatusChanged(boolean enabled) { 743 numCalls++; 744 status = enabled; 745 } 746 } 747 748 public class TestSoftApCallback implements WifiManager.SoftApCallback { 749 Object softApLock; 750 int currentState; 751 int currentFailureReason; 752 List<SoftApInfo> apInfoList = new ArrayList<>(); 753 SoftApInfo apInfoOnSingleApMode; 754 Map<SoftApInfo, List<WifiClient>> apInfoClients = new HashMap<>(); 755 List<WifiClient> currentClientList; 756 SoftApCapability currentSoftApCapability; 757 MacAddress lastBlockedClientMacAddress; 758 int lastBlockedClientReason; 759 boolean onStateChangedCalled = false; 760 boolean onSoftApCapabilityChangedCalled = false; 761 boolean onConnectedClientCalled = false; 762 boolean onConnectedClientChangedWithInfoCalled = false; 763 boolean onBlockedClientConnectingCalled = false; 764 int onSoftapInfoChangedCalledCount = 0; 765 int onSoftapInfoChangedWithListCalledCount = 0; 766 TestSoftApCallback(Object lock)767 TestSoftApCallback(Object lock) { 768 softApLock = lock; 769 } 770 getOnStateChangedCalled()771 public boolean getOnStateChangedCalled() { 772 synchronized(softApLock) { 773 return onStateChangedCalled; 774 } 775 } 776 getOnSoftapInfoChangedCalledCount()777 public int getOnSoftapInfoChangedCalledCount() { 778 synchronized(softApLock) { 779 return onSoftapInfoChangedCalledCount; 780 } 781 } 782 getOnSoftApInfoChangedWithListCalledCount()783 public int getOnSoftApInfoChangedWithListCalledCount() { 784 synchronized(softApLock) { 785 return onSoftapInfoChangedWithListCalledCount; 786 } 787 } 788 getOnSoftApCapabilityChangedCalled()789 public boolean getOnSoftApCapabilityChangedCalled() { 790 synchronized(softApLock) { 791 return onSoftApCapabilityChangedCalled; 792 } 793 } 794 getOnConnectedClientChangedWithInfoCalled()795 public boolean getOnConnectedClientChangedWithInfoCalled() { 796 synchronized(softApLock) { 797 return onConnectedClientChangedWithInfoCalled; 798 } 799 } 800 getOnConnectedClientCalled()801 public boolean getOnConnectedClientCalled() { 802 synchronized(softApLock) { 803 return onConnectedClientCalled; 804 } 805 } 806 getOnBlockedClientConnectingCalled()807 public boolean getOnBlockedClientConnectingCalled() { 808 synchronized(softApLock) { 809 return onBlockedClientConnectingCalled; 810 } 811 } 812 getCurrentState()813 public int getCurrentState() { 814 synchronized(softApLock) { 815 return currentState; 816 } 817 } 818 getCurrentStateFailureReason()819 public int getCurrentStateFailureReason() { 820 synchronized(softApLock) { 821 return currentFailureReason; 822 } 823 } 824 getCurrentClientList()825 public List<WifiClient> getCurrentClientList() { 826 synchronized(softApLock) { 827 return new ArrayList<>(currentClientList); 828 } 829 } 830 getCurrentSoftApInfo()831 public SoftApInfo getCurrentSoftApInfo() { 832 synchronized(softApLock) { 833 return apInfoOnSingleApMode; 834 } 835 } 836 getCurrentSoftApInfoList()837 public List<SoftApInfo> getCurrentSoftApInfoList() { 838 synchronized(softApLock) { 839 return new ArrayList<>(apInfoList); 840 } 841 } 842 getCurrentSoftApCapability()843 public SoftApCapability getCurrentSoftApCapability() { 844 synchronized(softApLock) { 845 return currentSoftApCapability; 846 } 847 } 848 getLastBlockedClientMacAddress()849 public MacAddress getLastBlockedClientMacAddress() { 850 synchronized(softApLock) { 851 return lastBlockedClientMacAddress; 852 } 853 } 854 getLastBlockedClientReason()855 public int getLastBlockedClientReason() { 856 synchronized(softApLock) { 857 return lastBlockedClientReason; 858 } 859 } 860 861 @Override onStateChanged(int state, int failureReason)862 public void onStateChanged(int state, int failureReason) { 863 synchronized(softApLock) { 864 currentState = state; 865 currentFailureReason = failureReason; 866 onStateChangedCalled = true; 867 } 868 } 869 870 @Override onConnectedClientsChanged(List<WifiClient> clients)871 public void onConnectedClientsChanged(List<WifiClient> clients) { 872 synchronized(softApLock) { 873 currentClientList = new ArrayList<>(clients); 874 onConnectedClientCalled = true; 875 } 876 } 877 878 @Override onConnectedClientsChanged(SoftApInfo info, List<WifiClient> clients)879 public void onConnectedClientsChanged(SoftApInfo info, List<WifiClient> clients) { 880 synchronized(softApLock) { 881 apInfoClients.put(info, clients); 882 onConnectedClientChangedWithInfoCalled = true; 883 } 884 } 885 886 @Override onInfoChanged(List<SoftApInfo> infoList)887 public void onInfoChanged(List<SoftApInfo> infoList) { 888 synchronized(softApLock) { 889 apInfoList = new ArrayList<>(infoList); 890 onSoftapInfoChangedWithListCalledCount++; 891 } 892 } 893 894 @Override onInfoChanged(SoftApInfo softApInfo)895 public void onInfoChanged(SoftApInfo softApInfo) { 896 synchronized(softApLock) { 897 apInfoOnSingleApMode = softApInfo; 898 onSoftapInfoChangedCalledCount++; 899 } 900 } 901 902 @Override onCapabilityChanged(SoftApCapability softApCapability)903 public void onCapabilityChanged(SoftApCapability softApCapability) { 904 synchronized(softApLock) { 905 currentSoftApCapability = softApCapability; 906 onSoftApCapabilityChangedCalled = true; 907 } 908 } 909 910 @Override onBlockedClientConnecting(WifiClient client, int blockedReason)911 public void onBlockedClientConnecting(WifiClient client, int blockedReason) { 912 synchronized(softApLock) { 913 lastBlockedClientMacAddress = client.getMacAddress(); 914 lastBlockedClientReason = blockedReason; 915 onBlockedClientConnectingCalled = true; 916 } 917 } 918 } 919 920 private static class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback { 921 Object hotspotLock; 922 WifiManager.LocalOnlyHotspotReservation reservation = null; 923 boolean onStartedCalled = false; 924 boolean onStoppedCalled = false; 925 boolean onFailedCalled = false; 926 int failureReason = -1; 927 TestLocalOnlyHotspotCallback(Object lock)928 TestLocalOnlyHotspotCallback(Object lock) { 929 hotspotLock = lock; 930 } 931 932 @Override onStarted(WifiManager.LocalOnlyHotspotReservation r)933 public void onStarted(WifiManager.LocalOnlyHotspotReservation r) { 934 synchronized (hotspotLock) { 935 reservation = r; 936 onStartedCalled = true; 937 hotspotLock.notify(); 938 } 939 } 940 941 @Override onStopped()942 public void onStopped() { 943 synchronized (hotspotLock) { 944 onStoppedCalled = true; 945 hotspotLock.notify(); 946 } 947 } 948 949 @Override onFailed(int reason)950 public void onFailed(int reason) { 951 synchronized (hotspotLock) { 952 onFailedCalled = true; 953 failureReason = reason; 954 hotspotLock.notify(); 955 } 956 } 957 } 958 getSupportedSoftApBand(SoftApCapability capability)959 private List<Integer> getSupportedSoftApBand(SoftApCapability capability) { 960 List<Integer> supportedApBands = new ArrayList<>(); 961 if (mWifiManager.is24GHzBandSupported() && 962 capability.areFeaturesSupported( 963 SoftApCapability.SOFTAP_FEATURE_BAND_24G_SUPPORTED)) { 964 supportedApBands.add(SoftApConfiguration.BAND_2GHZ); 965 } 966 if (mWifiManager.is5GHzBandSupported() && 967 capability.areFeaturesSupported( 968 SoftApCapability.SOFTAP_FEATURE_BAND_5G_SUPPORTED)) { 969 supportedApBands.add(SoftApConfiguration.BAND_5GHZ); 970 } 971 if (mWifiManager.is6GHzBandSupported() && 972 capability.areFeaturesSupported( 973 SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED)) { 974 supportedApBands.add(SoftApConfiguration.BAND_6GHZ); 975 } 976 if (mWifiManager.is60GHzBandSupported() && 977 capability.areFeaturesSupported( 978 SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED)) { 979 supportedApBands.add(SoftApConfiguration.BAND_60GHZ); 980 } 981 return supportedApBands; 982 } 983 startLocalOnlyHotspot()984 private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() { 985 // Location mode must be enabled for this test 986 if (!isLocationEnabled()) { 987 fail("Please enable location for this test"); 988 } 989 990 TestExecutor executor = new TestExecutor(); 991 TestSoftApCallback capabilityCallback = new TestSoftApCallback(mLock); 992 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 993 List<Integer> supportedSoftApBands = new ArrayList<>(); 994 try { 995 uiAutomation.adoptShellPermissionIdentity(); 996 verifyRegisterSoftApCallback(executor, capabilityCallback); 997 supportedSoftApBands = getSupportedSoftApBand( 998 capabilityCallback.getCurrentSoftApCapability()); 999 } catch (Exception ex) { 1000 } finally { 1001 // clean up 1002 mWifiManager.unregisterSoftApCallback(capabilityCallback); 1003 uiAutomation.dropShellPermissionIdentity(); 1004 } 1005 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 1006 synchronized (mLock) { 1007 try { 1008 mWifiManager.startLocalOnlyHotspot(callback, null); 1009 // now wait for callback 1010 mLock.wait(TEST_WAIT_DURATION_MS); 1011 } catch (InterruptedException e) { 1012 } 1013 // check if we got the callback 1014 assertTrue(callback.onStartedCalled); 1015 1016 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 1017 assertNotNull(softApConfig); 1018 int securityType = softApConfig.getSecurityType(); 1019 if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN 1020 || securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK 1021 || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) { 1022 assertNotNull(softApConfig.toWifiConfiguration()); 1023 } else { 1024 assertNull(softApConfig.toWifiConfiguration()); 1025 } 1026 if (!hasAutomotiveFeature()) { 1027 assertEquals(supportedSoftApBands.size() > 0 ? supportedSoftApBands.get(0) 1028 : SoftApConfiguration.BAND_2GHZ, 1029 callback.reservation.getSoftApConfiguration().getBand()); 1030 } 1031 assertFalse(callback.onFailedCalled); 1032 assertFalse(callback.onStoppedCalled); 1033 } 1034 return callback; 1035 } 1036 stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled)1037 private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) { 1038 synchronized (mMySync) { 1039 // we are expecting a new state 1040 mMySync.expectedState = STATE_WIFI_CHANGING; 1041 1042 // now shut down LocalOnlyHotspot 1043 callback.reservation.close(); 1044 1045 try { 1046 waitForExpectedWifiState(wifiEnabled); 1047 } catch (InterruptedException e) {} 1048 } 1049 } 1050 1051 /** 1052 * Verify that calls to startLocalOnlyHotspot succeed with proper permissions. 1053 * 1054 * Note: Location mode must be enabled for this test. 1055 */ testStartLocalOnlyHotspotSuccess()1056 public void testStartLocalOnlyHotspotSuccess() throws Exception { 1057 if (!WifiFeature.isWifiSupported(getContext())) { 1058 // skip the test if WiFi is not supported 1059 return; 1060 } 1061 // check that softap mode is supported by the device 1062 if (!mWifiManager.isPortableHotspotSupported()) { 1063 return; 1064 } 1065 1066 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1067 1068 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 1069 1070 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization. 1071 // TODO: remove this sleep as soon as b/124330089 is fixed. 1072 Log.d(TAG, "Sleeping for 2 seconds"); 1073 Thread.sleep(2000); 1074 1075 stopLocalOnlyHotspot(callback, wifiEnabled); 1076 1077 // wifi should either stay on, or come back on 1078 assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); 1079 } 1080 1081 /** 1082 * Verify calls to deprecated API's all fail for non-settings apps targeting >= Q SDK. 1083 */ testDeprecatedApis()1084 public void testDeprecatedApis() throws Exception { 1085 if (!WifiFeature.isWifiSupported(getContext())) { 1086 // skip the test if WiFi is not supported 1087 return; 1088 } 1089 setWifiEnabled(true); 1090 waitForConnection(); // ensures that there is at-least 1 saved network on the device. 1091 1092 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 1093 wifiConfiguration.SSID = SSID1; 1094 wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 1095 1096 assertEquals(INVALID_NETWORK_ID, 1097 mWifiManager.addNetwork(wifiConfiguration)); 1098 assertEquals(INVALID_NETWORK_ID, 1099 mWifiManager.updateNetwork(wifiConfiguration)); 1100 assertFalse(mWifiManager.enableNetwork(0, true)); 1101 assertFalse(mWifiManager.disableNetwork(0)); 1102 assertFalse(mWifiManager.removeNetwork(0)); 1103 assertFalse(mWifiManager.disconnect()); 1104 assertFalse(mWifiManager.reconnect()); 1105 assertFalse(mWifiManager.reassociate()); 1106 assertTrue(mWifiManager.getConfiguredNetworks().isEmpty()); 1107 1108 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1109 // now we should fail to toggle wifi state. 1110 assertFalse(mWifiManager.setWifiEnabled(!wifiEnabled)); 1111 Thread.sleep(TEST_WAIT_DURATION_MS); 1112 assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); 1113 } 1114 1115 /** 1116 * Test the WifiManager APIs that return whether a feature is supported. 1117 */ testGetSupportedFeatures()1118 public void testGetSupportedFeatures() { 1119 if (!WifiFeature.isWifiSupported(getContext())) { 1120 // skip the test if WiFi is not supported 1121 return; 1122 } 1123 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1124 // Skip the test if wifi module version is older than S. 1125 return; 1126 } 1127 mWifiManager.isMakeBeforeBreakWifiSwitchingSupported(); 1128 mWifiManager.isStaBridgedApConcurrencySupported(); 1129 } 1130 1131 /** 1132 * Verify non DO apps cannot call removeNonCallerConfiguredNetworks. 1133 */ testRemoveNonCallerConfiguredNetworksNotAllowed()1134 public void testRemoveNonCallerConfiguredNetworksNotAllowed() { 1135 if (!WifiFeature.isWifiSupported(getContext())) { 1136 // skip the test if WiFi is not supported 1137 return; 1138 } 1139 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1140 // Skip the test if wifi module version is older than S. 1141 return; 1142 } 1143 try { 1144 mWifiManager.removeNonCallerConfiguredNetworks(); 1145 fail("Expected security exception for non DO app"); 1146 } catch (SecurityException e) { 1147 } 1148 } 1149 1150 /** 1151 * Test coverage for the constructor of AddNetworkResult. 1152 */ testAddNetworkResultCreation()1153 public void testAddNetworkResultCreation() { 1154 if (!WifiFeature.isWifiSupported(getContext())) { 1155 // skip the test if WiFi is not supported 1156 return; 1157 } 1158 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1159 // Skip the test if wifi module version is older than S. 1160 return; 1161 } 1162 int statusCode = WifiManager.AddNetworkResult.STATUS_NO_PERMISSION; 1163 int networkId = 5; 1164 WifiManager.AddNetworkResult result = new WifiManager.AddNetworkResult( 1165 statusCode, networkId); 1166 assertEquals("statusCode should match", statusCode, result.statusCode); 1167 assertEquals("networkId should match", networkId, result.networkId); 1168 } 1169 1170 /** 1171 * Verify that {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} throws a 1172 * SecurityException when called by a normal app. 1173 */ testAddNetworkPrivilegedNotAllowedForNormalApps()1174 public void testAddNetworkPrivilegedNotAllowedForNormalApps() { 1175 if (!WifiFeature.isWifiSupported(getContext())) { 1176 // skip the test if WiFi is not supported 1177 return; 1178 } 1179 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1180 // Skip the test if wifi module version is older than S. 1181 return; 1182 } 1183 try { 1184 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 1185 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 1186 mWifiManager.addNetworkPrivileged(newOpenNetwork); 1187 fail("A normal app should not be able to call this API."); 1188 } catch (SecurityException e) { 1189 } 1190 } 1191 1192 /** 1193 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} throws an exception when 1194 * null is the input. 1195 */ testAddNetworkPrivilegedBadInput()1196 public void testAddNetworkPrivilegedBadInput() { 1197 if (!WifiFeature.isWifiSupported(getContext())) { 1198 // skip the test if WiFi is not supported 1199 return; 1200 } 1201 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1202 // Skip the test if wifi module version is older than S. 1203 return; 1204 } 1205 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1206 try { 1207 uiAutomation.adoptShellPermissionIdentity(); 1208 mWifiManager.addNetworkPrivileged(null); 1209 fail("Expected IllegalArgumentException"); 1210 } catch (IllegalArgumentException e) { 1211 } finally { 1212 uiAutomation.dropShellPermissionIdentity(); 1213 } 1214 } 1215 1216 /** 1217 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works properly when the 1218 * calling app has permissions. 1219 */ testAddNetworkPrivilegedSuccess()1220 public void testAddNetworkPrivilegedSuccess() { 1221 if (!WifiFeature.isWifiSupported(getContext())) { 1222 // skip the test if WiFi is not supported 1223 return; 1224 } 1225 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1226 // Skip the test if wifi module version is older than S. 1227 return; 1228 } 1229 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1230 WifiManager.AddNetworkResult result = null; 1231 try { 1232 uiAutomation.adoptShellPermissionIdentity(); 1233 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 1234 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 1235 result = mWifiManager.addNetworkPrivileged(newOpenNetwork); 1236 assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode); 1237 assertTrue(result.networkId >= 0); 1238 List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks(); 1239 boolean found = false; 1240 for (WifiConfiguration config : configuredNetworks) { 1241 if (config.networkId == result.networkId 1242 && config.SSID.equals(newOpenNetwork.SSID)) { 1243 found = true; 1244 break; 1245 } 1246 } 1247 assertTrue("addNetworkPrivileged returns success" 1248 + "but the network is not found in getConfiguredNetworks", found); 1249 1250 List<WifiConfiguration> privilegedConfiguredNetworks = 1251 mWifiManager.getPrivilegedConfiguredNetworks(); 1252 found = false; 1253 for (WifiConfiguration config : privilegedConfiguredNetworks) { 1254 if (config.networkId == result.networkId 1255 && config.SSID.equals(newOpenNetwork.SSID)) { 1256 found = true; 1257 break; 1258 } 1259 } 1260 assertTrue("addNetworkPrivileged returns success" 1261 + "but the network is not found in getPrivilegedConfiguredNetworks", found); 1262 1263 List<WifiConfiguration> callerConfiguredNetworks = 1264 mWifiManager.getCallerConfiguredNetworks(); 1265 found = false; 1266 for (WifiConfiguration config : callerConfiguredNetworks) { 1267 if (config.networkId == result.networkId 1268 && config.SSID.equals(newOpenNetwork.SSID)) { 1269 found = true; 1270 break; 1271 } 1272 } 1273 assertTrue("addNetworkPrivileged returns success" 1274 + "but the network is not found in getCallerConfiguredNetworks", found); 1275 } finally { 1276 if (null != result) { 1277 mWifiManager.removeNetwork(result.networkId); 1278 } 1279 uiAutomation.dropShellPermissionIdentity(); 1280 } 1281 } 1282 createConfig( String ssid, int type)1283 private WifiConfiguration createConfig( 1284 String ssid, int type) { 1285 WifiConfiguration config = new WifiConfiguration(); 1286 config.SSID = "\"" + ssid + "\""; 1287 config.setSecurityParams(type); 1288 // set necessary fields for different types. 1289 switch (type) { 1290 case WifiConfiguration.SECURITY_TYPE_OPEN: 1291 case WifiConfiguration.SECURITY_TYPE_OWE: 1292 break; 1293 case WifiConfiguration.SECURITY_TYPE_PSK: 1294 case WifiConfiguration.SECURITY_TYPE_SAE: 1295 config.preSharedKey = "\"1qaz@WSX\""; 1296 break; 1297 case WifiConfiguration.SECURITY_TYPE_EAP: 1298 case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE: 1299 case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT: 1300 config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); 1301 break; 1302 } 1303 return config; 1304 } 1305 assertConfigsAreFound( List<WifiConfiguration> expectedConfigs, List<WifiConfiguration> configs)1306 private void assertConfigsAreFound( 1307 List<WifiConfiguration> expectedConfigs, 1308 List<WifiConfiguration> configs) { 1309 for (WifiConfiguration expectedConfig: expectedConfigs) { 1310 boolean found = false; 1311 for (WifiConfiguration config : configs) { 1312 if (config.networkId == expectedConfig.networkId 1313 && config.getKey().equals(expectedConfig.getKey())) { 1314 found = true; 1315 break; 1316 } 1317 } 1318 assertTrue("the network " + expectedConfig.getKey() + " is not found", found); 1319 } 1320 } 1321 1322 /** 1323 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works 1324 * with merging types properly when the calling app has permissions. 1325 */ testAddNetworkPrivilegedMergingTypeSuccess()1326 public void testAddNetworkPrivilegedMergingTypeSuccess() { 1327 if (!WifiFeature.isWifiSupported(getContext())) { 1328 // skip the test if WiFi is not supported 1329 return; 1330 } 1331 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) { 1332 // Skip the test if wifi module version is older than S. 1333 return; 1334 } 1335 List<WifiConfiguration> testConfigs = new ArrayList<>(); 1336 testConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OPEN)); 1337 testConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OWE)); 1338 testConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_PSK)); 1339 testConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_SAE)); 1340 testConfigs.add(createConfig("test-wpa2e-wpa3e-plki", 1341 WifiConfiguration.SECURITY_TYPE_EAP)); 1342 testConfigs.add(createConfig("test-wpa2e-wpa3e-plki", 1343 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)); 1344 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1345 try { 1346 uiAutomation.adoptShellPermissionIdentity(); 1347 final int originalConfiguredNetworksNumber = mWifiManager.getConfiguredNetworks().size(); 1348 final int originalPrivilegedConfiguredNetworksNumber = 1349 mWifiManager.getPrivilegedConfiguredNetworks().size(); 1350 final int originalCallerConfiguredNetworksNumber = 1351 mWifiManager.getCallerConfiguredNetworks().size(); 1352 for (WifiConfiguration c: testConfigs) { 1353 WifiManager.AddNetworkResult result = mWifiManager.addNetworkPrivileged(c); 1354 assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode); 1355 assertTrue(result.networkId >= 0); 1356 c.networkId = result.networkId; 1357 } 1358 List<WifiConfiguration> expectedConfigs = testConfigs; 1359 if (SdkLevel.isAtLeastS()) { 1360 // open/owe, psk/sae, and wpa2e/wpa3e should be merged 1361 // so they should have the same network ID. 1362 assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId); 1363 assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId); 1364 assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId); 1365 } else { 1366 // Network IDs for different security types should be unique for R 1367 assertNotEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId); 1368 assertNotEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId); 1369 assertNotEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId); 1370 // WPA3-Enterprise is omitted when WPA2-Enterprise is present for R 1371 expectedConfigs = testConfigs.subList(0, 5); 1372 } 1373 List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks(); 1374 assertEquals(originalConfiguredNetworksNumber + expectedConfigs.size(), 1375 configuredNetworks.size()); 1376 assertConfigsAreFound(expectedConfigs, configuredNetworks); 1377 1378 List<WifiConfiguration> privilegedConfiguredNetworks = 1379 mWifiManager.getPrivilegedConfiguredNetworks(); 1380 assertEquals(originalPrivilegedConfiguredNetworksNumber + expectedConfigs.size(), 1381 privilegedConfiguredNetworks.size()); 1382 assertConfigsAreFound(expectedConfigs, privilegedConfiguredNetworks); 1383 1384 List<WifiConfiguration> callerConfiguredNetworks = 1385 mWifiManager.getCallerConfiguredNetworks(); 1386 assertEquals(originalCallerConfiguredNetworksNumber + expectedConfigs.size(), 1387 callerConfiguredNetworks.size()); 1388 assertConfigsAreFound(expectedConfigs, callerConfiguredNetworks); 1389 1390 } finally { 1391 for (WifiConfiguration c: testConfigs) { 1392 if (c.networkId >= 0) { 1393 mWifiManager.removeNetwork(c.networkId); 1394 } 1395 } 1396 uiAutomation.dropShellPermissionIdentity(); 1397 } 1398 } 1399 1400 /** 1401 * Verify that applications can only have one registered LocalOnlyHotspot request at a time. 1402 * 1403 * Note: Location mode must be enabled for this test. 1404 */ testStartLocalOnlyHotspotSingleRequestByApps()1405 public void testStartLocalOnlyHotspotSingleRequestByApps() throws Exception { 1406 if (!WifiFeature.isWifiSupported(getContext())) { 1407 // skip the test if WiFi is not supported 1408 return; 1409 } 1410 // check that softap mode is supported by the device 1411 if (!mWifiManager.isPortableHotspotSupported()) { 1412 return; 1413 } 1414 1415 boolean caughtException = false; 1416 1417 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1418 1419 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 1420 1421 // now make a second request - this should fail. 1422 TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLock); 1423 try { 1424 mWifiManager.startLocalOnlyHotspot(callback2, null); 1425 } catch (IllegalStateException e) { 1426 Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice"); 1427 caughtException = true; 1428 } 1429 if (!caughtException) { 1430 // second start did not fail, should clean up the hotspot. 1431 1432 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization. 1433 // TODO: remove this sleep as soon as b/124330089 is fixed. 1434 Log.d(TAG, "Sleeping for 2 seconds"); 1435 Thread.sleep(2000); 1436 1437 stopLocalOnlyHotspot(callback2, wifiEnabled); 1438 } 1439 assertTrue(caughtException); 1440 1441 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization. 1442 // TODO: remove this sleep as soon as b/124330089 is fixed. 1443 Log.d(TAG, "Sleeping for 2 seconds"); 1444 Thread.sleep(2000); 1445 1446 stopLocalOnlyHotspot(callback, wifiEnabled); 1447 } 1448 1449 private static class TestExecutor implements Executor { 1450 private ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>(); 1451 1452 @Override execute(Runnable task)1453 public void execute(Runnable task) { 1454 tasks.add(task); 1455 } 1456 runAll()1457 private void runAll() { 1458 Runnable task = tasks.poll(); 1459 while (task != null) { 1460 task.run(); 1461 task = tasks.poll(); 1462 } 1463 } 1464 } 1465 testStartLocalOnlyHotspotWithConfigBssid()1466 public void testStartLocalOnlyHotspotWithConfigBssid() throws Exception { 1467 if (!WifiFeature.isWifiSupported(getContext())) { 1468 // skip the test if WiFi is not supported 1469 return; 1470 } 1471 // check that softap mode is supported by the device 1472 if (!mWifiManager.isPortableHotspotSupported()) { 1473 return; 1474 } 1475 1476 TestExecutor executor = new TestExecutor(); 1477 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 1478 TestSoftApCallback capabilityCallback = new TestSoftApCallback(mLock); 1479 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1480 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1481 try { 1482 uiAutomation.adoptShellPermissionIdentity(); 1483 verifyRegisterSoftApCallback(executor, capabilityCallback); 1484 SoftApConfiguration.Builder customConfigBuilder = new SoftApConfiguration.Builder() 1485 .setSsid(TEST_SSID_UNQUOTED) 1486 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); 1487 1488 boolean isSupportCustomizedMac = capabilityCallback.getCurrentSoftApCapability() 1489 .areFeaturesSupported( 1490 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 1491 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 1492 if (isSupportCustomizedMac) { 1493 customConfigBuilder.setBssid(TEST_MAC); 1494 } 1495 SoftApConfiguration customConfig = customConfigBuilder.build(); 1496 1497 mWifiManager.startLocalOnlyHotspot(customConfig, executor, callback); 1498 // now wait for callback 1499 Thread.sleep(TEST_WAIT_DURATION_MS); 1500 1501 // Verify callback is run on the supplied executor 1502 assertFalse(callback.onStartedCalled); 1503 executor.runAll(); 1504 assertTrue(callback.onStartedCalled); 1505 1506 assertNotNull(callback.reservation); 1507 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 1508 assertNotNull(softApConfig); 1509 if (isSupportCustomizedMac) { 1510 assertEquals(TEST_MAC, softApConfig.getBssid()); 1511 } 1512 assertEquals(TEST_SSID_UNQUOTED, softApConfig.getSsid()); 1513 assertEquals(TEST_PASSPHRASE, softApConfig.getPassphrase()); 1514 } finally { 1515 // clean up 1516 stopLocalOnlyHotspot(callback, wifiEnabled); 1517 mWifiManager.unregisterSoftApCallback(capabilityCallback); 1518 uiAutomation.dropShellPermissionIdentity(); 1519 } 1520 } 1521 testStartLocalOnlyHotspotWithNullBssidConfig()1522 public void testStartLocalOnlyHotspotWithNullBssidConfig() throws Exception { 1523 if (!WifiFeature.isWifiSupported(getContext())) { 1524 // skip the test if WiFi is not supported 1525 return; 1526 } 1527 // check that softap mode is supported by the device 1528 if (!mWifiManager.isPortableHotspotSupported()) { 1529 return; 1530 } 1531 SoftApConfiguration customConfig = new SoftApConfiguration.Builder() 1532 .setSsid(TEST_SSID_UNQUOTED) 1533 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 1534 .build(); 1535 TestExecutor executor = new TestExecutor(); 1536 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 1537 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1538 boolean wifiEnabled = mWifiManager.isWifiEnabled(); 1539 try { 1540 uiAutomation.adoptShellPermissionIdentity(); 1541 1542 mWifiManager.startLocalOnlyHotspot(customConfig, executor, callback); 1543 // now wait for callback 1544 Thread.sleep(TEST_WAIT_DURATION_MS); 1545 1546 // Verify callback is run on the supplied executor 1547 assertFalse(callback.onStartedCalled); 1548 executor.runAll(); 1549 assertTrue(callback.onStartedCalled); 1550 1551 assertNotNull(callback.reservation); 1552 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 1553 assertNotNull(softApConfig); 1554 assertEquals(TEST_SSID_UNQUOTED, softApConfig.getSsid()); 1555 assertEquals(TEST_PASSPHRASE, softApConfig.getPassphrase()); 1556 } finally { 1557 // clean up 1558 stopLocalOnlyHotspot(callback, wifiEnabled); 1559 uiAutomation.dropShellPermissionIdentity(); 1560 } 1561 } 1562 1563 /** 1564 * Read the content of the given resource file into a String. 1565 * 1566 * @param filename String name of the file 1567 * @return String 1568 * @throws IOException 1569 */ loadResourceFile(String filename)1570 private String loadResourceFile(String filename) throws IOException { 1571 InputStream in = getClass().getClassLoader().getResourceAsStream(filename); 1572 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 1573 StringBuilder builder = new StringBuilder(); 1574 String line; 1575 while ((line = reader.readLine()) != null) { 1576 builder.append(line).append("\n"); 1577 } 1578 return builder.toString(); 1579 } 1580 1581 /** 1582 * Verify that changing the mac randomization setting of a Passpoint configuration. 1583 */ testMacRandomizationSettingPasspoint()1584 public void testMacRandomizationSettingPasspoint() throws Exception { 1585 if (!WifiFeature.isWifiSupported(getContext())) { 1586 // skip the test if WiFi is not supported 1587 return; 1588 } 1589 String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT); 1590 PasspointConfiguration config = 1591 ConfigParser.parsePasspointConfig(TYPE_WIFI_CONFIG, configStr.getBytes()); 1592 String fqdn = config.getHomeSp().getFqdn(); 1593 String uniqueId = config.getUniqueId(); 1594 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1595 try { 1596 uiAutomation.adoptShellPermissionIdentity(); 1597 1598 mWifiManager.addOrUpdatePasspointConfiguration(config); 1599 PasspointConfiguration passpointConfig = getTargetPasspointConfiguration( 1600 mWifiManager.getPasspointConfigurations(), uniqueId); 1601 assertNotNull("The installed passpoint profile is missing", passpointConfig); 1602 assertTrue("Mac randomization should be enabled for passpoint networks by default.", 1603 passpointConfig.isMacRandomizationEnabled()); 1604 1605 mWifiManager.setMacRandomizationSettingPasspointEnabled(fqdn, false); 1606 passpointConfig = getTargetPasspointConfiguration( 1607 mWifiManager.getPasspointConfigurations(), uniqueId); 1608 assertNotNull("The installed passpoint profile is missing", passpointConfig); 1609 assertFalse("Mac randomization should be disabled by the API call.", 1610 passpointConfig.isMacRandomizationEnabled()); 1611 } finally { 1612 // Clean up 1613 mWifiManager.removePasspointConfiguration(fqdn); 1614 uiAutomation.dropShellPermissionIdentity(); 1615 } 1616 } 1617 /** 1618 * Verify that the {@link android.Manifest.permission#NETWORK_STACK} permission is never held by 1619 * any package. 1620 * <p> 1621 * No apps should <em>ever</em> attempt to acquire this permission, since it would give those 1622 * apps extremely broad access to connectivity functionality. 1623 */ testNetworkStackPermission()1624 public void testNetworkStackPermission() { 1625 if (!WifiFeature.isWifiSupported(getContext())) { 1626 // skip the test if WiFi is not supported 1627 return; 1628 } 1629 final PackageManager pm = getContext().getPackageManager(); 1630 1631 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1632 android.Manifest.permission.NETWORK_STACK 1633 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1634 for (PackageInfo pi : holding) { 1635 fail("The NETWORK_STACK permission must not be held by " + pi.packageName 1636 + " and must be revoked for security reasons"); 1637 } 1638 } 1639 1640 /** 1641 * Verify that the {@link android.Manifest.permission#NETWORK_SETTINGS} permission is 1642 * never held by any package. 1643 * <p> 1644 * Only Settings, SysUi, NetworkStack and shell apps should <em>ever</em> attempt to acquire 1645 * this permission, since it would give those apps extremely broad access to connectivity 1646 * functionality. The permission is intended to be granted to only those apps with direct user 1647 * access and no others. 1648 */ testNetworkSettingsPermission()1649 public void testNetworkSettingsPermission() { 1650 if (!WifiFeature.isWifiSupported(getContext())) { 1651 // skip the test if WiFi is not supported 1652 return; 1653 } 1654 final PackageManager pm = getContext().getPackageManager(); 1655 1656 final ArraySet<String> allowedPackages = new ArraySet(); 1657 final ArraySet<Integer> allowedUIDs = new ArraySet(); 1658 // explicitly add allowed UIDs 1659 allowedUIDs.add(Process.SYSTEM_UID); 1660 allowedUIDs.add(Process.SHELL_UID); 1661 allowedUIDs.add(Process.PHONE_UID); 1662 allowedUIDs.add(Process.NETWORK_STACK_UID); 1663 allowedUIDs.add(Process.NFC_UID); 1664 1665 // only quick settings is allowed to bind to the BIND_QUICK_SETTINGS_TILE permission, using 1666 // this fact to determined allowed package name for sysui. This is a signature permission, 1667 // so allow any package with this permission. 1668 final List<PackageInfo> sysuiPackages = pm.getPackagesHoldingPermissions(new String[] { 1669 android.Manifest.permission.BIND_QUICK_SETTINGS_TILE 1670 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1671 for (PackageInfo info : sysuiPackages) { 1672 allowedPackages.add(info.packageName); 1673 } 1674 1675 // the captive portal flow also currently holds the NETWORK_SETTINGS permission 1676 final Intent intent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); 1677 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 1678 if (ri != null) { 1679 allowedPackages.add(ri.activityInfo.packageName); 1680 } 1681 1682 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1683 android.Manifest.permission.NETWORK_SETTINGS 1684 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1685 StringBuilder stringBuilder = new StringBuilder(); 1686 for (PackageInfo pi : holding) { 1687 String packageName = pi.packageName; 1688 1689 // this is an explicitly allowed package 1690 if (allowedPackages.contains(packageName)) continue; 1691 1692 // now check if the packages are from allowed UIDs 1693 int uid = -1; 1694 try { 1695 uid = pm.getPackageUidAsUser(packageName, UserHandle.USER_SYSTEM); 1696 } catch (PackageManager.NameNotFoundException e) { 1697 continue; 1698 } 1699 if (!allowedUIDs.contains(uid)) { 1700 stringBuilder.append("The NETWORK_SETTINGS permission must not be held by " 1701 + packageName + ":" + uid + " and must be revoked for security reasons\n"); 1702 } 1703 } 1704 if (stringBuilder.length() > 0) { 1705 fail(stringBuilder.toString()); 1706 } 1707 } 1708 1709 /** 1710 * Verify that the {@link android.Manifest.permission#NETWORK_SETUP_WIZARD} permission is 1711 * only held by the device setup wizard application. 1712 * <p> 1713 * Only the SetupWizard app should <em>ever</em> attempt to acquire this 1714 * permission, since it would give those apps extremely broad access to connectivity 1715 * functionality. The permission is intended to be granted to only the device setup wizard. 1716 */ testNetworkSetupWizardPermission()1717 public void testNetworkSetupWizardPermission() { 1718 if (!WifiFeature.isWifiSupported(getContext())) { 1719 // skip the test if WiFi is not supported 1720 return; 1721 } 1722 final ArraySet<String> allowedPackages = new ArraySet(); 1723 1724 final PackageManager pm = getContext().getPackageManager(); 1725 1726 final Intent intent = new Intent(Intent.ACTION_MAIN); 1727 intent.addCategory(Intent.CATEGORY_SETUP_WIZARD); 1728 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 1729 String validPkg = ""; 1730 if (ri != null) { 1731 allowedPackages.add(ri.activityInfo.packageName); 1732 validPkg = ri.activityInfo.packageName; 1733 } 1734 1735 final Intent preIntent = new Intent("com.android.setupwizard.OEM_PRE_SETUP"); 1736 preIntent.addCategory(Intent.CATEGORY_DEFAULT); 1737 final ResolveInfo preRi = pm 1738 .resolveActivity(preIntent, PackageManager.MATCH_DISABLED_COMPONENTS); 1739 String prePackageName = ""; 1740 if (null != preRi) { 1741 prePackageName = preRi.activityInfo.packageName; 1742 } 1743 1744 final Intent postIntent = new Intent("com.android.setupwizard.OEM_POST_SETUP"); 1745 postIntent.addCategory(Intent.CATEGORY_DEFAULT); 1746 final ResolveInfo postRi = pm 1747 .resolveActivity(postIntent, PackageManager.MATCH_DISABLED_COMPONENTS); 1748 String postPackageName = ""; 1749 if (null != postRi) { 1750 postPackageName = postRi.activityInfo.packageName; 1751 } 1752 if (!TextUtils.isEmpty(prePackageName) && !TextUtils.isEmpty(postPackageName) 1753 && prePackageName.equals(postPackageName)) { 1754 allowedPackages.add(prePackageName); 1755 } 1756 1757 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[]{ 1758 android.Manifest.permission.NETWORK_SETUP_WIZARD 1759 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1760 for (PackageInfo pi : holding) { 1761 if (!allowedPackages.contains(pi.packageName)) { 1762 fail("The NETWORK_SETUP_WIZARD permission must not be held by " + pi.packageName 1763 + " and must be revoked for security reasons [" + validPkg + "]"); 1764 } 1765 } 1766 } 1767 1768 /** 1769 * Verify that the {@link android.Manifest.permission#NETWORK_MANAGED_PROVISIONING} permission 1770 * is only held by the device managed provisioning application. 1771 * <p> 1772 * Only the ManagedProvisioning app should <em>ever</em> attempt to acquire this 1773 * permission, since it would give those apps extremely broad access to connectivity 1774 * functionality. The permission is intended to be granted to only the device managed 1775 * provisioning. 1776 */ testNetworkManagedProvisioningPermission()1777 public void testNetworkManagedProvisioningPermission() { 1778 if (!WifiFeature.isWifiSupported(getContext())) { 1779 // skip the test if WiFi is not supported 1780 return; 1781 } 1782 final PackageManager pm = getContext().getPackageManager(); 1783 1784 // TODO(b/115980767): Using hardcoded package name. Need a better mechanism to find the 1785 // managed provisioning app. 1786 // Ensure that the package exists. 1787 final Intent intent = new Intent(Intent.ACTION_MAIN); 1788 intent.setPackage(MANAGED_PROVISIONING_PACKAGE_NAME); 1789 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 1790 String validPkg = ""; 1791 if (ri != null) { 1792 validPkg = ri.activityInfo.packageName; 1793 } 1794 1795 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1796 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 1797 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1798 for (PackageInfo pi : holding) { 1799 if (!Objects.equals(pi.packageName, validPkg)) { 1800 fail("The NETWORK_MANAGED_PROVISIONING permission must not be held by " 1801 + pi.packageName + " and must be revoked for security reasons [" 1802 + validPkg +"]"); 1803 } 1804 } 1805 } 1806 1807 /** 1808 * Verify that the {@link android.Manifest.permission#WIFI_SET_DEVICE_MOBILITY_STATE} permission 1809 * is held by at most one application. 1810 */ testWifiSetDeviceMobilityStatePermission()1811 public void testWifiSetDeviceMobilityStatePermission() { 1812 if (!WifiFeature.isWifiSupported(getContext())) { 1813 // skip the test if WiFi is not supported 1814 return; 1815 } 1816 final PackageManager pm = getContext().getPackageManager(); 1817 1818 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1819 android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE 1820 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1821 1822 List<String> uniquePackageNames = holding 1823 .stream() 1824 .map(pi -> pi.packageName) 1825 .distinct() 1826 .collect(Collectors.toList()); 1827 1828 if (uniquePackageNames.size() > 1) { 1829 fail("The WIFI_SET_DEVICE_MOBILITY_STATE permission must not be held by more than one " 1830 + "application, but is held by " + uniquePackageNames.size() + " applications: " 1831 + String.join(", ", uniquePackageNames)); 1832 } 1833 } 1834 1835 /** 1836 * Verify that the {@link android.Manifest.permission#NETWORK_CARRIER_PROVISIONING} permission 1837 * is held by at most one application. 1838 */ testNetworkCarrierProvisioningPermission()1839 public void testNetworkCarrierProvisioningPermission() { 1840 if (!WifiFeature.isWifiSupported(getContext())) { 1841 // skip the test if WiFi is not supported 1842 return; 1843 } 1844 final PackageManager pm = getContext().getPackageManager(); 1845 1846 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1847 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 1848 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1849 1850 List<String> uniquePackageNames = holding 1851 .stream() 1852 .map(pi -> pi.packageName) 1853 .distinct() 1854 .collect(Collectors.toList()); 1855 1856 if (uniquePackageNames.size() > 2) { 1857 fail("The NETWORK_CARRIER_PROVISIONING permission must not be held by more than two " 1858 + "applications, but is held by " + uniquePackageNames.size() + " applications: " 1859 + String.join(", ", uniquePackageNames)); 1860 } 1861 } 1862 1863 /** 1864 * Verify that the {@link android.Manifest.permission#WIFI_UPDATE_USABILITY_STATS_SCORE} 1865 * permission is held by at most one application. 1866 */ testUpdateWifiUsabilityStatsScorePermission()1867 public void testUpdateWifiUsabilityStatsScorePermission() { 1868 if (!WifiFeature.isWifiSupported(getContext())) { 1869 // skip the test if WiFi is not supported 1870 return; 1871 } 1872 final PackageManager pm = getContext().getPackageManager(); 1873 1874 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 1875 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE 1876 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 1877 1878 Set<String> uniqueNonSystemPackageNames = new HashSet<>(); 1879 for (PackageInfo pi : holding) { 1880 String packageName = pi.packageName; 1881 // Shell is allowed to hold this permission for testing. 1882 int uid = -1; 1883 try { 1884 uid = pm.getPackageUidAsUser(packageName, UserHandle.USER_SYSTEM); 1885 } catch (PackageManager.NameNotFoundException e) { 1886 continue; 1887 } 1888 if (uid == Process.SHELL_UID) continue; 1889 1890 uniqueNonSystemPackageNames.add(packageName); 1891 } 1892 1893 if (uniqueNonSystemPackageNames.size() > 1) { 1894 fail("The WIFI_UPDATE_USABILITY_STATS_SCORE permission must not be held by more than " 1895 + "one application, but is held by " + uniqueNonSystemPackageNames.size() 1896 + " applications: " + String.join(", ", uniqueNonSystemPackageNames)); 1897 } 1898 } 1899 turnScreenOnNoDelay()1900 private void turnScreenOnNoDelay() throws Exception { 1901 mUiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP"); 1902 mUiDevice.executeShellCommand("wm dismiss-keyguard"); 1903 } 1904 turnScreenOn()1905 private void turnScreenOn() throws Exception { 1906 turnScreenOnNoDelay(); 1907 // Since the screen on/off intent is ordered, they will not be sent right now. 1908 Thread.sleep(DURATION_SCREEN_TOGGLE); 1909 } 1910 turnScreenOffNoDelay()1911 private void turnScreenOffNoDelay() throws Exception { 1912 mUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP"); 1913 } 1914 turnScreenOff()1915 private void turnScreenOff() throws Exception { 1916 turnScreenOffNoDelay(); 1917 // Since the screen on/off intent is ordered, they will not be sent right now. 1918 Thread.sleep(DURATION_SCREEN_TOGGLE); 1919 } 1920 assertWifiScanningIsOn()1921 private void assertWifiScanningIsOn() { 1922 if (!mWifiManager.isScanAlwaysAvailable()) { 1923 fail("Wi-Fi scanning should be on."); 1924 } 1925 } 1926 runWithScanningEnabled(ThrowingRunnable r)1927 private void runWithScanningEnabled(ThrowingRunnable r) throws Exception { 1928 boolean wasScanEnabledForTest = false; 1929 if (!mWifiManager.isScanAlwaysAvailable()) { 1930 ShellIdentityUtils.invokeWithShellPermissions( 1931 () -> mWifiManager.setScanAlwaysAvailable(true)); 1932 wasScanEnabledForTest = true; 1933 } 1934 try { 1935 r.run(); 1936 } finally { 1937 if (wasScanEnabledForTest) { 1938 ShellIdentityUtils.invokeWithShellPermissions( 1939 () -> mWifiManager.setScanAlwaysAvailable(false)); 1940 } 1941 } 1942 } 1943 1944 /** 1945 * Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is disabled 1946 * but location is on. 1947 * @throws Exception 1948 */ testScreenOffDoesNotTurnOffWifiScanningWhenWifiDisabled()1949 public void testScreenOffDoesNotTurnOffWifiScanningWhenWifiDisabled() throws Exception { 1950 if (FeatureUtil.isTV() || FeatureUtil.isAutomotive()) { 1951 // TV and auto do not support the setting options of WIFI scanning and Bluetooth 1952 // scanning 1953 return; 1954 } 1955 if (!WifiFeature.isWifiSupported(getContext())) { 1956 // skip the test if WiFi is not supported 1957 return; 1958 } 1959 if (!hasLocationFeature()) { 1960 // skip the test if location is not supported 1961 return; 1962 } 1963 if (!isLocationEnabled()) { 1964 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 1965 + " empty when location is disabled!"); 1966 } 1967 runWithScanningEnabled(() -> { 1968 setWifiEnabled(false); 1969 turnScreenOn(); 1970 assertWifiScanningIsOn(); 1971 // Toggle screen and verify Wi-Fi scanning is still on. 1972 turnScreenOff(); 1973 assertWifiScanningIsOn(); 1974 turnScreenOn(); 1975 assertWifiScanningIsOn(); 1976 }); 1977 } 1978 1979 /** 1980 * Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is enabled. 1981 * @throws Exception 1982 */ testScreenOffDoesNotTurnOffWifiScanningWhenWifiEnabled()1983 public void testScreenOffDoesNotTurnOffWifiScanningWhenWifiEnabled() throws Exception { 1984 if (FeatureUtil.isTV() || FeatureUtil.isAutomotive()) { 1985 // TV and auto do not support the setting options of WIFI scanning and Bluetooth 1986 // scanning 1987 return; 1988 } 1989 if (!WifiFeature.isWifiSupported(getContext())) { 1990 // skip the test if WiFi is not supported 1991 return; 1992 } 1993 if (!hasLocationFeature()) { 1994 // skip the test if location is not supported 1995 return; 1996 } 1997 if (!isLocationEnabled()) { 1998 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 1999 + " empty when location is disabled!"); 2000 } 2001 runWithScanningEnabled(() -> { 2002 setWifiEnabled(true); 2003 turnScreenOn(); 2004 assertWifiScanningIsOn(); 2005 // Toggle screen and verify Wi-Fi scanning is still on. 2006 turnScreenOff(); 2007 assertWifiScanningIsOn(); 2008 turnScreenOn(); 2009 assertWifiScanningIsOn(); 2010 }); 2011 } 2012 2013 /** 2014 * Verify that the platform supports a reasonable number of suggestions per app. 2015 * @throws Exception 2016 */ testMaxNumberOfNetworkSuggestionsPerApp()2017 public void testMaxNumberOfNetworkSuggestionsPerApp() throws Exception { 2018 if (!WifiFeature.isWifiSupported(getContext())) { 2019 // skip the test if WiFi is not supported 2020 return; 2021 } 2022 assertTrue(mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp() 2023 > ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP); 2024 } 2025 verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback)2026 private void verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback) 2027 throws Exception { 2028 // Register callback to get SoftApCapability 2029 mWifiManager.registerSoftApCallback(executor, callback); 2030 PollingCheck.check( 2031 "SoftAp register failed!", 5_000, 2032 () -> { 2033 executor.runAll(); 2034 // Verify callback is run on the supplied executor and called 2035 return callback.getOnStateChangedCalled() && 2036 callback.getOnSoftapInfoChangedCalledCount() > 0 && 2037 callback.getOnSoftApCapabilityChangedCalled() && 2038 callback.getOnConnectedClientCalled(); 2039 }); 2040 } 2041 verifySetGetSoftApConfig(SoftApConfiguration targetConfig)2042 private void verifySetGetSoftApConfig(SoftApConfiguration targetConfig) { 2043 mWifiManager.setSoftApConfiguration(targetConfig); 2044 // Bssid set dodesn't support for tethered hotspot 2045 SoftApConfiguration currentConfig = mWifiManager.getSoftApConfiguration(); 2046 compareSoftApConfiguration(targetConfig, currentConfig); 2047 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2048 assertTrue(currentConfig.isUserConfiguration()); 2049 } 2050 } 2051 compareSoftApConfiguration(SoftApConfiguration currentConfig, SoftApConfiguration testSoftApConfig)2052 private void compareSoftApConfiguration(SoftApConfiguration currentConfig, 2053 SoftApConfiguration testSoftApConfig) { 2054 assertEquals(currentConfig.getSsid(), testSoftApConfig.getSsid()); 2055 assertEquals(currentConfig.getBssid(), testSoftApConfig.getBssid()); 2056 assertEquals(currentConfig.getSecurityType(), testSoftApConfig.getSecurityType()); 2057 assertEquals(currentConfig.getPassphrase(), testSoftApConfig.getPassphrase()); 2058 assertEquals(currentConfig.isHiddenSsid(), testSoftApConfig.isHiddenSsid()); 2059 assertEquals(currentConfig.getBand(), testSoftApConfig.getBand()); 2060 assertEquals(currentConfig.getChannel(), testSoftApConfig.getChannel()); 2061 assertEquals(currentConfig.getMaxNumberOfClients(), 2062 testSoftApConfig.getMaxNumberOfClients()); 2063 assertEquals(currentConfig.isAutoShutdownEnabled(), 2064 testSoftApConfig.isAutoShutdownEnabled()); 2065 assertEquals(currentConfig.getShutdownTimeoutMillis(), 2066 testSoftApConfig.getShutdownTimeoutMillis()); 2067 assertEquals(currentConfig.isClientControlByUserEnabled(), 2068 testSoftApConfig.isClientControlByUserEnabled()); 2069 assertEquals(currentConfig.getAllowedClientList(), 2070 testSoftApConfig.getAllowedClientList()); 2071 assertEquals(currentConfig.getBlockedClientList(), 2072 testSoftApConfig.getBlockedClientList()); 2073 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2074 assertEquals(currentConfig.getMacRandomizationSetting(), 2075 testSoftApConfig.getMacRandomizationSetting()); 2076 assertEquals(currentConfig.getChannels().toString(), 2077 testSoftApConfig.getChannels().toString()); 2078 assertEquals(currentConfig.isBridgedModeOpportunisticShutdownEnabled(), 2079 testSoftApConfig.isBridgedModeOpportunisticShutdownEnabled()); 2080 assertEquals(currentConfig.isIeee80211axEnabled(), 2081 testSoftApConfig.isIeee80211axEnabled()); 2082 } 2083 } 2084 turnOffWifiAndTetheredHotspotIfEnabled()2085 private void turnOffWifiAndTetheredHotspotIfEnabled() throws Exception { 2086 if (mWifiManager.isWifiEnabled()) { 2087 Log.d(TAG, "Turn off WiFi"); 2088 mWifiManager.setWifiEnabled(false); 2089 PollingCheck.check( 2090 "Wifi turn off failed!", 2_000, 2091 () -> mWifiManager.isWifiEnabled() == false); 2092 } 2093 if (mWifiManager.isWifiApEnabled()) { 2094 mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2095 Log.d(TAG, "Turn off tethered Hotspot"); 2096 PollingCheck.check( 2097 "SoftAp turn off failed!", 2_000, 2098 () -> mWifiManager.isWifiApEnabled() == false); 2099 mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2100 } 2101 } 2102 verifyBridgedModeSoftApCallback(TestExecutor executor, TestSoftApCallback callback, boolean shouldFallbackSingleApMode, boolean isEnabled)2103 private void verifyBridgedModeSoftApCallback(TestExecutor executor, 2104 TestSoftApCallback callback, boolean shouldFallbackSingleApMode, boolean isEnabled) 2105 throws Exception { 2106 // Verify state and info callback value as expected 2107 PollingCheck.check( 2108 "SoftAp state and info on bridged AP mode are mismatch!!!" 2109 + " shouldFallbackSingleApMode = " + shouldFallbackSingleApMode 2110 + ", isEnabled = " + isEnabled, 10_000, 2111 () -> { 2112 executor.runAll(); 2113 int expectedState = isEnabled ? WifiManager.WIFI_AP_STATE_ENABLED 2114 : WifiManager.WIFI_AP_STATE_DISABLED; 2115 int expectedInfoSize = isEnabled 2116 ? (shouldFallbackSingleApMode ? 1 : 2) : 0; 2117 return expectedState == callback.getCurrentState() 2118 && callback.getCurrentSoftApInfoList().size() == expectedInfoSize; 2119 }); 2120 } 2121 shouldFallbackToSingleAp(int[] bands, SoftApCapability capability)2122 private boolean shouldFallbackToSingleAp(int[] bands, SoftApCapability capability) { 2123 for (int band : bands) { 2124 if (capability.getSupportedChannelList(band).length == 0) { 2125 return true; 2126 } 2127 } 2128 return false; 2129 } 2130 getAvailableBandAndChannelForTesting(SoftApCapability capability)2131 private SparseIntArray getAvailableBandAndChannelForTesting(SoftApCapability capability) { 2132 final int[] bands = {SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_5GHZ, 2133 SoftApConfiguration.BAND_6GHZ, SoftApConfiguration.BAND_60GHZ}; 2134 SparseIntArray testBandsAndChannels = new SparseIntArray(); 2135 if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2136 testBandsAndChannels.put(SoftApConfiguration.BAND_2GHZ, 1); 2137 return testBandsAndChannels; 2138 } 2139 for (int band : bands) { 2140 int[] supportedList = capability.getSupportedChannelList(band); 2141 if (supportedList.length != 0) { 2142 testBandsAndChannels.put(band, supportedList[0]); 2143 } 2144 } 2145 return testBandsAndChannels; 2146 } 2147 2148 2149 /** 2150 * Test bridged AP enable succeeful when device supports it. 2151 * Also verify the callback info update correctly. 2152 * @throws Exception 2153 */ 2154 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testTetheredBridgedAp()2155 public void testTetheredBridgedAp() throws Exception { 2156 // check that softap bridged mode is supported by the device 2157 if (!mWifiManager.isBridgedApConcurrencySupported()) { 2158 return; 2159 } 2160 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2161 TestExecutor executor = new TestExecutor(); 2162 TestSoftApCallback callback = new TestSoftApCallback(mLock); 2163 try { 2164 uiAutomation.adoptShellPermissionIdentity(); 2165 // Off/On Wifi to make sure that we get the supported channel 2166 turnOffWifiAndTetheredHotspotIfEnabled(); 2167 mWifiManager.setWifiEnabled(true); 2168 PollingCheck.check( 2169 "Wifi turn on failed!", 2_000, 2170 () -> mWifiManager.isWifiEnabled() == true); 2171 turnOffWifiAndTetheredHotspotIfEnabled(); 2172 verifyRegisterSoftApCallback(executor, callback); 2173 int[] testBands = {SoftApConfiguration.BAND_2GHZ, 2174 SoftApConfiguration.BAND_5GHZ}; 2175 int[] expectedBands = {SoftApConfiguration.BAND_2GHZ, 2176 SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ}; 2177 // Test bridged SoftApConfiguration set and get (setBands) 2178 SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder() 2179 .setSsid(TEST_SSID_UNQUOTED) 2180 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 2181 .setBands(expectedBands) 2182 .build(); 2183 boolean shouldFallbackToSingleAp = shouldFallbackToSingleAp(testBands, 2184 callback.getCurrentSoftApCapability()); 2185 verifySetGetSoftApConfig(testSoftApConfig); 2186 2187 // start tethering which used to verify startTetheredHotspot 2188 mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 2189 new TetheringManager.StartTetheringCallback() { 2190 @Override 2191 public void onTetheringFailed(final int result) { 2192 } 2193 }); 2194 verifyBridgedModeSoftApCallback(executor, callback, 2195 shouldFallbackToSingleAp, true /* enabled */); 2196 // stop tethering which used to verify stopSoftAp 2197 mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2198 verifyBridgedModeSoftApCallback(executor, callback, 2199 shouldFallbackToSingleAp, false /* disabled */); 2200 } finally { 2201 mWifiManager.unregisterSoftApCallback(callback); 2202 uiAutomation.dropShellPermissionIdentity(); 2203 } 2204 } 2205 2206 /** 2207 * Test bridged AP with forced channel config enable succeeful when device supports it. 2208 * Also verify the callback info update correctly. 2209 * @throws Exception 2210 */ 2211 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testTetheredBridgedApWifiForcedChannel()2212 public void testTetheredBridgedApWifiForcedChannel() throws Exception { 2213 // check that softap bridged mode is supported by the device 2214 if (!mWifiManager.isBridgedApConcurrencySupported()) { 2215 return; 2216 } 2217 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2218 TestExecutor executor = new TestExecutor(); 2219 TestSoftApCallback callback = new TestSoftApCallback(mLock); 2220 try { 2221 uiAutomation.adoptShellPermissionIdentity(); 2222 // Off/On Wifi to make sure that we get the supported channel 2223 turnOffWifiAndTetheredHotspotIfEnabled(); 2224 mWifiManager.setWifiEnabled(true); 2225 PollingCheck.check( 2226 "Wifi turn on failed!", 2_000, 2227 () -> mWifiManager.isWifiEnabled() == true); 2228 turnOffWifiAndTetheredHotspotIfEnabled(); 2229 verifyRegisterSoftApCallback(executor, callback); 2230 2231 boolean shouldFallbackToSingleAp = shouldFallbackToSingleAp( 2232 new int[] {SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_5GHZ}, 2233 callback.getCurrentSoftApCapability()); 2234 2235 // Test when there are supported channels in both of the bands. 2236 if (!shouldFallbackToSingleAp) { 2237 // Test bridged SoftApConfiguration set and get (setChannels) 2238 SparseIntArray dual_channels = new SparseIntArray(2); 2239 dual_channels.put(SoftApConfiguration.BAND_2GHZ, 2240 callback.getCurrentSoftApCapability() 2241 .getSupportedChannelList(SoftApConfiguration.BAND_2GHZ)[0]); 2242 dual_channels.put(SoftApConfiguration.BAND_5GHZ, 2243 callback.getCurrentSoftApCapability() 2244 .getSupportedChannelList(SoftApConfiguration.BAND_5GHZ)[0]); 2245 SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder() 2246 .setSsid(TEST_SSID_UNQUOTED) 2247 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 2248 .setChannels(dual_channels) 2249 .build(); 2250 2251 verifySetGetSoftApConfig(testSoftApConfig); 2252 2253 // start tethering which used to verify startTetheredHotspot 2254 mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 2255 new TetheringManager.StartTetheringCallback() { 2256 @Override 2257 public void onTetheringFailed(final int result) { 2258 } 2259 }); 2260 verifyBridgedModeSoftApCallback(executor, callback, 2261 shouldFallbackToSingleAp, true /* enabled */); 2262 // stop tethering which used to verify stopSoftAp 2263 mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2264 verifyBridgedModeSoftApCallback(executor, callback, 2265 shouldFallbackToSingleAp, false /* disabled */); 2266 } 2267 } finally { 2268 mWifiManager.unregisterSoftApCallback(callback); 2269 uiAutomation.dropShellPermissionIdentity(); 2270 } 2271 } 2272 2273 /** 2274 * Verify that the configuration from getSoftApConfiguration is same as the configuration which 2275 * set by setSoftApConfiguration. And depends softap capability callback to test different 2276 * configuration. 2277 * @throws Exception 2278 */ 2279 @VirtualDeviceNotSupported testSetGetSoftApConfigurationAndSoftApCapabilityCallback()2280 public void testSetGetSoftApConfigurationAndSoftApCapabilityCallback() throws Exception { 2281 if (!WifiFeature.isWifiSupported(getContext())) { 2282 // skip the test if WiFi is not supported 2283 return; 2284 } 2285 // check that softap mode is supported by the device 2286 if (!mWifiManager.isPortableHotspotSupported()) { 2287 return; 2288 } 2289 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2290 TestExecutor executor = new TestExecutor(); 2291 TestSoftApCallback callback = new TestSoftApCallback(mLock); 2292 try { 2293 uiAutomation.adoptShellPermissionIdentity(); 2294 turnOffWifiAndTetheredHotspotIfEnabled(); 2295 verifyRegisterSoftApCallback(executor, callback); 2296 2297 SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder() 2298 .setSsid(TEST_SSID_UNQUOTED) 2299 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 2300 .setAutoShutdownEnabled(true) 2301 .setShutdownTimeoutMillis(100000) 2302 .setBand(getAvailableBandAndChannelForTesting( 2303 callback.getCurrentSoftApCapability()).keyAt(0)) 2304 .setHiddenSsid(false); 2305 2306 // Test SoftApConfiguration set and get 2307 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2308 2309 boolean isSupportCustomizedMac = callback.getCurrentSoftApCapability() 2310 .areFeaturesSupported( 2311 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 2312 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 2313 2314 //Test MAC_ADDRESS_CUSTOMIZATION supported config 2315 if (isSupportCustomizedMac) { 2316 softApConfigBuilder.setBssid(TEST_MAC) 2317 .setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE); 2318 2319 // Test SoftApConfiguration set and get 2320 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2321 } 2322 2323 // Test CLIENT_FORCE_DISCONNECT supported config. 2324 if (callback.getCurrentSoftApCapability() 2325 .areFeaturesSupported( 2326 SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) { 2327 softApConfigBuilder.setMaxNumberOfClients(10); 2328 softApConfigBuilder.setClientControlByUserEnabled(true); 2329 softApConfigBuilder.setBlockedClientList(new ArrayList<>()); 2330 softApConfigBuilder.setAllowedClientList(new ArrayList<>()); 2331 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2332 } 2333 2334 // Test SAE config 2335 if (callback.getCurrentSoftApCapability() 2336 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) { 2337 softApConfigBuilder 2338 .setPassphrase(TEST_PASSPHRASE, 2339 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); 2340 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2341 softApConfigBuilder 2342 .setPassphrase(TEST_PASSPHRASE, 2343 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); 2344 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2345 } 2346 2347 // Test 11 AX control config. 2348 if (callback.getCurrentSoftApCapability() 2349 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX)) { 2350 softApConfigBuilder.setIeee80211axEnabled(true); 2351 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2352 } 2353 2354 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2355 softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled(false); 2356 verifySetGetSoftApConfig(softApConfigBuilder.build()); 2357 } 2358 2359 } finally { 2360 mWifiManager.unregisterSoftApCallback(callback); 2361 uiAutomation.dropShellPermissionIdentity(); 2362 } 2363 } 2364 2365 /** 2366 * Verify that startTetheredHotspot with specific channel config. 2367 * @throws Exception 2368 */ 2369 @VirtualDeviceNotSupported testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback()2370 public void testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback() 2371 throws Exception { 2372 if (!WifiFeature.isWifiSupported(getContext())) { 2373 // skip the test if WiFi is not supported 2374 return; 2375 } 2376 // check that softap mode is supported by the device 2377 if (!mWifiManager.isPortableHotspotSupported()) { 2378 return; 2379 } 2380 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2381 TestExecutor executor = new TestExecutor(); 2382 TestSoftApCallback callback = new TestSoftApCallback(mLock); 2383 try { 2384 uiAutomation.adoptShellPermissionIdentity(); 2385 // check that tethering is supported by the device 2386 if (!mTetheringManager.isTetheringSupported()) { 2387 return; 2388 } 2389 turnOffWifiAndTetheredHotspotIfEnabled(); 2390 verifyRegisterSoftApCallback(executor, callback); 2391 2392 SparseIntArray testBandsAndChannels = getAvailableBandAndChannelForTesting( 2393 callback.getCurrentSoftApCapability()); 2394 2395 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2396 assertNotEquals(0, testBandsAndChannels.size()); 2397 } 2398 boolean isSupportCustomizedMac = callback.getCurrentSoftApCapability() 2399 .areFeaturesSupported( 2400 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 2401 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 2402 2403 SoftApConfiguration.Builder testSoftApConfigBuilder = new SoftApConfiguration.Builder() 2404 .setSsid(TEST_SSID_UNQUOTED) 2405 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 2406 .setChannel(testBandsAndChannels.valueAt(0), testBandsAndChannels.keyAt(0)); 2407 2408 if (isSupportCustomizedMac) testSoftApConfigBuilder.setBssid(TEST_MAC); 2409 2410 SoftApConfiguration testSoftApConfig = testSoftApConfigBuilder.build(); 2411 2412 mWifiManager.setSoftApConfiguration(testSoftApConfig); 2413 2414 // start tethering which used to verify startTetheredHotspot 2415 mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 2416 new TetheringManager.StartTetheringCallback() { 2417 @Override 2418 public void onTetheringFailed(final int result) { 2419 } 2420 }); 2421 2422 // Verify state and info callback value as expected 2423 PollingCheck.check( 2424 "SoftAp channel and state mismatch!!!", 10_000, 2425 () -> { 2426 executor.runAll(); 2427 int sapChannel = ScanResult.convertFrequencyMhzToChannelIfSupported( 2428 callback.getCurrentSoftApInfo().getFrequency()); 2429 boolean isInfoCallbackSupported = 2430 callback.getOnSoftapInfoChangedCalledCount() > 1; 2431 if (isInfoCallbackSupported) { 2432 return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState() 2433 && testBandsAndChannels.valueAt(0) == sapChannel; 2434 } 2435 return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState(); 2436 }); 2437 // After Soft Ap enabled, check SoftAp info if it supported 2438 if (isSupportCustomizedMac && callback.getOnSoftapInfoChangedCalledCount() > 1) { 2439 assertEquals(callback.getCurrentSoftApInfo().getBssid(), TEST_MAC); 2440 } 2441 if (PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S) 2442 && callback.getOnSoftapInfoChangedCalledCount() > 1) { 2443 assertNotEquals(callback.getCurrentSoftApInfo().getWifiStandard(), 2444 ScanResult.WIFI_STANDARD_UNKNOWN); 2445 } 2446 2447 if (callback.getOnSoftapInfoChangedCalledCount() > 1) { 2448 assertTrue(callback.getCurrentSoftApInfo().getAutoShutdownTimeoutMillis() > 0); 2449 } 2450 } finally { 2451 // stop tethering which used to verify stopSoftAp 2452 mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2453 2454 // Verify clean up 2455 PollingCheck.check( 2456 "Stop Softap failed", 3_000, 2457 () -> { 2458 executor.runAll(); 2459 return WifiManager.WIFI_AP_STATE_DISABLED == callback.getCurrentState() && 2460 0 == callback.getCurrentSoftApInfo().getBandwidth() && 2461 0 == callback.getCurrentSoftApInfo().getFrequency(); 2462 }); 2463 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2464 assertEquals(callback.getCurrentSoftApInfo().getBssid(), null); 2465 assertEquals(ScanResult.WIFI_STANDARD_UNKNOWN, 2466 callback.getCurrentSoftApInfo().getWifiStandard()); 2467 } 2468 mWifiManager.unregisterSoftApCallback(callback); 2469 uiAutomation.dropShellPermissionIdentity(); 2470 } 2471 } 2472 2473 private static class TestActionListener implements WifiManager.ActionListener { 2474 private final Object mLock; 2475 public boolean onSuccessCalled = false; 2476 public boolean onFailedCalled = false; 2477 public int failureReason = -1; 2478 TestActionListener(Object lock)2479 TestActionListener(Object lock) { 2480 mLock = lock; 2481 } 2482 2483 @Override onSuccess()2484 public void onSuccess() { 2485 synchronized (mLock) { 2486 onSuccessCalled = true; 2487 mLock.notify(); 2488 } 2489 } 2490 2491 @Override onFailure(int reason)2492 public void onFailure(int reason) { 2493 synchronized (mLock) { 2494 onFailedCalled = true; 2495 failureReason = reason; 2496 mLock.notify(); 2497 } 2498 } 2499 } 2500 2501 /** 2502 * Triggers connection to one of the saved networks using {@link WifiManager#connect( 2503 * int, WifiManager.ActionListener)} or {@link WifiManager#connect(WifiConfiguration, 2504 * WifiManager.ActionListener)} 2505 * 2506 * @param withNetworkId Use networkId for triggering connection, false for using 2507 * WifiConfiguration. 2508 * @throws Exception 2509 */ testConnect(boolean withNetworkId)2510 private void testConnect(boolean withNetworkId) throws Exception { 2511 TestActionListener actionListener = new TestActionListener(mLock); 2512 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2513 List<WifiConfiguration> savedNetworks = null; 2514 try { 2515 uiAutomation.adoptShellPermissionIdentity(); 2516 // These below API's only work with privileged permissions (obtained via shell identity 2517 // for test) 2518 savedNetworks = mWifiManager.getConfiguredNetworks(); 2519 2520 // Disable all the saved networks to trigger disconnect & disable autojoin. 2521 for (WifiConfiguration network : savedNetworks) { 2522 assertTrue(mWifiManager.disableNetwork(network.networkId)); 2523 } 2524 waitForDisconnection(); 2525 2526 // Now trigger connection to the last saved network. 2527 WifiConfiguration savedNetworkToConnect = 2528 savedNetworks.get(savedNetworks.size() - 1); 2529 synchronized (mLock) { 2530 try { 2531 if (withNetworkId) { 2532 mWifiManager.connect(savedNetworkToConnect.networkId, actionListener); 2533 } else { 2534 mWifiManager.connect(savedNetworkToConnect, actionListener); 2535 } 2536 // now wait for callback 2537 mLock.wait(TEST_WAIT_DURATION_MS); 2538 } catch (InterruptedException e) { 2539 } 2540 } 2541 // check if we got the success callback 2542 assertTrue(actionListener.onSuccessCalled); 2543 // Wait for connection to complete & ensure we are connected to the saved network. 2544 waitForConnection(); 2545 if (SdkLevel.isAtLeastS()) { 2546 assertEquals(savedNetworkToConnect.networkId, 2547 mWifiManager.getConnectionInfo().getNetworkId()); 2548 } else { 2549 // In R, auto-upgraded network IDs may be different from the original saved network. 2550 // Since we may end up selecting the auto-upgraded network ID for connection and end 2551 // up connected to the original saved network with a different network ID, we should 2552 // instead match by SSID. 2553 assertEquals(savedNetworkToConnect.SSID, 2554 mWifiManager.getConnectionInfo().getSSID()); 2555 } 2556 } finally { 2557 // Re-enable all saved networks before exiting. 2558 if (savedNetworks != null) { 2559 for (WifiConfiguration network : savedNetworks) { 2560 mWifiManager.enableNetwork(network.networkId, true); 2561 } 2562 } 2563 uiAutomation.dropShellPermissionIdentity(); 2564 } 2565 } 2566 2567 /** 2568 * Tests {@link WifiManager#connect(int, WifiManager.ActionListener)} to an existing saved 2569 * network. 2570 */ testConnectWithNetworkId()2571 public void testConnectWithNetworkId() throws Exception { 2572 if (!WifiFeature.isWifiSupported(getContext())) { 2573 // skip the test if WiFi is not supported 2574 return; 2575 } 2576 testConnect(true); 2577 } 2578 2579 /** 2580 * Tests {@link WifiManager#connect(WifiConfiguration, WifiManager.ActionListener)} to an 2581 * existing saved network. 2582 */ testConnectWithWifiConfiguration()2583 public void testConnectWithWifiConfiguration() throws Exception { 2584 if (!WifiFeature.isWifiSupported(getContext())) { 2585 // skip the test if WiFi is not supported 2586 return; 2587 } 2588 testConnect(false); 2589 2590 } 2591 2592 private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback { 2593 private final Object mLock; 2594 public boolean onAvailableCalled = false; 2595 public Network network; 2596 public NetworkCapabilities networkCapabilities; 2597 TestNetworkCallback(Object lock)2598 TestNetworkCallback(Object lock) { 2599 mLock = lock; 2600 } 2601 2602 @Override onAvailable(Network network)2603 public void onAvailable(Network network) { 2604 synchronized (mLock) { 2605 onAvailableCalled = true; 2606 this.network = network; 2607 } 2608 } 2609 2610 @Override onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)2611 public void onCapabilitiesChanged(Network network, 2612 NetworkCapabilities networkCapabilities) { 2613 synchronized (mLock) { 2614 this.networkCapabilities = networkCapabilities; 2615 mLock.notify(); 2616 } 2617 } 2618 } 2619 waitForNetworkCallbackAndCheckForMeteredness(boolean expectMetered)2620 private void waitForNetworkCallbackAndCheckForMeteredness(boolean expectMetered) { 2621 TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock); 2622 synchronized (mLock) { 2623 try { 2624 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder() 2625 .addTransportType(TRANSPORT_WIFI); 2626 if (expectMetered) { 2627 networkRequestBuilder.removeCapability(NET_CAPABILITY_NOT_METERED); 2628 } else { 2629 networkRequestBuilder.addCapability(NET_CAPABILITY_NOT_METERED); 2630 } 2631 // File a request for wifi network. 2632 mConnectivityManager.registerNetworkCallback( 2633 networkRequestBuilder.build(), networkCallbackListener); 2634 // now wait for callback 2635 mLock.wait(TEST_WAIT_DURATION_MS); 2636 } catch (InterruptedException e) { 2637 } 2638 } 2639 assertTrue(networkCallbackListener.onAvailableCalled); 2640 } 2641 2642 /** 2643 * Tests {@link WifiManager#save(WifiConfiguration, WifiManager.ActionListener)} by marking 2644 * an existing saved network metered. 2645 */ testSave()2646 public void testSave() throws Exception { 2647 if (!WifiFeature.isWifiSupported(getContext())) { 2648 // skip the test if WiFi is not supported 2649 return; 2650 } 2651 TestActionListener actionListener = new TestActionListener(mLock); 2652 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2653 List<WifiConfiguration> savedNetworks = null; 2654 WifiConfiguration currentConfig = null; 2655 try { 2656 uiAutomation.adoptShellPermissionIdentity(); 2657 // These below API's only work with privileged permissions (obtained via shell identity 2658 // for test) 2659 2660 // Trigger a scan & wait for connection to one of the saved networks. 2661 mWifiManager.startScan(); 2662 waitForConnection(); 2663 2664 WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 2665 savedNetworks = mWifiManager.getConfiguredNetworks(); 2666 2667 // find the current network's WifiConfiguration 2668 currentConfig = savedNetworks 2669 .stream() 2670 .filter(config -> config.networkId == wifiInfo.getNetworkId()) 2671 .findAny() 2672 .get(); 2673 2674 // Ensure that the current network is not metered. 2675 assertNotEquals("Ensure that the saved network is configured as unmetered", 2676 currentConfig.meteredOverride, 2677 WifiConfiguration.METERED_OVERRIDE_METERED); 2678 2679 // Disable all except the currently connected networks to avoid reconnecting to the 2680 // wrong network after later setting the current network as metered. 2681 for (WifiConfiguration network : savedNetworks) { 2682 if (network.networkId != currentConfig.networkId) { 2683 assertTrue(mWifiManager.disableNetwork(network.networkId)); 2684 } 2685 } 2686 2687 // Check the network capabilities to ensure that the network is marked not metered. 2688 waitForNetworkCallbackAndCheckForMeteredness(false); 2689 2690 // Now mark the network metered and save. 2691 synchronized (mLock) { 2692 try { 2693 WifiConfiguration modSavedNetwork = new WifiConfiguration(currentConfig); 2694 modSavedNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; 2695 mWifiManager.save(modSavedNetwork, actionListener); 2696 // now wait for callback 2697 mLock.wait(TEST_WAIT_DURATION_MS); 2698 } catch (InterruptedException e) { 2699 } 2700 } 2701 // check if we got the success callback 2702 assertTrue(actionListener.onSuccessCalled); 2703 // Ensure we disconnected on marking the network metered & connect back. 2704 waitForDisconnection(); 2705 waitForConnection(); 2706 // Check the network capabilities to ensure that the network is marked metered now. 2707 waitForNetworkCallbackAndCheckForMeteredness(true); 2708 2709 } finally { 2710 // Restore original network config (restore the meteredness back); 2711 if (currentConfig != null) { 2712 mWifiManager.updateNetwork(currentConfig); 2713 } 2714 // re-enable all networks 2715 if (savedNetworks != null) { 2716 for (WifiConfiguration network : savedNetworks) { 2717 mWifiManager.enableNetwork(network.networkId, true); 2718 } 2719 } 2720 uiAutomation.dropShellPermissionIdentity(); 2721 } 2722 } 2723 2724 /** 2725 * Tests {@link WifiManager#forget(int, WifiManager.ActionListener)} by adding/removing a new 2726 * network. 2727 */ 2728 @AsbSecurityTest(cveBugId = 159373687) testForget()2729 public void testForget() throws Exception { 2730 if (!WifiFeature.isWifiSupported(getContext())) { 2731 // skip the test if WiFi is not supported 2732 return; 2733 } 2734 TestActionListener actionListener = new TestActionListener(mLock); 2735 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2736 int newNetworkId = INVALID_NETWORK_ID; 2737 try { 2738 uiAutomation.adoptShellPermissionIdentity(); 2739 // These below API's only work with privileged permissions (obtained via shell identity 2740 // for test) 2741 List<WifiConfiguration> savedNetworks = mWifiManager.getConfiguredNetworks(); 2742 2743 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 2744 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 2745 newNetworkId = mWifiManager.addNetwork(newOpenNetwork); 2746 assertNotEquals(INVALID_NETWORK_ID, newNetworkId); 2747 2748 // Multi-type configurations might be converted to more than 1 configuration. 2749 assertThat(savedNetworks.size() < mWifiManager.getConfiguredNetworks().size()).isTrue(); 2750 2751 // Need an effectively-final holder because we need to modify inner Intent in callback. 2752 class IntentHolder { 2753 Intent intent; 2754 } 2755 IntentHolder intentHolder = new IntentHolder(); 2756 mContext.registerReceiver(new BroadcastReceiver() { 2757 @Override 2758 public void onReceive(Context context, Intent intent) { 2759 Log.i(TAG, "Received CONFIGURED_NETWORKS_CHANGED_ACTION broadcast: " + intent); 2760 intentHolder.intent = intent; 2761 } 2762 }, new IntentFilter(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION)); 2763 2764 // Now remove the network 2765 synchronized (mLock) { 2766 try { 2767 mWifiManager.forget(newNetworkId, actionListener); 2768 // now wait for callback 2769 mLock.wait(TEST_WAIT_DURATION_MS); 2770 } catch (InterruptedException e) { 2771 } 2772 } 2773 // check if we got the success callback 2774 assertTrue(actionListener.onSuccessCalled); 2775 2776 PollingCheck.check( 2777 "Didn't receive CONFIGURED_NETWORKS_CHANGED_ACTION broadcast!", 2778 TEST_WAIT_DURATION_MS, 2779 () -> intentHolder.intent != null); 2780 Intent intent = intentHolder.intent; 2781 assertEquals(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION, intent.getAction()); 2782 assertTrue(intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false)); 2783 assertEquals(WifiManager.CHANGE_REASON_REMOVED, 2784 intent.getIntExtra(WifiManager.EXTRA_CHANGE_REASON, -1)); 2785 assertNull(intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION)); 2786 2787 // Ensure that the new network has been successfully removed. 2788 assertEquals(savedNetworks.size(), mWifiManager.getConfiguredNetworks().size()); 2789 } finally { 2790 // For whatever reason, if the forget fails, try removing using the public remove API. 2791 if (newNetworkId != INVALID_NETWORK_ID) mWifiManager.removeNetwork(newNetworkId); 2792 uiAutomation.dropShellPermissionIdentity(); 2793 } 2794 } 2795 2796 /** 2797 * Tests {@link WifiManager#getFactoryMacAddresses()} returns at least one valid MAC address. 2798 */ 2799 @VirtualDeviceNotSupported testGetFactoryMacAddresses()2800 public void testGetFactoryMacAddresses() throws Exception { 2801 if (!WifiFeature.isWifiSupported(getContext())) { 2802 // skip the test if WiFi is not supported 2803 return; 2804 } 2805 TestActionListener actionListener = new TestActionListener(mLock); 2806 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2807 int newNetworkId = INVALID_NETWORK_ID; 2808 try { 2809 uiAutomation.adoptShellPermissionIdentity(); 2810 // Obtain the factory MAC address 2811 String[] macAddresses = mWifiManager.getFactoryMacAddresses(); 2812 assertTrue("At list one MAC address should be returned.", macAddresses.length > 0); 2813 try { 2814 MacAddress mac = MacAddress.fromString(macAddresses[0]); 2815 assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mac); 2816 assertFalse(MacAddressUtils.isMulticastAddress(mac)); 2817 } catch (IllegalArgumentException e) { 2818 fail("Factory MAC address is invalid"); 2819 } 2820 } finally { 2821 uiAutomation.dropShellPermissionIdentity(); 2822 } 2823 } 2824 2825 /** 2826 * Tests {@link WifiManager#isApMacRandomizationSupported()} does not crash. 2827 */ testIsApMacRandomizationSupported()2828 public void testIsApMacRandomizationSupported() throws Exception { 2829 if (!WifiFeature.isWifiSupported(getContext())) { 2830 // skip the test if WiFi is not supported 2831 return; 2832 } 2833 mWifiManager.isApMacRandomizationSupported(); 2834 } 2835 2836 /** 2837 * Tests {@link WifiManager#isConnectedMacRandomizationSupported()} does not crash. 2838 */ testIsConnectedMacRandomizationSupported()2839 public void testIsConnectedMacRandomizationSupported() throws Exception { 2840 if (!WifiFeature.isWifiSupported(getContext())) { 2841 // skip the test if WiFi is not supported 2842 return; 2843 } 2844 mWifiManager.isConnectedMacRandomizationSupported(); 2845 } 2846 2847 /** 2848 * Tests {@link WifiManager#isPreferredNetworkOffloadSupported()} does not crash. 2849 */ testIsPreferredNetworkOffloadSupported()2850 public void testIsPreferredNetworkOffloadSupported() throws Exception { 2851 if (!WifiFeature.isWifiSupported(getContext())) { 2852 // skip the test if WiFi is not supported 2853 return; 2854 } 2855 mWifiManager.isPreferredNetworkOffloadSupported(); 2856 } 2857 2858 /** Test that PNO scans reconnects us when the device is disconnected and the screen is off. */ testPnoScan()2859 public void testPnoScan() throws Exception { 2860 if (!WifiFeature.isWifiSupported(getContext())) { 2861 // skip the test if WiFi is not supported 2862 return; 2863 } 2864 if (!mWifiManager.isPreferredNetworkOffloadSupported()) { 2865 // skip the test if PNO scanning is not supported 2866 return; 2867 } 2868 2869 // make sure we're connected 2870 waitForConnection(); 2871 2872 WifiInfo currentNetwork = ShellIdentityUtils.invokeWithShellPermissions( 2873 mWifiManager::getConnectionInfo); 2874 2875 // disable all networks that aren't already disabled 2876 List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 2877 mWifiManager::getConfiguredNetworks); 2878 Set<Integer> disabledNetworkIds = new HashSet<>(); 2879 for (WifiConfiguration config : savedNetworks) { 2880 if (config.getNetworkSelectionStatus().getNetworkSelectionDisableReason() 2881 == WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE) { 2882 ShellIdentityUtils.invokeWithShellPermissions( 2883 () -> mWifiManager.disableNetwork(config.networkId)); 2884 disabledNetworkIds.add(config.networkId); 2885 } 2886 } 2887 2888 try { 2889 // wait for disconnection from current network 2890 waitForDisconnection(); 2891 2892 // turn screen off 2893 turnScreenOffNoDelay(); 2894 2895 // re-enable the current network - this will trigger PNO 2896 ShellIdentityUtils.invokeWithShellPermissions( 2897 () -> mWifiManager.enableNetwork(currentNetwork.getNetworkId(), false)); 2898 disabledNetworkIds.remove(currentNetwork.getNetworkId()); 2899 2900 // PNO should reconnect us back to the network we disconnected from 2901 waitForConnection(); 2902 } finally { 2903 // re-enable disabled networks 2904 for (int disabledNetworkId : disabledNetworkIds) { 2905 ShellIdentityUtils.invokeWithShellPermissions( 2906 () -> mWifiManager.enableNetwork(disabledNetworkId, true)); 2907 } 2908 } 2909 } 2910 2911 /** 2912 * Tests {@link WifiManager#isTdlsSupported()} does not crash. 2913 */ testIsTdlsSupported()2914 public void testIsTdlsSupported() throws Exception { 2915 if (!WifiFeature.isWifiSupported(getContext())) { 2916 // skip the test if WiFi is not supported 2917 return; 2918 } 2919 mWifiManager.isTdlsSupported(); 2920 } 2921 2922 /** 2923 * Tests {@link WifiManager#isStaApConcurrencySupported(). 2924 */ testIsStaApConcurrencySupported()2925 public void testIsStaApConcurrencySupported() throws Exception { 2926 if (!WifiFeature.isWifiSupported(getContext())) { 2927 // skip the test if WiFi is not supported 2928 return; 2929 } 2930 // check that softap mode is supported by the device 2931 if (!mWifiManager.isPortableHotspotSupported()) { 2932 return; 2933 } 2934 assertTrue(mWifiManager.isWifiEnabled()); 2935 2936 boolean isStaApConcurrencySupported = mWifiManager.isStaApConcurrencySupported(); 2937 // start local only hotspot. 2938 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 2939 try { 2940 if (isStaApConcurrencySupported) { 2941 assertTrue(mWifiManager.isWifiEnabled()); 2942 } else { 2943 // no concurrency, wifi should be disabled. 2944 assertFalse(mWifiManager.isWifiEnabled()); 2945 } 2946 } finally { 2947 // clean up local only hotspot no matter if assertion passed or failed 2948 stopLocalOnlyHotspot(callback, true); 2949 } 2950 2951 assertTrue(mWifiManager.isWifiEnabled()); 2952 } 2953 2954 /** 2955 * state is a bitset, where bit 0 indicates whether there was data in, and bit 1 indicates 2956 * whether there was data out. Only count down on the latch once there was both data in and out. 2957 */ 2958 private static class TestTrafficStateCallback implements WifiManager.TrafficStateCallback { 2959 public final CountDownLatch latch = new CountDownLatch(1); 2960 private int mAccumulator = 0; 2961 2962 @Override onStateChanged(int state)2963 public void onStateChanged(int state) { 2964 mAccumulator |= state; 2965 if (mAccumulator == DATA_ACTIVITY_INOUT) { 2966 latch.countDown(); 2967 } 2968 } 2969 } 2970 sendTraffic()2971 private void sendTraffic() { 2972 boolean didAnyConnectionSucceed = false; 2973 for (int i = 0; i < 10; i++) { 2974 // Do some network operations 2975 HttpURLConnection connection = null; 2976 try { 2977 URL url = new URL("http://www.google.com/"); 2978 connection = (HttpURLConnection) url.openConnection(); 2979 connection.setInstanceFollowRedirects(false); 2980 connection.setConnectTimeout(TEST_WAIT_DURATION_MS); 2981 connection.setReadTimeout(TEST_WAIT_DURATION_MS); 2982 connection.setUseCaches(false); 2983 InputStream stream = connection.getInputStream(); 2984 byte[] bytes = new byte[100]; 2985 int receivedBytes = stream.read(bytes); 2986 if (receivedBytes > 0) { 2987 didAnyConnectionSucceed = true; 2988 } 2989 } catch (Exception e) { 2990 // ignore 2991 } finally { 2992 if (connection != null) connection.disconnect(); 2993 } 2994 } 2995 assertTrue("All connections failed!", didAnyConnectionSucceed); 2996 } 2997 2998 /** 2999 * Tests {@link WifiManager#registerTrafficStateCallback(Executor, 3000 * WifiManager.TrafficStateCallback)} by sending some traffic. 3001 */ testTrafficStateCallback()3002 public void testTrafficStateCallback() throws Exception { 3003 if (!WifiFeature.isWifiSupported(getContext())) { 3004 // skip the test if WiFi is not supported 3005 return; 3006 } 3007 TestTrafficStateCallback callback = new TestTrafficStateCallback(); 3008 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3009 try { 3010 uiAutomation.adoptShellPermissionIdentity(); 3011 // Trigger a scan & wait for connection to one of the saved networks. 3012 mWifiManager.startScan(); 3013 waitForConnection(); 3014 3015 // Turn screen on for wifi traffic polling. 3016 turnScreenOn(); 3017 mWifiManager.registerTrafficStateCallback( 3018 Executors.newSingleThreadExecutor(), callback); 3019 // Send some traffic to trigger the traffic state change callbacks. 3020 sendTraffic(); 3021 // now wait for callback 3022 boolean success = callback.latch.await(TEST_WAIT_DURATION_MS, TimeUnit.MILLISECONDS); 3023 // check if we got the state changed callback with both data in and out 3024 assertTrue(success); 3025 } finally { 3026 turnScreenOff(); 3027 mWifiManager.unregisterTrafficStateCallback(callback); 3028 uiAutomation.dropShellPermissionIdentity(); 3029 } 3030 } 3031 3032 /** 3033 * Tests {@link WifiManager#setScanAlwaysAvailable(boolean)} & 3034 * {@link WifiManager#isScanAlwaysAvailable()}. 3035 */ testScanAlwaysAvailable()3036 public void testScanAlwaysAvailable() throws Exception { 3037 if (!WifiFeature.isWifiSupported(getContext())) { 3038 // skip the test if WiFi is not supported 3039 return; 3040 } 3041 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3042 Boolean currState = null; 3043 try { 3044 uiAutomation.adoptShellPermissionIdentity(); 3045 currState = mWifiManager.isScanAlwaysAvailable(); 3046 boolean newState = !currState; 3047 mWifiManager.setScanAlwaysAvailable(newState); 3048 PollingCheck.check( 3049 "Wifi settings toggle failed!", 3050 DURATION_SETTINGS_TOGGLE, 3051 () -> mWifiManager.isScanAlwaysAvailable() == newState); 3052 assertEquals(newState, mWifiManager.isScanAlwaysAvailable()); 3053 } finally { 3054 if (currState != null) mWifiManager.setScanAlwaysAvailable(currState); 3055 uiAutomation.dropShellPermissionIdentity(); 3056 } 3057 } 3058 3059 /** 3060 * Tests {@link WifiManager#setScanThrottleEnabled(boolean)} & 3061 * {@link WifiManager#isScanThrottleEnabled()}. 3062 */ testScanThrottleEnabled()3063 public void testScanThrottleEnabled() throws Exception { 3064 if (!WifiFeature.isWifiSupported(getContext())) { 3065 // skip the test if WiFi is not supported 3066 return; 3067 } 3068 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3069 Boolean currState = null; 3070 try { 3071 uiAutomation.adoptShellPermissionIdentity(); 3072 currState = mWifiManager.isScanThrottleEnabled(); 3073 boolean newState = !currState; 3074 mWifiManager.setScanThrottleEnabled(newState); 3075 PollingCheck.check( 3076 "Wifi settings toggle failed!", 3077 DURATION_SETTINGS_TOGGLE, 3078 () -> mWifiManager.isScanThrottleEnabled() == newState); 3079 assertEquals(newState, mWifiManager.isScanThrottleEnabled()); 3080 } finally { 3081 if (currState != null) mWifiManager.setScanThrottleEnabled(currState); 3082 uiAutomation.dropShellPermissionIdentity(); 3083 } 3084 } 3085 3086 /** 3087 * Tests {@link WifiManager#setAutoWakeupEnabled(boolean)} & 3088 * {@link WifiManager#isAutoWakeupEnabled()}. 3089 */ testAutoWakeUpEnabled()3090 public void testAutoWakeUpEnabled() throws Exception { 3091 if (!WifiFeature.isWifiSupported(getContext())) { 3092 // skip the test if WiFi is not supported 3093 return; 3094 } 3095 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3096 Boolean currState = null; 3097 try { 3098 uiAutomation.adoptShellPermissionIdentity(); 3099 currState = mWifiManager.isAutoWakeupEnabled(); 3100 boolean newState = !currState; 3101 mWifiManager.setAutoWakeupEnabled(newState); 3102 PollingCheck.check( 3103 "Wifi settings toggle failed!", 3104 DURATION_SETTINGS_TOGGLE, 3105 () -> mWifiManager.isAutoWakeupEnabled() == newState); 3106 assertEquals(newState, mWifiManager.isAutoWakeupEnabled()); 3107 } finally { 3108 if (currState != null) mWifiManager.setAutoWakeupEnabled(currState); 3109 uiAutomation.dropShellPermissionIdentity(); 3110 } 3111 } 3112 3113 /** 3114 * Tests {@link WifiManager#setVerboseLoggingEnabled(boolean)} & 3115 * {@link WifiManager#isVerboseLoggingEnabled()}. 3116 */ testVerboseLoggingEnabled()3117 public void testVerboseLoggingEnabled() throws Exception { 3118 if (!WifiFeature.isWifiSupported(getContext())) { 3119 // skip the test if WiFi is not supported 3120 return; 3121 } 3122 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3123 Boolean currState = null; 3124 TestWifiVerboseLoggingStatusChangedListener listener = 3125 WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext) ? 3126 new TestWifiVerboseLoggingStatusChangedListener() : null; 3127 try { 3128 uiAutomation.adoptShellPermissionIdentity(); 3129 if (listener != null) { 3130 mWifiManager.addWifiVerboseLoggingStatusChangedListener(mExecutor, listener); 3131 } 3132 currState = mWifiManager.isVerboseLoggingEnabled(); 3133 boolean newState = !currState; 3134 if (listener != null) { 3135 assertEquals(0, listener.numCalls); 3136 } 3137 mWifiManager.setVerboseLoggingEnabled(newState); 3138 PollingCheck.check( 3139 "Wifi verbose logging toggle failed!", 3140 DURATION_SETTINGS_TOGGLE, 3141 () -> mWifiManager.isVerboseLoggingEnabled() == newState); 3142 if (listener != null) { 3143 PollingCheck.check( 3144 "Verbose logging listener timeout", 3145 DURATION_SETTINGS_TOGGLE, 3146 () -> listener.status == newState && listener.numCalls == 1); 3147 } 3148 } finally { 3149 if (currState != null) mWifiManager.setVerboseLoggingEnabled(currState); 3150 if (listener != null) { 3151 mWifiManager.removeWifiVerboseLoggingStatusChangedListener(listener); 3152 } 3153 uiAutomation.dropShellPermissionIdentity(); 3154 } 3155 } 3156 3157 /** 3158 * Tests {@link WifiManager#setVerboseLoggingLevel(int)}. 3159 */ testSetVerboseLogging()3160 public void testSetVerboseLogging() throws Exception { 3161 if (!WifiFeature.isWifiSupported(getContext())) { 3162 // skip the test if WiFi is not supported 3163 return; 3164 } 3165 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3166 Boolean currState = null; 3167 try { 3168 uiAutomation.adoptShellPermissionIdentity(); 3169 currState = mWifiManager.isVerboseLoggingEnabled(); 3170 3171 mWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); 3172 assertTrue(mWifiManager.isVerboseLoggingEnabled()); 3173 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED, 3174 mWifiManager.getVerboseLoggingLevel()); 3175 3176 mWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED); 3177 assertFalse(mWifiManager.isVerboseLoggingEnabled()); 3178 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED, 3179 mWifiManager.getVerboseLoggingLevel()); 3180 } finally { 3181 if (currState != null) mWifiManager.setVerboseLoggingEnabled(currState); 3182 uiAutomation.dropShellPermissionIdentity(); 3183 } 3184 } 3185 3186 /** 3187 * Test {@link WifiManager#setVerboseLoggingLevel(int)} for show key mode. 3188 */ 3189 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testSetVerboseLoggingShowKeyModeNonUserBuild()3190 public void testSetVerboseLoggingShowKeyModeNonUserBuild() throws Exception { 3191 if (Build.TYPE.equals("user")) return; 3192 if (!WifiFeature.isWifiSupported(getContext())) { 3193 // skip the test if WiFi is not supported 3194 return; 3195 } 3196 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3197 Boolean currState = null; 3198 try { 3199 uiAutomation.adoptShellPermissionIdentity(); 3200 currState = mWifiManager.isVerboseLoggingEnabled(); 3201 3202 mWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY); 3203 assertTrue(mWifiManager.isVerboseLoggingEnabled()); 3204 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 3205 mWifiManager.getVerboseLoggingLevel()); 3206 } finally { 3207 if (currState != null) mWifiManager.setVerboseLoggingEnabled(currState); 3208 uiAutomation.dropShellPermissionIdentity(); 3209 } 3210 } 3211 3212 /** 3213 * Test {@link WifiManager#setVerboseLoggingLevel(int)} for show key mode. 3214 */ 3215 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testSetVerboseLoggingShowKeyModeUserBuild()3216 public void testSetVerboseLoggingShowKeyModeUserBuild() throws Exception { 3217 if (!Build.TYPE.equals("user")) return; 3218 if (!WifiFeature.isWifiSupported(getContext())) { 3219 // skip the test if WiFi is not supported 3220 return; 3221 } 3222 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3223 Boolean currState = null; 3224 try { 3225 uiAutomation.adoptShellPermissionIdentity(); 3226 currState = mWifiManager.isVerboseLoggingEnabled(); 3227 3228 mWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY); 3229 assertTrue(mWifiManager.isVerboseLoggingEnabled()); 3230 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 3231 mWifiManager.getVerboseLoggingLevel()); 3232 fail("Verbosing logging show key mode should not be allowed for user build."); 3233 } catch (SecurityException e) { 3234 // expected 3235 } finally { 3236 if (currState != null) mWifiManager.setVerboseLoggingEnabled(currState); 3237 uiAutomation.dropShellPermissionIdentity(); 3238 } 3239 } 3240 3241 /** 3242 * Tests {@link WifiManager#factoryReset()} cannot be invoked from a non-privileged app. 3243 * 3244 * Note: This intentionally does not test the full reset functionality because it causes 3245 * the existing saved networks on the device to be lost after the test. If you add the 3246 * networks back after reset, the ownership of saved networks will change. 3247 */ testFactoryReset()3248 public void testFactoryReset() throws Exception { 3249 if (!WifiFeature.isWifiSupported(getContext())) { 3250 // skip the test if WiFi is not supported 3251 return; 3252 } 3253 List<WifiConfiguration> beforeSavedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 3254 mWifiManager::getConfiguredNetworks); 3255 try { 3256 mWifiManager.factoryReset(); 3257 fail("Factory reset should not be allowed for non-privileged apps"); 3258 } catch (SecurityException e) { 3259 // expected 3260 } 3261 List<WifiConfiguration> afterSavedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 3262 mWifiManager::getConfiguredNetworks); 3263 assertEquals(beforeSavedNetworks.size(), afterSavedNetworks.size()); 3264 } 3265 3266 /** 3267 * Test {@link WifiNetworkConnectionStatistics} does not crash. 3268 * TODO(b/150891569): deprecate it in Android S, this API is not used anywhere. 3269 */ testWifiNetworkConnectionStatistics()3270 public void testWifiNetworkConnectionStatistics() { 3271 if (!WifiFeature.isWifiSupported(getContext())) { 3272 // skip the test if WiFi is not supported 3273 return; 3274 } 3275 new WifiNetworkConnectionStatistics(); 3276 WifiNetworkConnectionStatistics stats = new WifiNetworkConnectionStatistics(0, 0); 3277 new WifiNetworkConnectionStatistics(stats); 3278 } 3279 3280 /** 3281 * Verify that startRestrictingAutoJoinToSubscriptionId disconnects wifi and disables 3282 * auto-connect to non-carrier-merged networks. Then verify that 3283 * stopRestrictingAutoJoinToSubscriptionId makes the disabled networks clear to connect 3284 * again. 3285 */ 3286 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testStartAndStopRestrictingAutoJoinToSubscriptionId()3287 public void testStartAndStopRestrictingAutoJoinToSubscriptionId() throws Exception { 3288 if (!WifiFeature.isWifiSupported(getContext())) { 3289 // skip the test if WiFi is not supported 3290 return; 3291 } 3292 startScan(); 3293 waitForConnection(); 3294 int fakeSubscriptionId = 5; 3295 ShellIdentityUtils.invokeWithShellPermissions(() -> 3296 mWifiManager.startRestrictingAutoJoinToSubscriptionId(fakeSubscriptionId)); 3297 startScan(); 3298 ensureNotConnected(); 3299 ShellIdentityUtils.invokeWithShellPermissions(() -> 3300 mWifiManager.stopRestrictingAutoJoinToSubscriptionId()); 3301 startScan(); 3302 waitForConnection(); 3303 } 3304 3305 /** 3306 * Test that the wifi country code is either null, or a length-2 string. 3307 */ testGetCountryCode()3308 public void testGetCountryCode() throws Exception { 3309 if (!WifiFeature.isWifiSupported(getContext())) { 3310 // skip the test if WiFi is not supported 3311 return; 3312 } 3313 3314 String wifiCountryCode = ShellIdentityUtils.invokeWithShellPermissions( 3315 mWifiManager::getCountryCode); 3316 3317 if (wifiCountryCode == null) { 3318 return; 3319 } 3320 assertEquals(2, wifiCountryCode.length()); 3321 3322 // assert that the country code is all uppercase 3323 assertEquals(wifiCountryCode.toUpperCase(Locale.US), wifiCountryCode); 3324 3325 // skip if Telephony is unsupported 3326 if (!WifiFeature.isTelephonySupported(getContext())) { 3327 return; 3328 } 3329 3330 String telephonyCountryCode = getContext().getSystemService(TelephonyManager.class) 3331 .getNetworkCountryIso(); 3332 3333 // skip if Telephony country code is unavailable 3334 if (telephonyCountryCode == null || telephonyCountryCode.isEmpty()) { 3335 return; 3336 } 3337 3338 assertEquals(telephonyCountryCode, wifiCountryCode.toLowerCase(Locale.US)); 3339 } 3340 3341 /** 3342 * Test that {@link WifiManager#getCurrentNetwork()} returns a Network obeject consistent 3343 * with {@link ConnectivityManager#registerNetworkCallback} when connected to a Wifi network, 3344 * and returns null when not connected. 3345 */ testGetCurrentNetwork()3346 public void testGetCurrentNetwork() throws Exception { 3347 if (!WifiFeature.isWifiSupported(getContext())) { 3348 // skip the test if WiFi is not supported 3349 return; 3350 } 3351 3352 // ensure Wifi is connected 3353 ShellIdentityUtils.invokeWithShellPermissions(() -> mWifiManager.reconnect()); 3354 PollingCheck.check( 3355 "Wifi not connected - Please ensure there is a saved network in range of this " 3356 + "device", 3357 WIFI_CONNECT_TIMEOUT_MILLIS, 3358 () -> mWifiManager.getConnectionInfo().getNetworkId() != -1); 3359 3360 Network wifiCurrentNetwork = ShellIdentityUtils.invokeWithShellPermissions( 3361 mWifiManager::getCurrentNetwork); 3362 assertNotNull(wifiCurrentNetwork); 3363 3364 TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock); 3365 synchronized (mLock) { 3366 try { 3367 // File a request for wifi network. 3368 mConnectivityManager.registerNetworkCallback( 3369 new NetworkRequest.Builder() 3370 .addTransportType(TRANSPORT_WIFI) 3371 .build(), 3372 networkCallbackListener); 3373 // now wait for callback 3374 mLock.wait(TEST_WAIT_DURATION_MS); 3375 } catch (InterruptedException e) { 3376 } 3377 } 3378 assertTrue(networkCallbackListener.onAvailableCalled); 3379 Network connectivityCurrentNetwork = networkCallbackListener.network; 3380 assertEquals(connectivityCurrentNetwork, wifiCurrentNetwork); 3381 3382 setWifiEnabled(false); 3383 PollingCheck.check( 3384 "Wifi not disconnected!", 3385 20000, 3386 () -> mWifiManager.getConnectionInfo().getNetworkId() == -1); 3387 3388 assertNull(ShellIdentityUtils.invokeWithShellPermissions(mWifiManager::getCurrentNetwork)); 3389 } 3390 3391 /** 3392 * Tests {@link WifiManager#isWpa3SaeSupported()} does not crash. 3393 */ testIsWpa3SaeSupported()3394 public void testIsWpa3SaeSupported() throws Exception { 3395 if (!WifiFeature.isWifiSupported(getContext())) { 3396 // skip the test if WiFi is not supported 3397 return; 3398 } 3399 mWifiManager.isWpa3SaeSupported(); 3400 } 3401 3402 /** 3403 * Tests {@link WifiManager#isWpa3SuiteBSupported()} does not crash. 3404 */ testIsWpa3SuiteBSupported()3405 public void testIsWpa3SuiteBSupported() throws Exception { 3406 if (!WifiFeature.isWifiSupported(getContext())) { 3407 // skip the test if WiFi is not supported 3408 return; 3409 } 3410 mWifiManager.isWpa3SuiteBSupported(); 3411 } 3412 3413 /** 3414 * Tests {@link WifiManager#isEnhancedOpenSupported()} does not crash. 3415 */ testIsEnhancedOpenSupported()3416 public void testIsEnhancedOpenSupported() throws Exception { 3417 if (!WifiFeature.isWifiSupported(getContext())) { 3418 // skip the test if WiFi is not supported 3419 return; 3420 } 3421 mWifiManager.isEnhancedOpenSupported(); 3422 } 3423 3424 /** 3425 * Test that {@link WifiManager#is5GHzBandSupported()} returns successfully in 3426 * both WiFi enabled/disabled states. 3427 * Note that the response depends on device support and hence both true/false 3428 * are valid responses. 3429 */ testIs5GhzBandSupported()3430 public void testIs5GhzBandSupported() throws Exception { 3431 if (!WifiFeature.isWifiSupported(getContext())) { 3432 // skip the test if WiFi is not supported 3433 return; 3434 } 3435 3436 // Check for 5GHz support with wifi enabled 3437 setWifiEnabled(true); 3438 PollingCheck.check( 3439 "Wifi not enabled!", 3440 20000, 3441 () -> mWifiManager.isWifiEnabled()); 3442 boolean isSupportedEnabled = mWifiManager.is5GHzBandSupported(); 3443 3444 // Check for 5GHz support with wifi disabled 3445 setWifiEnabled(false); 3446 PollingCheck.check( 3447 "Wifi not disabled!", 3448 20000, 3449 () -> !mWifiManager.isWifiEnabled()); 3450 boolean isSupportedDisabled = mWifiManager.is5GHzBandSupported(); 3451 3452 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 3453 // Note, the reverse is a valid case. 3454 if (isSupportedDisabled) { 3455 assertTrue(isSupportedEnabled); 3456 } 3457 } 3458 3459 /** 3460 * Test that {@link WifiManager#is6GHzBandSupported()} returns successfully in 3461 * both Wifi enabled/disabled states. 3462 * Note that the response depends on device support and hence both true/false 3463 * are valid responses. 3464 */ testIs6GhzBandSupported()3465 public void testIs6GhzBandSupported() throws Exception { 3466 if (!WifiFeature.isWifiSupported(getContext())) { 3467 // skip the test if WiFi is not supported 3468 return; 3469 } 3470 3471 // Check for 6GHz support with wifi enabled 3472 setWifiEnabled(true); 3473 PollingCheck.check( 3474 "Wifi not enabled!", 3475 20000, 3476 () -> mWifiManager.isWifiEnabled()); 3477 boolean isSupportedEnabled = mWifiManager.is6GHzBandSupported(); 3478 3479 // Check for 6GHz support with wifi disabled 3480 setWifiEnabled(false); 3481 PollingCheck.check( 3482 "Wifi not disabled!", 3483 20000, 3484 () -> !mWifiManager.isWifiEnabled()); 3485 boolean isSupportedDisabled = mWifiManager.is6GHzBandSupported(); 3486 3487 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 3488 // Note, the reverse is a valid case. 3489 if (isSupportedDisabled) { 3490 assertTrue(isSupportedEnabled); 3491 } 3492 } 3493 3494 /** 3495 * Test that {@link WifiManager#is60GHzBandSupported()} returns successfully in 3496 * both Wifi enabled/disabled states. 3497 * Note that the response depends on device support and hence both true/false 3498 * are valid responses. 3499 */ testIs60GhzBandSupported()3500 public void testIs60GhzBandSupported() throws Exception { 3501 if (!(WifiFeature.isWifiSupported(getContext()) 3502 && ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S))) { 3503 // skip the test if WiFi is not supported 3504 return; 3505 } 3506 3507 // Check for 60GHz support with wifi enabled 3508 setWifiEnabled(true); 3509 PollingCheck.check( 3510 "Wifi not enabled!", 3511 20000, 3512 () -> mWifiManager.isWifiEnabled()); 3513 boolean isSupportedEnabled = mWifiManager.is60GHzBandSupported(); 3514 3515 // Check for 60GHz support with wifi disabled 3516 setWifiEnabled(false); 3517 PollingCheck.check( 3518 "Wifi not disabled!", 3519 20000, 3520 () -> !mWifiManager.isWifiEnabled()); 3521 boolean isSupportedDisabled = mWifiManager.is60GHzBandSupported(); 3522 3523 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 3524 // Note, the reverse is a valid case. 3525 if (isSupportedDisabled) { 3526 assertTrue(isSupportedEnabled); 3527 } 3528 } 3529 3530 /** 3531 * Test that {@link WifiManager#isWifiStandardSupported()} returns successfully in 3532 * both Wifi enabled/disabled states. The test is to be performed on 3533 * {@link WifiAnnotations}'s {@code WIFI_STANDARD_} 3534 * Note that the response depends on device support and hence both true/false 3535 * are valid responses. 3536 */ testIsWifiStandardsSupported()3537 public void testIsWifiStandardsSupported() throws Exception { 3538 if (!WifiFeature.isWifiSupported(getContext())) { 3539 // skip the test if WiFi is not supported 3540 return; 3541 } 3542 3543 // Check for WiFi standards support with wifi enabled 3544 setWifiEnabled(true); 3545 PollingCheck.check( 3546 "Wifi not enabled!", 3547 20000, 3548 () -> mWifiManager.isWifiEnabled()); 3549 boolean isLegacySupportedEnabled = 3550 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY); 3551 boolean is11nSupporedEnabled = 3552 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N); 3553 boolean is11acSupportedEnabled = 3554 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC); 3555 boolean is11axSupportedEnabled = 3556 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX); 3557 3558 // Check for WiFi standards support with wifi disabled 3559 setWifiEnabled(false); 3560 PollingCheck.check( 3561 "Wifi not disabled!", 3562 20000, 3563 () -> !mWifiManager.isWifiEnabled()); 3564 3565 boolean isLegacySupportedDisabled = 3566 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY); 3567 boolean is11nSupportedDisabled = 3568 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N); 3569 boolean is11acSupportedDisabled = 3570 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC); 3571 boolean is11axSupportedDisabled = 3572 mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX); 3573 3574 if (isLegacySupportedDisabled) { 3575 assertTrue(isLegacySupportedEnabled); 3576 } 3577 3578 if (is11nSupportedDisabled) { 3579 assertTrue(is11nSupporedEnabled); 3580 } 3581 3582 if (is11acSupportedDisabled) { 3583 assertTrue(is11acSupportedEnabled); 3584 } 3585 3586 if (is11axSupportedDisabled) { 3587 assertTrue(is11axSupportedEnabled); 3588 } 3589 } 3590 createPasspointConfiguration()3591 private static PasspointConfiguration createPasspointConfiguration() { 3592 PasspointConfiguration config = new PasspointConfiguration(); 3593 HomeSp homeSp = new HomeSp(); 3594 homeSp.setFqdn("test.com"); 3595 homeSp.setFriendlyName("friendly name"); 3596 homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66}); 3597 config.setHomeSp(homeSp); 3598 Credential.SimCredential simCred = new Credential.SimCredential(); 3599 simCred.setImsi("123456*"); 3600 simCred.setEapType(23 /* EAP_AKA */); 3601 Credential cred = new Credential(); 3602 cred.setRealm("realm"); 3603 cred.setSimCredential(simCred); 3604 config.setCredential(cred); 3605 3606 return config; 3607 } 3608 3609 /** 3610 * Tests {@link WifiManager#addOrUpdatePasspointConfiguration(PasspointConfiguration)} 3611 * adds a Passpoint configuration correctly by getting it once it is added, and comparing it 3612 * to the local copy of the configuration. 3613 */ testAddOrUpdatePasspointConfiguration()3614 public void testAddOrUpdatePasspointConfiguration() throws Exception { 3615 if (!WifiFeature.isWifiSupported(getContext())) { 3616 // skip the test if WiFi is not supported 3617 return; 3618 } 3619 3620 // Create and install a Passpoint configuration 3621 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 3622 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3623 try { 3624 uiAutomation.adoptShellPermissionIdentity(); 3625 mWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 3626 3627 // Compare configurations 3628 List<PasspointConfiguration> configurations = mWifiManager.getPasspointConfigurations(); 3629 assertNotNull("The installed passpoint profile is missing", configurations); 3630 assertEquals(passpointConfiguration, getTargetPasspointConfiguration(configurations, 3631 passpointConfiguration.getUniqueId())); 3632 } finally { 3633 // Clean up 3634 mWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn()); 3635 uiAutomation.dropShellPermissionIdentity(); 3636 } 3637 } 3638 3639 /** 3640 * Tests {@link WifiManager#setPasspointMeteredOverride(String, int)} 3641 * adds a Passpoint configuration correctly, check the default metered setting. Use API change 3642 * metered override, verify Passpoint configuration changes with it. 3643 */ testSetPasspointMeteredOverride()3644 public void testSetPasspointMeteredOverride() throws Exception { 3645 if (!WifiFeature.isWifiSupported(getContext())) { 3646 // skip the test if WiFi is not supported 3647 return; 3648 } 3649 // Create and install a Passpoint configuration 3650 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 3651 String fqdn = passpointConfiguration.getHomeSp().getFqdn(); 3652 String uniqueId = passpointConfiguration.getUniqueId(); 3653 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3654 3655 try { 3656 uiAutomation.adoptShellPermissionIdentity(); 3657 mWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 3658 PasspointConfiguration saved = getTargetPasspointConfiguration( 3659 mWifiManager.getPasspointConfigurations(), uniqueId); 3660 assertNotNull("The installed passpoint profile is missing", saved); 3661 // Verify meter override setting. 3662 assertEquals("Metered overrider default should be none", 3663 WifiConfiguration.METERED_OVERRIDE_NONE, saved.getMeteredOverride()); 3664 // Change the meter override setting. 3665 mWifiManager.setPasspointMeteredOverride(fqdn, 3666 WifiConfiguration.METERED_OVERRIDE_METERED); 3667 // Verify passpoint config change with the new setting. 3668 saved = getTargetPasspointConfiguration( 3669 mWifiManager.getPasspointConfigurations(), uniqueId); 3670 assertNotNull("The installed passpoint profile is missing", saved); 3671 assertEquals("Metered override should be metered", 3672 WifiConfiguration.METERED_OVERRIDE_METERED, saved.getMeteredOverride()); 3673 } finally { 3674 // Clean up 3675 mWifiManager.removePasspointConfiguration(fqdn); 3676 uiAutomation.dropShellPermissionIdentity(); 3677 } 3678 } 3679 3680 /** 3681 * Tests that 3682 * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, Executor, ProvisioningCallback)} 3683 * starts a subscription provisioning, and confirm a status callback invoked once. 3684 */ testStartSubscriptionProvisioning()3685 public void testStartSubscriptionProvisioning() throws Exception { 3686 if (!WifiFeature.isWifiSupported(getContext())) { 3687 // skip the test if WiFi is not supported 3688 return; 3689 } 3690 3691 // Using Java reflection to construct an OsuProvider instance because its constructor is 3692 // hidden and not available to apps. 3693 Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider"); 3694 Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class, 3695 Map.class, String.class, Uri.class, String.class, List.class); 3696 3697 OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID, 3698 TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, 3699 TEST_METHOD_LIST); 3700 3701 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3702 try { 3703 uiAutomation.adoptShellPermissionIdentity(); 3704 synchronized (mLock) { 3705 // Start a subscription provisioning for a non-existent Passpoint R2 AP 3706 mWifiManager.startSubscriptionProvisioning(osuProvider, mExecutor, 3707 mProvisioningCallback); 3708 mLock.wait(TEST_WAIT_DURATION_MS); 3709 } 3710 } finally { 3711 uiAutomation.dropShellPermissionIdentity(); 3712 } 3713 3714 // Expect only a single callback event, connecting. Since AP doesn't exist, it ends here 3715 assertEquals(ProvisioningCallback.OSU_STATUS_AP_CONNECTING, mProvisioningStatus); 3716 // No failure callbacks expected 3717 assertEquals(0, mProvisioningFailureStatus); 3718 // No completion callback expected 3719 assertFalse(mProvisioningComplete); 3720 } 3721 3722 /** 3723 * Tests {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} does not crash. 3724 */ testSetTdlsEnabled()3725 public void testSetTdlsEnabled() throws Exception { 3726 if (!WifiFeature.isWifiSupported(getContext())) { 3727 // skip the test if WiFi is not supported 3728 return; 3729 } 3730 // Trigger a scan & wait for connection to one of the saved networks. 3731 mWifiManager.startScan(); 3732 waitForConnection(); 3733 3734 InetAddress inetAddress = InetAddress.getByName(TEST_IP_ADDRESS); 3735 3736 mWifiManager.setTdlsEnabled(inetAddress, true); 3737 Thread.sleep(50); 3738 mWifiManager.setTdlsEnabled(inetAddress, false); 3739 } 3740 3741 /** 3742 * Tests {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} does not crash. 3743 */ testSetTdlsEnabledWithMacAddress()3744 public void testSetTdlsEnabledWithMacAddress() throws Exception { 3745 if (!WifiFeature.isWifiSupported(getContext())) { 3746 // skip the test if WiFi is not supported 3747 return; 3748 } 3749 // Trigger a scan & wait for connection to one of the saved networks. 3750 mWifiManager.startScan(); 3751 waitForConnection(); 3752 3753 mWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, true); 3754 Thread.sleep(50); 3755 mWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, false); 3756 } 3757 3758 /** 3759 * Verify WifiNetworkSuggestion.Builder.setMacRandomizationSetting(WifiNetworkSuggestion 3760 * .RANDOMIZATION_NON_PERSISTENT) creates a 3761 * WifiConfiguration with macRandomizationSetting == RANDOMIZATION_NON_PERSISTENT. 3762 * Then verify by default, a WifiConfiguration created by suggestions should have 3763 * macRandomizationSetting == RANDOMIZATION_PERSISTENT. 3764 */ 3765 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testSuggestionBuilderNonPersistentRandomization()3766 public void testSuggestionBuilderNonPersistentRandomization() throws Exception { 3767 if (!WifiFeature.isWifiSupported(getContext())) { 3768 // skip the test if WiFi is not supported 3769 return; 3770 } 3771 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 3772 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE) 3773 .setMacRandomizationSetting(WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT) 3774 .build(); 3775 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 3776 mWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 3777 verifySuggestionFoundWithMacRandomizationSetting(TEST_SSID, 3778 WifiConfiguration.RANDOMIZATION_NON_PERSISTENT); 3779 3780 suggestion = new WifiNetworkSuggestion.Builder() 3781 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE) 3782 .build(); 3783 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 3784 mWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 3785 verifySuggestionFoundWithMacRandomizationSetting(TEST_SSID, 3786 WifiConfiguration.RANDOMIZATION_PERSISTENT); 3787 } 3788 verifySuggestionFoundWithMacRandomizationSetting(String ssid, int macRandomizationSetting)3789 private void verifySuggestionFoundWithMacRandomizationSetting(String ssid, 3790 int macRandomizationSetting) { 3791 List<WifiNetworkSuggestion> retrievedSuggestions = mWifiManager.getNetworkSuggestions(); 3792 for (WifiNetworkSuggestion entry : retrievedSuggestions) { 3793 if (entry.getSsid().equals(ssid)) { 3794 assertEquals(macRandomizationSetting, 3795 entry.getWifiConfiguration().macRandomizationSetting); 3796 return; // pass test after the MAC randomization setting is verified. 3797 } 3798 } 3799 fail("WifiNetworkSuggestion not found for SSID=" + ssid + ", macRandomizationSetting=" 3800 + macRandomizationSetting); 3801 } 3802 3803 /** 3804 * Tests {@link WifiManager#getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(List)} 3805 */ testGetAllWifiConfigForMatchedNetworkSuggestion()3806 public void testGetAllWifiConfigForMatchedNetworkSuggestion() { 3807 if (!WifiFeature.isWifiSupported(getContext())) { 3808 // skip the test if WiFi is not supported 3809 return; 3810 } 3811 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3812 ScanResult scanResult = new ScanResult(); 3813 scanResult.SSID = TEST_SSID; 3814 scanResult.capabilities = TEST_PSK_CAP; 3815 scanResult.BSSID = TEST_BSSID; 3816 List<ScanResult> testList = Arrays.asList(scanResult); 3817 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 3818 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE).build(); 3819 3820 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 3821 mWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 3822 List<WifiConfiguration> matchedResult; 3823 try { 3824 uiAutomation.adoptShellPermissionIdentity(); 3825 matchedResult = mWifiManager 3826 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(testList); 3827 } finally { 3828 uiAutomation.dropShellPermissionIdentity(); 3829 } 3830 // As suggestion is not approved, will return empty list. 3831 assertTrue(matchedResult.isEmpty()); 3832 } 3833 3834 /** 3835 * Tests {@link WifiManager#getMatchingScanResults(List, List)} 3836 */ testGetMatchingScanResults()3837 public void testGetMatchingScanResults() { 3838 if (!WifiFeature.isWifiSupported(getContext())) { 3839 // skip the test if WiFi is not supported 3840 return; 3841 } 3842 // Create pair of ScanResult and WifiNetworkSuggestion 3843 ScanResult scanResult = new ScanResult(); 3844 scanResult.SSID = TEST_SSID; 3845 scanResult.capabilities = TEST_PSK_CAP; 3846 scanResult.BSSID = TEST_BSSID; 3847 3848 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 3849 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE).build(); 3850 3851 Map<WifiNetworkSuggestion, List<ScanResult>> matchedResults = mWifiManager 3852 .getMatchingScanResults(Arrays.asList(suggestion), Arrays.asList(scanResult)); 3853 // Verify result is matched pair of ScanResult and WifiNetworkSuggestion 3854 assertEquals(scanResult.SSID, matchedResults.get(suggestion).get(0).SSID); 3855 3856 // Change ScanResult to unmatched should return empty result. 3857 scanResult.SSID = TEST_SSID_UNQUOTED; 3858 matchedResults = mWifiManager 3859 .getMatchingScanResults(Arrays.asList(suggestion), Arrays.asList(scanResult)); 3860 assertTrue(matchedResults.get(suggestion).isEmpty()); 3861 } 3862 3863 /** 3864 * Tests {@link WifiManager#disableEphemeralNetwork(String)}. 3865 */ testDisableEphemeralNetwork()3866 public void testDisableEphemeralNetwork() throws Exception { 3867 if (!WifiFeature.isWifiSupported(getContext())) { 3868 // skip the test if WiFi is not supported 3869 return; 3870 } 3871 // Trigger a scan & wait for connection to one of the saved networks. 3872 mWifiManager.startScan(); 3873 waitForConnection(); 3874 3875 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3876 List<WifiConfiguration> savedNetworks = null; 3877 try { 3878 uiAutomation.adoptShellPermissionIdentity(); 3879 // Temporarily disable on all networks. 3880 savedNetworks = mWifiManager.getConfiguredNetworks(); 3881 for (WifiConfiguration network : savedNetworks) { 3882 mWifiManager.disableEphemeralNetwork(network.SSID); 3883 } 3884 // trigger a disconnect and wait for disconnect. 3885 mWifiManager.disconnect(); 3886 waitForDisconnection(); 3887 3888 // Now trigger scan and ensure that the device does not connect to any networks. 3889 mWifiManager.startScan(); 3890 ensureNotConnected(); 3891 } finally { 3892 uiAutomation.dropShellPermissionIdentity(); 3893 setWifiEnabled(false); 3894 } 3895 } 3896 3897 /** 3898 * Tests {@link WifiManager#allowAutojoin(int, boolean)}. 3899 */ testAllowAutojoin()3900 public void testAllowAutojoin() throws Exception { 3901 if (!WifiFeature.isWifiSupported(getContext())) { 3902 // skip the test if WiFi is not supported 3903 return; 3904 } 3905 // Trigger a scan & wait for connection to one of the saved networks. 3906 mWifiManager.startScan(); 3907 waitForConnection(); 3908 3909 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3910 List<WifiConfiguration> savedNetworks = null; 3911 try { 3912 uiAutomation.adoptShellPermissionIdentity(); 3913 // disable autojoin on all networks. 3914 savedNetworks = mWifiManager.getConfiguredNetworks(); 3915 for (WifiConfiguration network : savedNetworks) { 3916 mWifiManager.allowAutojoin(network.networkId, false); 3917 } 3918 // trigger a disconnect and wait for disconnect. 3919 mWifiManager.disconnect(); 3920 waitForDisconnection(); 3921 3922 // Now trigger scan and ensure that the device does not connect to any networks. 3923 mWifiManager.startScan(); 3924 ensureNotConnected(); 3925 3926 // Now enable autojoin on all networks. 3927 for (WifiConfiguration network : savedNetworks) { 3928 mWifiManager.allowAutojoin(network.networkId, true); 3929 } 3930 3931 // Trigger a scan & wait for connection to one of the saved networks. 3932 mWifiManager.startScan(); 3933 waitForConnection(); 3934 } finally { 3935 // Restore auto join state. 3936 if (savedNetworks != null) { 3937 for (WifiConfiguration network : savedNetworks) { 3938 mWifiManager.allowAutojoin(network.networkId, network.allowAutojoin); 3939 } 3940 } 3941 uiAutomation.dropShellPermissionIdentity(); 3942 } 3943 } 3944 3945 /** 3946 * Tests {@link WifiManager#allowAutojoinPasspoint(String, boolean)}. 3947 */ testAllowAutojoinPasspoint()3948 public void testAllowAutojoinPasspoint() throws Exception { 3949 if (!WifiFeature.isWifiSupported(getContext())) { 3950 // skip the test if WiFi is not supported 3951 return; 3952 } 3953 3954 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 3955 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3956 try { 3957 uiAutomation.adoptShellPermissionIdentity(); 3958 mWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 3959 // Turn off auto-join 3960 mWifiManager.allowAutojoinPasspoint( 3961 passpointConfiguration.getHomeSp().getFqdn(), false); 3962 // Turn on auto-join 3963 mWifiManager.allowAutojoinPasspoint( 3964 passpointConfiguration.getHomeSp().getFqdn(), true); 3965 } finally { 3966 mWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn()); 3967 uiAutomation.dropShellPermissionIdentity(); 3968 } 3969 } 3970 3971 /** 3972 * Tests {@link WifiManager#allowAutojoinGlobal(boolean)}. 3973 */ testAllowAutojoinGlobal()3974 public void testAllowAutojoinGlobal() throws Exception { 3975 if (!WifiFeature.isWifiSupported(getContext())) { 3976 // skip the test if WiFi is not supported 3977 return; 3978 } 3979 // Trigger a scan & wait for connection to one of the saved networks. 3980 mWifiManager.startScan(); 3981 waitForConnection(); 3982 3983 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3984 try { 3985 uiAutomation.adoptShellPermissionIdentity(); 3986 // disable autojoin on all networks. 3987 mWifiManager.allowAutojoinGlobal(false); 3988 3989 // trigger a disconnect and wait for disconnect. 3990 mWifiManager.disconnect(); 3991 waitForDisconnection(); 3992 3993 // Now trigger scan and ensure that the device does not connect to any networks. 3994 mWifiManager.startScan(); 3995 ensureNotConnected(); 3996 3997 // Now enable autojoin on all networks. 3998 mWifiManager.allowAutojoinGlobal(true); 3999 4000 // Trigger a scan & wait for connection to one of the saved networks. 4001 mWifiManager.startScan(); 4002 waitForConnection(); 4003 } finally { 4004 // Re-enable auto join if the test fails for some reason. 4005 mWifiManager.allowAutojoinGlobal(true); 4006 uiAutomation.dropShellPermissionIdentity(); 4007 } 4008 } 4009 4010 /** 4011 * Tests {@link WifiManager#isWapiSupported()} does not crash. 4012 */ testIsWapiSupported()4013 public void testIsWapiSupported() throws Exception { 4014 if (!WifiFeature.isWifiSupported(getContext())) { 4015 // skip the test if WiFi is not supported 4016 return; 4017 } 4018 mWifiManager.isWapiSupported(); 4019 } 4020 4021 /** 4022 * Tests {@link WifiManager#isWpa3SaePublicKeySupported()} does not crash. 4023 */ 4024 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testIsWpa3SaePublicKeySupported()4025 public void testIsWpa3SaePublicKeySupported() throws Exception { 4026 if (!WifiFeature.isWifiSupported(getContext())) { 4027 // skip the test if WiFi is not supported 4028 return; 4029 } 4030 mWifiManager.isWpa3SaePublicKeySupported(); 4031 } 4032 4033 /** 4034 * Tests {@link WifiManager#isWpa3SaeH2eSupported()} does not crash. 4035 */ 4036 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testIsWpa3SaeH2eSupported()4037 public void testIsWpa3SaeH2eSupported() throws Exception { 4038 if (!WifiFeature.isWifiSupported(getContext())) { 4039 // skip the test if WiFi is not supported 4040 return; 4041 } 4042 mWifiManager.isWpa3SaeH2eSupported(); 4043 } 4044 4045 /** 4046 * Tests {@link WifiManager#isWifiDisplayR2Supported()} does not crash. 4047 */ 4048 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testIsWifiDisplayR2Supported()4049 public void testIsWifiDisplayR2Supported() throws Exception { 4050 if (!WifiFeature.isWifiSupported(getContext())) { 4051 // skip the test if WiFi is not supported 4052 return; 4053 } 4054 mWifiManager.isWifiDisplayR2Supported(); 4055 } 4056 4057 /** 4058 * Tests {@link WifiManager#isP2pSupported()} returns true 4059 * if this device supports it, otherwise, ensure no crash. 4060 */ testIsP2pSupported()4061 public void testIsP2pSupported() throws Exception { 4062 if (!WifiFeature.isWifiSupported(getContext())) { 4063 // skip the test if WiFi is not supported 4064 return; 4065 } 4066 4067 if (WifiFeature.isP2pSupported(getContext())) { 4068 // if this device supports P2P, ensure hw capability is correct. 4069 assertTrue(mWifiManager.isP2pSupported()); 4070 } else { 4071 // ensure no crash. 4072 mWifiManager.isP2pSupported(); 4073 } 4074 4075 } 4076 4077 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testIsMultiStaConcurrencySupported()4078 public void testIsMultiStaConcurrencySupported() throws Exception { 4079 if (!WifiFeature.isWifiSupported(getContext())) { 4080 // skip the test if WiFi is not supported 4081 return; 4082 } 4083 // ensure no crash. 4084 mWifiManager.isStaApConcurrencySupported(); 4085 } 4086 getTargetPasspointConfiguration( List<PasspointConfiguration> configurationList, String uniqueId)4087 private PasspointConfiguration getTargetPasspointConfiguration( 4088 List<PasspointConfiguration> configurationList, String uniqueId) { 4089 if (configurationList == null || configurationList.isEmpty()) { 4090 return null; 4091 } 4092 for (PasspointConfiguration config : configurationList) { 4093 if (TextUtils.equals(config.getUniqueId(), uniqueId)) { 4094 return config; 4095 } 4096 } 4097 return null; 4098 } 4099 4100 /** 4101 * Test that {@link WifiManager#is60GHzBandSupported()} throws UnsupportedOperationException 4102 * if the release is older than S. 4103 */ 4104 @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.R) testIs60GhzBandSupportedOnROrOlder()4105 public void testIs60GhzBandSupportedOnROrOlder() throws Exception { 4106 if (!WifiFeature.isWifiSupported(getContext())) { 4107 // skip the test if WiFi is not supported 4108 return; 4109 } 4110 4111 // check for 60ghz support with wifi enabled 4112 try { 4113 boolean isSupported = mWifiManager.is60GHzBandSupported(); 4114 fail("Expected UnsupportedOperationException"); 4115 } catch (UnsupportedOperationException ex) { 4116 } 4117 4118 } 4119 4120 /** 4121 * Test that {@link WifiManager#is60GHzBandSupported()} returns successfully in 4122 * both Wifi enabled/disabled states for release newer than R. 4123 * Note that the response depends on device support and hence both true/false 4124 * are valid responses. 4125 */ 4126 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testIs60GhzBandSupportedOnSOrNewer()4127 public void testIs60GhzBandSupportedOnSOrNewer() throws Exception { 4128 if (!WifiFeature.isWifiSupported(getContext())) { 4129 // skip the test if WiFi is not supported 4130 return; 4131 } 4132 4133 // check for 60ghz support with wifi enabled 4134 boolean isSupportedWhenWifiEnabled = mWifiManager.is60GHzBandSupported(); 4135 4136 // Check for 60GHz support with wifi disabled 4137 setWifiEnabled(false); 4138 PollingCheck.check( 4139 "Wifi not disabled!", 4140 20000, 4141 () -> !mWifiManager.isWifiEnabled()); 4142 boolean isSupportedWhenWifiDisabled = mWifiManager.is60GHzBandSupported(); 4143 4144 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 4145 // Note, the reverse is a valid case. 4146 if (isSupportedWhenWifiDisabled) { 4147 assertTrue(isSupportedWhenWifiEnabled); 4148 } 4149 } 4150 4151 public class TestCoexCallback extends WifiManager.CoexCallback { 4152 private Object mCoexLock; 4153 private int mOnCoexUnsafeChannelChangedCount; 4154 private List<CoexUnsafeChannel> mCoexUnsafeChannels; 4155 private int mCoexRestrictions; 4156 TestCoexCallback(Object lock)4157 TestCoexCallback(Object lock) { 4158 mCoexLock = lock; 4159 } 4160 4161 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, int restrictions)4162 public void onCoexUnsafeChannelsChanged( 4163 @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) { 4164 synchronized (mCoexLock) { 4165 mCoexUnsafeChannels = unsafeChannels; 4166 mCoexRestrictions = restrictions; 4167 mOnCoexUnsafeChannelChangedCount++; 4168 mCoexLock.notify(); 4169 } 4170 } 4171 getOnCoexUnsafeChannelChangedCount()4172 public int getOnCoexUnsafeChannelChangedCount() { 4173 synchronized (mCoexLock) { 4174 return mOnCoexUnsafeChannelChangedCount; 4175 } 4176 } 4177 getCoexUnsafeChannels()4178 public List<CoexUnsafeChannel> getCoexUnsafeChannels() { 4179 return mCoexUnsafeChannels; 4180 } 4181 getCoexRestrictions()4182 public int getCoexRestrictions() { 4183 return mCoexRestrictions; 4184 } 4185 } 4186 4187 /** 4188 * Test that coex-related methods fail without the needed privileged permissions 4189 */ 4190 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testCoexMethodsShouldFailNoPermission()4191 public void testCoexMethodsShouldFailNoPermission() { 4192 if (!WifiFeature.isWifiSupported(getContext())) { 4193 // skip the test if WiFi is not supported 4194 return; 4195 } 4196 4197 try { 4198 mWifiManager.setCoexUnsafeChannels(Collections.emptyList(), 0); 4199 fail("setCoexUnsafeChannels should not succeed - privileged call"); 4200 } catch (SecurityException e) { 4201 // expected 4202 } 4203 final TestCoexCallback callback = new TestCoexCallback(mLock); 4204 try { 4205 mWifiManager.registerCoexCallback(mExecutor, callback); 4206 fail("registerCoexCallback should not succeed - privileged call"); 4207 } catch (SecurityException e) { 4208 // expected 4209 } 4210 try { 4211 mWifiManager.unregisterCoexCallback(callback); 4212 fail("unregisterCoexCallback should not succeed - privileged call"); 4213 } catch (SecurityException e) { 4214 // expected 4215 } 4216 } 4217 4218 /** 4219 * Test that coex-related methods succeed in setting the current unsafe channels and notifying 4220 * the listener. Since the default coex algorithm may be enabled, no-op is also valid behavior. 4221 */ 4222 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testListenOnCoexUnsafeChannels()4223 public void testListenOnCoexUnsafeChannels() { 4224 if (!WifiFeature.isWifiSupported(getContext())) { 4225 // skip the test if WiFi is not supported 4226 return; 4227 } 4228 4229 // These below API's only work with privileged permissions (obtained via shell identity 4230 // for test) 4231 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4232 List<CoexUnsafeChannel> prevUnsafeChannels = null; 4233 int prevRestrictions = -1; 4234 try { 4235 uiAutomation.adoptShellPermissionIdentity(); 4236 final TestCoexCallback callback = new TestCoexCallback(mLock); 4237 final List<CoexUnsafeChannel> testUnsafeChannels = new ArrayList<>(); 4238 testUnsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6)); 4239 final int testRestrictions = COEX_RESTRICTION_WIFI_DIRECT 4240 | COEX_RESTRICTION_SOFTAP | COEX_RESTRICTION_WIFI_AWARE; 4241 synchronized (mLock) { 4242 try { 4243 mWifiManager.registerCoexCallback(mExecutor, callback); 4244 // Callback should be called after registering 4245 mLock.wait(TEST_WAIT_DURATION_MS); 4246 assertEquals(1, callback.getOnCoexUnsafeChannelChangedCount()); 4247 // Store the previous coex channels and set new coex channels 4248 prevUnsafeChannels = callback.getCoexUnsafeChannels(); 4249 prevRestrictions = callback.getCoexRestrictions(); 4250 mWifiManager.setCoexUnsafeChannels(testUnsafeChannels, testRestrictions); 4251 mLock.wait(TEST_WAIT_DURATION_MS); 4252 // Unregister callback and try setting again 4253 mWifiManager.unregisterCoexCallback(callback); 4254 mWifiManager.setCoexUnsafeChannels(testUnsafeChannels, testRestrictions); 4255 // Callback should not be called here since it was unregistered. 4256 mLock.wait(TEST_WAIT_DURATION_MS); 4257 } catch (InterruptedException e) { 4258 fail("Thread interrupted unexpectedly while waiting on mLock"); 4259 } 4260 } 4261 if (callback.getOnCoexUnsafeChannelChangedCount() == 2) { 4262 // Default algorithm disabled, setter should set the getter values. 4263 assertEquals(testUnsafeChannels, callback.getCoexUnsafeChannels()); 4264 assertEquals(testRestrictions, callback.getCoexRestrictions()); 4265 } else if (callback.getOnCoexUnsafeChannelChangedCount() != 1) { 4266 fail("Coex callback called " + callback.mOnCoexUnsafeChannelChangedCount 4267 + " times. Expected 0 or 1 calls." ); 4268 } 4269 } finally { 4270 // Reset the previous unsafe channels if we overrode them. 4271 if (prevRestrictions != -1) { 4272 mWifiManager.setCoexUnsafeChannels(prevUnsafeChannels, prevRestrictions); 4273 } 4274 uiAutomation.dropShellPermissionIdentity(); 4275 } 4276 } 4277 4278 /** 4279 * Verify that secure WPA-Enterprise network configurations can be added and updated. 4280 */ 4281 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testSecureEnterpriseConfigurationsAccepted()4282 public void testSecureEnterpriseConfigurationsAccepted() throws Exception { 4283 if (!WifiFeature.isWifiSupported(getContext())) { 4284 // skip the test if WiFi is not supported 4285 return; 4286 } 4287 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 4288 wifiConfiguration.SSID = SSID1; 4289 wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); 4290 wifiConfiguration.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 4291 int networkId = INVALID_NETWORK_ID; 4292 4293 // These below API's only work with privileged permissions (obtained via shell identity 4294 // for test) 4295 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4296 try { 4297 uiAutomation.adoptShellPermissionIdentity(); 4298 4299 // Now configure it correctly with a Root CA cert and domain name 4300 wifiConfiguration.enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); 4301 wifiConfiguration.enterpriseConfig.setAltSubjectMatch(TEST_DOM_SUBJECT_MATCH); 4302 4303 // Verify that the network is added 4304 networkId = mWifiManager.addNetwork(wifiConfiguration); 4305 assertNotEquals(INVALID_NETWORK_ID, networkId); 4306 4307 // Verify that the update API accepts configurations configured securely 4308 wifiConfiguration.networkId = networkId; 4309 assertEquals(networkId, mWifiManager.updateNetwork(wifiConfiguration)); 4310 } finally { 4311 if (networkId != INVALID_NETWORK_ID) { 4312 // Clean up the previously added network 4313 mWifiManager.removeNetwork(networkId); 4314 } 4315 uiAutomation.dropShellPermissionIdentity(); 4316 } 4317 } 4318 4319 /** 4320 * Tests {@link WifiManager#isPasspointTermsAndConditionsSupported)} does not crash. 4321 */ testIsPasspointTermsAndConditionsSupported()4322 public void testIsPasspointTermsAndConditionsSupported() throws Exception { 4323 if (!WifiFeature.isWifiSupported(getContext())) { 4324 // skip the test if WiFi is not supported 4325 return; 4326 } 4327 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 4328 // Skip the test if wifi module version is older than S. 4329 return; 4330 } 4331 mWifiManager.isPasspointTermsAndConditionsSupported(); 4332 } 4333 4334 /** 4335 * Test that call to {@link WifiManager#setOverrideCountryCode()}, 4336 * {@link WifiManager#clearOverrideCountryCode()} and 4337 * {@link WifiManager#setDefaultCountryCode()} need privileged permission 4338 * and the permission is not even given to shell user. 4339 */ 4340 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testManageCountryCodeMethodsFailWithoutPermissions()4341 public void testManageCountryCodeMethodsFailWithoutPermissions() throws Exception { 4342 if (!WifiFeature.isWifiSupported(getContext())) { 4343 // skip the test if WiFi is not supported 4344 return; 4345 } 4346 ShellIdentityUtils.invokeWithShellPermissions(() -> { 4347 try { 4348 mWifiManager.setOverrideCountryCode(TEST_COUNTRY_CODE); 4349 fail("setOverrideCountryCode() expected to fail - privileged call"); 4350 } catch (SecurityException e) { 4351 // expected 4352 } 4353 4354 try { 4355 mWifiManager.clearOverrideCountryCode(); 4356 fail("clearOverrideCountryCode() expected to fail - privileged call"); 4357 } catch (SecurityException e) { 4358 // expected 4359 } 4360 4361 try { 4362 mWifiManager.setDefaultCountryCode(TEST_COUNTRY_CODE); 4363 fail("setDefaultCountryCode() expected to fail - privileged call"); 4364 } catch (SecurityException e) { 4365 // expected 4366 } 4367 }); 4368 } 4369 4370 /** 4371 * Tests {@link WifiManager#flushPasspointAnqpCache)} does not crash. 4372 */ testFlushPasspointAnqpCache()4373 public void testFlushPasspointAnqpCache() throws Exception { 4374 if (!WifiFeature.isWifiSupported(getContext())) { 4375 // skip the test if WiFi is not supported 4376 return; 4377 } 4378 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 4379 // Skip the test if wifi module version is older than S. 4380 return; 4381 } 4382 // The below API only works with privileged permissions (obtained via shell identity 4383 // for test) 4384 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4385 try { 4386 uiAutomation.adoptShellPermissionIdentity(); 4387 mWifiManager.flushPasspointAnqpCache(); 4388 } finally { 4389 uiAutomation.dropShellPermissionIdentity(); 4390 } 4391 } 4392 4393 /** 4394 * Tests {@link WifiManager#isDecoratedIdentitySupported)} does not crash. 4395 */ testIsDecoratedIdentitySupported()4396 public void testIsDecoratedIdentitySupported() throws Exception { 4397 if (!WifiFeature.isWifiSupported(getContext())) { 4398 // skip the test if WiFi is not supported 4399 return; 4400 } 4401 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 4402 // Skip the test if wifi module version is older than S. 4403 return; 4404 } 4405 mWifiManager.isDecoratedIdentitySupported(); 4406 } 4407 4408 /** 4409 * Tests {@link WifiManager#setCarrierNetworkOffloadEnabled)} and 4410 * {@link WifiManager#isCarrierNetworkOffloadEnabled} work as expected. 4411 */ testSetCarrierNetworkOffloadEnabled()4412 public void testSetCarrierNetworkOffloadEnabled() { 4413 if (!WifiFeature.isWifiSupported(getContext()) 4414 || !WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 4415 // skip the test if WiFi is not supported 4416 return; 4417 } 4418 assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 4419 // The below API only works with privileged permissions (obtained via shell identity 4420 // for test) 4421 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4422 try { 4423 uiAutomation.adoptShellPermissionIdentity(); 4424 mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, false, false); 4425 assertFalse(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 4426 } finally { 4427 mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, false, true); 4428 uiAutomation.dropShellPermissionIdentity(); 4429 } 4430 assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 4431 } 4432 4433 /** 4434 * Test that {@link WifiManager#getUsableChannels(int, int)}, 4435 * {@link WifiManager#getAllowedChannels(int, int)} 4436 * throws UnsupportedOperationException if the release is older than S. 4437 */ 4438 @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.R) testGetAllowedUsableChannelsOnROrOlder()4439 public void testGetAllowedUsableChannelsOnROrOlder() throws Exception { 4440 if (!WifiFeature.isWifiSupported(getContext())) { 4441 // skip the test if WiFi is not supported 4442 return; 4443 } 4444 try { 4445 mWifiManager.getAllowedChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 4446 fail("getAllowedChannels Expected to fail - UnsupportedOperationException"); 4447 } catch (UnsupportedOperationException ex) {} 4448 4449 try { 4450 mWifiManager.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 4451 fail("getUsableChannels Expected to fail - UnsupportedOperationException"); 4452 } catch (UnsupportedOperationException ex) {} 4453 } 4454 4455 /** 4456 * Tests {@link WifiManager#getAllowedChannels(int, int))} does not crash 4457 */ 4458 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testGetAllowedChannels()4459 public void testGetAllowedChannels() throws Exception { 4460 if (!WifiFeature.isWifiSupported(getContext())) { 4461 // skip the test if WiFi is not supported 4462 return; 4463 } 4464 // The below API only works with privileged permissions (obtained via shell identity 4465 // for test) 4466 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4467 try { 4468 4469 WifiAvailableChannel channel = new WifiAvailableChannel(2412, OP_MODE_SAP); 4470 assertEquals(channel.getFrequencyMhz(), 2412); 4471 assertEquals(channel.getOperationalModes(), OP_MODE_SAP); 4472 final List<Integer> valid24GhzFreqs = Arrays.asList( 4473 2412, 2417, 2422, 2427, 2432, 2437, 2442, 4474 2447, 2452, 2457, 2462, 2467, 2472, 2484); 4475 Set<Integer> supported24GhzFreqs = new HashSet<Integer>(); 4476 uiAutomation.adoptShellPermissionIdentity(); 4477 List<WifiAvailableChannel> allowedChannels = 4478 mWifiManager.getAllowedChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 4479 assertNotNull(allowedChannels); 4480 for (WifiAvailableChannel ch : allowedChannels) { 4481 //Must contain a valid 2.4GHz frequency 4482 assertTrue(valid24GhzFreqs.contains(ch.getFrequencyMhz())); 4483 if(ch.getFrequencyMhz() <= 2462) { 4484 //Channels 1-11 are supported for STA in all countries 4485 assertEquals(ch.getOperationalModes() & OP_MODE_STA, OP_MODE_STA); 4486 supported24GhzFreqs.add(ch.getFrequencyMhz()); 4487 } 4488 } 4489 //Channels 1-11 are supported for STA in all countries 4490 assertEquals(supported24GhzFreqs.size(), 11); 4491 } catch (UnsupportedOperationException ex) { 4492 //expected if the device does not support this API 4493 } catch (Exception ex) { 4494 fail("getAllowedChannels unexpected Exception " + ex); 4495 } finally { 4496 uiAutomation.dropShellPermissionIdentity(); 4497 } 4498 } 4499 4500 /** 4501 * Tests {@link WifiManager#getUsableChannels(int, int))} does not crash. 4502 */ 4503 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testGetUsableChannels()4504 public void testGetUsableChannels() throws Exception { 4505 if (!WifiFeature.isWifiSupported(getContext())) { 4506 // skip the test if WiFi is not supported 4507 return; 4508 } 4509 // The below API only works with privileged permissions (obtained via shell identity 4510 // for test) 4511 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4512 try { 4513 uiAutomation.adoptShellPermissionIdentity(); 4514 List<WifiAvailableChannel> usableChannels = 4515 mWifiManager.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 4516 //There must be at least one usable channel in 2.4GHz band 4517 assertFalse(usableChannels.isEmpty()); 4518 } catch (UnsupportedOperationException ex) { 4519 //expected if the device does not support this API 4520 } catch (Exception ex) { 4521 fail("getUsableChannels unexpected Exception " + ex); 4522 } finally { 4523 uiAutomation.dropShellPermissionIdentity(); 4524 } 4525 } 4526 4527 /** 4528 * Validate that the Passpoint feature is enabled on the device. 4529 */ 4530 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testPasspointCapability()4531 public void testPasspointCapability() { 4532 if (!WifiFeature.isWifiSupported(getContext())) { 4533 // skip the test if WiFi is not supported 4534 return; 4535 } 4536 PackageManager packageManager = mContext.getPackageManager(); 4537 assertTrue("Passpoint must be supported", 4538 packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)); 4539 } 4540 4541 /** 4542 * Validate add and remove SuggestionUserApprovalStatusListener. And verify the listener's 4543 * stickiness. 4544 */ testAddRemoveSuggestionUserApprovalStatusListener()4545 public void testAddRemoveSuggestionUserApprovalStatusListener() throws Exception { 4546 if (!WifiFeature.isWifiSupported(getContext()) 4547 || !WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 4548 return; 4549 } 4550 CountDownLatch countDownLatch = new CountDownLatch(1); 4551 TestUserApprovalStatusListener listener = new TestUserApprovalStatusListener( 4552 countDownLatch); 4553 try { 4554 mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, listener); 4555 assertTrue(countDownLatch.await(TEST_WAIT_DURATION_MS, TimeUnit.MILLISECONDS)); 4556 } finally { 4557 mWifiManager.removeSuggestionUserApprovalStatusListener(listener); 4558 } 4559 } 4560 4561 private static class TestUserApprovalStatusListener implements 4562 WifiManager.SuggestionUserApprovalStatusListener { 4563 private final CountDownLatch mBlocker; 4564 TestUserApprovalStatusListener(CountDownLatch countDownLatch)4565 public TestUserApprovalStatusListener(CountDownLatch countDownLatch) { 4566 mBlocker = countDownLatch; 4567 } 4568 @Override onUserApprovalStatusChange(int status)4569 public void onUserApprovalStatusChange(int status) { 4570 mBlocker.countDown(); 4571 } 4572 } 4573 } 4574