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