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.content.Context.RECEIVER_EXPORTED; 20 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 21 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 22 import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; 23 import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP; 24 import static android.net.wifi.WifiAvailableChannel.OP_MODE_STA; 25 import static android.net.wifi.WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO; 26 import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; 27 import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP; 28 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE; 29 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT; 30 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 31 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 32 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 33 import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; 34 import static android.os.Process.myUid; 35 36 import static com.google.common.truth.Truth.assertThat; 37 import static com.google.common.truth.Truth.assertWithMessage; 38 39 import static org.junit.Assert.assertArrayEquals; 40 import static org.junit.Assert.assertEquals; 41 import static org.junit.Assert.assertFalse; 42 import static org.junit.Assert.assertNotEquals; 43 import static org.junit.Assert.assertNotNull; 44 import static org.junit.Assert.assertNull; 45 import static org.junit.Assert.assertThrows; 46 import static org.junit.Assert.assertTrue; 47 import static org.junit.Assert.fail; 48 import static org.junit.Assume.assumeTrue; 49 50 import android.annotation.NonNull; 51 import android.app.UiAutomation; 52 import android.app.admin.DevicePolicyManager; 53 import android.app.admin.WifiSsidPolicy; 54 import android.content.BroadcastReceiver; 55 import android.content.Context; 56 import android.content.Intent; 57 import android.content.IntentFilter; 58 import android.content.pm.PackageInfo; 59 import android.content.pm.PackageManager; 60 import android.content.pm.ResolveInfo; 61 import android.net.ConnectivityManager; 62 import android.net.MacAddress; 63 import android.net.Network; 64 import android.net.NetworkCapabilities; 65 import android.net.NetworkInfo; 66 import android.net.NetworkRequest; 67 import android.net.TetheringManager; 68 import android.net.Uri; 69 import android.net.wifi.BlockingOption; 70 import android.net.wifi.CoexUnsafeChannel; 71 import android.net.wifi.MloLink; 72 import android.net.wifi.MscsParams; 73 import android.net.wifi.OuiKeyedData; 74 import android.net.wifi.QosCharacteristics; 75 import android.net.wifi.QosPolicyParams; 76 import android.net.wifi.ScanResult; 77 import android.net.wifi.SoftApCapability; 78 import android.net.wifi.SoftApConfiguration; 79 import android.net.wifi.SoftApInfo; 80 import android.net.wifi.SoftApState; 81 import android.net.wifi.UriParserResults; 82 import android.net.wifi.WifiAvailableChannel; 83 import android.net.wifi.WifiClient; 84 import android.net.wifi.WifiConfiguration; 85 import android.net.wifi.WifiEnterpriseConfig; 86 import android.net.wifi.WifiInfo; 87 import android.net.wifi.WifiManager; 88 import android.net.wifi.WifiManager.SubsystemRestartTrackingCallback; 89 import android.net.wifi.WifiManager.WifiLock; 90 import android.net.wifi.WifiNetworkConnectionStatistics; 91 import android.net.wifi.WifiNetworkSelectionConfig; 92 import android.net.wifi.WifiNetworkSuggestion; 93 import android.net.wifi.WifiScanner; 94 import android.net.wifi.WifiSsid; 95 import android.net.wifi.WifiUriParser; 96 import android.net.wifi.hotspot2.ConfigParser; 97 import android.net.wifi.hotspot2.OsuProvider; 98 import android.net.wifi.hotspot2.PasspointConfiguration; 99 import android.net.wifi.hotspot2.ProvisioningCallback; 100 import android.net.wifi.hotspot2.pps.Credential; 101 import android.net.wifi.hotspot2.pps.HomeSp; 102 import android.net.wifi.twt.TwtRequest; 103 import android.net.wifi.twt.TwtSession; 104 import android.net.wifi.twt.TwtSessionCallback; 105 import android.os.Build; 106 import android.os.Bundle; 107 import android.os.Handler; 108 import android.os.HandlerExecutor; 109 import android.os.HandlerThread; 110 import android.os.PersistableBundle; 111 import android.os.PowerManager; 112 import android.os.Process; 113 import android.os.SystemClock; 114 import android.os.SystemProperties; 115 import android.os.UserHandle; 116 import android.platform.test.annotations.AppModeFull; 117 import android.platform.test.annotations.AsbSecurityTest; 118 import android.platform.test.annotations.RequiresDevice; 119 import android.platform.test.annotations.RequiresFlagsEnabled; 120 import android.platform.test.flag.junit.CheckFlagsRule; 121 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 122 import android.provider.DeviceConfig; 123 import android.provider.Settings; 124 import android.security.advancedprotection.AdvancedProtectionFeature; 125 import android.support.test.uiautomator.UiDevice; 126 import android.telephony.TelephonyManager; 127 import android.text.TextUtils; 128 import android.util.ArraySet; 129 import android.util.Log; 130 import android.util.SparseArray; 131 import android.util.SparseIntArray; 132 133 import androidx.test.ext.junit.runners.AndroidJUnit4; 134 import androidx.test.filters.SdkSuppress; 135 import androidx.test.platform.app.InstrumentationRegistry; 136 137 import com.android.compatibility.common.util.ApiLevelUtil; 138 import com.android.compatibility.common.util.ApiTest; 139 import com.android.compatibility.common.util.FeatureUtil; 140 import com.android.compatibility.common.util.PollingCheck; 141 import com.android.compatibility.common.util.PropertyUtil; 142 import com.android.compatibility.common.util.ShellIdentityUtils; 143 import com.android.compatibility.common.util.SystemUtil; 144 import com.android.compatibility.common.util.ThrowingRunnable; 145 import com.android.modules.utils.build.SdkLevel; 146 import com.android.net.module.util.MacAddressUtils; 147 import com.android.wifi.flags.Flags; 148 149 import com.google.common.collect.Range; 150 151 import org.junit.AfterClass; 152 import org.junit.Before; 153 import org.junit.BeforeClass; 154 import org.junit.Rule; 155 import org.junit.Test; 156 import org.junit.runner.RunWith; 157 158 import java.io.BufferedReader; 159 import java.io.IOException; 160 import java.io.InputStream; 161 import java.io.InputStreamReader; 162 import java.lang.reflect.Constructor; 163 import java.net.HttpURLConnection; 164 import java.net.InetAddress; 165 import java.net.URL; 166 import java.nio.charset.StandardCharsets; 167 import java.time.Duration; 168 import java.util.ArrayList; 169 import java.util.Arrays; 170 import java.util.Collections; 171 import java.util.HashMap; 172 import java.util.HashSet; 173 import java.util.List; 174 import java.util.Locale; 175 import java.util.Map; 176 import java.util.Objects; 177 import java.util.Set; 178 import java.util.concurrent.ConcurrentLinkedQueue; 179 import java.util.concurrent.CountDownLatch; 180 import java.util.concurrent.Executor; 181 import java.util.concurrent.Executors; 182 import java.util.concurrent.TimeUnit; 183 import java.util.concurrent.atomic.AtomicBoolean; 184 import java.util.concurrent.atomic.AtomicInteger; 185 import java.util.concurrent.atomic.AtomicReference; 186 import java.util.function.BiConsumer; 187 import java.util.function.Consumer; 188 import java.util.function.IntConsumer; 189 import java.util.stream.Collectors; 190 191 @RunWith(AndroidJUnit4.class) 192 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 193 public class WifiManagerTest extends WifiJUnit4TestBase { 194 private static Context sContext; 195 private static boolean sShouldRunTest = false; 196 197 private static class MySync { 198 int expectedState = STATE_NULL; 199 } 200 201 private static WifiManager sWifiManager; 202 private static ConnectivityManager sConnectivityManager; 203 private static TetheringManager sTetheringManager; 204 private static MySync sMySync; 205 private static List<ScanResult> sScanResults = null; 206 private static NetworkInfo sNetworkInfo = 207 new NetworkInfo(ConnectivityManager.TYPE_WIFI, TelephonyManager.NETWORK_TYPE_UNKNOWN, 208 "wifi", "unknown"); 209 private final Object mLock = new Object(); 210 private static UiDevice sUiDevice; 211 private static boolean sWasVerboseLoggingEnabled; 212 private static boolean sWasScanThrottleEnabled; 213 private static SoftApConfiguration sOriginalSoftApConfig = null; 214 private static PowerManager sPowerManager; 215 private static PowerManager.WakeLock sWakeLock; 216 // Please refer to WifiManager 217 private static final int MIN_RSSI = -100; 218 private static final int MAX_RSSI = -55; 219 220 private static final int STATE_NULL = 0; 221 private static final int STATE_WIFI_CHANGING = 1; 222 private static final int STATE_WIFI_ENABLED = 2; 223 private static final int STATE_WIFI_DISABLED = 3; 224 private static final int STATE_SCANNING = 4; 225 private static final int STATE_SCAN_DONE = 5; 226 227 private static final String TAG = "WifiManagerTest"; 228 private static final String SSID1 = "\"WifiManagerTest\""; 229 private static final String BOOT_DEFAULT_WIFI_COUNTRY_CODE = "ro.boot.wificountrycode"; 230 // A full single scan duration is typically about 6-7 seconds, but 231 // depending on devices it takes more time (9-11 seconds). For a 232 // safety margin, the test waits for 15 seconds. 233 private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000; 234 private static final int TEST_WAIT_DURATION_MS = 10_000; 235 private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000; 236 private static final int WIFI_OFF_ON_TIMEOUT_MILLIS = 5_000; 237 private static final int WIFI_PNO_CONNECT_TIMEOUT_MILLIS = 90_000; 238 private static final int WAIT_MSEC = 60; 239 private static final int DURATION_SCREEN_TOGGLE = 2000; 240 private static final int DURATION_SETTINGS_TOGGLE = 1_000; 241 private static final int DURATION_SOFTAP_START_MS = 6_000; 242 private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000; 243 private static final String DEVICE_CONFIG_NAMESPACE = "wifi"; 244 245 private static final int ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP = 50; 246 247 private static final String TEST_PAC_URL = "http://www.example.com/proxy.pac"; 248 private static final String MANAGED_PROVISIONING_PACKAGE_NAME 249 = "com.android.managedprovisioning"; 250 251 private static final String TEST_SSID_UNQUOTED = "testSsid1"; 252 private static final String TEST_IP_ADDRESS = "192.168.5.5"; 253 private static final String TEST_MAC_ADDRESS = "aa:bb:cc:dd:ee:ff"; 254 private static final MacAddress TEST_MAC = MacAddress.fromString(TEST_MAC_ADDRESS); 255 private static final String TEST_PASSPHRASE = "passphrase"; 256 private static final String PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT = 257 "assets/ValidPasspointProfile.base64"; 258 private static final String TYPE_WIFI_CONFIG = "application/x-wifi-config"; 259 private static final String TEST_PSK_CAP = "[RSN-PSK-CCMP]"; 260 private static final String TEST_BSSID = "00:01:02:03:04:05"; 261 private static final String TEST_COUNTRY_CODE = "JP"; 262 private static final String TEST_DOM_SUBJECT_MATCH = "domSubjectMatch"; 263 private static final int TEST_SUB_ID = 2; 264 private static final int EID_VSA = 221; // Copied from ScanResult.InformationElement 265 266 private static final int TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS = 1000; 267 private static final List<ScanResult.InformationElement> TEST_VENDOR_ELEMENTS = 268 new ArrayList<>(Arrays.asList( 269 new ScanResult.InformationElement(221, 0, new byte[]{ 1, 2, 3, 4 }), 270 new ScanResult.InformationElement( 271 221, 272 0, 273 new byte[]{ (byte) 170, (byte) 187, (byte) 204, (byte) 221 }) 274 )); 275 private static final int[] TEST_RSSI2_THRESHOLDS = {-81, -79, -73, -60}; 276 private static final int[] TEST_RSSI5_THRESHOLDS = {-80, -77, -71, -55}; 277 private static final int[] TEST_RSSI6_THRESHOLDS = {-79, -72, -65, -55}; 278 private static final SparseArray<Integer> TEST_FREQUENCY_WEIGHTS = new SparseArray<>(); 279 280 private IntentFilter mIntentFilter; 281 282 @Rule 283 public final CheckFlagsRule mCheckFlagsRule = 284 DeviceFlagsValueProvider.createCheckFlagsRule(); 285 private static final BroadcastReceiver sReceiver = new BroadcastReceiver() { 286 @Override 287 public void onReceive(Context context, Intent intent) { 288 final String action = intent.getAction(); 289 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 290 synchronized (sMySync) { 291 if (intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) { 292 sScanResults = sWifiManager.getScanResults(); 293 } else { 294 sScanResults = null; 295 } 296 sMySync.expectedState = STATE_SCAN_DONE; 297 sMySync.notifyAll(); 298 } 299 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 300 int newState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 301 WifiManager.WIFI_STATE_UNKNOWN); 302 synchronized (sMySync) { 303 if (newState == WIFI_STATE_ENABLED) { 304 Log.d(TAG, "*** New WiFi state is ENABLED ***"); 305 sMySync.expectedState = STATE_WIFI_ENABLED; 306 sMySync.notifyAll(); 307 } else if (newState == WIFI_STATE_DISABLED) { 308 Log.d(TAG, "*** New WiFi state is DISABLED ***"); 309 sMySync.expectedState = STATE_WIFI_DISABLED; 310 sMySync.notifyAll(); 311 } 312 } 313 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 314 synchronized (sMySync) { 315 sNetworkInfo = 316 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 317 if (sNetworkInfo.getState() == NetworkInfo.State.CONNECTED) { 318 sMySync.notifyAll(); 319 } 320 } 321 } 322 } 323 }; 324 325 private static class TestProvisioningCallback extends ProvisioningCallback { 326 private final Object mObject; 327 // Initialize with an invalid status value (0) 328 public int mProvisioningStatus = 0; 329 // Initialize with an invalid status value (0) 330 public int mProvisioningFailureStatus = 0; 331 public boolean mProvisioningComplete = false; 332 333 TestProvisioningCallback(Object lock)334 TestProvisioningCallback(Object lock) { 335 mObject = lock; 336 } 337 338 @Override onProvisioningFailure(int status)339 public void onProvisioningFailure(int status) { 340 synchronized (mObject) { 341 mProvisioningFailureStatus = status; 342 mObject.notify(); 343 } 344 } 345 346 @Override onProvisioningStatus(int status)347 public void onProvisioningStatus(int status) { 348 synchronized (mObject) { 349 mProvisioningStatus = status; 350 mObject.notify(); 351 } 352 } 353 354 @Override onProvisioningComplete()355 public void onProvisioningComplete() { 356 mProvisioningComplete = true; 357 } 358 } 359 360 private static class TestSubsystemRestartTrackingCallback 361 extends SubsystemRestartTrackingCallback { 362 private final Object mObject; 363 364 public int mSubsystemRestartStatus = 0; // 0: nada, 1: restarting, 2: restarted 365 TestSubsystemRestartTrackingCallback(Object lock)366 TestSubsystemRestartTrackingCallback(Object lock) { 367 mObject = lock; 368 } 369 @Override onSubsystemRestarting()370 public void onSubsystemRestarting() { 371 synchronized (mObject) { 372 mSubsystemRestartStatus = 1; 373 mObject.notify(); 374 } 375 } 376 377 @Override onSubsystemRestarted()378 public void onSubsystemRestarted() { 379 synchronized (mObject) { 380 mSubsystemRestartStatus = 2; 381 mObject.notify(); 382 383 } 384 } 385 } 386 387 private static final String TEST_SSID = "TEST SSID"; 388 private static final String TEST_FRIENDLY_NAME = "Friendly Name"; 389 private static final Map<String, String> TEST_FRIENDLY_NAMES = new HashMap<>(); 390 static { 391 TEST_FRIENDLY_NAMES.put("en", TEST_FRIENDLY_NAME); 392 TEST_FRIENDLY_NAMES.put("kr", TEST_FRIENDLY_NAME + 2); 393 TEST_FRIENDLY_NAMES.put("jp", TEST_FRIENDLY_NAME + 3); 394 } 395 396 private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service"; 397 private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com"); 398 private static final String TEST_NAI = "test.access.com"; 399 private static final List<Integer> TEST_METHOD_LIST = 400 Arrays.asList(1 /* METHOD_SOAP_XML_SPP */); 401 private final HandlerThread mHandlerThread = new HandlerThread("WifiManagerTest"); 402 protected final Executor mExecutor; 403 { mHandlerThread.start()404 mHandlerThread.start(); 405 mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper())); 406 } 407 408 /** 409 * Class which can be used to fetch an object out of a lambda. Fetching an object 410 * out of a local scope with HIDL is a common operation (although usually it can 411 * and should be avoided). 412 * 413 * @param <E> Inner object type. 414 */ 415 public static final class Mutable<E> { 416 public E value; 417 Mutable()418 public Mutable() { 419 value = null; 420 } 421 Mutable(E value)422 public Mutable(E value) { 423 this.value = value; 424 } 425 } 426 427 @BeforeClass setUpClass()428 public static void setUpClass() throws Exception { 429 sContext = InstrumentationRegistry.getInstrumentation().getContext(); 430 if (!WifiFeature.isWifiSupported(sContext)) { 431 // skip the test if WiFi is not supported 432 return; 433 } 434 sShouldRunTest = true; 435 sPowerManager = sContext.getSystemService(PowerManager.class); 436 sWakeLock = sPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 437 sMySync = new MySync(); 438 IntentFilter intentFilter = new IntentFilter(); 439 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 440 intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 441 intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 442 intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 443 intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 444 intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 445 intentFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); 446 intentFilter.addAction(WifiManager.ACTION_PICK_WIFI_NETWORK); 447 intentFilter.setPriority(999); 448 449 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { 450 sContext.registerReceiver(sReceiver, intentFilter, RECEIVER_EXPORTED); 451 } else { 452 sContext.registerReceiver(sReceiver, intentFilter); 453 } 454 sWifiManager = sContext.getSystemService(WifiManager.class); 455 sConnectivityManager = sContext.getSystemService(ConnectivityManager.class); 456 sTetheringManager = sContext.getSystemService(TetheringManager.class); 457 assertThat(sWifiManager).isNotNull(); 458 assertThat(sTetheringManager).isNotNull(); 459 460 // turn on verbose logging for tests 461 sWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions( 462 () -> sWifiManager.isVerboseLoggingEnabled()); 463 ShellIdentityUtils.invokeWithShellPermissions( 464 () -> sWifiManager.setVerboseLoggingEnabled(true)); 465 // Disable scan throttling for tests. 466 sWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions( 467 () -> sWifiManager.isScanThrottleEnabled()); 468 ShellIdentityUtils.invokeWithShellPermissions( 469 () -> sWifiManager.setScanThrottleEnabled(false)); 470 471 sUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 472 turnScreenOnNoDelay(); 473 474 synchronized (sMySync) { 475 sMySync.expectedState = STATE_NULL; 476 } 477 478 List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 479 sWifiManager::getConfiguredNetworks); 480 assertThat(savedNetworks.isEmpty()).isFalse(); 481 482 // Get original config for restore 483 sOriginalSoftApConfig = ShellIdentityUtils.invokeWithShellPermissions( 484 sWifiManager::getSoftApConfiguration); 485 } 486 487 @AfterClass tearDownClass()488 public static void tearDownClass() throws Exception { 489 if (!sShouldRunTest) { 490 return; 491 } 492 if (!sWifiManager.isWifiEnabled()) { 493 setWifiEnabled(true); 494 } 495 sContext.unregisterReceiver(sReceiver); 496 ShellIdentityUtils.invokeWithShellPermissions( 497 () -> sWifiManager.setScanThrottleEnabled(sWasScanThrottleEnabled)); 498 ShellIdentityUtils.invokeWithShellPermissions( 499 () -> sWifiManager.setVerboseLoggingEnabled(sWasVerboseLoggingEnabled)); 500 // restore original softap config 501 ShellIdentityUtils.invokeWithShellPermissions( 502 () -> sWifiManager.setSoftApConfiguration(sOriginalSoftApConfig)); 503 Thread.sleep(TEST_WAIT_DURATION_MS); 504 if (sWakeLock.isHeld()) { 505 sWakeLock.release(); 506 } 507 } 508 509 @Before setUp()510 public void setUp() throws Exception { 511 assumeTrue(sShouldRunTest); 512 // enable Wifi 513 if (!sWifiManager.isWifiEnabled()) { 514 setWifiEnabled(true); 515 startScan(); 516 } 517 PollingCheck.check("Wifi not enabled", TEST_WAIT_DURATION_MS, 518 () -> sWifiManager.isWifiEnabled()); 519 520 waitForConnection(); 521 } 522 setWifiEnabled(boolean enable)523 private static void setWifiEnabled(boolean enable) throws Exception { 524 synchronized (sMySync) { 525 if (sWifiManager.isWifiEnabled() != enable) { 526 // the new state is different, we expect it to change 527 sMySync.expectedState = STATE_WIFI_CHANGING; 528 } else { 529 sMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 530 } 531 ShellIdentityUtils.invokeWithShellPermissions( 532 () -> sWifiManager.setWifiEnabled(enable)); 533 waitForExpectedWifiState(enable); 534 } 535 } 536 waitForExpectedWifiState(boolean enabled)537 private static void waitForExpectedWifiState(boolean enabled) throws InterruptedException { 538 synchronized (sMySync) { 539 long timeout = System.currentTimeMillis() + TEST_WAIT_DURATION_MS; 540 int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); 541 while (System.currentTimeMillis() < timeout 542 && sMySync.expectedState != expected) { 543 sMySync.wait(WAIT_MSEC); 544 } 545 } 546 } 547 548 // Get the current scan status from sticky broadcast. isScanCurrentlyAvailable()549 private boolean isScanCurrentlyAvailable() { 550 IntentFilter intentFilter = new IntentFilter(); 551 intentFilter.addAction(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED); 552 Intent intent = sContext.registerReceiver(null, intentFilter); 553 assertNotNull(intent); 554 if (intent.getAction().equals(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED)) { 555 return intent.getBooleanExtra(WifiManager.EXTRA_SCAN_AVAILABLE, false); 556 } 557 return false; 558 } 559 startScan()560 private void startScan() throws Exception { 561 synchronized (sMySync) { 562 sMySync.expectedState = STATE_SCANNING; 563 sScanResults = null; 564 assertTrue(sWifiManager.startScan()); 565 long timeout = System.currentTimeMillis() + SCAN_TEST_WAIT_DURATION_MS; 566 while (System.currentTimeMillis() < timeout 567 && sMySync.expectedState == STATE_SCANNING) { 568 sMySync.wait(WAIT_MSEC); 569 } 570 } 571 } 572 waitForNetworkInfoState(NetworkInfo.State state, int timeoutMillis)573 private void waitForNetworkInfoState(NetworkInfo.State state, int timeoutMillis) 574 throws Exception { 575 synchronized (sMySync) { 576 if (sNetworkInfo.getState() == state) return; 577 long timeout = System.currentTimeMillis() + timeoutMillis; 578 while (System.currentTimeMillis() < timeout 579 && sNetworkInfo.getState() != state) 580 sMySync.wait(WAIT_MSEC); 581 assertEquals(state, sNetworkInfo.getState()); 582 } 583 } 584 waitForConnection(int timeoutMillis)585 private void waitForConnection(int timeoutMillis) throws Exception { 586 waitForNetworkInfoState(NetworkInfo.State.CONNECTED, timeoutMillis); 587 } 588 waitForConnection()589 private void waitForConnection() throws Exception { 590 waitForNetworkInfoState(NetworkInfo.State.CONNECTED, WIFI_CONNECT_TIMEOUT_MILLIS); 591 } 592 waitForDisconnection()593 private void waitForDisconnection() throws Exception { 594 waitForNetworkInfoState(NetworkInfo.State.DISCONNECTED, TEST_WAIT_DURATION_MS); 595 } 596 ensureNotNetworkInfoState(NetworkInfo.State state)597 private void ensureNotNetworkInfoState(NetworkInfo.State state) throws Exception { 598 synchronized (sMySync) { 599 long timeout = System.currentTimeMillis() + TEST_WAIT_DURATION_MS + WAIT_MSEC; 600 while (System.currentTimeMillis() < timeout) { 601 assertNotEquals(state, sNetworkInfo.getState()); 602 sMySync.wait(WAIT_MSEC); 603 } 604 } 605 } 606 ensureNotConnected()607 private void ensureNotConnected() throws Exception { 608 ensureNotNetworkInfoState(NetworkInfo.State.CONNECTED); 609 } 610 ensureNotDisconnected()611 private void ensureNotDisconnected() throws Exception { 612 ensureNotNetworkInfoState(NetworkInfo.State.DISCONNECTED); 613 } 614 existSSID(String ssid)615 private boolean existSSID(String ssid) { 616 for (final WifiConfiguration w : sWifiManager.getConfiguredNetworks()) { 617 if (w.SSID.equals(ssid)) 618 return true; 619 } 620 return false; 621 } 622 findConfiguredNetworks(String SSID, List<WifiConfiguration> networks)623 private int findConfiguredNetworks(String SSID, List<WifiConfiguration> networks) { 624 for (final WifiConfiguration w : networks) { 625 if (w.SSID.equals(SSID)) 626 return networks.indexOf(w); 627 } 628 return -1; 629 } 630 631 /** 632 * Test creation of WifiManager Lock. 633 */ 634 @Test testWifiManagerLock()635 public void testWifiManagerLock() throws Exception { 636 final String TAG = "Test"; 637 assertNotNull(sWifiManager.createWifiLock(TAG)); 638 assertNotNull(sWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 639 } 640 641 /** 642 * Test wifi scanning when Wifi is off and location scanning is turned on. 643 */ 644 @Test testWifiManagerScanWhenWifiOffLocationTurnedOn()645 public void testWifiManagerScanWhenWifiOffLocationTurnedOn() throws Exception { 646 if (!hasLocationFeature()) { 647 Log.d(TAG, "Skipping test as location is not supported"); 648 return; 649 } 650 if (!isLocationEnabled()) { 651 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 652 + " empty when location is disabled!"); 653 } 654 runWithScanning(() -> { 655 setWifiEnabled(false); 656 Thread.sleep(TEST_WAIT_DURATION_MS); 657 startScan(); 658 if (sWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) { 659 // Make sure at least one AP is found. 660 assertNotNull("mScanResult should not be null!", sScanResults); 661 assertFalse("empty scan results!", sScanResults.isEmpty()); 662 } else { 663 // Make sure no scan results are available. 664 assertNull("mScanResult should be null!", sScanResults); 665 } 666 final String TAG = "Test"; 667 assertNotNull(sWifiManager.createWifiLock(TAG)); 668 assertNotNull(sWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG)); 669 }, true /* run with enabled*/); 670 } 671 672 /** 673 * Restart WiFi subsystem - verify that privileged call fails. 674 */ 675 @Test 676 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testRestartWifiSubsystemShouldFailNoPermission()677 public void testRestartWifiSubsystemShouldFailNoPermission() throws Exception { 678 try { 679 sWifiManager.restartWifiSubsystem(); 680 fail("The restartWifiSubsystem should not succeed - privileged call"); 681 } catch (SecurityException e) { 682 // expected 683 } 684 } 685 686 /** 687 * Restart WiFi subsystem and verify transition through states. 688 */ 689 @Test 690 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) testRestartWifiSubsystem()691 public void testRestartWifiSubsystem() throws Exception { 692 TestSubsystemRestartTrackingCallback callback = 693 new TestSubsystemRestartTrackingCallback(mLock); 694 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 695 try { 696 uiAutomation.adoptShellPermissionIdentity(); 697 sWifiManager.registerSubsystemRestartTrackingCallback(mExecutor, callback); 698 synchronized (mLock) { 699 sWifiManager.restartWifiSubsystem(); 700 mLock.wait(TEST_WAIT_DURATION_MS); 701 } 702 assertEquals(callback.mSubsystemRestartStatus, 1); // 1: restarting 703 waitForExpectedWifiState(false); 704 assertFalse(sWifiManager.isWifiEnabled()); 705 synchronized (mLock) { 706 mLock.wait(TEST_WAIT_DURATION_MS); 707 assertEquals(callback.mSubsystemRestartStatus, 2); // 2: restarted 708 } 709 waitForExpectedWifiState(true); 710 assertTrue(sWifiManager.isWifiEnabled()); 711 } finally { 712 // cleanup 713 sWifiManager.unregisterSubsystemRestartTrackingCallback(callback); 714 uiAutomation.dropShellPermissionIdentity(); 715 } 716 } 717 718 /** 719 * test point of wifiManager properties: 720 * 1.enable properties 721 * 2.DhcpInfo properties 722 * 3.wifi state 723 * 4.ConnectionInfo 724 */ 725 @Test testWifiManagerProperties()726 public void testWifiManagerProperties() throws Exception { 727 setWifiEnabled(true); 728 assertTrue(sWifiManager.isWifiEnabled()); 729 assertNotNull(sWifiManager.getDhcpInfo()); 730 assertEquals(WIFI_STATE_ENABLED, sWifiManager.getWifiState()); 731 sWifiManager.getConnectionInfo(); 732 setWifiEnabled(false); 733 assertFalse(sWifiManager.isWifiEnabled()); 734 } 735 736 737 public static class TestWifiStateChangedListener 738 implements WifiManager.WifiStateChangedListener { 739 private final Object mWifiStateLock; 740 private int mWifiStateChangedCount; 741 TestWifiStateChangedListener(Object lock)742 TestWifiStateChangedListener(Object lock) { 743 mWifiStateLock = lock; 744 } 745 746 @Override onWifiStateChanged()747 public void onWifiStateChanged() { 748 synchronized (mWifiStateLock) { 749 mWifiStateChangedCount++; 750 mWifiStateLock.notify(); 751 } 752 } 753 754 /** 755 * Gets the number of Wi-fi states recorded since registering this listener. 756 */ getWifiStateChangedCount()757 public int getWifiStateChangedCount() { 758 synchronized (mWifiStateLock) { 759 return mWifiStateChangedCount; 760 } 761 } 762 763 /** 764 * Verifies that onWifiStateChanged is called a given number of times. 765 * 766 * @throws InterruptedException 767 */ verifyWifiStateChangeCount(int times)768 public void verifyWifiStateChangeCount(int times) throws InterruptedException { 769 long now = System.currentTimeMillis(); 770 long deadline = now + TEST_WAIT_DURATION_MS; 771 while (now < deadline) { 772 mWifiStateLock.wait(deadline - now); 773 if (getWifiStateChangedCount() >= times) { 774 return; 775 } 776 now = System.currentTimeMillis(); 777 } 778 assertEquals(times, getWifiStateChangedCount()); 779 } 780 } 781 782 /** 783 * Test that WifiStateChangedListener receives updates to the Wifi enabled state. 784 */ 785 @Test testWifiStateChangedListener()786 public void testWifiStateChangedListener() throws Exception { 787 if (!Flags.wifiStateChangedListener()) { 788 // Skip the test if flag is not enabled. 789 return; 790 } 791 synchronized (mLock) { 792 final TestWifiStateChangedListener listener = new TestWifiStateChangedListener(mLock); 793 try { 794 sWifiManager.addWifiStateChangedListener(mExecutor, listener); 795 listener.verifyWifiStateChangeCount(1); 796 797 // Wi-Fi is already enabled in #setUp, so set Wi-Fi to disabled and verify 798 // WifiStateChangedListener was called twice (ENABLED -> DISABLING -> DISABLED). 799 setWifiEnabled(false); 800 listener.verifyWifiStateChangeCount(3); 801 } catch (InterruptedException e) { 802 throw new AssertionError( 803 "Thread interrupted unexpectedly while waiting on mLock", e); 804 } finally { 805 sWifiManager.removeWifiStateChangedListener(listener); 806 } 807 } 808 } 809 810 /** 811 * Test WiFi scan timestamp - fails when WiFi scan timestamps are inconsistent with 812 * {@link SystemClock#elapsedRealtime()} on device.<p> 813 * To run this test in cts-tradefed: 814 * run cts --class android.net.wifi.cts.WifiManagerTest --method testWifiScanTimestamp 815 */ 816 @Test 817 @RequiresDevice testWifiScanTimestamp()818 public void testWifiScanTimestamp() throws Exception { 819 if (!hasLocationFeature()) { 820 Log.d(TAG, "Skipping test as location is not supported"); 821 return; 822 } 823 if (!isLocationEnabled()) { 824 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 825 + " empty when location is disabled!"); 826 } 827 if (!sWifiManager.isWifiEnabled()) { 828 setWifiEnabled(true); 829 } 830 // Make sure the scan timestamps are consistent with the device timestamp within the range 831 // of WIFI_SCAN_TEST_CACHE_DELAY_MILLIS. 832 startScan(); 833 // Make sure at least one AP is found. 834 assertTrue("mScanResult should not be null. This may be due to a scan timeout", 835 sScanResults != null); 836 assertFalse("empty scan results!", sScanResults.isEmpty()); 837 long nowMillis = SystemClock.elapsedRealtime(); 838 // Keep track of how many APs are fresh in one scan. 839 int numFreshAps = 0; 840 for (ScanResult result : sScanResults) { 841 long scanTimeMillis = TimeUnit.MICROSECONDS.toMillis(result.timestamp); 842 if (Math.abs(nowMillis - scanTimeMillis) < WIFI_SCAN_TEST_CACHE_DELAY_MILLIS) { 843 numFreshAps++; 844 } 845 } 846 // At least half of the APs in the scan should be fresh. 847 int numTotalAps = sScanResults.size(); 848 String msg = "Stale AP count: " + (numTotalAps - numFreshAps) + ", fresh AP count: " 849 + numFreshAps; 850 assertTrue(msg, numFreshAps * 2 >= sScanResults.size()); 851 } 852 853 @Test testConvertBetweenChannelFrequencyMhz()854 public void testConvertBetweenChannelFrequencyMhz() throws Exception { 855 int[] testFrequency_2G = {2412, 2437, 2462, 2484}; 856 int[] testFrequency_5G = {5180, 5220, 5540, 5745}; 857 int[] testFrequency_6G = {5955, 6435, 6535, 7115}; 858 int[] testFrequency_60G = {58320, 64800}; 859 SparseArray<int[]> testData = new SparseArray<>() {{ 860 put(ScanResult.WIFI_BAND_24_GHZ, testFrequency_2G); 861 put(ScanResult.WIFI_BAND_5_GHZ, testFrequency_5G); 862 put(ScanResult.WIFI_BAND_6_GHZ, testFrequency_6G); 863 put(ScanResult.WIFI_BAND_60_GHZ, testFrequency_60G); 864 }}; 865 866 for (int i = 0; i < testData.size(); i++) { 867 for (int frequency : testData.valueAt(i)) { 868 assertEquals(frequency, ScanResult.convertChannelToFrequencyMhzIfSupported( 869 ScanResult.convertFrequencyMhzToChannelIfSupported(frequency), testData.keyAt(i))); 870 } 871 } 872 } 873 874 // Return true if location is enabled. isLocationEnabled()875 private boolean isLocationEnabled() { 876 return Settings.Secure.getInt(sContext.getContentResolver(), 877 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) != 878 Settings.Secure.LOCATION_MODE_OFF; 879 } 880 881 // Returns true if the device has location feature. hasLocationFeature()882 private boolean hasLocationFeature() { 883 return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION); 884 } 885 hasAutomotiveFeature()886 private boolean hasAutomotiveFeature() { 887 return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 888 } 889 hasWifiDirect()890 private boolean hasWifiDirect() { 891 return sContext.getPackageManager().hasSystemFeature( 892 PackageManager.FEATURE_WIFI_DIRECT); 893 } 894 hasWifiAware()895 private boolean hasWifiAware() { 896 return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE); 897 } 898 899 @Test testSignal()900 public void testSignal() { 901 final int numLevels = 9; 902 int expectLevel = 0; 903 assertEquals(expectLevel, WifiManager.calculateSignalLevel(MIN_RSSI, numLevels)); 904 assertEquals(numLevels - 1, WifiManager.calculateSignalLevel(MAX_RSSI, numLevels)); 905 expectLevel = 4; 906 assertEquals(expectLevel, WifiManager.calculateSignalLevel((MIN_RSSI + MAX_RSSI) / 2, 907 numLevels)); 908 int rssiA = 4; 909 int rssiB = 5; 910 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) < 0); 911 rssiB = 4; 912 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) == 0); 913 rssiA = 5; 914 rssiB = 4; 915 assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) > 0); 916 } 917 918 /** 919 * Test that {@link WifiManager#calculateSignalLevel(int)} returns a value in the range 920 * [0, {@link WifiManager#getMaxSignalLevel()}], and its value is monotonically increasing as 921 * the RSSI increases. 922 */ 923 @Test testCalculateSignalLevel()924 public void testCalculateSignalLevel() { 925 int maxSignalLevel = sWifiManager.getMaxSignalLevel(); 926 927 int prevSignalLevel = 0; 928 for (int rssi = -150; rssi <= 50; rssi++) { 929 int signalLevel = sWifiManager.calculateSignalLevel(rssi); 930 931 // between [0, maxSignalLevel] 932 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(0); 933 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtMost(maxSignalLevel); 934 935 // calculateSignalLevel(rssi) <= calculateSignalLevel(rssi + 1) 936 assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(prevSignalLevel); 937 prevSignalLevel = signalLevel; 938 } 939 } 940 941 public class TestWifiVerboseLoggingStatusChangedListener implements 942 WifiManager.WifiVerboseLoggingStatusChangedListener { 943 public int numCalls; 944 public boolean status; 945 946 @Override onWifiVerboseLoggingStatusChanged(boolean enabled)947 public void onWifiVerboseLoggingStatusChanged(boolean enabled) { 948 numCalls++; 949 status = enabled; 950 } 951 } 952 953 public class TestSoftApCallback implements WifiManager.SoftApCallback { 954 final Object mSoftApLock; 955 SoftApState mCurrentSoftApState; 956 int currentState; 957 int currentFailureReason; 958 List<SoftApInfo> apInfoList = new ArrayList<>(); 959 SoftApInfo apInfoOnSingleApMode; 960 Map<SoftApInfo, List<WifiClient>> apInfoClients = new HashMap<>(); 961 List<WifiClient> currentClientList; 962 SoftApCapability currentSoftApCapability; 963 MacAddress lastBlockedClientMacAddress; 964 int lastBlockedClientReason; 965 int mLastDisconnectedClientReason; 966 boolean onStateChangedCalled = false; 967 boolean mOnSoftApStateChangedCalled = false; 968 boolean onSoftApCapabilityChangedCalled = false; 969 boolean onConnectedClientCalled = false; 970 boolean onConnectedClientChangedWithInfoCalled = false; 971 boolean onBlockedClientConnectingCalled = false; 972 boolean mOnClientsDisconnected = false; 973 int onSoftapInfoChangedCalledCount = 0; 974 int onSoftapInfoChangedWithListCalledCount = 0; 975 TestSoftApCallback(Object lock)976 TestSoftApCallback(Object lock) { 977 mSoftApLock = lock; 978 } 979 getOnStateChangedCalled()980 public boolean getOnStateChangedCalled() { 981 synchronized (mSoftApLock) { 982 return onStateChangedCalled; 983 } 984 } 985 986 /** 987 * Returns {@code true} if #onStateChanged(SoftApstate) was called, else {@code false}. 988 */ getOnSoftApStateChangedCalled()989 public boolean getOnSoftApStateChangedCalled() { 990 synchronized (mSoftApLock) { 991 return mOnSoftApStateChangedCalled; 992 } 993 } 994 getOnSoftapInfoChangedCalledCount()995 public int getOnSoftapInfoChangedCalledCount() { 996 synchronized (mSoftApLock) { 997 return onSoftapInfoChangedCalledCount; 998 } 999 } 1000 getOnSoftApInfoChangedWithListCalledCount()1001 public int getOnSoftApInfoChangedWithListCalledCount() { 1002 synchronized (mSoftApLock) { 1003 return onSoftapInfoChangedWithListCalledCount; 1004 } 1005 } 1006 getOnSoftApCapabilityChangedCalled()1007 public boolean getOnSoftApCapabilityChangedCalled() { 1008 synchronized (mSoftApLock) { 1009 return onSoftApCapabilityChangedCalled; 1010 } 1011 } 1012 getOnConnectedClientChangedWithInfoCalled()1013 public boolean getOnConnectedClientChangedWithInfoCalled() { 1014 synchronized (mSoftApLock) { 1015 return onConnectedClientChangedWithInfoCalled; 1016 } 1017 } 1018 getOnConnectedClientCalled()1019 public boolean getOnConnectedClientCalled() { 1020 synchronized (mSoftApLock) { 1021 return onConnectedClientCalled; 1022 } 1023 } 1024 getOnBlockedClientConnectingCalled()1025 public boolean getOnBlockedClientConnectingCalled() { 1026 synchronized (mSoftApLock) { 1027 return onBlockedClientConnectingCalled; 1028 } 1029 } 1030 1031 /** 1032 * Returns {@code true} if #onClientsDisconnected was called, else {@code false}. 1033 */ getOnClientsDisconnectedCalled()1034 public boolean getOnClientsDisconnectedCalled() { 1035 synchronized (mSoftApLock) { 1036 return mOnClientsDisconnected; 1037 } 1038 } 1039 1040 /** 1041 * Returns the latest SoftApState passed into #onStateChanged(SoftApState). 1042 */ getCurrentSoftApState()1043 public SoftApState getCurrentSoftApState() { 1044 synchronized (mSoftApLock) { 1045 return mCurrentSoftApState; 1046 } 1047 } 1048 getCurrentState()1049 public int getCurrentState() { 1050 synchronized (mSoftApLock) { 1051 return currentState; 1052 } 1053 } 1054 getCurrentStateFailureReason()1055 public int getCurrentStateFailureReason() { 1056 synchronized (mSoftApLock) { 1057 return currentFailureReason; 1058 } 1059 } 1060 getCurrentClientList()1061 public List<WifiClient> getCurrentClientList() { 1062 synchronized (mSoftApLock) { 1063 return new ArrayList<>(currentClientList); 1064 } 1065 } 1066 getCurrentSoftApInfo()1067 public SoftApInfo getCurrentSoftApInfo() { 1068 synchronized (mSoftApLock) { 1069 return apInfoOnSingleApMode; 1070 } 1071 } 1072 getCurrentSoftApInfoList()1073 public List<SoftApInfo> getCurrentSoftApInfoList() { 1074 synchronized (mSoftApLock) { 1075 return new ArrayList<>(apInfoList); 1076 } 1077 } 1078 getCurrentSoftApCapability()1079 public SoftApCapability getCurrentSoftApCapability() { 1080 synchronized (mSoftApLock) { 1081 return currentSoftApCapability; 1082 } 1083 } 1084 getLastBlockedClientMacAddress()1085 public MacAddress getLastBlockedClientMacAddress() { 1086 synchronized (mSoftApLock) { 1087 return lastBlockedClientMacAddress; 1088 } 1089 } 1090 getLastBlockedClientReason()1091 public int getLastBlockedClientReason() { 1092 synchronized (mSoftApLock) { 1093 return lastBlockedClientReason; 1094 } 1095 } 1096 1097 @Override onStateChanged(int state, int failureReason)1098 public void onStateChanged(int state, int failureReason) { 1099 synchronized (mSoftApLock) { 1100 currentState = state; 1101 currentFailureReason = failureReason; 1102 onStateChangedCalled = true; 1103 } 1104 } 1105 1106 @Override onStateChanged(SoftApState state)1107 public void onStateChanged(SoftApState state) { 1108 synchronized (mSoftApLock) { 1109 mCurrentSoftApState = state; 1110 mOnSoftApStateChangedCalled = true; 1111 onStateChanged(state.getState(), 1112 state.getState() == WIFI_AP_STATE_FAILED ? state.getFailureReason() : 0); 1113 } 1114 } 1115 1116 @Override onConnectedClientsChanged(List<WifiClient> clients)1117 public void onConnectedClientsChanged(List<WifiClient> clients) { 1118 synchronized (mSoftApLock) { 1119 currentClientList = new ArrayList<>(clients); 1120 onConnectedClientCalled = true; 1121 } 1122 } 1123 1124 @Override onConnectedClientsChanged(SoftApInfo info, List<WifiClient> clients)1125 public void onConnectedClientsChanged(SoftApInfo info, List<WifiClient> clients) { 1126 synchronized (mSoftApLock) { 1127 apInfoClients.put(info, clients); 1128 onConnectedClientChangedWithInfoCalled = true; 1129 } 1130 } 1131 1132 @Override onInfoChanged(List<SoftApInfo> infoList)1133 public void onInfoChanged(List<SoftApInfo> infoList) { 1134 synchronized (mSoftApLock) { 1135 apInfoList = new ArrayList<>(infoList); 1136 onSoftapInfoChangedWithListCalledCount++; 1137 } 1138 } 1139 1140 @Override onInfoChanged(SoftApInfo softApInfo)1141 public void onInfoChanged(SoftApInfo softApInfo) { 1142 synchronized (mSoftApLock) { 1143 apInfoOnSingleApMode = softApInfo; 1144 onSoftapInfoChangedCalledCount++; 1145 } 1146 } 1147 1148 @Override onCapabilityChanged(SoftApCapability softApCapability)1149 public void onCapabilityChanged(SoftApCapability softApCapability) { 1150 synchronized (mSoftApLock) { 1151 currentSoftApCapability = softApCapability; 1152 onSoftApCapabilityChangedCalled = true; 1153 } 1154 } 1155 1156 @Override onBlockedClientConnecting(WifiClient client, int blockedReason)1157 public void onBlockedClientConnecting(WifiClient client, int blockedReason) { 1158 synchronized (mSoftApLock) { 1159 lastBlockedClientMacAddress = client.getMacAddress(); 1160 lastBlockedClientReason = blockedReason; 1161 onBlockedClientConnectingCalled = true; 1162 } 1163 } 1164 1165 @Override onClientsDisconnected(SoftApInfo info, List<WifiClient> clients)1166 public void onClientsDisconnected(SoftApInfo info, List<WifiClient> clients) { 1167 synchronized (mSoftApLock) { 1168 WifiClient client = clients.getFirst(); 1169 mLastDisconnectedClientReason = client.getDisconnectReason(); 1170 mOnClientsDisconnected = true; 1171 } 1172 } 1173 } 1174 1175 private static class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback { 1176 Object hotspotLock; 1177 WifiManager.LocalOnlyHotspotReservation reservation = null; 1178 boolean onStartedCalled = false; 1179 boolean onStoppedCalled = false; 1180 boolean onFailedCalled = false; 1181 int failureReason = -1; 1182 TestLocalOnlyHotspotCallback(Object lock)1183 TestLocalOnlyHotspotCallback(Object lock) { 1184 hotspotLock = lock; 1185 } 1186 1187 @Override onStarted(WifiManager.LocalOnlyHotspotReservation r)1188 public void onStarted(WifiManager.LocalOnlyHotspotReservation r) { 1189 synchronized (hotspotLock) { 1190 reservation = r; 1191 onStartedCalled = true; 1192 hotspotLock.notify(); 1193 } 1194 } 1195 1196 @Override onStopped()1197 public void onStopped() { 1198 synchronized (hotspotLock) { 1199 onStoppedCalled = true; 1200 hotspotLock.notify(); 1201 } 1202 } 1203 1204 @Override onFailed(int reason)1205 public void onFailed(int reason) { 1206 synchronized (hotspotLock) { 1207 onFailedCalled = true; 1208 failureReason = reason; 1209 hotspotLock.notify(); 1210 } 1211 } 1212 } 1213 getSupportedSoftApBand(SoftApCapability capability)1214 private List<Integer> getSupportedSoftApBand(SoftApCapability capability) { 1215 List<Integer> supportedApBands = new ArrayList<>(); 1216 if (sWifiManager.is24GHzBandSupported() && capability.areFeaturesSupported( 1217 SoftApCapability.SOFTAP_FEATURE_BAND_24G_SUPPORTED)) { 1218 supportedApBands.add(SoftApConfiguration.BAND_2GHZ); 1219 } 1220 if (sWifiManager.is5GHzBandSupported() && capability.areFeaturesSupported( 1221 SoftApCapability.SOFTAP_FEATURE_BAND_5G_SUPPORTED)) { 1222 supportedApBands.add(SoftApConfiguration.BAND_5GHZ); 1223 } 1224 if (sWifiManager.is6GHzBandSupported() && capability.areFeaturesSupported( 1225 SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED)) { 1226 supportedApBands.add(SoftApConfiguration.BAND_6GHZ); 1227 } 1228 if (sWifiManager.is60GHzBandSupported() && capability.areFeaturesSupported( 1229 SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED)) { 1230 supportedApBands.add(SoftApConfiguration.BAND_60GHZ); 1231 } 1232 return supportedApBands; 1233 } 1234 startLocalOnlyHotspot()1235 private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() { 1236 // Location mode must be enabled for this test 1237 if (!isLocationEnabled()) { 1238 fail("Please enable location for this test"); 1239 } 1240 1241 TestExecutor executor = new TestExecutor(); 1242 TestSoftApCallback lohsSoftApCallback = new TestSoftApCallback(mLock); 1243 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1244 List<Integer> supportedSoftApBands = new ArrayList<>(); 1245 try { 1246 uiAutomation.adoptShellPermissionIdentity(); 1247 verifyLohsRegisterSoftApCallback(executor, lohsSoftApCallback); 1248 supportedSoftApBands = getSupportedSoftApBand( 1249 lohsSoftApCallback.getCurrentSoftApCapability()); 1250 } catch (Exception ex) { 1251 } finally { 1252 // clean up 1253 unregisterLocalOnlyHotspotSoftApCallback(lohsSoftApCallback); 1254 uiAutomation.dropShellPermissionIdentity(); 1255 } 1256 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 1257 synchronized (mLock) { 1258 try { 1259 sWifiManager.startLocalOnlyHotspot(callback, null); 1260 // now wait for callback 1261 mLock.wait(TEST_WAIT_DURATION_MS); 1262 } catch (InterruptedException e) { 1263 } 1264 // check if we got the callback 1265 assertTrue(callback.onStartedCalled); 1266 1267 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 1268 assertNotNull(softApConfig); 1269 int securityType = softApConfig.getSecurityType(); 1270 if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN 1271 || securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK 1272 || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) { 1273 assertNotNull(softApConfig.toWifiConfiguration()); 1274 } else { 1275 assertNull(softApConfig.toWifiConfiguration()); 1276 } 1277 if (!hasAutomotiveFeature()) { 1278 assertEquals(supportedSoftApBands.size() > 0 ? supportedSoftApBands.get(0) 1279 : SoftApConfiguration.BAND_2GHZ, 1280 callback.reservation.getSoftApConfiguration().getBand()); 1281 } 1282 assertFalse(callback.onFailedCalled); 1283 assertFalse(callback.onStoppedCalled); 1284 } 1285 return callback; 1286 } 1287 stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled)1288 private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) { 1289 synchronized (sMySync) { 1290 // we are expecting a new state 1291 sMySync.expectedState = STATE_WIFI_CHANGING; 1292 1293 // now shut down LocalOnlyHotspot 1294 if (callback.reservation != null) { 1295 callback.reservation.close(); 1296 } 1297 1298 try { 1299 waitForExpectedWifiState(wifiEnabled); 1300 } catch (InterruptedException e) { } 1301 } 1302 } 1303 1304 /** 1305 * Verify that calls to startLocalOnlyHotspot succeed with proper permissions. 1306 * 1307 * Note: Location mode must be enabled for this test. 1308 */ 1309 @Test testStartLocalOnlyHotspotSuccess()1310 public void testStartLocalOnlyHotspotSuccess() throws Exception { 1311 // check that softap mode is supported by the device 1312 if (!sWifiManager.isPortableHotspotSupported()) { 1313 return; 1314 } 1315 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 1316 if (wifiEnabled) { 1317 // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's 1318 // no STA+AP concurrency. 1319 ShellIdentityUtils.invokeWithShellPermissions(() -> 1320 sWifiManager.setWifiEnabled(false)); 1321 PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 1322 () -> !sWifiManager.isWifiEnabled()); 1323 SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); 1324 PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 1325 () -> sWifiManager.isWifiEnabled()); 1326 } 1327 runWithScanning(() -> { 1328 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 1329 1330 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController 1331 // initialization. 1332 // TODO: remove this sleep as soon as b/124330089 is fixed. 1333 Log.d(TAG, "Sleeping for 2 seconds"); 1334 Thread.sleep(2000); 1335 1336 stopLocalOnlyHotspot(callback, wifiEnabled); 1337 1338 // wifi should either stay on, or come back on 1339 assertEquals(wifiEnabled, sWifiManager.isWifiEnabled()); 1340 }, false); 1341 } 1342 1343 /** 1344 * Verify calls to deprecated API's all fail for non-settings apps targeting >= Q SDK. 1345 */ 1346 @Test testDeprecatedApis()1347 public void testDeprecatedApis() throws Exception { 1348 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 1349 wifiConfiguration.SSID = SSID1; 1350 wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 1351 1352 assertEquals(INVALID_NETWORK_ID, 1353 sWifiManager.addNetwork(wifiConfiguration)); 1354 assertEquals(INVALID_NETWORK_ID, 1355 sWifiManager.updateNetwork(wifiConfiguration)); 1356 assertFalse(sWifiManager.enableNetwork(0, true)); 1357 assertFalse(sWifiManager.disableNetwork(0)); 1358 assertFalse(sWifiManager.removeNetwork(0)); 1359 assertFalse(sWifiManager.disconnect()); 1360 assertFalse(sWifiManager.reconnect()); 1361 assertFalse(sWifiManager.reassociate()); 1362 assertTrue(sWifiManager.getConfiguredNetworks().isEmpty()); 1363 1364 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 1365 // now we should fail to toggle wifi state. 1366 assertFalse(sWifiManager.setWifiEnabled(!wifiEnabled)); 1367 Thread.sleep(TEST_WAIT_DURATION_MS); 1368 assertEquals(wifiEnabled, sWifiManager.isWifiEnabled()); 1369 } 1370 1371 /** 1372 * Test the WifiManager APIs that return whether a feature is supported. 1373 */ 1374 @Test testGetSupportedFeatures()1375 public void testGetSupportedFeatures() { 1376 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1377 // Skip the test if wifi module version is older than S. 1378 return; 1379 } 1380 sWifiManager.isMakeBeforeBreakWifiSwitchingSupported(); 1381 sWifiManager.isStaBridgedApConcurrencySupported(); 1382 sWifiManager.isDualBandSimultaneousSupported(); 1383 sWifiManager.isTidToLinkMappingNegotiationSupported(); 1384 } 1385 1386 /** 1387 * Verify non DO apps cannot call removeNonCallerConfiguredNetworks. 1388 */ 1389 @Test testRemoveNonCallerConfiguredNetworksNotAllowed()1390 public void testRemoveNonCallerConfiguredNetworksNotAllowed() { 1391 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1392 // Skip the test if wifi module version is older than S. 1393 return; 1394 } 1395 try { 1396 sWifiManager.removeNonCallerConfiguredNetworks(); 1397 fail("Expected security exception for non DO app"); 1398 } catch (SecurityException e) { 1399 } 1400 } 1401 buildTestNetworkSelectionConfig()1402 private WifiNetworkSelectionConfig buildTestNetworkSelectionConfig() { 1403 TEST_FREQUENCY_WEIGHTS.put(2400, WifiNetworkSelectionConfig.FREQUENCY_WEIGHT_LOW); 1404 TEST_FREQUENCY_WEIGHTS.put(6000, WifiNetworkSelectionConfig.FREQUENCY_WEIGHT_HIGH); 1405 1406 return new WifiNetworkSelectionConfig.Builder() 1407 .setAssociatedNetworkSelectionOverride( 1408 WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SELECTION_OVERRIDE_ENABLED) 1409 .setSufficiencyCheckEnabledWhenScreenOff(false) 1410 .setSufficiencyCheckEnabledWhenScreenOn(false) 1411 .setUserConnectChoiceOverrideEnabled(false) 1412 .setLastSelectionWeightEnabled(false) 1413 .setRssiThresholds(ScanResult.WIFI_BAND_24_GHZ, TEST_RSSI2_THRESHOLDS) 1414 .setRssiThresholds(ScanResult.WIFI_BAND_5_GHZ, TEST_RSSI5_THRESHOLDS) 1415 .setRssiThresholds(ScanResult.WIFI_BAND_6_GHZ, TEST_RSSI6_THRESHOLDS) 1416 .setFrequencyWeights(TEST_FREQUENCY_WEIGHTS) 1417 .build(); 1418 } 1419 1420 /** 1421 * Verify the invalid and valid usages of {@code WifiManager#setNetworkSelectionConfig}. 1422 */ 1423 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1424 @Test testSetNetworkSelectionConfig()1425 public void testSetNetworkSelectionConfig() throws Exception { 1426 AtomicReference<WifiNetworkSelectionConfig> config = new AtomicReference<>(); 1427 Consumer<WifiNetworkSelectionConfig> listener = new Consumer<WifiNetworkSelectionConfig>() { 1428 @Override 1429 public void accept(WifiNetworkSelectionConfig value) { 1430 synchronized (mLock) { 1431 config.set(value); 1432 mLock.notify(); 1433 } 1434 } 1435 }; 1436 1437 // cache current WifiNetworkSelectionConfig 1438 ShellIdentityUtils.invokeWithShellPermissions( 1439 () -> sWifiManager.getNetworkSelectionConfig(mExecutor, listener)); 1440 synchronized (mLock) { 1441 mLock.wait(TEST_WAIT_DURATION_MS); 1442 } 1443 WifiNetworkSelectionConfig currentConfig = config.get(); 1444 1445 try { 1446 WifiNetworkSelectionConfig nsConfig = buildTestNetworkSelectionConfig(); 1447 assertTrue(nsConfig.getAssociatedNetworkSelectionOverride() 1448 == WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SELECTION_OVERRIDE_ENABLED); 1449 assertFalse(nsConfig.isSufficiencyCheckEnabledWhenScreenOff()); 1450 assertFalse(nsConfig.isSufficiencyCheckEnabledWhenScreenOn()); 1451 assertFalse(nsConfig.isUserConnectChoiceOverrideEnabled()); 1452 assertFalse(nsConfig.isLastSelectionWeightEnabled()); 1453 assertArrayEquals(TEST_RSSI2_THRESHOLDS, 1454 nsConfig.getRssiThresholds(ScanResult.WIFI_BAND_24_GHZ)); 1455 assertArrayEquals(TEST_RSSI5_THRESHOLDS, 1456 nsConfig.getRssiThresholds(ScanResult.WIFI_BAND_5_GHZ)); 1457 assertArrayEquals(TEST_RSSI6_THRESHOLDS, 1458 nsConfig.getRssiThresholds(ScanResult.WIFI_BAND_6_GHZ)); 1459 assertTrue(TEST_FREQUENCY_WEIGHTS.contentEquals(nsConfig.getFrequencyWeights())); 1460 assertThrows(SecurityException.class, 1461 () -> sWifiManager.setNetworkSelectionConfig(nsConfig)); 1462 ShellIdentityUtils.invokeWithShellPermissions( 1463 () -> sWifiManager.setNetworkSelectionConfig(nsConfig)); 1464 ShellIdentityUtils.invokeWithShellPermissions( 1465 () -> sWifiManager.setNetworkSelectionConfig( 1466 new WifiNetworkSelectionConfig.Builder().build())); 1467 } finally { 1468 // restore WifiNetworkSelectionConfig 1469 ShellIdentityUtils.invokeWithShellPermissions( 1470 () -> sWifiManager.setNetworkSelectionConfig(currentConfig)); 1471 } 1472 } 1473 1474 /** 1475 * Verify the invalid and valid usages of {@code WifiManager#getNetworkSelectionConfig}. 1476 */ 1477 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu") 1478 @Test testGetNetworkSelectionConfig()1479 public void testGetNetworkSelectionConfig() throws Exception { 1480 AtomicReference<WifiNetworkSelectionConfig> config = new AtomicReference<>(); 1481 Consumer<WifiNetworkSelectionConfig> listener = new Consumer<WifiNetworkSelectionConfig>() { 1482 @Override 1483 public void accept(WifiNetworkSelectionConfig value) { 1484 synchronized (mLock) { 1485 config.set(value); 1486 mLock.notify(); 1487 } 1488 } 1489 }; 1490 1491 // cache current WifiNetworkSelectionConfig 1492 ShellIdentityUtils.invokeWithShellPermissions( 1493 () -> sWifiManager.getNetworkSelectionConfig(mExecutor, listener)); 1494 synchronized (mLock) { 1495 mLock.wait(TEST_WAIT_DURATION_MS); 1496 } 1497 WifiNetworkSelectionConfig currentConfig = config.get(); 1498 1499 try { 1500 // Test invalid inputs trigger IllegalArgumentException 1501 assertThrows("null executor should trigger exception", NullPointerException.class, 1502 () -> sWifiManager.getNetworkSelectionConfig(null, listener)); 1503 assertThrows("null listener should trigger exception", NullPointerException.class, 1504 () -> sWifiManager.getNetworkSelectionConfig(mExecutor, null)); 1505 1506 // Test caller with no permission triggers SecurityException. 1507 assertThrows("No permission should trigger SecurityException", SecurityException.class, 1508 () -> sWifiManager.getNetworkSelectionConfig(mExecutor, listener)); 1509 1510 // Test get/set WifiNetworkSelectionConfig 1511 WifiNetworkSelectionConfig nsConfig = buildTestNetworkSelectionConfig(); 1512 ShellIdentityUtils.invokeWithShellPermissions( 1513 () -> sWifiManager.setNetworkSelectionConfig(nsConfig)); 1514 ShellIdentityUtils.invokeWithShellPermissions( 1515 () -> sWifiManager.getNetworkSelectionConfig(mExecutor, listener)); 1516 synchronized (mLock) { 1517 mLock.wait(TEST_WAIT_DURATION_MS); 1518 } 1519 assertTrue(config.get().equals(nsConfig)); 1520 } finally { 1521 // restore WifiNetworkSelectionConfig 1522 ShellIdentityUtils.invokeWithShellPermissions( 1523 () -> sWifiManager.setNetworkSelectionConfig(currentConfig)); 1524 } 1525 } 1526 1527 /** 1528 * Verify setting the screen-on connectivity scan delay. 1529 */ 1530 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1531 @Test testSetOneShotScreenOnConnectivityScanDelayMillis()1532 public void testSetOneShotScreenOnConnectivityScanDelayMillis() { 1533 assertThrows(SecurityException.class, 1534 () -> sWifiManager.setOneShotScreenOnConnectivityScanDelayMillis(100)); 1535 assertThrows(IllegalArgumentException.class, () -> { 1536 ShellIdentityUtils.invokeWithShellPermissions( 1537 () -> sWifiManager.setOneShotScreenOnConnectivityScanDelayMillis(-1)); 1538 }); 1539 ShellIdentityUtils.invokeWithShellPermissions( 1540 () -> sWifiManager.setOneShotScreenOnConnectivityScanDelayMillis(10000)); 1541 ShellIdentityUtils.invokeWithShellPermissions( 1542 () -> sWifiManager.setOneShotScreenOnConnectivityScanDelayMillis(0)); 1543 } 1544 1545 /** 1546 * Verify setting the scan schedule. 1547 */ 1548 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1549 @Test testSetScreenOnScanSchedule()1550 public void testSetScreenOnScanSchedule() { 1551 List<WifiManager.ScreenOnScanSchedule> schedules = new ArrayList<>(); 1552 schedules.add(new WifiManager.ScreenOnScanSchedule(Duration.ofSeconds(20), 1553 WifiScanner.SCAN_TYPE_HIGH_ACCURACY)); 1554 schedules.add(new WifiManager.ScreenOnScanSchedule(Duration.ofSeconds(40), 1555 WifiScanner.SCAN_TYPE_LOW_LATENCY)); 1556 assertEquals(20, schedules.get(0).getScanInterval().toSeconds()); 1557 assertEquals(40, schedules.get(1).getScanInterval().toSeconds()); 1558 assertEquals(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, schedules.get(0).getScanType()); 1559 assertEquals(WifiScanner.SCAN_TYPE_LOW_LATENCY, schedules.get(1).getScanType()); 1560 ShellIdentityUtils.invokeWithShellPermissions( 1561 () -> sWifiManager.setScreenOnScanSchedule(schedules)); 1562 ShellIdentityUtils.invokeWithShellPermissions( 1563 () -> sWifiManager.setScreenOnScanSchedule(null)); 1564 1565 // Creating an invalid ScanSchedule should throw an exception 1566 assertThrows(IllegalArgumentException.class, () -> new WifiManager.ScreenOnScanSchedule( 1567 null, WifiScanner.SCAN_TYPE_HIGH_ACCURACY)); 1568 } 1569 1570 /** 1571 * Verify a normal app cannot set the scan schedule. 1572 */ 1573 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1574 @Test testSetScreenOnScanScheduleNoPermission()1575 public void testSetScreenOnScanScheduleNoPermission() { 1576 assertThrows(SecurityException.class, () -> sWifiManager.setScreenOnScanSchedule(null)); 1577 } 1578 1579 /** 1580 * Test coverage for the constructor of AddNetworkResult. 1581 */ 1582 @Test testAddNetworkResultCreation()1583 public void testAddNetworkResultCreation() { 1584 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1585 // Skip the test if wifi module version is older than S. 1586 return; 1587 } 1588 int statusCode = WifiManager.AddNetworkResult.STATUS_NO_PERMISSION; 1589 int networkId = 5; 1590 WifiManager.AddNetworkResult result = new WifiManager.AddNetworkResult( 1591 statusCode, networkId); 1592 assertEquals("statusCode should match", statusCode, result.statusCode); 1593 assertEquals("networkId should match", networkId, result.networkId); 1594 } 1595 1596 /** 1597 * Verify {@link WifiManager#setSsidsAllowlist(Set)} can be called with sufficient 1598 * privilege. 1599 */ 1600 @Test testGetAndSetSsidsAllowlist()1601 public void testGetAndSetSsidsAllowlist() { 1602 Set<WifiSsid> ssids = new ArraySet<>(); 1603 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1604 ShellIdentityUtils.invokeWithShellPermissions( 1605 () -> sWifiManager.setSsidsAllowlist(ssids)); 1606 1607 ShellIdentityUtils.invokeWithShellPermissions( 1608 () -> assertEquals("Ssids should match", ssids, 1609 sWifiManager.getSsidsAllowlist())); 1610 1611 ShellIdentityUtils.invokeWithShellPermissions( 1612 () -> sWifiManager.setSsidsAllowlist(Collections.EMPTY_SET)); 1613 ShellIdentityUtils.invokeWithShellPermissions( 1614 () -> assertEquals("Should equal to empty set", 1615 Collections.EMPTY_SET, 1616 sWifiManager.getSsidsAllowlist())); 1617 1618 try { 1619 sWifiManager.setSsidsAllowlist(Collections.EMPTY_SET); 1620 fail("Expected SecurityException when called without permission"); 1621 } catch (SecurityException e) { 1622 // expect the exception 1623 } 1624 } 1625 1626 class TestPnoScanResultsCallback implements WifiManager.PnoScanResultsCallback { 1627 public CountDownLatch latch = new CountDownLatch(1); 1628 private boolean mRegisterSuccess; 1629 private int mRegisterFailedReason = -1; 1630 private int mRemovedReason = -1; 1631 private List<ScanResult> mScanResults; 1632 1633 @Override onScanResultsAvailable(List<ScanResult> scanResults)1634 public void onScanResultsAvailable(List<ScanResult> scanResults) { 1635 mScanResults = scanResults; 1636 latch.countDown(); 1637 } 1638 1639 @Override onRegisterSuccess()1640 public void onRegisterSuccess() { 1641 mRegisterSuccess = true; 1642 latch.countDown(); 1643 } 1644 1645 @Override onRegisterFailed(int reason)1646 public void onRegisterFailed(int reason) { 1647 mRegisterFailedReason = reason; 1648 latch.countDown(); 1649 } 1650 1651 @Override onRemoved(int reason)1652 public void onRemoved(int reason) { 1653 mRemovedReason = reason; 1654 latch.countDown(); 1655 } 1656 isRegisterSuccess()1657 public boolean isRegisterSuccess() { 1658 return mRegisterSuccess; 1659 } 1660 getRemovedReason()1661 public int getRemovedReason() { 1662 return mRemovedReason; 1663 } 1664 getRegisterFailedReason()1665 public int getRegisterFailedReason() { 1666 return mRegisterFailedReason; 1667 } 1668 getScanResults()1669 public List<ScanResult> getScanResults() { 1670 return mScanResults; 1671 } 1672 } 1673 1674 /** 1675 * Verify {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 1676 * WifiManager.PnoScanResultsCallback)} can be called with proper permissions. 1677 */ 1678 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1679 @Test testSetExternalPnoScanRequestSuccess()1680 public void testSetExternalPnoScanRequestSuccess() throws Exception { 1681 TestPnoScanResultsCallback callback = new TestPnoScanResultsCallback(); 1682 List<WifiSsid> ssids = new ArrayList<>(); 1683 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1684 int[] frequencies = new int[] {2412, 5180, 5805}; 1685 1686 assertFalse("Callback should be initialized unregistered", callback.isRegisterSuccess()); 1687 ShellIdentityUtils.invokeWithShellPermissions( 1688 () -> sWifiManager.setExternalPnoScanRequest( 1689 ssids, frequencies, Executors.newSingleThreadExecutor(), callback)); 1690 1691 callback.latch.await(TEST_WAIT_DURATION_MS, TimeUnit.MILLISECONDS); 1692 if (sWifiManager.isPreferredNetworkOffloadSupported()) { 1693 assertTrue("Expect register success or failed due to resource busy", 1694 callback.isRegisterSuccess() 1695 || callback.getRegisterFailedReason() == WifiManager.PnoScanResultsCallback 1696 .REGISTER_PNO_CALLBACK_RESOURCE_BUSY); 1697 } else { 1698 assertEquals("Expect register fail due to not supported.", 1699 WifiManager.PnoScanResultsCallback.REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED, 1700 callback.getRegisterFailedReason()); 1701 } 1702 sWifiManager.clearExternalPnoScanRequest(); 1703 } 1704 1705 /** 1706 * Verify {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 1707 * WifiManager.PnoScanResultsCallback)} can be called with null frequency. 1708 */ 1709 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1710 @Test testSetExternalPnoScanRequestSuccessNullFrequency()1711 public void testSetExternalPnoScanRequestSuccessNullFrequency() throws Exception { 1712 TestPnoScanResultsCallback callback = new TestPnoScanResultsCallback(); 1713 List<WifiSsid> ssids = new ArrayList<>(); 1714 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1715 1716 ShellIdentityUtils.invokeWithShellPermissions( 1717 () -> sWifiManager.setExternalPnoScanRequest( 1718 ssids, null, Executors.newSingleThreadExecutor(), callback)); 1719 sWifiManager.clearExternalPnoScanRequest(); 1720 } 1721 1722 /** 1723 * Verify {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 1724 * WifiManager.PnoScanResultsCallback)} throws an Exception if called with too many SSIDs. 1725 */ 1726 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1727 @Test testSetExternalPnoScanRequestTooManySsidsException()1728 public void testSetExternalPnoScanRequestTooManySsidsException() throws Exception { 1729 TestPnoScanResultsCallback callback = new TestPnoScanResultsCallback(); 1730 List<WifiSsid> ssids = new ArrayList<>(); 1731 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1732 ssids.add(WifiSsid.fromBytes("TEST_SSID_2".getBytes(StandardCharsets.UTF_8))); 1733 ssids.add(WifiSsid.fromBytes("TEST_SSID_3".getBytes(StandardCharsets.UTF_8))); 1734 1735 assertFalse("Callback should be initialized unregistered", callback.isRegisterSuccess()); 1736 assertThrows(IllegalArgumentException.class, () -> { 1737 ShellIdentityUtils.invokeWithShellPermissions( 1738 () -> sWifiManager.setExternalPnoScanRequest( 1739 ssids, null, Executors.newSingleThreadExecutor(), callback)); 1740 }); 1741 } 1742 1743 /** 1744 * Verify {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 1745 * WifiManager.PnoScanResultsCallback)} throws an Exception if called with too many frequencies. 1746 */ 1747 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1748 @Test testSetExternalPnoScanRequestTooManyFrequenciesException()1749 public void testSetExternalPnoScanRequestTooManyFrequenciesException() throws Exception { 1750 TestPnoScanResultsCallback callback = new TestPnoScanResultsCallback(); 1751 List<WifiSsid> ssids = new ArrayList<>(); 1752 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1753 int[] frequencies = new int[] {2412, 2417, 2422, 2427, 2432, 2437, 2447, 2452, 2457, 2462, 1754 5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805}; 1755 1756 assertFalse("Callback should be initialized unregistered", callback.isRegisterSuccess()); 1757 assertThrows(IllegalArgumentException.class, () -> { 1758 ShellIdentityUtils.invokeWithShellPermissions( 1759 () -> sWifiManager.setExternalPnoScanRequest( 1760 ssids, frequencies, Executors.newSingleThreadExecutor(), callback)); 1761 }); 1762 } 1763 1764 /** 1765 * Verify {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 1766 * WifiManager.PnoScanResultsCallback)} cannot be called without permission. 1767 */ 1768 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1769 @Test testSetExternalPnoScanRequestNoPermission()1770 public void testSetExternalPnoScanRequestNoPermission() throws Exception { 1771 TestExecutor executor = new TestExecutor(); 1772 TestPnoScanResultsCallback callback = new TestPnoScanResultsCallback(); 1773 List<WifiSsid> ssids = new ArrayList<>(); 1774 ssids.add(WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8))); 1775 1776 assertFalse("Callback should be initialized unregistered", callback.isRegisterSuccess()); 1777 assertThrows(SecurityException.class, 1778 () -> sWifiManager.setExternalPnoScanRequest(ssids, null, executor, callback)); 1779 } 1780 1781 /** 1782 * Verify the invalid and valid usages of {@code WifiManager#getLastCallerInfoForApi}. 1783 */ 1784 @Test testGetLastCallerInfoForApi()1785 public void testGetLastCallerInfoForApi() throws Exception { 1786 AtomicReference<String> packageName = new AtomicReference<>(); 1787 AtomicBoolean enabled = new AtomicBoolean(false); 1788 BiConsumer<String, Boolean> listener = new BiConsumer<String, Boolean>() { 1789 @Override 1790 public void accept(String caller, Boolean value) { 1791 synchronized (mLock) { 1792 packageName.set(caller); 1793 enabled.set(value); 1794 mLock.notify(); 1795 } 1796 } 1797 }; 1798 // Test invalid inputs trigger IllegalArgumentException 1799 assertThrows("Invalid apiType should trigger exception", IllegalArgumentException.class, 1800 () -> sWifiManager.getLastCallerInfoForApi(-1, mExecutor, listener)); 1801 assertThrows("null executor should trigger exception", IllegalArgumentException.class, 1802 () -> sWifiManager.getLastCallerInfoForApi(WifiManager.API_SOFT_AP, null, 1803 listener)); 1804 assertThrows("null listener should trigger exception", IllegalArgumentException.class, 1805 () -> sWifiManager.getLastCallerInfoForApi(WifiManager.API_SOFT_AP, mExecutor, 1806 null)); 1807 1808 // Test caller with no permission triggers SecurityException. 1809 assertThrows("No permission should trigger SecurityException", SecurityException.class, 1810 () -> sWifiManager.getLastCallerInfoForApi(WifiManager.API_SOFT_AP, 1811 mExecutor, listener)); 1812 1813 String expectedPackage = "android.net.wifi.cts"; 1814 boolean isEnabledBefore = sWifiManager.isWifiEnabled(); 1815 // toggle wifi and verify getting last caller 1816 setWifiEnabled(!isEnabledBefore); 1817 ShellIdentityUtils.invokeWithShellPermissions( 1818 () -> sWifiManager.getLastCallerInfoForApi(WifiManager.API_WIFI_ENABLED, mExecutor, 1819 listener)); 1820 synchronized (mLock) { 1821 mLock.wait(TEST_WAIT_DURATION_MS); 1822 } 1823 1824 assertEquals("package does not match", expectedPackage, packageName.get()); 1825 assertEquals("enabled does not match", !isEnabledBefore, enabled.get()); 1826 1827 // toggle wifi again and verify last caller 1828 packageName.set(null); 1829 setWifiEnabled(isEnabledBefore); 1830 ShellIdentityUtils.invokeWithShellPermissions( 1831 () -> sWifiManager.getLastCallerInfoForApi(WifiManager.API_WIFI_ENABLED, mExecutor, 1832 listener)); 1833 synchronized (mLock) { 1834 mLock.wait(TEST_WAIT_DURATION_MS); 1835 } 1836 assertEquals("package does not match", expectedPackage, packageName.get()); 1837 assertEquals("enabled does not match", isEnabledBefore, enabled.get()); 1838 } 1839 1840 /** 1841 * Verify that {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} throws a 1842 * SecurityException when called by a normal app. 1843 */ 1844 @Test testAddNetworkPrivilegedNotAllowedForNormalApps()1845 public void testAddNetworkPrivilegedNotAllowedForNormalApps() { 1846 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1847 // Skip the test if wifi module version is older than S. 1848 return; 1849 } 1850 try { 1851 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 1852 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 1853 sWifiManager.addNetworkPrivileged(newOpenNetwork); 1854 fail("A normal app should not be able to call this API."); 1855 } catch (SecurityException e) { 1856 } 1857 } 1858 1859 /** 1860 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} throws an exception when 1861 * null is the input. 1862 */ 1863 @Test testAddNetworkPrivilegedBadInput()1864 public void testAddNetworkPrivilegedBadInput() { 1865 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1866 // Skip the test if wifi module version is older than S. 1867 return; 1868 } 1869 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1870 try { 1871 uiAutomation.adoptShellPermissionIdentity(); 1872 sWifiManager.addNetworkPrivileged(null); 1873 fail("Expected IllegalArgumentException"); 1874 } catch (IllegalArgumentException e) { 1875 } finally { 1876 uiAutomation.dropShellPermissionIdentity(); 1877 } 1878 } 1879 1880 /** 1881 * Verify {@link WifiManager#getPrivilegedConnectedNetwork()} returns the currently 1882 * connected WifiConfiguration with randomized MAC address filtered out. 1883 */ 1884 @Test testGetPrivilegedConnectedNetworkSuccess()1885 public void testGetPrivilegedConnectedNetworkSuccess() throws Exception { 1886 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1887 try { 1888 uiAutomation.adoptShellPermissionIdentity(); 1889 sWifiManager.startScan(); 1890 1891 WifiInfo wifiInfo = sWifiManager.getConnectionInfo(); 1892 int curNetworkId = wifiInfo.getNetworkId(); 1893 assertNotEquals("Should be connected to valid networkId", INVALID_NETWORK_ID, 1894 curNetworkId); 1895 WifiConfiguration curConfig = sWifiManager.getPrivilegedConnectedNetwork(); 1896 assertEquals("NetworkId should match", curNetworkId, curConfig.networkId); 1897 assertEquals("SSID should match", wifiInfo.getSSID(), curConfig.SSID); 1898 assertEquals("Randomized MAC should be filtered out", WifiInfo.DEFAULT_MAC_ADDRESS, 1899 curConfig.getRandomizedMacAddress().toString()); 1900 } finally { 1901 uiAutomation.dropShellPermissionIdentity(); 1902 } 1903 } 1904 1905 /** 1906 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works properly when the 1907 * calling app has permissions. 1908 */ 1909 @Test testAddNetworkPrivilegedSuccess()1910 public void testAddNetworkPrivilegedSuccess() { 1911 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 1912 // Skip the test if wifi module version is older than S. 1913 return; 1914 } 1915 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1916 WifiManager.AddNetworkResult result = null; 1917 try { 1918 uiAutomation.adoptShellPermissionIdentity(); 1919 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 1920 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 1921 result = sWifiManager.addNetworkPrivileged(newOpenNetwork); 1922 assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode); 1923 assertTrue(result.networkId >= 0); 1924 List<WifiConfiguration> configuredNetworks = sWifiManager.getConfiguredNetworks(); 1925 boolean found = false; 1926 for (WifiConfiguration config : configuredNetworks) { 1927 if (config.networkId == result.networkId 1928 && config.SSID.equals(newOpenNetwork.SSID)) { 1929 found = true; 1930 break; 1931 } 1932 } 1933 assertTrue("addNetworkPrivileged returns success" 1934 + "but the network is not found in getConfiguredNetworks", found); 1935 1936 List<WifiConfiguration> privilegedConfiguredNetworks = 1937 sWifiManager.getPrivilegedConfiguredNetworks(); 1938 found = false; 1939 for (WifiConfiguration config : privilegedConfiguredNetworks) { 1940 if (config.networkId == result.networkId 1941 && config.SSID.equals(newOpenNetwork.SSID)) { 1942 found = true; 1943 break; 1944 } 1945 } 1946 assertTrue("addNetworkPrivileged returns success" 1947 + "but the network is not found in getPrivilegedConfiguredNetworks", found); 1948 1949 List<WifiConfiguration> callerConfiguredNetworks = 1950 sWifiManager.getCallerConfiguredNetworks(); 1951 found = false; 1952 for (WifiConfiguration config : callerConfiguredNetworks) { 1953 if (config.networkId == result.networkId 1954 && config.SSID.equals(newOpenNetwork.SSID)) { 1955 found = true; 1956 break; 1957 } 1958 } 1959 assertTrue("addNetworkPrivileged returns success" 1960 + "but the network is not found in getCallerConfiguredNetworks", found); 1961 } finally { 1962 if (null != result) { 1963 sWifiManager.removeNetwork(result.networkId); 1964 } 1965 uiAutomation.dropShellPermissionIdentity(); 1966 } 1967 } 1968 createConfig( String ssid, int type)1969 private WifiConfiguration createConfig( 1970 String ssid, int type) { 1971 WifiConfiguration config = new WifiConfiguration(); 1972 config.SSID = "\"" + ssid + "\""; 1973 config.setSecurityParams(type); 1974 // set necessary fields for different types. 1975 switch (type) { 1976 case WifiConfiguration.SECURITY_TYPE_OPEN: 1977 case WifiConfiguration.SECURITY_TYPE_OWE: 1978 break; 1979 case WifiConfiguration.SECURITY_TYPE_PSK: 1980 case WifiConfiguration.SECURITY_TYPE_SAE: 1981 config.preSharedKey = "\"1qaz@WSX\""; 1982 break; 1983 case WifiConfiguration.SECURITY_TYPE_EAP: 1984 case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE: 1985 case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT: 1986 config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); 1987 break; 1988 } 1989 return config; 1990 } 1991 assertConfigsAreFound( List<WifiConfiguration> expectedConfigs, List<WifiConfiguration> configs)1992 private void assertConfigsAreFound( 1993 List<WifiConfiguration> expectedConfigs, 1994 List<WifiConfiguration> configs) { 1995 for (WifiConfiguration expectedConfig: expectedConfigs) { 1996 boolean found = false; 1997 for (WifiConfiguration config : configs) { 1998 if (config.networkId == expectedConfig.networkId 1999 && config.getKey().equals(expectedConfig.getKey())) { 2000 found = true; 2001 break; 2002 } 2003 } 2004 assertTrue("the network " + expectedConfig.getKey() + " is not found", found); 2005 } 2006 } 2007 2008 /** 2009 * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works 2010 * with merging types properly when the calling app has permissions. 2011 */ 2012 @Test testAddNetworkPrivilegedMergingTypeSuccess()2013 public void testAddNetworkPrivilegedMergingTypeSuccess() { 2014 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 2015 // Skip the test if wifi module version is older than S. 2016 return; 2017 } 2018 List<WifiConfiguration> baseConfigs = new ArrayList<>(); 2019 baseConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OPEN)); 2020 baseConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_PSK)); 2021 baseConfigs.add(createConfig("test-wpa2e-wpa3e-plki", 2022 WifiConfiguration.SECURITY_TYPE_EAP)); 2023 List<WifiConfiguration> upgradeConfigs = new ArrayList<>(); 2024 upgradeConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OWE)); 2025 upgradeConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_SAE)); 2026 upgradeConfigs.add(createConfig("test-wpa2e-wpa3e-plki", 2027 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)); 2028 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2029 try { 2030 uiAutomation.adoptShellPermissionIdentity(); 2031 final int originalConfiguredNetworksNumber = 2032 sWifiManager.getConfiguredNetworks().size(); 2033 final int originalPrivilegedConfiguredNetworksNumber = 2034 sWifiManager.getPrivilegedConfiguredNetworks().size(); 2035 final int originalCallerConfiguredNetworksNumber = 2036 sWifiManager.getCallerConfiguredNetworks().size(); 2037 for (WifiConfiguration c: baseConfigs) { 2038 WifiManager.AddNetworkResult result = sWifiManager.addNetworkPrivileged(c); 2039 assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode); 2040 assertTrue(result.networkId >= 0); 2041 c.networkId = result.networkId; 2042 } 2043 for (WifiConfiguration c: upgradeConfigs) { 2044 WifiManager.AddNetworkResult result = sWifiManager.addNetworkPrivileged(c); 2045 assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode); 2046 assertTrue(result.networkId >= 0); 2047 c.networkId = result.networkId; 2048 } 2049 // open/owe, psk/sae, and wpa2e/wpa3e should be merged 2050 // so they should have the same network ID. 2051 for (int i = 0; i < baseConfigs.size(); i++) { 2052 assertEquals(baseConfigs.get(i).networkId, upgradeConfigs.get(i).networkId); 2053 } 2054 2055 int numAddedConfigs = baseConfigs.size(); 2056 List<WifiConfiguration> expectedConfigs = new ArrayList<>(baseConfigs); 2057 if (SdkLevel.isAtLeastS()) { 2058 // S devices and above will return one additional config per each security type 2059 // added, so we include the number of both base and upgrade configs. 2060 numAddedConfigs += upgradeConfigs.size(); 2061 expectedConfigs.addAll(upgradeConfigs); 2062 } 2063 List<WifiConfiguration> configuredNetworks = sWifiManager.getConfiguredNetworks(); 2064 assertEquals(originalConfiguredNetworksNumber + numAddedConfigs, 2065 configuredNetworks.size()); 2066 assertConfigsAreFound(expectedConfigs, configuredNetworks); 2067 2068 List<WifiConfiguration> privilegedConfiguredNetworks = 2069 sWifiManager.getPrivilegedConfiguredNetworks(); 2070 assertEquals(originalPrivilegedConfiguredNetworksNumber + numAddedConfigs, 2071 privilegedConfiguredNetworks.size()); 2072 assertConfigsAreFound(expectedConfigs, privilegedConfiguredNetworks); 2073 2074 List<WifiConfiguration> callerConfiguredNetworks = 2075 sWifiManager.getCallerConfiguredNetworks(); 2076 assertEquals(originalCallerConfiguredNetworksNumber + numAddedConfigs, 2077 callerConfiguredNetworks.size()); 2078 assertConfigsAreFound(expectedConfigs, callerConfiguredNetworks); 2079 2080 } finally { 2081 for (WifiConfiguration c: baseConfigs) { 2082 if (c.networkId >= 0) { 2083 sWifiManager.removeNetwork(c.networkId); 2084 } 2085 } 2086 uiAutomation.dropShellPermissionIdentity(); 2087 } 2088 } 2089 2090 /** 2091 * Verify that applications can only have one registered LocalOnlyHotspot request at a time. 2092 * 2093 * Note: Location mode must be enabled for this test. 2094 */ 2095 @Test testStartLocalOnlyHotspotSingleRequestByApps()2096 public void testStartLocalOnlyHotspotSingleRequestByApps() throws Exception { 2097 // check that softap mode is supported by the device 2098 assumeTrue(sWifiManager.isPortableHotspotSupported()); 2099 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 2100 if (wifiEnabled) { 2101 // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's 2102 // no STA+AP concurrency. 2103 ShellIdentityUtils.invokeWithShellPermissions(() -> 2104 sWifiManager.setWifiEnabled(false)); 2105 PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 2106 () -> !sWifiManager.isWifiEnabled()); 2107 SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); 2108 PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 2109 () -> sWifiManager.isWifiEnabled()); 2110 } 2111 2112 runWithScanning(() -> { 2113 boolean caughtException = false; 2114 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 2115 2116 // now make a second request - this should fail. 2117 TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLock); 2118 try { 2119 sWifiManager.startLocalOnlyHotspot(callback2, null); 2120 } catch (IllegalStateException e) { 2121 Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice"); 2122 caughtException = true; 2123 } 2124 if (!caughtException) { 2125 // second start did not fail, should clean up the hotspot. 2126 2127 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController 2128 // initialization. 2129 // TODO: remove this sleep as soon as b/124330089 is fixed. 2130 Log.d(TAG, "Sleeping for 2 seconds"); 2131 Thread.sleep(2000); 2132 2133 stopLocalOnlyHotspot(callback2, wifiEnabled); 2134 } 2135 assertTrue(caughtException); 2136 2137 // add sleep to avoid calling stopLocalOnlyHotspot before TetherController 2138 // initialization. 2139 // TODO: remove this sleep as soon as b/124330089 is fixed. 2140 Log.d(TAG, "Sleeping for 2 seconds"); 2141 Thread.sleep(2000); 2142 2143 stopLocalOnlyHotspot(callback, wifiEnabled); 2144 }, false); 2145 } 2146 2147 private static class TestExecutor implements Executor { 2148 private ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>(); 2149 2150 @Override execute(Runnable task)2151 public void execute(Runnable task) { 2152 tasks.add(task); 2153 } 2154 runAll()2155 private void runAll() { 2156 Runnable task = tasks.poll(); 2157 while (task != null) { 2158 task.run(); 2159 task = tasks.poll(); 2160 } 2161 } 2162 } 2163 generateSoftApConfigBuilderWithSsid(String ssid)2164 private SoftApConfiguration.Builder generateSoftApConfigBuilderWithSsid(String ssid) { 2165 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2166 return new SoftApConfiguration.Builder().setWifiSsid( 2167 WifiSsid.fromBytes(ssid.getBytes(StandardCharsets.UTF_8))); 2168 } 2169 return new SoftApConfiguration.Builder().setSsid(ssid); 2170 } 2171 assertSsidEquals(SoftApConfiguration config, String expectedSsid)2172 private void assertSsidEquals(SoftApConfiguration config, String expectedSsid) { 2173 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2174 assertEquals(WifiSsid.fromBytes(expectedSsid.getBytes(StandardCharsets.UTF_8)), 2175 config.getWifiSsid()); 2176 } else { 2177 assertEquals(expectedSsid, config.getSsid()); 2178 } 2179 } 2180 unregisterLocalOnlyHotspotSoftApCallback(TestSoftApCallback lohsSoftApCallback)2181 private void unregisterLocalOnlyHotspotSoftApCallback(TestSoftApCallback lohsSoftApCallback) { 2182 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2183 sWifiManager.unregisterLocalOnlyHotspotSoftApCallback(lohsSoftApCallback); 2184 } else { 2185 sWifiManager.unregisterSoftApCallback(lohsSoftApCallback); 2186 } 2187 } 2188 testStartLocalOnlyHotspotWithSupportedBand(boolean testSystemApi)2189 private void testStartLocalOnlyHotspotWithSupportedBand(boolean testSystemApi) 2190 throws Exception { 2191 // check that softap mode is supported by the device 2192 if (!sWifiManager.isPortableHotspotSupported()) { 2193 return; 2194 } 2195 2196 TestExecutor executor = new TestExecutor(); 2197 TestSoftApCallback lohsSoftApCallback = new TestSoftApCallback(mLock); 2198 setWifiEnabled(false); 2199 Thread.sleep(TEST_WAIT_DURATION_MS); 2200 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 2201 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2202 try { 2203 uiAutomation.adoptShellPermissionIdentity(); 2204 verifyLohsRegisterSoftApCallback(executor, lohsSoftApCallback); 2205 SoftApConfiguration.Builder customConfigBuilder = 2206 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 2207 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); 2208 2209 SparseIntArray testBandsAndChannels = getAvailableBandAndChannelForTesting( 2210 lohsSoftApCallback.getCurrentSoftApCapability()); 2211 // The devices which doesn't have SIM and default country code in system property 2212 // (ro.boot.wificountrycodeCountry) will return a null country code. Since country code 2213 // is mandatory for 5GHz/6GHz band, skip the softap operation on 5GHz & 6GHz only band. 2214 boolean skip5g6gBand = false; 2215 String wifiCountryCode = sWifiManager.getCountryCode(); 2216 if (wifiCountryCode == null) { 2217 skip5g6gBand = true; 2218 Log.e(TAG, "Country Code is not available - Skip 5GHz and 6GHz test"); 2219 } 2220 for (int i = 0; i < testBandsAndChannels.size(); i++) { 2221 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 2222 int testBand = testBandsAndChannels.keyAt(i); 2223 if (lohsSoftApCallback 2224 .getCurrentSoftApCapability() 2225 .getSupportedChannelList(testBand) 2226 .length 2227 == 0) { 2228 // Skip if test band isn't supported anymore. 2229 continue; 2230 } 2231 if (skip5g6gBand && (testBand == SoftApConfiguration.BAND_6GHZ 2232 || testBand == SoftApConfiguration.BAND_5GHZ)) { 2233 continue; 2234 } 2235 // WPA2_PSK is not allowed in 6GHz band. So test with WPA3_SAE which is 2236 // mandatory to support in 6GHz band. 2237 if (testBand == SoftApConfiguration.BAND_6GHZ) { 2238 if (lohsSoftApCallback.getCurrentSoftApCapability() 2239 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) { 2240 customConfigBuilder.setPassphrase(TEST_PASSPHRASE, 2241 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); 2242 } else { 2243 Log.e(TAG, "SoftAp 6GHz capability is advertized without WPA3 support"); 2244 continue; 2245 } 2246 } 2247 customConfigBuilder.setBand(testBand); 2248 if (testSystemApi) { 2249 sWifiManager.startLocalOnlyHotspot( 2250 customConfigBuilder.build(), executor, callback); 2251 } else { 2252 uiAutomation.dropShellPermissionIdentity(); 2253 sWifiManager.startLocalOnlyHotspotWithConfiguration( 2254 customConfigBuilder.build(), executor, callback); 2255 uiAutomation.adoptShellPermissionIdentity(); 2256 } 2257 // now wait for callback 2258 Thread.sleep(DURATION_SOFTAP_START_MS); 2259 2260 // Verify callback is run on the supplied executor 2261 assertFalse(callback.onStartedCalled); 2262 executor.runAll(); 2263 assertTrue(callback.onStartedCalled); 2264 assertNotNull(callback.reservation); 2265 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 2266 WifiSsid testSsid = 2267 WifiSsid.fromBytes(TEST_SSID_UNQUOTED.getBytes(StandardCharsets.UTF_8)); 2268 if (testSystemApi) { 2269 // Only system api call can force SSID and passphrase 2270 assertEquals(testSsid, softApConfig.getWifiSsid()); 2271 assertEquals(TEST_PASSPHRASE, softApConfig.getPassphrase()); 2272 } else { 2273 assertNotEquals(testSsid, softApConfig.getWifiSsid()); 2274 } 2275 // Automotive mode can force the LOHS to specific bands 2276 if (!hasAutomotiveFeature()) { 2277 assertEquals(testBand, softApConfig.getBand()); 2278 } 2279 if (lohsSoftApCallback.getOnSoftapInfoChangedCalledCount() > 1) { 2280 assertTrue(lohsSoftApCallback.getCurrentSoftApInfo().getFrequency() > 0); 2281 } 2282 stopLocalOnlyHotspot(callback, wifiEnabled); 2283 } 2284 } finally { 2285 // clean up 2286 sWifiManager.unregisterSoftApCallback(lohsSoftApCallback); 2287 uiAutomation.dropShellPermissionIdentity(); 2288 } 2289 } 2290 2291 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 2292 @Test testStartLocalOnlyHotspotWithSupportedBand()2293 public void testStartLocalOnlyHotspotWithSupportedBand() throws Exception { 2294 testStartLocalOnlyHotspotWithSupportedBand(true /* testSystemApi */); 2295 } 2296 2297 /** Tests {@link WifiManager#startLocalOnlyHotspotWithConfiguration()}. */ 2298 @RequiresFlagsEnabled(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 2299 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") 2300 @Test testStartLocalOnlyHotspotWithConfiguration()2301 public void testStartLocalOnlyHotspotWithConfiguration() throws Exception { 2302 testStartLocalOnlyHotspotWithSupportedBand(false /* testSystemApi */); 2303 } 2304 2305 @Test testStartLocalOnlyHotspotWithConfigBssid()2306 public void testStartLocalOnlyHotspotWithConfigBssid() throws Exception { 2307 // check that softap mode is supported by the device 2308 if (!sWifiManager.isPortableHotspotSupported()) { 2309 return; 2310 } 2311 2312 TestExecutor executor = new TestExecutor(); 2313 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 2314 TestSoftApCallback lohsSoftApCallback = new TestSoftApCallback(mLock); 2315 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2316 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 2317 try { 2318 uiAutomation.adoptShellPermissionIdentity(); 2319 verifyLohsRegisterSoftApCallback(executor, lohsSoftApCallback); 2320 SoftApConfiguration.Builder customConfigBuilder = 2321 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 2322 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); 2323 2324 boolean isSupportCustomizedMac = lohsSoftApCallback.getCurrentSoftApCapability() 2325 .areFeaturesSupported( 2326 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 2327 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 2328 if (isSupportCustomizedMac) { 2329 customConfigBuilder.setBssid(TEST_MAC).setMacRandomizationSetting( 2330 SoftApConfiguration.RANDOMIZATION_NONE); 2331 } 2332 SoftApConfiguration customConfig = customConfigBuilder.build(); 2333 2334 sWifiManager.startLocalOnlyHotspot(customConfig, executor, callback); 2335 // now wait for callback 2336 Thread.sleep(TEST_WAIT_DURATION_MS); 2337 2338 // Verify callback is run on the supplied executor 2339 assertFalse(callback.onStartedCalled); 2340 executor.runAll(); 2341 assertTrue(callback.onStartedCalled); 2342 2343 assertNotNull(callback.reservation); 2344 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 2345 assertNotNull(softApConfig); 2346 if (isSupportCustomizedMac) { 2347 assertEquals(TEST_MAC, softApConfig.getBssid()); 2348 } 2349 assertSsidEquals(softApConfig, TEST_SSID_UNQUOTED); 2350 assertEquals(TEST_PASSPHRASE, softApConfig.getPassphrase()); 2351 } finally { 2352 // clean up 2353 stopLocalOnlyHotspot(callback, wifiEnabled); 2354 unregisterLocalOnlyHotspotSoftApCallback(lohsSoftApCallback); 2355 uiAutomation.dropShellPermissionIdentity(); 2356 } 2357 } 2358 2359 @Test testStartLocalOnlyHotspotWithNullBssidConfig()2360 public void testStartLocalOnlyHotspotWithNullBssidConfig() throws Exception { 2361 // check that softap mode is supported by the device 2362 if (!sWifiManager.isPortableHotspotSupported()) { 2363 return; 2364 } 2365 SoftApConfiguration customConfig = 2366 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 2367 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 2368 .build(); 2369 2370 TestExecutor executor = new TestExecutor(); 2371 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock); 2372 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2373 boolean wifiEnabled = sWifiManager.isWifiEnabled(); 2374 try { 2375 uiAutomation.adoptShellPermissionIdentity(); 2376 2377 sWifiManager.startLocalOnlyHotspot(customConfig, executor, callback); 2378 // now wait for callback 2379 Thread.sleep(TEST_WAIT_DURATION_MS); 2380 2381 // Verify callback is run on the supplied executor 2382 assertFalse(callback.onStartedCalled); 2383 executor.runAll(); 2384 assertTrue(callback.onStartedCalled); 2385 2386 assertNotNull(callback.reservation); 2387 SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration(); 2388 assertNotNull(softApConfig); 2389 assertSsidEquals(softApConfig, TEST_SSID_UNQUOTED); 2390 assertEquals(TEST_PASSPHRASE, softApConfig.getPassphrase()); 2391 } finally { 2392 // clean up 2393 stopLocalOnlyHotspot(callback, wifiEnabled); 2394 uiAutomation.dropShellPermissionIdentity(); 2395 } 2396 } 2397 2398 /** 2399 * Read the content of the given resource file into a String. 2400 * 2401 * @param filename String name of the file 2402 * @return String 2403 * @throws IOException 2404 */ loadResourceFile(String filename)2405 private String loadResourceFile(String filename) throws IOException { 2406 InputStream in = getClass().getClassLoader().getResourceAsStream(filename); 2407 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 2408 StringBuilder builder = new StringBuilder(); 2409 String line; 2410 while ((line = reader.readLine()) != null) { 2411 builder.append(line).append("\n"); 2412 } 2413 return builder.toString(); 2414 } 2415 2416 /** 2417 * Verify that changing the mac randomization setting of a Passpoint configuration. 2418 */ 2419 @Test testMacRandomizationSettingPasspoint()2420 public void testMacRandomizationSettingPasspoint() throws Exception { 2421 String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT); 2422 PasspointConfiguration config = 2423 ConfigParser.parsePasspointConfig(TYPE_WIFI_CONFIG, configStr.getBytes()); 2424 String fqdn = config.getHomeSp().getFqdn(); 2425 String uniqueId = config.getUniqueId(); 2426 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 2427 try { 2428 uiAutomation.adoptShellPermissionIdentity(); 2429 2430 sWifiManager.addOrUpdatePasspointConfiguration(config); 2431 PasspointConfiguration passpointConfig = getTargetPasspointConfiguration( 2432 sWifiManager.getPasspointConfigurations(), uniqueId); 2433 assertNotNull("The installed passpoint profile is missing", passpointConfig); 2434 assertTrue("Mac randomization should be enabled for passpoint networks by default.", 2435 passpointConfig.isMacRandomizationEnabled()); 2436 2437 sWifiManager.setMacRandomizationSettingPasspointEnabled(fqdn, false); 2438 passpointConfig = getTargetPasspointConfiguration( 2439 sWifiManager.getPasspointConfigurations(), uniqueId); 2440 assertNotNull("The installed passpoint profile is missing", passpointConfig); 2441 assertFalse("Mac randomization should be disabled by the API call.", 2442 passpointConfig.isMacRandomizationEnabled()); 2443 } finally { 2444 // Clean up 2445 sWifiManager.removePasspointConfiguration(fqdn); 2446 uiAutomation.dropShellPermissionIdentity(); 2447 } 2448 } 2449 /** 2450 * Verify that the {@link android.Manifest.permission#NETWORK_STACK} permission is never held by 2451 * any package. 2452 * <p> 2453 * No apps should <em>ever</em> attempt to acquire this permission, since it would give those 2454 * apps extremely broad access to connectivity functionality. 2455 */ 2456 @Test testNetworkStackPermission()2457 public void testNetworkStackPermission() { 2458 final PackageManager pm = sContext.getPackageManager(); 2459 2460 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2461 android.Manifest.permission.NETWORK_STACK 2462 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2463 for (PackageInfo pi : holding) { 2464 fail("The NETWORK_STACK permission must not be held by " + pi.packageName 2465 + " and must be revoked for security reasons"); 2466 } 2467 } 2468 2469 /** 2470 * Verify that the {@link android.Manifest.permission#NETWORK_SETTINGS} permission is 2471 * never held by any package. 2472 * <p> 2473 * Only Settings, SysUi, NetworkStack and shell apps should <em>ever</em> attempt to acquire 2474 * this permission, since it would give those apps extremely broad access to connectivity 2475 * functionality. The permission is intended to be granted to only those apps with direct user 2476 * access and no others. 2477 */ 2478 @Test testNetworkSettingsPermission()2479 public void testNetworkSettingsPermission() { 2480 final PackageManager pm = sContext.getPackageManager(); 2481 2482 final ArraySet<String> allowedPackages = new ArraySet(); 2483 final ArraySet<Integer> allowedUIDs = new ArraySet(); 2484 // explicitly add allowed UIDs 2485 allowedUIDs.add(Process.SYSTEM_UID); 2486 allowedUIDs.add(Process.SHELL_UID); 2487 allowedUIDs.add(Process.PHONE_UID); 2488 allowedUIDs.add(Process.NETWORK_STACK_UID); 2489 if (!SdkLevel.isAtLeastV()) { 2490 allowedUIDs.add(Process.NFC_UID); 2491 } 2492 2493 // only quick settings is allowed to bind to the BIND_QUICK_SETTINGS_TILE permission, using 2494 // this fact to determined allowed package name for sysui. This is a signature permission, 2495 // so allow any package with this permission. 2496 final List<PackageInfo> sysuiPackages = pm.getPackagesHoldingPermissions(new String[] { 2497 android.Manifest.permission.BIND_QUICK_SETTINGS_TILE 2498 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2499 for (PackageInfo info : sysuiPackages) { 2500 allowedPackages.add(info.packageName); 2501 } 2502 2503 // the captive portal flow also currently holds the NETWORK_SETTINGS permission 2504 final Intent intent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); 2505 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 2506 if (ri != null) { 2507 allowedPackages.add(ri.activityInfo.packageName); 2508 } 2509 2510 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2511 android.Manifest.permission.NETWORK_SETTINGS 2512 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2513 StringBuilder stringBuilder = new StringBuilder(); 2514 for (PackageInfo pi : holding) { 2515 String packageName = pi.packageName; 2516 2517 // this is an explicitly allowed package 2518 if (allowedPackages.contains(packageName)) continue; 2519 2520 // now check if the packages are from allowed UIDs 2521 int uid = -1; 2522 try { 2523 uid = pm.getPackageUidAsUser(packageName, UserHandle.USER_SYSTEM); 2524 } catch (PackageManager.NameNotFoundException e) { 2525 continue; 2526 } 2527 if (!allowedUIDs.contains(uid)) { 2528 stringBuilder.append("The NETWORK_SETTINGS permission must not be held by " 2529 + packageName + ":" + uid + " and must be revoked for security reasons\n"); 2530 } 2531 } 2532 if (stringBuilder.length() > 0) { 2533 fail(stringBuilder.toString()); 2534 } 2535 } 2536 2537 /** 2538 * Verify that the {@link android.Manifest.permission#NETWORK_SETUP_WIZARD} permission is 2539 * only held by the device setup wizard application. 2540 * <p> 2541 * Only the SetupWizard app should <em>ever</em> attempt to acquire this 2542 * permission, since it would give those apps extremely broad access to connectivity 2543 * functionality. The permission is intended to be granted to only the device setup wizard. 2544 */ 2545 @Test testNetworkSetupWizardPermission()2546 public void testNetworkSetupWizardPermission() { 2547 final ArraySet<String> allowedPackages = new ArraySet(); 2548 2549 final PackageManager pm = sContext.getPackageManager(); 2550 2551 final Intent intent = new Intent(Intent.ACTION_MAIN); 2552 intent.addCategory(Intent.CATEGORY_SETUP_WIZARD); 2553 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 2554 String validPkg = ""; 2555 if (ri != null) { 2556 allowedPackages.add(ri.activityInfo.packageName); 2557 validPkg = ri.activityInfo.packageName; 2558 } 2559 2560 final Intent preIntent = new Intent("com.android.setupwizard.OEM_PRE_SETUP"); 2561 preIntent.addCategory(Intent.CATEGORY_DEFAULT); 2562 final ResolveInfo preRi = pm 2563 .resolveActivity(preIntent, PackageManager.MATCH_DISABLED_COMPONENTS); 2564 String prePackageName = ""; 2565 if (null != preRi) { 2566 prePackageName = preRi.activityInfo.packageName; 2567 } 2568 2569 final Intent postIntent = new Intent("com.android.setupwizard.OEM_POST_SETUP"); 2570 postIntent.addCategory(Intent.CATEGORY_DEFAULT); 2571 final ResolveInfo postRi = pm 2572 .resolveActivity(postIntent, PackageManager.MATCH_DISABLED_COMPONENTS); 2573 String postPackageName = ""; 2574 if (null != postRi) { 2575 postPackageName = postRi.activityInfo.packageName; 2576 } 2577 if (!TextUtils.isEmpty(prePackageName) && !TextUtils.isEmpty(postPackageName) 2578 && prePackageName.equals(postPackageName)) { 2579 allowedPackages.add(prePackageName); 2580 } 2581 2582 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[]{ 2583 android.Manifest.permission.NETWORK_SETUP_WIZARD 2584 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2585 for (PackageInfo pi : holding) { 2586 if (!allowedPackages.contains(pi.packageName)) { 2587 fail("The NETWORK_SETUP_WIZARD permission must not be held by " + pi.packageName 2588 + " and must be revoked for security reasons" 2589 + " | validPkg=" + validPkg); 2590 } 2591 } 2592 } 2593 2594 /** 2595 * Verify that the {@link android.Manifest.permission#NETWORK_MANAGED_PROVISIONING} permission 2596 * is only held by the device managed provisioning application. 2597 * <p> 2598 * Only the ManagedProvisioning app should <em>ever</em> attempt to acquire this 2599 * permission, since it would give those apps extremely broad access to connectivity 2600 * functionality. The permission is intended to be granted to only the device managed 2601 * provisioning. 2602 */ 2603 @Test testNetworkManagedProvisioningPermission()2604 public void testNetworkManagedProvisioningPermission() { 2605 final PackageManager pm = sContext.getPackageManager(); 2606 2607 // TODO(b/115980767): Using hardcoded package name. Need a better mechanism to find the 2608 // managed provisioning app. 2609 // Ensure that the package exists. 2610 final Intent intent = new Intent(Intent.ACTION_MAIN); 2611 intent.setPackage(MANAGED_PROVISIONING_PACKAGE_NAME); 2612 final ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DISABLED_COMPONENTS); 2613 String validPkg = ""; 2614 if (ri != null) { 2615 validPkg = ri.activityInfo.packageName; 2616 } 2617 String dpmHolderName = null; 2618 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2619 DevicePolicyManager dpm = sContext.getSystemService(DevicePolicyManager.class); 2620 if (dpm != null) { 2621 dpmHolderName = dpm.getDevicePolicyManagementRoleHolderPackage(); 2622 } 2623 } 2624 2625 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2626 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 2627 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2628 for (PackageInfo pi : holding) { 2629 if (!Objects.equals(pi.packageName, validPkg) 2630 && !Objects.equals(pi.packageName, dpmHolderName)) { 2631 fail("The NETWORK_MANAGED_PROVISIONING permission must not be held by " 2632 + pi.packageName + " and must be revoked for security reasons [" 2633 + validPkg + ", " + dpmHolderName + "]"); 2634 } 2635 } 2636 } 2637 2638 /** 2639 * Verify that the {@link android.Manifest.permission#WIFI_SET_DEVICE_MOBILITY_STATE} permission 2640 * is held by at most one application. 2641 */ 2642 @Test testWifiSetDeviceMobilityStatePermission()2643 public void testWifiSetDeviceMobilityStatePermission() { 2644 final PackageManager pm = sContext.getPackageManager(); 2645 2646 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2647 android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE 2648 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2649 2650 List<String> uniquePackageNames = holding 2651 .stream() 2652 .map(pi -> pi.packageName) 2653 .distinct() 2654 .collect(Collectors.toList()); 2655 2656 if (uniquePackageNames.size() > 1) { 2657 fail("The WIFI_SET_DEVICE_MOBILITY_STATE permission must not be held by more than one " 2658 + "application, but is held by " + uniquePackageNames.size() + " applications: " 2659 + String.join(", ", uniquePackageNames)); 2660 } 2661 } 2662 2663 /** 2664 * Verify that the {@link android.Manifest.permission#NETWORK_CARRIER_PROVISIONING} permission 2665 * is held by at most one application. 2666 */ 2667 @Test testNetworkCarrierProvisioningPermission()2668 public void testNetworkCarrierProvisioningPermission() { 2669 final PackageManager pm = sContext.getPackageManager(); 2670 2671 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2672 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 2673 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2674 2675 List<String> uniquePackageNames = holding 2676 .stream() 2677 .map(pi -> pi.packageName) 2678 .distinct() 2679 .collect(Collectors.toList()); 2680 2681 if (uniquePackageNames.size() > 2) { 2682 fail( 2683 "The NETWORK_CARRIER_PROVISIONING permission must not be held by more than two " 2684 + "applications, but is held by " 2685 + uniquePackageNames.size() 2686 + " applications: " 2687 + String.join(", ", uniquePackageNames)); 2688 } 2689 } 2690 2691 /** 2692 * Verify that the {@link android.Manifest.permission#WIFI_UPDATE_USABILITY_STATS_SCORE} 2693 * permission is held by at most two applications. 2694 */ 2695 @Test testUpdateWifiUsabilityStatsScorePermission()2696 public void testUpdateWifiUsabilityStatsScorePermission() { 2697 final PackageManager pm = sContext.getPackageManager(); 2698 2699 final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] { 2700 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE 2701 }, PackageManager.MATCH_UNINSTALLED_PACKAGES); 2702 2703 Set<String> uniqueNonSystemPackageNames = new HashSet<>(); 2704 for (PackageInfo pi : holding) { 2705 String packageName = pi.packageName; 2706 // Shell is allowed to hold this permission for testing. 2707 int uid = -1; 2708 try { 2709 uid = pm.getPackageUidAsUser(packageName, UserHandle.USER_SYSTEM); 2710 } catch (PackageManager.NameNotFoundException e) { 2711 continue; 2712 } 2713 if (uid == Process.SHELL_UID) continue; 2714 2715 uniqueNonSystemPackageNames.add(packageName); 2716 } 2717 2718 if (uniqueNonSystemPackageNames.size() > 2) { 2719 fail("The WIFI_UPDATE_USABILITY_STATS_SCORE permission must not be held by more than " 2720 + "two applications, but is held by " + uniqueNonSystemPackageNames.size() 2721 + " applications: " + String.join(", ", uniqueNonSystemPackageNames)); 2722 } 2723 } 2724 turnScreenOnNoDelay()2725 private static void turnScreenOnNoDelay() throws Exception { 2726 if (sWakeLock.isHeld()) sWakeLock.release(); 2727 sUiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP"); 2728 sUiDevice.executeShellCommand("wm dismiss-keyguard"); 2729 } 2730 turnScreenOn()2731 private void turnScreenOn() throws Exception { 2732 turnScreenOnNoDelay(); 2733 // Since the screen on/off intent is ordered, they will not be sent right now. 2734 Thread.sleep(DURATION_SCREEN_TOGGLE); 2735 } 2736 turnScreenOffNoDelay()2737 private void turnScreenOffNoDelay() throws Exception { 2738 sUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP"); 2739 } 2740 turnScreenOff()2741 private void turnScreenOff() throws Exception { 2742 if (!sWakeLock.isHeld()) sWakeLock.acquire(); 2743 turnScreenOffNoDelay(); 2744 // Since the screen on/off intent is ordered, they will not be sent right now. 2745 Thread.sleep(DURATION_SCREEN_TOGGLE); 2746 } 2747 assertWifiScanningIsOn()2748 private void assertWifiScanningIsOn() { 2749 if (!sWifiManager.isScanAlwaysAvailable()) { 2750 fail("Wi-Fi scanning should be on."); 2751 } 2752 } 2753 runWithScanning(ThrowingRunnable r, boolean isEnabled)2754 private void runWithScanning(ThrowingRunnable r, boolean isEnabled) throws Exception { 2755 boolean scanModeChangedForTest = false; 2756 if (sWifiManager.isScanAlwaysAvailable() != isEnabled) { 2757 ShellIdentityUtils.invokeWithShellPermissions( 2758 () -> sWifiManager.setScanAlwaysAvailable(isEnabled)); 2759 scanModeChangedForTest = true; 2760 } 2761 try { 2762 r.run(); 2763 } finally { 2764 if (scanModeChangedForTest) { 2765 ShellIdentityUtils.invokeWithShellPermissions( 2766 () -> sWifiManager.setScanAlwaysAvailable(!isEnabled)); 2767 } 2768 } 2769 } 2770 2771 /** 2772 * Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is disabled 2773 * but location is on. 2774 * @throws Exception 2775 */ 2776 @Test testScreenOffDoesNotTurnOffWifiScanningWhenWifiDisabled()2777 public void testScreenOffDoesNotTurnOffWifiScanningWhenWifiDisabled() throws Exception { 2778 if (FeatureUtil.isTV() || FeatureUtil.isAutomotive()) { 2779 // TV and auto do not support the setting options of WIFI scanning and Bluetooth 2780 // scanning 2781 return; 2782 } 2783 2784 if (!hasLocationFeature()) { 2785 // skip the test if location is not supported 2786 return; 2787 } 2788 if (!isLocationEnabled()) { 2789 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 2790 + " empty when location is disabled!"); 2791 } 2792 runWithScanning(() -> { 2793 setWifiEnabled(false); 2794 turnScreenOn(); 2795 assertWifiScanningIsOn(); 2796 // Toggle screen and verify Wi-Fi scanning is still on. 2797 turnScreenOff(); 2798 assertWifiScanningIsOn(); 2799 turnScreenOn(); 2800 assertWifiScanningIsOn(); 2801 }, true /* run with enabled*/); 2802 } 2803 2804 /** 2805 * Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is enabled. 2806 * @throws Exception 2807 */ 2808 @Test testScreenOffDoesNotTurnOffWifiScanningWhenWifiEnabled()2809 public void testScreenOffDoesNotTurnOffWifiScanningWhenWifiEnabled() throws Exception { 2810 if (FeatureUtil.isTV() || FeatureUtil.isAutomotive()) { 2811 // TV and auto do not support the setting options of WIFI scanning and Bluetooth 2812 // scanning 2813 return; 2814 } 2815 2816 if (!hasLocationFeature()) { 2817 // skip the test if location is not supported 2818 return; 2819 } 2820 if (!isLocationEnabled()) { 2821 fail("Please enable location for this test - since Marshmallow WiFi scan results are" 2822 + " empty when location is disabled!"); 2823 } 2824 runWithScanning(() -> { 2825 setWifiEnabled(true); 2826 turnScreenOn(); 2827 assertWifiScanningIsOn(); 2828 // Toggle screen and verify Wi-Fi scanning is still on. 2829 turnScreenOff(); 2830 assertWifiScanningIsOn(); 2831 turnScreenOn(); 2832 assertWifiScanningIsOn(); 2833 }, true /* run with enabled*/); 2834 } 2835 2836 /** 2837 * Verify that the platform supports a reasonable number of suggestions per app. 2838 * @throws Exception 2839 */ 2840 @Test testMaxNumberOfNetworkSuggestionsPerApp()2841 public void testMaxNumberOfNetworkSuggestionsPerApp() throws Exception { 2842 assertTrue(sWifiManager.getMaxNumberOfNetworkSuggestionsPerApp() 2843 > ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP); 2844 } 2845 verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback)2846 private void verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback) 2847 throws Exception { 2848 // Register callback to get SoftApCapability 2849 sWifiManager.registerSoftApCallback(executor, callback); 2850 PollingCheck.check( 2851 "SoftAp register failed!", 5_000, 2852 () -> { 2853 executor.runAll(); 2854 // Verify callback is run on the supplied executor and called 2855 return callback.getOnStateChangedCalled() 2856 && callback.getOnSoftapInfoChangedCalledCount() > 0 2857 && callback.getOnSoftApCapabilityChangedCalled() 2858 && callback.getOnConnectedClientCalled(); 2859 }); 2860 } 2861 verifyLohsRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback)2862 private void verifyLohsRegisterSoftApCallback(TestExecutor executor, 2863 TestSoftApCallback callback) throws Exception { 2864 // Register callback to get SoftApCapability 2865 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2866 sWifiManager.registerLocalOnlyHotspotSoftApCallback(executor, callback); 2867 } else { 2868 sWifiManager.registerSoftApCallback(executor, callback); 2869 } 2870 PollingCheck.check( 2871 "SoftAp register failed!", 5_000, 2872 () -> { 2873 executor.runAll(); 2874 // Verify callback is run on the supplied executor and called 2875 return callback.getOnStateChangedCalled() && 2876 callback.getOnSoftapInfoChangedCalledCount() > 0 && 2877 callback.getOnSoftApCapabilityChangedCalled() && 2878 callback.getOnConnectedClientCalled(); 2879 }); 2880 } 2881 verifySetGetSoftApConfig(SoftApConfiguration targetConfig)2882 private void verifySetGetSoftApConfig(SoftApConfiguration targetConfig) { 2883 assertTrue(sWifiManager.validateSoftApConfiguration(targetConfig)); 2884 sWifiManager.setSoftApConfiguration(targetConfig); 2885 // Bssid set dodesn't support for tethered hotspot 2886 SoftApConfiguration currentConfig = sWifiManager.getSoftApConfiguration(); 2887 compareSoftApConfiguration(targetConfig, currentConfig); 2888 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2889 assertTrue(currentConfig.isUserConfiguration()); 2890 } 2891 assertNotNull(currentConfig.getPersistentRandomizedMacAddress()); 2892 2893 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2894 // Verify set/get with the deprecated set/getSsid() 2895 SoftApConfiguration oldSsidConfig = new SoftApConfiguration.Builder(targetConfig) 2896 .setWifiSsid(null) 2897 .setSsid(targetConfig.getSsid()).build(); 2898 sWifiManager.setSoftApConfiguration(oldSsidConfig); 2899 currentConfig = sWifiManager.getSoftApConfiguration(); 2900 compareSoftApConfiguration(oldSsidConfig, currentConfig); 2901 } 2902 } 2903 compareSoftApConfiguration(SoftApConfiguration currentConfig, SoftApConfiguration testSoftApConfig)2904 private void compareSoftApConfiguration(SoftApConfiguration currentConfig, 2905 SoftApConfiguration testSoftApConfig) { 2906 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2907 assertEquals(currentConfig.getWifiSsid(), testSoftApConfig.getWifiSsid()); 2908 } 2909 assertEquals(currentConfig.getSsid(), testSoftApConfig.getSsid()); 2910 assertEquals(currentConfig.getBssid(), testSoftApConfig.getBssid()); 2911 assertEquals(currentConfig.getSecurityType(), testSoftApConfig.getSecurityType()); 2912 assertEquals(currentConfig.getPassphrase(), testSoftApConfig.getPassphrase()); 2913 assertEquals(currentConfig.isHiddenSsid(), testSoftApConfig.isHiddenSsid()); 2914 assertEquals(currentConfig.getBand(), testSoftApConfig.getBand()); 2915 assertEquals(currentConfig.getChannel(), testSoftApConfig.getChannel()); 2916 assertEquals(currentConfig.getMaxNumberOfClients(), 2917 testSoftApConfig.getMaxNumberOfClients()); 2918 assertEquals(currentConfig.isAutoShutdownEnabled(), 2919 testSoftApConfig.isAutoShutdownEnabled()); 2920 assertEquals(currentConfig.getShutdownTimeoutMillis(), 2921 testSoftApConfig.getShutdownTimeoutMillis()); 2922 assertEquals(currentConfig.isClientControlByUserEnabled(), 2923 testSoftApConfig.isClientControlByUserEnabled()); 2924 assertEquals(currentConfig.getAllowedClientList(), 2925 testSoftApConfig.getAllowedClientList()); 2926 assertEquals(currentConfig.getBlockedClientList(), 2927 testSoftApConfig.getBlockedClientList()); 2928 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 2929 assertEquals(currentConfig.getMacRandomizationSetting(), 2930 testSoftApConfig.getMacRandomizationSetting()); 2931 assertEquals(currentConfig.getChannels().toString(), 2932 testSoftApConfig.getChannels().toString()); 2933 assertEquals(currentConfig.isBridgedModeOpportunisticShutdownEnabled(), 2934 testSoftApConfig.isBridgedModeOpportunisticShutdownEnabled()); 2935 assertEquals(currentConfig.isIeee80211axEnabled(), 2936 testSoftApConfig.isIeee80211axEnabled()); 2937 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 2938 assertEquals(currentConfig.getBridgedModeOpportunisticShutdownTimeoutMillis(), 2939 testSoftApConfig.getBridgedModeOpportunisticShutdownTimeoutMillis()); 2940 assertEquals(currentConfig.isIeee80211beEnabled(), 2941 testSoftApConfig.isIeee80211beEnabled()); 2942 assertEquals(currentConfig.getVendorElements(), 2943 testSoftApConfig.getVendorElements()); 2944 assertArrayEquals( 2945 currentConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_2GHZ), 2946 testSoftApConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_2GHZ)); 2947 assertArrayEquals( 2948 currentConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_5GHZ), 2949 testSoftApConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_5GHZ)); 2950 assertArrayEquals( 2951 currentConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_6GHZ), 2952 testSoftApConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_6GHZ)); 2953 assertEquals(currentConfig.getMaxChannelBandwidth(), 2954 testSoftApConfig.getMaxChannelBandwidth()); 2955 } 2956 if (Flags.androidVWifiApi() 2957 && SdkLevel.isAtLeastV()) { 2958 assertTrue(Objects.equals( 2959 currentConfig.getVendorData(), testSoftApConfig.getVendorData())); 2960 } 2961 2962 if (Flags.apIsolate() && WifiBuildCompat.isAtLeastB()) { 2963 assertEquals(currentConfig.isClientIsolationEnabled(), 2964 testSoftApConfig.isClientIsolationEnabled()); 2965 } 2966 } 2967 } 2968 turnOffWifiAndTetheredHotspotIfEnabled()2969 private void turnOffWifiAndTetheredHotspotIfEnabled() throws Exception { 2970 if (sWifiManager.isWifiEnabled()) { 2971 Log.d(TAG, "Turn off WiFi"); 2972 sWifiManager.setWifiEnabled(false); 2973 PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 2974 () -> !sWifiManager.isWifiEnabled()); 2975 } 2976 if (sWifiManager.isWifiApEnabled()) { 2977 sTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 2978 Log.d(TAG, "Turn off tethered Hotspot"); 2979 PollingCheck.check("SoftAp turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 2980 () -> !sWifiManager.isWifiApEnabled()); 2981 } 2982 } 2983 verifyBridgedModeSoftApCallback(TestExecutor executor, TestSoftApCallback callback, boolean shouldFallbackSingleApMode, boolean isEnabled)2984 private void verifyBridgedModeSoftApCallback(TestExecutor executor, 2985 TestSoftApCallback callback, boolean shouldFallbackSingleApMode, boolean isEnabled) 2986 throws Exception { 2987 // Verify state and info callback value as expected 2988 PollingCheck.check( 2989 "SoftAp state and info on bridged AP mode are mismatch!!!" 2990 + " shouldFallbackSingleApMode = " + shouldFallbackSingleApMode 2991 + ", isEnabled = " + isEnabled, 10_000, 2992 () -> { 2993 executor.runAll(); 2994 int expectedState = isEnabled ? WifiManager.WIFI_AP_STATE_ENABLED 2995 : WifiManager.WIFI_AP_STATE_DISABLED; 2996 int expectedInfoSize = isEnabled 2997 ? (shouldFallbackSingleApMode ? 1 : 2) : 0; 2998 return expectedState == callback.getCurrentState() 2999 && callback.getCurrentSoftApInfoList().size() == expectedInfoSize; 3000 }); 3001 } 3002 shouldFallbackToSingleAp(int[] bands, SoftApCapability capability)3003 private boolean shouldFallbackToSingleAp(int[] bands, SoftApCapability capability) { 3004 for (int band : bands) { 3005 if (capability.getSupportedChannelList(band).length == 0) { 3006 return true; 3007 } 3008 } 3009 return false; 3010 } 3011 getAvailableBandAndChannelForTesting(SoftApCapability capability)3012 private SparseIntArray getAvailableBandAndChannelForTesting(SoftApCapability capability) { 3013 final int[] bands = {SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_5GHZ, 3014 SoftApConfiguration.BAND_6GHZ, SoftApConfiguration.BAND_60GHZ}; 3015 SparseIntArray testBandsAndChannels = new SparseIntArray(); 3016 if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 3017 testBandsAndChannels.put(SoftApConfiguration.BAND_2GHZ, 1); 3018 return testBandsAndChannels; 3019 } 3020 for (int band : bands) { 3021 int[] supportedList = capability.getSupportedChannelList(band); 3022 if (supportedList.length != 0) { 3023 testBandsAndChannels.put(band, supportedList[0]); 3024 } 3025 } 3026 return testBandsAndChannels; 3027 } 3028 3029 @Test testLastConfiguredPassphraseIsKeepInSoftApConfigurationWhenChangingToNone()3030 public void testLastConfiguredPassphraseIsKeepInSoftApConfigurationWhenChangingToNone() 3031 throws Exception { 3032 final SoftApConfiguration currentConfig = ShellIdentityUtils.invokeWithShellPermissions( 3033 sWifiManager::getSoftApConfiguration); 3034 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3035 try { 3036 uiAutomation.adoptShellPermissionIdentity(); 3037 Mutable<String> lastPassphrase = new Mutable<>(); 3038 final String testPassphrase = "testPassphrase"; 3039 sWifiManager.setSoftApConfiguration( 3040 new SoftApConfiguration.Builder(currentConfig) 3041 .setPassphrase(testPassphrase, 3042 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK).build()); 3043 sWifiManager.queryLastConfiguredTetheredApPassphraseSinceBoot(mExecutor, 3044 new Consumer<String>() { 3045 @Override 3046 public void accept(String value) { 3047 synchronized (mLock) { 3048 lastPassphrase.value = value; 3049 mLock.notify(); 3050 } 3051 } 3052 }); 3053 synchronized (mLock) { 3054 mLock.wait(TEST_WAIT_DURATION_MS); 3055 } 3056 assertEquals(lastPassphrase.value, testPassphrase); 3057 3058 sWifiManager.setSoftApConfiguration( 3059 new SoftApConfiguration.Builder(currentConfig) 3060 .setPassphrase(null, 3061 SoftApConfiguration.SECURITY_TYPE_OPEN).build()); 3062 sWifiManager.queryLastConfiguredTetheredApPassphraseSinceBoot(mExecutor, 3063 new Consumer<String>() { 3064 @Override 3065 public void accept(String value) { 3066 synchronized (mLock) { 3067 lastPassphrase.value = value; 3068 mLock.notify(); 3069 } 3070 } 3071 }); 3072 synchronized (mLock) { 3073 mLock.wait(TEST_WAIT_DURATION_MS); 3074 } 3075 assertEquals(lastPassphrase.value, testPassphrase); 3076 } finally { 3077 // Restore SoftApConfiguration 3078 sWifiManager.setSoftApConfiguration(currentConfig); 3079 uiAutomation.dropShellPermissionIdentity(); 3080 } 3081 } 3082 3083 /** 3084 * Skip the test if telephony is not supported and default country code 3085 * is not stored in system property. 3086 */ shouldSkipCountryCodeDependentTest()3087 private boolean shouldSkipCountryCodeDependentTest() { 3088 String countryCode = SystemProperties.get(BOOT_DEFAULT_WIFI_COUNTRY_CODE); 3089 return TextUtils.isEmpty(countryCode) && !WifiFeature.isTelephonySupported(sContext); 3090 } 3091 3092 /** 3093 * Test SoftApConfiguration#getPersistentRandomizedMacAddress(). There are two test cases in 3094 * this test. 3095 * 1. configure two different SoftApConfigurations (different SSID) and verify that randomized 3096 * MAC address is different. 3097 * 2. configure A then B then A (SSIDs) and verify that the 1st and 3rd MAC addresses are the 3098 * same. 3099 */ 3100 @Test testSoftApConfigurationGetPersistentRandomizedMacAddress()3101 public void testSoftApConfigurationGetPersistentRandomizedMacAddress() throws Exception { 3102 SoftApConfiguration currentConfig = ShellIdentityUtils.invokeWithShellPermissions( 3103 sWifiManager::getSoftApConfiguration); 3104 final String ssid = currentConfig.getSsid().length() <= 28 3105 ? currentConfig.getSsid() + "test" 3106 : "AndroidTest"; 3107 ShellIdentityUtils.invokeWithShellPermissions( 3108 () -> sWifiManager.setSoftApConfiguration(new SoftApConfiguration.Builder() 3109 .setSsid(ssid).build())); 3110 SoftApConfiguration changedSsidConfig = ShellIdentityUtils.invokeWithShellPermissions( 3111 sWifiManager::getSoftApConfiguration); 3112 assertNotEquals(currentConfig.getPersistentRandomizedMacAddress(), 3113 changedSsidConfig.getPersistentRandomizedMacAddress()); 3114 3115 // set currentConfig 3116 ShellIdentityUtils.invokeWithShellPermissions( 3117 () -> sWifiManager.setSoftApConfiguration(currentConfig)); 3118 3119 SoftApConfiguration changedSsidBackConfig = ShellIdentityUtils.invokeWithShellPermissions( 3120 sWifiManager::getSoftApConfiguration); 3121 3122 assertEquals(currentConfig.getPersistentRandomizedMacAddress(), 3123 changedSsidBackConfig.getPersistentRandomizedMacAddress()); 3124 } 3125 3126 /** 3127 * Test bridged AP enable succeeful when device supports it. 3128 * Also verify the callback info update correctly. 3129 * @throws Exception 3130 */ 3131 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 3132 @Test testTetheredBridgedAp()3133 public void testTetheredBridgedAp() throws Exception { 3134 // check that softap bridged mode is supported by the device 3135 if (!sWifiManager.isBridgedApConcurrencySupported()) { 3136 return; 3137 } 3138 runWithScanning(() -> { 3139 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation() 3140 .getUiAutomation(); 3141 TestExecutor executor = new TestExecutor(); 3142 TestSoftApCallback callback = new TestSoftApCallback(mLock); 3143 try { 3144 uiAutomation.adoptShellPermissionIdentity(); 3145 // Off/On Wifi to make sure that we get the supported channel 3146 turnOffWifiAndTetheredHotspotIfEnabled(); 3147 sWifiManager.setWifiEnabled(true); 3148 PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 3149 () -> sWifiManager.isWifiEnabled()); 3150 turnOffWifiAndTetheredHotspotIfEnabled(); 3151 verifyRegisterSoftApCallback(executor, callback); 3152 if (!callback.getCurrentSoftApCapability() 3153 .areFeaturesSupported(SOFTAP_FEATURE_ACS_OFFLOAD)) { 3154 return; 3155 } 3156 int[] testBands = {SoftApConfiguration.BAND_2GHZ, 3157 SoftApConfiguration.BAND_5GHZ}; 3158 int[] expectedBands = {SoftApConfiguration.BAND_2GHZ, 3159 SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ}; 3160 // Test bridged SoftApConfiguration set and get (setBands) 3161 SoftApConfiguration testSoftApConfig = 3162 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 3163 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 3164 .setBands(expectedBands) 3165 .build(); 3166 3167 boolean shouldFallbackToSingleAp = shouldFallbackToSingleAp(testBands, 3168 callback.getCurrentSoftApCapability()); 3169 verifySetGetSoftApConfig(testSoftApConfig); 3170 3171 // start tethering which used to verify startTetheredHotspot 3172 sTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 3173 new TetheringManager.StartTetheringCallback() { 3174 @Override 3175 public void onTetheringFailed(final int result) { 3176 } 3177 }); 3178 verifyBridgedModeSoftApCallback(executor, callback, 3179 shouldFallbackToSingleAp, true /* enabled */); 3180 // stop tethering which used to verify stopSoftAp 3181 sTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 3182 verifyBridgedModeSoftApCallback(executor, callback, 3183 shouldFallbackToSingleAp, false /* disabled */); 3184 } finally { 3185 sWifiManager.unregisterSoftApCallback(callback); 3186 uiAutomation.dropShellPermissionIdentity(); 3187 } 3188 }, false /* run with disabled */); 3189 } 3190 3191 /** 3192 * Test bridged AP with forced channel config enable succeeful when device supports it. 3193 * Also verify the callback info update correctly. 3194 * @throws Exception 3195 */ 3196 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 3197 @Test testTetheredBridgedApWifiForcedChannel()3198 public void testTetheredBridgedApWifiForcedChannel() throws Exception { 3199 // check that softap bridged mode is supported by the device 3200 if (!sWifiManager.isBridgedApConcurrencySupported()) { 3201 return; 3202 } 3203 runWithScanning(() -> { 3204 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation() 3205 .getUiAutomation(); 3206 TestExecutor executor = new TestExecutor(); 3207 TestSoftApCallback callback = new TestSoftApCallback(mLock); 3208 try { 3209 uiAutomation.adoptShellPermissionIdentity(); 3210 // Off/On Wifi to make sure that we get the supported channel 3211 turnOffWifiAndTetheredHotspotIfEnabled(); 3212 sWifiManager.setWifiEnabled(true); 3213 PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 3214 () -> sWifiManager.isWifiEnabled()); 3215 turnOffWifiAndTetheredHotspotIfEnabled(); 3216 verifyRegisterSoftApCallback(executor, callback); 3217 3218 boolean shouldFallbackToSingleAp = shouldFallbackToSingleAp( 3219 new int[] {SoftApConfiguration.BAND_2GHZ, SoftApConfiguration.BAND_5GHZ}, 3220 callback.getCurrentSoftApCapability()); 3221 3222 // Test when there are supported channels in both of the bands. 3223 if (!shouldFallbackToSingleAp) { 3224 // Test bridged SoftApConfiguration set and get (setChannels) 3225 SparseIntArray dual_channels = new SparseIntArray(2); 3226 dual_channels.put(SoftApConfiguration.BAND_2GHZ, 3227 callback.getCurrentSoftApCapability() 3228 .getSupportedChannelList(SoftApConfiguration.BAND_2GHZ)[0]); 3229 dual_channels.put(SoftApConfiguration.BAND_5GHZ, 3230 callback.getCurrentSoftApCapability() 3231 .getSupportedChannelList(SoftApConfiguration.BAND_5GHZ)[0]); 3232 SoftApConfiguration testSoftApConfig = 3233 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 3234 .setPassphrase(TEST_PASSPHRASE, 3235 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 3236 .setChannels(dual_channels) 3237 .build(); 3238 3239 verifySetGetSoftApConfig(testSoftApConfig); 3240 3241 // start tethering which used to verify startTetheredHotspot 3242 sTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 3243 new TetheringManager.StartTetheringCallback() { 3244 @Override 3245 public void onTetheringFailed(final int result) { 3246 } 3247 }); 3248 verifyBridgedModeSoftApCallback(executor, callback, 3249 shouldFallbackToSingleAp, true /* enabled */); 3250 // stop tethering which used to verify stopSoftAp 3251 sTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 3252 verifyBridgedModeSoftApCallback(executor, callback, 3253 shouldFallbackToSingleAp, false /* disabled */); 3254 } 3255 } finally { 3256 sWifiManager.unregisterSoftApCallback(callback); 3257 uiAutomation.dropShellPermissionIdentity(); 3258 } 3259 }, false /* run with disabled */); 3260 } 3261 3262 /** 3263 * Test startTetheringRequest() starts a soft AP and relays the TetheringRequest object back via 3264 * SoftApCallback. 3265 * @throws Exception 3266 */ 3267 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 3268 @Test testStartTetheredHotspotWithTetheringRequest()3269 public void testStartTetheredHotspotWithTetheringRequest() throws Exception { 3270 // check that softap is supported by the device 3271 if (!sWifiManager.isPortableHotspotSupported()) { 3272 return; 3273 } 3274 runWithScanning(() -> { 3275 TestExecutor executor = new TestExecutor(); 3276 TestSoftApCallback callback = new TestSoftApCallback(mLock); 3277 try { 3278 TetheringManager.TetheringRequest request = 3279 new TetheringManager.TetheringRequest.Builder( 3280 TetheringManager.TETHERING_WIFI).build(); 3281 sWifiManager.startTetheredHotspot(request, executor, callback); 3282 fail("startTetheredHotspot succeeded even without NETWORK_STACK permission!"); 3283 } catch (SecurityException e) { 3284 // Expected to fail without NETWORK_STACK 3285 } 3286 }, false /* run with disabled */); 3287 } 3288 3289 /** 3290 * Verify that the configuration from getSoftApConfiguration is same as the configuration which 3291 * set by setSoftApConfiguration. And depends softap capability callback to test different 3292 * configuration. 3293 * @throws Exception 3294 */ 3295 @RequiresDevice 3296 @Test testSetGetSoftApConfigurationAndSoftApCapabilityCallback()3297 public void testSetGetSoftApConfigurationAndSoftApCapabilityCallback() throws Exception { 3298 // check that softap mode is supported by the device 3299 if (!sWifiManager.isPortableHotspotSupported()) { 3300 return; 3301 } 3302 if (shouldSkipCountryCodeDependentTest()) { 3303 // skip the test when there is no Country Code available 3304 return; 3305 } 3306 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3307 TestExecutor executor = new TestExecutor(); 3308 TestSoftApCallback callback = new TestSoftApCallback(mLock); 3309 try { 3310 uiAutomation.adoptShellPermissionIdentity(); 3311 turnOffWifiAndTetheredHotspotIfEnabled(); 3312 verifyRegisterSoftApCallback(executor, callback); 3313 3314 SoftApConfiguration.Builder softApConfigBuilder = 3315 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 3316 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 3317 .setAutoShutdownEnabled(true) 3318 .setShutdownTimeoutMillis(100000) 3319 .setBand(getAvailableBandAndChannelForTesting( 3320 callback.getCurrentSoftApCapability()).keyAt(0)) 3321 .setHiddenSsid(false); 3322 3323 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 3324 softApConfigBuilder.setBridgedModeOpportunisticShutdownTimeoutMillis(30_000); 3325 softApConfigBuilder.setVendorElements(TEST_VENDOR_ELEMENTS); 3326 softApConfigBuilder.setAllowedAcsChannels( 3327 SoftApConfiguration.BAND_2GHZ, new int[] {1, 6, 11}); 3328 softApConfigBuilder.setAllowedAcsChannels( 3329 SoftApConfiguration.BAND_5GHZ, new int[] {149}); 3330 softApConfigBuilder.setAllowedAcsChannels( 3331 SoftApConfiguration.BAND_6GHZ, new int[] {}); 3332 softApConfigBuilder.setMaxChannelBandwidth(SoftApInfo.CHANNEL_WIDTH_80MHZ); 3333 } 3334 3335 if (Flags.androidVWifiApi() 3336 && SdkLevel.isAtLeastV()) { 3337 OuiKeyedData vendorDataElement = 3338 new OuiKeyedData.Builder(0x00112233, new PersistableBundle()).build(); 3339 softApConfigBuilder.setVendorData(Arrays.asList(vendorDataElement)); 3340 } 3341 if (Flags.apIsolate() && WifiBuildCompat.isAtLeastB()) { 3342 softApConfigBuilder.setClientIsolationEnabled(true); 3343 } 3344 // Test SoftApConfiguration set and get 3345 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3346 3347 boolean isSupportCustomizedMac = callback.getCurrentSoftApCapability() 3348 .areFeaturesSupported( 3349 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 3350 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 3351 3352 //Test MAC_ADDRESS_CUSTOMIZATION supported config 3353 if (isSupportCustomizedMac) { 3354 softApConfigBuilder.setBssid(TEST_MAC) 3355 .setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE); 3356 3357 // Test SoftApConfiguration set and get 3358 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3359 } 3360 3361 assertThat(callback.getCurrentSoftApCapability().getMaxSupportedClients()) 3362 .isGreaterThan(0); 3363 // Test CLIENT_FORCE_DISCONNECT supported config. 3364 if (callback.getCurrentSoftApCapability() 3365 .areFeaturesSupported( 3366 SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) { 3367 softApConfigBuilder.setMaxNumberOfClients(10); 3368 softApConfigBuilder.setClientControlByUserEnabled(true); 3369 softApConfigBuilder.setBlockedClientList(new ArrayList<>()); 3370 softApConfigBuilder.setAllowedClientList(new ArrayList<>()); 3371 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3372 } 3373 3374 // Test SAE config 3375 if (callback.getCurrentSoftApCapability() 3376 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) { 3377 softApConfigBuilder 3378 .setPassphrase(TEST_PASSPHRASE, 3379 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); 3380 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3381 softApConfigBuilder 3382 .setPassphrase(TEST_PASSPHRASE, 3383 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); 3384 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3385 } 3386 3387 // Test 11 BE control config 3388 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { 3389 if (callback.getCurrentSoftApCapability() 3390 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE)) { 3391 softApConfigBuilder.setIeee80211beEnabled(true); 3392 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3393 } 3394 } 3395 3396 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 3397 // Test 11 AX control config. 3398 if (callback.getCurrentSoftApCapability() 3399 .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX)) { 3400 softApConfigBuilder.setIeee80211axEnabled(true); 3401 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3402 } 3403 softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled(false); 3404 verifySetGetSoftApConfig(softApConfigBuilder.build()); 3405 } 3406 } finally { 3407 sWifiManager.unregisterSoftApCallback(callback); 3408 uiAutomation.dropShellPermissionIdentity(); 3409 } 3410 } 3411 3412 /** 3413 * Verify that startTetheredHotspot with specific channel config. 3414 * @throws Exception 3415 */ 3416 @RequiresDevice 3417 @Test testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback()3418 public void testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback() 3419 throws Exception { 3420 // check that softap mode is supported by the device 3421 if (!sWifiManager.isPortableHotspotSupported()) { 3422 return; 3423 } 3424 if (shouldSkipCountryCodeDependentTest()) { 3425 // skip the test when there is no Country Code available 3426 return; 3427 } 3428 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3429 TestExecutor executor = new TestExecutor(); 3430 TestSoftApCallback callback = new TestSoftApCallback(mLock); 3431 try { 3432 uiAutomation.adoptShellPermissionIdentity(); 3433 // check that tethering is supported by the device 3434 if (!sTetheringManager.isTetheringSupported()) { 3435 return; 3436 } 3437 turnOffWifiAndTetheredHotspotIfEnabled(); 3438 verifyRegisterSoftApCallback(executor, callback); 3439 3440 SparseIntArray testBandsAndChannels = getAvailableBandAndChannelForTesting( 3441 callback.getCurrentSoftApCapability()); 3442 3443 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 3444 assertNotEquals(0, testBandsAndChannels.size()); 3445 } 3446 boolean isSupportCustomizedMac = callback.getCurrentSoftApCapability() 3447 .areFeaturesSupported( 3448 SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION) 3449 && PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S); 3450 3451 SoftApConfiguration.Builder testSoftApConfigBuilder = 3452 generateSoftApConfigBuilderWithSsid(TEST_SSID_UNQUOTED) 3453 .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) 3454 .setChannel(testBandsAndChannels.valueAt(0), testBandsAndChannels.keyAt(0)); 3455 3456 if (isSupportCustomizedMac) { 3457 testSoftApConfigBuilder.setBssid(TEST_MAC) 3458 .setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE); 3459 } 3460 3461 SoftApConfiguration testSoftApConfig = testSoftApConfigBuilder.build(); 3462 3463 sWifiManager.setSoftApConfiguration(testSoftApConfig); 3464 3465 // start tethering which used to verify startTetheredHotspot 3466 sTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor, 3467 new TetheringManager.StartTetheringCallback() { 3468 @Override 3469 public void onTetheringFailed(final int result) { 3470 } 3471 }); 3472 3473 // Verify state and info callback value as expected 3474 PollingCheck.check( 3475 "SoftAp channel and state mismatch!!!", 10_000, 3476 () -> { 3477 executor.runAll(); 3478 int sapChannel = ScanResult.convertFrequencyMhzToChannelIfSupported( 3479 callback.getCurrentSoftApInfo().getFrequency()); 3480 boolean isInfoCallbackSupported = 3481 callback.getOnSoftapInfoChangedCalledCount() > 1; 3482 if (isInfoCallbackSupported) { 3483 return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState() 3484 && testBandsAndChannels.valueAt(0) == sapChannel; 3485 } 3486 return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState(); 3487 }); 3488 // After Soft Ap enabled, check SoftAp info if it supported 3489 if (isSupportCustomizedMac && callback.getOnSoftapInfoChangedCalledCount() > 1) { 3490 assertEquals(callback.getCurrentSoftApInfo().getBssid(), TEST_MAC); 3491 } 3492 if (PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.S) 3493 && callback.getOnSoftapInfoChangedCalledCount() > 1) { 3494 assertNotEquals(callback.getCurrentSoftApInfo().getWifiStandard(), 3495 ScanResult.WIFI_STANDARD_UNKNOWN); 3496 } 3497 if (Flags.androidVWifiApi() 3498 && SdkLevel.isAtLeastV() 3499 && callback.getOnSoftapInfoChangedCalledCount() > 1) { 3500 assertNotNull(callback.getCurrentSoftApInfo().getVendorData()); 3501 } 3502 3503 if (callback.getOnSoftapInfoChangedCalledCount() > 1) { 3504 assertTrue(callback.getCurrentSoftApInfo().getAutoShutdownTimeoutMillis() > 0); 3505 if (Flags.mloSap()) { 3506 // Test AP configuration is WPA2, MldAddress should be NULL 3507 assertNull(callback.getCurrentSoftApInfo().getMldAddress()); 3508 } 3509 } 3510 } finally { 3511 // stop tethering which used to verify stopSoftAp 3512 sTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 3513 3514 // Verify clean up 3515 PollingCheck.check( 3516 "Stop Softap failed", 3_000, 3517 () -> { 3518 executor.runAll(); 3519 return WifiManager.WIFI_AP_STATE_DISABLED == callback.getCurrentState() && 3520 0 == callback.getCurrentSoftApInfo().getBandwidth() && 3521 0 == callback.getCurrentSoftApInfo().getFrequency(); 3522 }); 3523 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) { 3524 assertEquals(callback.getCurrentSoftApInfo().getBssid(), null); 3525 assertEquals(ScanResult.WIFI_STANDARD_UNKNOWN, 3526 callback.getCurrentSoftApInfo().getWifiStandard()); 3527 } 3528 sWifiManager.unregisterSoftApCallback(callback); 3529 uiAutomation.dropShellPermissionIdentity(); 3530 } 3531 } 3532 3533 private static class TestActionListener implements WifiManager.ActionListener { 3534 private final Object mLock; 3535 public boolean onSuccessCalled = false; 3536 public boolean onFailedCalled = false; 3537 public int failureReason = -1; 3538 TestActionListener(Object lock)3539 TestActionListener(Object lock) { 3540 mLock = lock; 3541 } 3542 3543 @Override onSuccess()3544 public void onSuccess() { 3545 synchronized (mLock) { 3546 onSuccessCalled = true; 3547 mLock.notify(); 3548 } 3549 } 3550 3551 @Override onFailure(int reason)3552 public void onFailure(int reason) { 3553 synchronized (mLock) { 3554 onFailedCalled = true; 3555 failureReason = reason; 3556 mLock.notify(); 3557 } 3558 } 3559 } 3560 3561 /** 3562 * Triggers connection to one of the saved networks using {@link WifiManager#connect( 3563 * int, WifiManager.ActionListener)} or {@link WifiManager#connect(WifiConfiguration, 3564 * WifiManager.ActionListener)} 3565 * 3566 * @param withNetworkId Use networkId for triggering connection, false for using 3567 * WifiConfiguration. 3568 * @throws Exception 3569 */ testConnect(boolean withNetworkId)3570 private void testConnect(boolean withNetworkId) throws Exception { 3571 TestActionListener actionListener = new TestActionListener(mLock); 3572 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3573 List<WifiConfiguration> savedNetworks = null; 3574 try { 3575 uiAutomation.adoptShellPermissionIdentity(); 3576 // These below API's only work with privileged permissions (obtained via shell identity 3577 // for test) 3578 savedNetworks = sWifiManager.getConfiguredNetworks(); 3579 3580 // Disable all the saved networks to trigger disconnect & disable autojoin. 3581 for (WifiConfiguration network : savedNetworks) { 3582 assertTrue(sWifiManager.disableNetwork(network.networkId)); 3583 } 3584 waitForDisconnection(); 3585 3586 // Now trigger connection to the last saved network. 3587 WifiConfiguration savedNetworkToConnect = 3588 savedNetworks.get(savedNetworks.size() - 1); 3589 synchronized (mLock) { 3590 try { 3591 if (withNetworkId) { 3592 sWifiManager.connect(savedNetworkToConnect.networkId, actionListener); 3593 } else { 3594 sWifiManager.connect(savedNetworkToConnect, actionListener); 3595 } 3596 // now wait for callback 3597 mLock.wait(TEST_WAIT_DURATION_MS); 3598 } catch (InterruptedException e) { 3599 } 3600 } 3601 // check if we got the success callback 3602 assertTrue(actionListener.onSuccessCalled); 3603 // Wait for connection to complete & ensure we are connected to the saved network. 3604 waitForConnection(); 3605 assertEquals(savedNetworkToConnect.networkId, 3606 sWifiManager.getConnectionInfo().getNetworkId()); 3607 } finally { 3608 // Re-enable all saved networks before exiting. 3609 if (savedNetworks != null) { 3610 for (WifiConfiguration network : savedNetworks) { 3611 sWifiManager.enableNetwork(network.networkId, true); 3612 } 3613 } 3614 uiAutomation.dropShellPermissionIdentity(); 3615 } 3616 } 3617 3618 /** 3619 * Tests {@link WifiManager#connect(int, WifiManager.ActionListener)} to an existing saved 3620 * network. 3621 */ 3622 @Test testConnectWithNetworkId()3623 public void testConnectWithNetworkId() throws Exception { 3624 testConnect(true); 3625 } 3626 3627 /** 3628 * Tests {@link WifiManager#connect(WifiConfiguration, WifiManager.ActionListener)} to an 3629 * existing saved network. 3630 */ 3631 @Test testConnectWithWifiConfiguration()3632 public void testConnectWithWifiConfiguration() throws Exception { 3633 testConnect(false); 3634 3635 } 3636 3637 private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback { 3638 private final Object mLock; 3639 public boolean onAvailableCalled = false; 3640 public Network network; 3641 public NetworkCapabilities networkCapabilities; 3642 TestNetworkCallback(Object lock)3643 TestNetworkCallback(Object lock) { 3644 mLock = lock; 3645 } 3646 3647 @Override onAvailable(Network network)3648 public void onAvailable(Network network) { 3649 synchronized (mLock) { 3650 onAvailableCalled = true; 3651 this.network = network; 3652 } 3653 } 3654 3655 @Override onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)3656 public void onCapabilitiesChanged(Network network, 3657 NetworkCapabilities networkCapabilities) { 3658 synchronized (mLock) { 3659 this.networkCapabilities = networkCapabilities; 3660 mLock.notify(); 3661 } 3662 } 3663 } 3664 waitForNetworkCallbackAndCheckForMeteredness(boolean expectMetered)3665 private void waitForNetworkCallbackAndCheckForMeteredness(boolean expectMetered) { 3666 Object lock = new Object(); 3667 TestNetworkCallback networkCallbackListener = new TestNetworkCallback(lock); 3668 synchronized (lock) { 3669 try { 3670 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder() 3671 .addTransportType(TRANSPORT_WIFI); 3672 if (expectMetered) { 3673 networkRequestBuilder.removeCapability(NET_CAPABILITY_NOT_METERED); 3674 } else { 3675 networkRequestBuilder.addCapability(NET_CAPABILITY_NOT_METERED); 3676 } 3677 // File a request for wifi network. 3678 sConnectivityManager.registerNetworkCallback( 3679 networkRequestBuilder.build(), networkCallbackListener); 3680 // now wait for callback 3681 lock.wait(TEST_WAIT_DURATION_MS); 3682 } catch (InterruptedException e) { 3683 } 3684 } 3685 assertTrue(networkCallbackListener.onAvailableCalled); 3686 } 3687 3688 /** 3689 * Tests {@link WifiManager#save(WifiConfiguration, WifiManager.ActionListener)} by marking 3690 * an existing saved network metered. 3691 */ 3692 @Test testSave()3693 public void testSave() throws Exception { 3694 Object lock = new Object(); 3695 TestActionListener actionListener = new TestActionListener(lock); 3696 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3697 List<WifiConfiguration> savedNetworks = null; 3698 WifiConfiguration currentConfig = null; 3699 try { 3700 uiAutomation.adoptShellPermissionIdentity(); 3701 // These below API's only work with privileged permissions (obtained via shell identity 3702 // for test) 3703 3704 WifiInfo wifiInfo = sWifiManager.getConnectionInfo(); 3705 savedNetworks = sWifiManager.getConfiguredNetworks(); 3706 3707 // find the current network's WifiConfiguration 3708 currentConfig = savedNetworks 3709 .stream() 3710 .filter(config -> config.networkId == wifiInfo.getNetworkId()) 3711 .findAny() 3712 .get(); 3713 3714 // Ensure that the current network is not metered. 3715 assertNotEquals("Ensure that the saved network is configured as unmetered", 3716 currentConfig.meteredOverride, 3717 WifiConfiguration.METERED_OVERRIDE_METERED); 3718 3719 // Disable all except the currently connected networks to avoid reconnecting to the 3720 // wrong network after later setting the current network as metered. 3721 for (WifiConfiguration network : savedNetworks) { 3722 if (network.networkId != currentConfig.networkId) { 3723 assertTrue(sWifiManager.disableNetwork(network.networkId)); 3724 } 3725 } 3726 3727 // Check the network capabilities to ensure that the network is marked not metered. 3728 waitForNetworkCallbackAndCheckForMeteredness(false); 3729 3730 // Now mark the network metered and save. 3731 synchronized (lock) { 3732 try { 3733 WifiConfiguration modSavedNetwork = new WifiConfiguration(currentConfig); 3734 modSavedNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED; 3735 sWifiManager.save(modSavedNetwork, actionListener); 3736 // now wait for callback 3737 lock.wait(TEST_WAIT_DURATION_MS); 3738 } catch (InterruptedException e) { 3739 } 3740 } 3741 // check if we got the success callback 3742 assertTrue(actionListener.onSuccessCalled); 3743 // Ensure we disconnected on marking the network metered & connect back. 3744 waitForDisconnection(); 3745 waitForConnection(); 3746 // Check the network capabilities to ensure that the network is marked metered now. 3747 waitForNetworkCallbackAndCheckForMeteredness(true); 3748 3749 } finally { 3750 // Restore original network config (restore the meteredness back); 3751 if (currentConfig != null) { 3752 sWifiManager.updateNetwork(currentConfig); 3753 } 3754 // re-enable all networks 3755 if (savedNetworks != null) { 3756 for (WifiConfiguration network : savedNetworks) { 3757 sWifiManager.enableNetwork(network.networkId, true); 3758 } 3759 } 3760 uiAutomation.dropShellPermissionIdentity(); 3761 } 3762 } 3763 3764 /** 3765 * Tests {@link WifiManager#forget(int, WifiManager.ActionListener)} by adding/removing a new 3766 * network. 3767 */ 3768 @AsbSecurityTest(cveBugId = 159373687) 3769 @Test testForget()3770 public void testForget() throws Exception { 3771 TestActionListener actionListener = new TestActionListener(mLock); 3772 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3773 int newNetworkId = INVALID_NETWORK_ID; 3774 try { 3775 uiAutomation.adoptShellPermissionIdentity(); 3776 // These below API's only work with privileged permissions (obtained via shell identity 3777 // for test) 3778 List<WifiConfiguration> savedNetworks = sWifiManager.getConfiguredNetworks(); 3779 3780 WifiConfiguration newOpenNetwork = new WifiConfiguration(); 3781 newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\""; 3782 newNetworkId = sWifiManager.addNetwork(newOpenNetwork); 3783 assertNotEquals(INVALID_NETWORK_ID, newNetworkId); 3784 3785 // Multi-type configurations might be converted to more than 1 configuration. 3786 assertThat(savedNetworks.size() < sWifiManager.getConfiguredNetworks().size()).isTrue(); 3787 3788 // Need an effectively-final holder because we need to modify inner Intent in callback. 3789 class IntentHolder { 3790 Intent intent; 3791 } 3792 IntentHolder intentHolder = new IntentHolder(); 3793 sContext.registerReceiver(new BroadcastReceiver() { 3794 @Override 3795 public void onReceive(Context context, Intent intent) { 3796 Log.i(TAG, "Received CONFIGURED_NETWORKS_CHANGED_ACTION broadcast: " + intent); 3797 intentHolder.intent = intent; 3798 } 3799 }, new IntentFilter(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION)); 3800 3801 // Now remove the network 3802 synchronized (mLock) { 3803 try { 3804 sWifiManager.forget(newNetworkId, actionListener); 3805 // now wait for callback 3806 mLock.wait(TEST_WAIT_DURATION_MS); 3807 } catch (InterruptedException e) { 3808 } 3809 } 3810 // check if we got the success callback 3811 assertTrue(actionListener.onSuccessCalled); 3812 3813 PollingCheck.check( 3814 "Didn't receive CONFIGURED_NETWORKS_CHANGED_ACTION broadcast!", 3815 TEST_WAIT_DURATION_MS, 3816 () -> intentHolder.intent != null); 3817 Intent intent = intentHolder.intent; 3818 assertEquals(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION, intent.getAction()); 3819 assertTrue(intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false)); 3820 assertEquals(WifiManager.CHANGE_REASON_REMOVED, 3821 intent.getIntExtra(WifiManager.EXTRA_CHANGE_REASON, -1)); 3822 assertNull(intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION)); 3823 3824 // Ensure that the new network has been successfully removed. 3825 assertEquals(savedNetworks.size(), sWifiManager.getConfiguredNetworks().size()); 3826 } finally { 3827 // For whatever reason, if the forget fails, try removing using the public remove API. 3828 if (newNetworkId != INVALID_NETWORK_ID) sWifiManager.removeNetwork(newNetworkId); 3829 uiAutomation.dropShellPermissionIdentity(); 3830 } 3831 } 3832 3833 /** 3834 * Tests {@link WifiManager#getFactoryMacAddresses()} returns at least one valid MAC address. 3835 */ 3836 @RequiresDevice 3837 @Test testGetFactoryMacAddresses()3838 public void testGetFactoryMacAddresses() throws Exception { 3839 TestActionListener actionListener = new TestActionListener(mLock); 3840 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 3841 int newNetworkId = INVALID_NETWORK_ID; 3842 try { 3843 uiAutomation.adoptShellPermissionIdentity(); 3844 // Obtain the factory MAC address 3845 String[] macAddresses = sWifiManager.getFactoryMacAddresses(); 3846 assertTrue("At list one MAC address should be returned.", macAddresses.length > 0); 3847 try { 3848 MacAddress mac = MacAddress.fromString(macAddresses[0]); 3849 assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mac); 3850 assertFalse(MacAddressUtils.isMulticastAddress(mac)); 3851 } catch (IllegalArgumentException e) { 3852 fail("Factory MAC address is invalid"); 3853 } 3854 } finally { 3855 uiAutomation.dropShellPermissionIdentity(); 3856 } 3857 } 3858 3859 /** 3860 * Tests {@link WifiManager#isApMacRandomizationSupported()} does not crash. 3861 */ 3862 @Test testIsApMacRandomizationSupported()3863 public void testIsApMacRandomizationSupported() throws Exception { 3864 sWifiManager.isApMacRandomizationSupported(); 3865 } 3866 3867 /** 3868 * Tests {@link WifiManager#isConnectedMacRandomizationSupported()} does not crash. 3869 */ 3870 @Test testIsConnectedMacRandomizationSupported()3871 public void testIsConnectedMacRandomizationSupported() throws Exception { 3872 sWifiManager.isConnectedMacRandomizationSupported(); 3873 } 3874 3875 /** 3876 * Tests {@link WifiManager#isPreferredNetworkOffloadSupported()} does not crash. 3877 */ 3878 @Test testIsPreferredNetworkOffloadSupported()3879 public void testIsPreferredNetworkOffloadSupported() throws Exception { 3880 sWifiManager.isPreferredNetworkOffloadSupported(); 3881 } 3882 3883 /** Test that PNO scans reconnects us when the device is disconnected and the screen is off. */ 3884 @Test testPnoScan()3885 public void testPnoScan() throws Exception { 3886 if (!sWifiManager.isPreferredNetworkOffloadSupported()) { 3887 // skip the test if PNO scanning is not supported 3888 return; 3889 } 3890 3891 WifiInfo currentNetwork = ShellIdentityUtils.invokeWithShellPermissions( 3892 sWifiManager::getConnectionInfo); 3893 3894 // disable all networks that aren't already disabled 3895 List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 3896 sWifiManager::getConfiguredNetworks); 3897 Set<Integer> disabledNetworkIds = new HashSet<>(); 3898 for (WifiConfiguration config : savedNetworks) { 3899 if (config.getNetworkSelectionStatus().getNetworkSelectionDisableReason() 3900 == WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE) { 3901 ShellIdentityUtils.invokeWithShellPermissions( 3902 () -> sWifiManager.disableNetwork(config.networkId)); 3903 disabledNetworkIds.add(config.networkId); 3904 } 3905 } 3906 3907 try { 3908 // wait for disconnection from current network 3909 waitForDisconnection(); 3910 3911 // turn screen off 3912 turnScreenOffNoDelay(); 3913 3914 // re-enable the current network - this will trigger PNO 3915 ShellIdentityUtils.invokeWithShellPermissions( 3916 () -> sWifiManager.enableNetwork(currentNetwork.getNetworkId(), false)); 3917 disabledNetworkIds.remove(currentNetwork.getNetworkId()); 3918 3919 // PNO should reconnect us back to the network we disconnected from 3920 waitForConnection(WIFI_PNO_CONNECT_TIMEOUT_MILLIS); 3921 } finally { 3922 // re-enable disabled networks 3923 for (int disabledNetworkId : disabledNetworkIds) { 3924 ShellIdentityUtils.invokeWithShellPermissions( 3925 () -> sWifiManager.enableNetwork(disabledNetworkId, true)); 3926 } 3927 turnScreenOn(); 3928 } 3929 } 3930 3931 /** 3932 * Tests {@link WifiManager#isStaApConcurrencySupported()}. 3933 */ 3934 @Test testIsStaApConcurrencySupported()3935 public void testIsStaApConcurrencySupported() throws Exception { 3936 // check that softap mode is supported by the device 3937 assumeTrue(sWifiManager.isPortableHotspotSupported()); 3938 // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no 3939 // STA+AP concurrency. 3940 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); 3941 PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled()); 3942 SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); 3943 PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS, 3944 () -> sWifiManager.isWifiEnabled()); 3945 3946 runWithScanning(() -> { 3947 boolean isStaApConcurrencySupported = sWifiManager.isStaApConcurrencySupported(); 3948 // start local only hotspot. 3949 TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); 3950 try { 3951 if (isStaApConcurrencySupported) { 3952 assertTrue(sWifiManager.isWifiEnabled()); 3953 } else { 3954 // no concurrency, wifi should be disabled. 3955 assertFalse(sWifiManager.isWifiEnabled()); 3956 } 3957 } finally { 3958 // clean up local only hotspot no matter if assertion passed or failed 3959 stopLocalOnlyHotspot(callback, true); 3960 } 3961 3962 assertTrue(sWifiManager.isWifiEnabled()); 3963 }, false); 3964 } 3965 3966 /** 3967 * state is a bitset, where bit 0 indicates whether there was data in, and bit 1 indicates 3968 * whether there was data out. Only count down on the latch once there was both data in and out. 3969 */ 3970 private static class TestTrafficStateCallback implements WifiManager.TrafficStateCallback { 3971 public final CountDownLatch latch = new CountDownLatch(1); 3972 private int mAccumulator = 0; 3973 3974 @Override onStateChanged(int state)3975 public void onStateChanged(int state) { 3976 mAccumulator |= state; 3977 if (mAccumulator == DATA_ACTIVITY_INOUT) { 3978 latch.countDown(); 3979 } 3980 } 3981 } 3982 sendTraffic()3983 private void sendTraffic() { 3984 boolean didAnyConnectionSucceed = false; 3985 for (int i = 0; i < 10; i++) { 3986 // Do some network operations 3987 HttpURLConnection connection = null; 3988 try { 3989 URL url = new URL("http://www.google.com/"); 3990 connection = (HttpURLConnection) url.openConnection(); 3991 connection.setInstanceFollowRedirects(false); 3992 connection.setConnectTimeout(TEST_WAIT_DURATION_MS); 3993 connection.setReadTimeout(TEST_WAIT_DURATION_MS); 3994 connection.setUseCaches(false); 3995 InputStream stream = connection.getInputStream(); 3996 byte[] bytes = new byte[100]; 3997 int receivedBytes = stream.read(bytes); 3998 if (receivedBytes > 0) { 3999 didAnyConnectionSucceed = true; 4000 } 4001 } catch (Exception e) { 4002 // ignore 4003 } finally { 4004 if (connection != null) connection.disconnect(); 4005 } 4006 } 4007 assertTrue("All connections failed!", didAnyConnectionSucceed); 4008 } 4009 4010 /** 4011 * Tests {@link WifiManager#registerTrafficStateCallback(Executor, 4012 * WifiManager.TrafficStateCallback)} by sending some traffic. 4013 */ 4014 @Test testTrafficStateCallback()4015 public void testTrafficStateCallback() throws Exception { 4016 TestTrafficStateCallback callback = new TestTrafficStateCallback(); 4017 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4018 try { 4019 uiAutomation.adoptShellPermissionIdentity(); 4020 4021 // Turn screen on for wifi traffic polling. 4022 turnScreenOn(); 4023 sWifiManager.registerTrafficStateCallback( 4024 Executors.newSingleThreadExecutor(), callback); 4025 // Send some traffic to trigger the traffic state change callbacks. 4026 sendTraffic(); 4027 // now wait for callback 4028 boolean success = callback.latch.await(TEST_WAIT_DURATION_MS, TimeUnit.MILLISECONDS); 4029 // check if we got the state changed callback with both data in and out 4030 assertTrue(success); 4031 } finally { 4032 sWifiManager.unregisterTrafficStateCallback(callback); 4033 uiAutomation.dropShellPermissionIdentity(); 4034 } 4035 } 4036 4037 /** 4038 * Tests {@link WifiManager#setScanAlwaysAvailable(boolean)} & 4039 * {@link WifiManager#isScanAlwaysAvailable()}. 4040 */ 4041 @Test testScanAlwaysAvailable()4042 public void testScanAlwaysAvailable() throws Exception { 4043 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4044 Boolean currState = null; 4045 try { 4046 uiAutomation.adoptShellPermissionIdentity(); 4047 currState = sWifiManager.isScanAlwaysAvailable(); 4048 boolean newState = !currState; 4049 sWifiManager.setScanAlwaysAvailable(newState); 4050 PollingCheck.check( 4051 "Wifi scanning toggle failed!", 4052 DURATION_SETTINGS_TOGGLE, 4053 () -> sWifiManager.isScanAlwaysAvailable() == newState); 4054 assertEquals(newState, sWifiManager.isScanAlwaysAvailable()); 4055 } finally { 4056 if (currState != null) sWifiManager.setScanAlwaysAvailable(currState); 4057 uiAutomation.dropShellPermissionIdentity(); 4058 } 4059 } 4060 4061 /** 4062 * Tests {@link WifiManager#setScanThrottleEnabled(boolean)} & 4063 * {@link WifiManager#isScanThrottleEnabled()}. 4064 */ 4065 @Test testScanThrottleEnabled()4066 public void testScanThrottleEnabled() throws Exception { 4067 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4068 Boolean currState = null; 4069 try { 4070 uiAutomation.adoptShellPermissionIdentity(); 4071 currState = sWifiManager.isScanThrottleEnabled(); 4072 boolean newState = !currState; 4073 sWifiManager.setScanThrottleEnabled(newState); 4074 PollingCheck.check( 4075 "Wifi settings toggle failed!", 4076 DURATION_SETTINGS_TOGGLE, 4077 () -> sWifiManager.isScanThrottleEnabled() == newState); 4078 assertEquals(newState, sWifiManager.isScanThrottleEnabled()); 4079 } finally { 4080 if (currState != null) sWifiManager.setScanThrottleEnabled(currState); 4081 uiAutomation.dropShellPermissionIdentity(); 4082 } 4083 } 4084 4085 /** 4086 * Tests {@link WifiManager#setAutoWakeupEnabled(boolean)} & 4087 * {@link WifiManager#isAutoWakeupEnabled()}. 4088 */ 4089 @Test testAutoWakeUpEnabled()4090 public void testAutoWakeUpEnabled() throws Exception { 4091 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4092 Boolean currState = null; 4093 try { 4094 uiAutomation.adoptShellPermissionIdentity(); 4095 currState = sWifiManager.isAutoWakeupEnabled(); 4096 boolean newState = !currState; 4097 sWifiManager.setAutoWakeupEnabled(newState); 4098 PollingCheck.check( 4099 "Wifi settings toggle failed!", 4100 DURATION_SETTINGS_TOGGLE, 4101 () -> sWifiManager.isAutoWakeupEnabled() == newState); 4102 assertEquals(newState, sWifiManager.isAutoWakeupEnabled()); 4103 } finally { 4104 if (currState != null) sWifiManager.setAutoWakeupEnabled(currState); 4105 uiAutomation.dropShellPermissionIdentity(); 4106 } 4107 } 4108 4109 /** 4110 * Tests {@link WifiManager#setVerboseLoggingEnabled(boolean)} & 4111 * {@link WifiManager#isVerboseLoggingEnabled()}. 4112 */ 4113 @Test testVerboseLoggingEnabled()4114 public void testVerboseLoggingEnabled() throws Exception { 4115 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4116 Boolean currState = null; 4117 TestWifiVerboseLoggingStatusChangedListener listener = 4118 WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext) 4119 ? new TestWifiVerboseLoggingStatusChangedListener() : null; 4120 try { 4121 uiAutomation.adoptShellPermissionIdentity(); 4122 if (listener != null) { 4123 sWifiManager.addWifiVerboseLoggingStatusChangedListener(mExecutor, listener); 4124 } 4125 currState = sWifiManager.isVerboseLoggingEnabled(); 4126 boolean newState = !currState; 4127 if (listener != null) { 4128 assertEquals(0, listener.numCalls); 4129 } 4130 sWifiManager.setVerboseLoggingEnabled(newState); 4131 PollingCheck.check( 4132 "Wifi verbose logging toggle failed!", 4133 DURATION_SETTINGS_TOGGLE, 4134 () -> sWifiManager.isVerboseLoggingEnabled() == newState); 4135 if (listener != null) { 4136 PollingCheck.check( 4137 "Verbose logging listener timeout", 4138 DURATION_SETTINGS_TOGGLE, 4139 () -> listener.status == newState && listener.numCalls == 1); 4140 } 4141 } finally { 4142 if (currState != null) sWifiManager.setVerboseLoggingEnabled(currState); 4143 if (listener != null) { 4144 sWifiManager.removeWifiVerboseLoggingStatusChangedListener(listener); 4145 } 4146 uiAutomation.dropShellPermissionIdentity(); 4147 } 4148 } 4149 4150 /** 4151 * Tests {@link WifiManager#setVerboseLoggingLevel(int)}. 4152 */ 4153 @Test testSetVerboseLogging()4154 public void testSetVerboseLogging() throws Exception { 4155 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4156 Boolean currState = null; 4157 try { 4158 uiAutomation.adoptShellPermissionIdentity(); 4159 currState = sWifiManager.isVerboseLoggingEnabled(); 4160 4161 sWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); 4162 assertTrue(sWifiManager.isVerboseLoggingEnabled()); 4163 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED, 4164 sWifiManager.getVerboseLoggingLevel()); 4165 4166 sWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED); 4167 assertFalse(sWifiManager.isVerboseLoggingEnabled()); 4168 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED, 4169 sWifiManager.getVerboseLoggingLevel()); 4170 } finally { 4171 if (currState != null) sWifiManager.setVerboseLoggingEnabled(currState); 4172 uiAutomation.dropShellPermissionIdentity(); 4173 } 4174 } 4175 4176 /** 4177 * Test {@link WifiManager#setVerboseLoggingLevel(int)} for show key mode. 4178 */ 4179 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 4180 @Test testSetVerboseLoggingShowKeyModeNonUserBuild()4181 public void testSetVerboseLoggingShowKeyModeNonUserBuild() throws Exception { 4182 if (Build.TYPE.equals("user")) return; 4183 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4184 Boolean currState = null; 4185 try { 4186 uiAutomation.adoptShellPermissionIdentity(); 4187 currState = sWifiManager.isVerboseLoggingEnabled(); 4188 4189 sWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY); 4190 assertTrue(sWifiManager.isVerboseLoggingEnabled()); 4191 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 4192 sWifiManager.getVerboseLoggingLevel()); 4193 } finally { 4194 if (currState != null) sWifiManager.setVerboseLoggingEnabled(currState); 4195 uiAutomation.dropShellPermissionIdentity(); 4196 } 4197 } 4198 4199 /** 4200 * Test {@link WifiManager#setVerboseLoggingLevel(int)} for show key mode. 4201 */ 4202 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 4203 @Test testSetVerboseLoggingShowKeyModeUserBuild()4204 public void testSetVerboseLoggingShowKeyModeUserBuild() throws Exception { 4205 if (!Build.TYPE.equals("user")) return; 4206 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4207 Boolean currState = null; 4208 try { 4209 uiAutomation.adoptShellPermissionIdentity(); 4210 currState = sWifiManager.isVerboseLoggingEnabled(); 4211 4212 sWifiManager.setVerboseLoggingLevel(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY); 4213 assertTrue(sWifiManager.isVerboseLoggingEnabled()); 4214 assertEquals(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 4215 sWifiManager.getVerboseLoggingLevel()); 4216 fail("Verbosing logging show key mode should not be allowed for user build."); 4217 } catch (SecurityException e) { 4218 // expected 4219 } finally { 4220 if (currState != null) sWifiManager.setVerboseLoggingEnabled(currState); 4221 uiAutomation.dropShellPermissionIdentity(); 4222 } 4223 } 4224 4225 /** 4226 * Tests {@link WifiManager#factoryReset()} cannot be invoked from a non-privileged app. 4227 * 4228 * Note: This intentionally does not test the full reset functionality because it causes 4229 * the existing saved networks on the device to be lost after the test. If you add the 4230 * networks back after reset, the ownership of saved networks will change. 4231 */ 4232 @Test testFactoryReset()4233 public void testFactoryReset() throws Exception { 4234 List<WifiConfiguration> beforeSavedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 4235 sWifiManager::getConfiguredNetworks); 4236 try { 4237 sWifiManager.factoryReset(); 4238 fail("Factory reset should not be allowed for non-privileged apps"); 4239 } catch (SecurityException e) { 4240 // expected 4241 } 4242 List<WifiConfiguration> afterSavedNetworks = ShellIdentityUtils.invokeWithShellPermissions( 4243 sWifiManager::getConfiguredNetworks); 4244 assertEquals(beforeSavedNetworks.size(), afterSavedNetworks.size()); 4245 } 4246 4247 /** 4248 * Test {@link WifiNetworkConnectionStatistics} does not crash. 4249 * TODO(b/150891569): deprecate it in Android S, this API is not used anywhere. 4250 */ 4251 @Test testWifiNetworkConnectionStatistics()4252 public void testWifiNetworkConnectionStatistics() { 4253 new WifiNetworkConnectionStatistics(); 4254 WifiNetworkConnectionStatistics stats = new WifiNetworkConnectionStatistics(0, 0); 4255 new WifiNetworkConnectionStatistics(stats); 4256 } 4257 4258 /** 4259 * Verify that startRestrictingAutoJoinToSubscriptionId disconnects wifi and disables 4260 * auto-connect to non-carrier-merged networks. Then verify that 4261 * stopRestrictingAutoJoinToSubscriptionId makes the disabled networks clear to connect 4262 * again. 4263 */ 4264 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 4265 @Test testStartAndStopRestrictingAutoJoinToSubscriptionId()4266 public void testStartAndStopRestrictingAutoJoinToSubscriptionId() throws Exception { 4267 int fakeSubscriptionId = 5; 4268 ShellIdentityUtils.invokeWithShellPermissions(() -> 4269 sWifiManager.startRestrictingAutoJoinToSubscriptionId(fakeSubscriptionId)); 4270 waitForDisconnection(); 4271 startScan(); 4272 ensureNotConnected(); 4273 ShellIdentityUtils.invokeWithShellPermissions(() -> 4274 sWifiManager.stopRestrictingAutoJoinToSubscriptionId()); 4275 startScan(); 4276 waitForConnection(); 4277 } 4278 4279 private class TestActiveCountryCodeChangedCallback implements 4280 WifiManager.ActiveCountryCodeChangedCallback { 4281 private String mCurrentCountryCode; 4282 private boolean mIsOnActiveCountryCodeChangedCalled = false; 4283 private boolean mIsOnCountryCodeInactiveCalled = false; 4284 isOnActiveCountryCodeChangedCalled()4285 public boolean isOnActiveCountryCodeChangedCalled() { 4286 return mIsOnActiveCountryCodeChangedCalled; 4287 } 4288 isOnCountryCodeInactiveCalled()4289 public boolean isOnCountryCodeInactiveCalled() { 4290 return mIsOnCountryCodeInactiveCalled; 4291 } resetCallbackCallededHistory()4292 public void resetCallbackCallededHistory() { 4293 mIsOnActiveCountryCodeChangedCalled = false; 4294 mIsOnCountryCodeInactiveCalled = false; 4295 } 4296 getCurrentDriverCountryCode()4297 public String getCurrentDriverCountryCode() { 4298 return mCurrentCountryCode; 4299 } 4300 4301 @Override onActiveCountryCodeChanged(String country)4302 public void onActiveCountryCodeChanged(String country) { 4303 Log.d(TAG, "Receive DriverCountryCodeChanged to " + country); 4304 mCurrentCountryCode = country; 4305 mIsOnActiveCountryCodeChangedCalled = true; 4306 } 4307 4308 @Override onCountryCodeInactive()4309 public void onCountryCodeInactive() { 4310 Log.d(TAG, "Receive onCountryCodeInactive"); 4311 mCurrentCountryCode = null; 4312 mIsOnCountryCodeInactiveCalled = true; 4313 } 4314 } 4315 4316 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 4317 @Test testActiveCountryCodeChangedCallback()4318 public void testActiveCountryCodeChangedCallback() throws Exception { 4319 if (!hasLocationFeature()) { 4320 // skip the test if location is not supported 4321 return; 4322 } 4323 if (!isLocationEnabled()) { 4324 fail("Please enable location for this test - since country code is not available" 4325 + " when location is disabled!"); 4326 } 4327 if (shouldSkipCountryCodeDependentTest()) { 4328 // skip the test when there is no Country Code available 4329 return; 4330 } 4331 if (!PropertyUtil.isVndkApiLevelAtLeast(Build.VERSION_CODES.TIRAMISU)) { 4332 // skip the test if vendor version is lower than T 4333 return; 4334 } 4335 TestActiveCountryCodeChangedCallback testCountryCodeChangedCallback = 4336 new TestActiveCountryCodeChangedCallback(); 4337 TestExecutor executor = new TestExecutor(); 4338 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4339 try { 4340 // Run with scanning disable to make sure there is no active mode. 4341 runWithScanning(() -> { 4342 uiAutomation.adoptShellPermissionIdentity(); 4343 turnOffWifiAndTetheredHotspotIfEnabled(); 4344 sWifiManager.registerActiveCountryCodeChangedCallback( 4345 executor, testCountryCodeChangedCallback); 4346 4347 4348 PollingCheck.check( 4349 "DriverCountryCode is non-null when wifi off", 4350 5000, 4351 () -> { 4352 executor.runAll(); 4353 return testCountryCodeChangedCallback 4354 .isOnCountryCodeInactiveCalled() 4355 && testCountryCodeChangedCallback.getCurrentDriverCountryCode() 4356 == null; 4357 }); 4358 // Enable wifi to make sure country code has been updated. 4359 sWifiManager.setWifiEnabled(true); 4360 PollingCheck.check( 4361 "DriverCountryCode is null when wifi on", 4362 5000, 4363 () -> { 4364 executor.runAll(); 4365 return testCountryCodeChangedCallback 4366 .isOnActiveCountryCodeChangedCalled() 4367 && testCountryCodeChangedCallback.getCurrentDriverCountryCode() 4368 != null; 4369 }); 4370 // Disable wifi to trigger country code change 4371 sWifiManager.setWifiEnabled(false); 4372 PollingCheck.check( 4373 "DriverCountryCode should be null when wifi off", 4374 5000, 4375 () -> { 4376 executor.runAll(); 4377 return testCountryCodeChangedCallback.isOnCountryCodeInactiveCalled() 4378 && testCountryCodeChangedCallback 4379 .getCurrentDriverCountryCode() == null; 4380 }); 4381 sWifiManager.unregisterActiveCountryCodeChangedCallback( 4382 testCountryCodeChangedCallback); 4383 testCountryCodeChangedCallback.resetCallbackCallededHistory(); 4384 sWifiManager.setWifiEnabled(true); 4385 // Check there is no callback has been called. 4386 PollingCheck.check( 4387 "Callback is called after unregister", 4388 5000, 4389 () -> { 4390 executor.runAll(); 4391 return !testCountryCodeChangedCallback.isOnCountryCodeInactiveCalled() 4392 && !testCountryCodeChangedCallback 4393 .isOnActiveCountryCodeChangedCalled(); 4394 }); 4395 }, false /* Run with disabled */); 4396 } finally { 4397 uiAutomation.dropShellPermissionIdentity(); 4398 } 4399 } 4400 4401 /** 4402 * Test that the wifi country code is either null, or a length-2 string. 4403 */ 4404 @Test testGetCountryCode()4405 public void testGetCountryCode() throws Exception { 4406 String wifiCountryCode = ShellIdentityUtils.invokeWithShellPermissions( 4407 sWifiManager::getCountryCode); 4408 4409 if (wifiCountryCode == null) { 4410 return; 4411 } 4412 assertEquals(2, wifiCountryCode.length()); 4413 4414 // assert that the country code is all uppercase 4415 assertEquals(wifiCountryCode.toUpperCase(Locale.US), wifiCountryCode); 4416 4417 // skip if Telephony is unsupported 4418 if (!WifiFeature.isTelephonySupported(sContext)) { 4419 return; 4420 } 4421 4422 String telephonyCountryCode = sContext.getSystemService(TelephonyManager.class) 4423 .getNetworkCountryIso(); 4424 4425 // skip if Telephony country code is unavailable 4426 if (telephonyCountryCode == null || telephonyCountryCode.isEmpty()) { 4427 return; 4428 } 4429 4430 assertEquals(telephonyCountryCode, wifiCountryCode.toLowerCase(Locale.US)); 4431 } 4432 4433 /** 4434 * Helper function to test getCurrentNetwork 4435 * @param shouldDisableWifi true to disable wifi, false to disconnect 4436 * @throws Exception 4437 */ testGetCurrentNetwork(boolean shouldDisableWifi)4438 private void testGetCurrentNetwork(boolean shouldDisableWifi) throws Exception { 4439 // ensure Wifi is connected 4440 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.reconnect()); 4441 PollingCheck.check( 4442 "Connection info network id is invalid - Please ensure there is a " + 4443 " saved network in range of this device", 4444 WIFI_CONNECT_TIMEOUT_MILLIS, 4445 () -> sWifiManager.getConnectionInfo().getNetworkId() != -1); 4446 PollingCheck.check( 4447 "Wifi current network is null - Please ensure there is a saved network " + 4448 " in range of this device", 4449 WIFI_CONNECT_TIMEOUT_MILLIS, 4450 () -> ShellIdentityUtils.invokeWithShellPermissions(sWifiManager::getCurrentNetwork) 4451 != null); 4452 4453 String networkKey = sWifiManager.getConnectionInfo().getNetworkKey(); 4454 assertNotNull(networkKey); 4455 4456 Network wifiCurrentNetwork = ShellIdentityUtils.invokeWithShellPermissions( 4457 sWifiManager::getCurrentNetwork); 4458 assertNotNull(wifiCurrentNetwork); 4459 4460 List<WifiConfiguration> configuredNetwork = ShellIdentityUtils.invokeWithShellPermissions( 4461 sWifiManager::getConfiguredNetworks); 4462 4463 boolean isNetworkKeyExist = false; 4464 for (WifiConfiguration config : configuredNetwork) { 4465 if (config.getAllNetworkKeys().contains(networkKey)) { 4466 isNetworkKeyExist = true; 4467 break; 4468 } 4469 } 4470 4471 assertTrue(isNetworkKeyExist); 4472 4473 TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock); 4474 synchronized (mLock) { 4475 try { 4476 // File a request for wifi network. 4477 sConnectivityManager.registerNetworkCallback( 4478 new NetworkRequest.Builder() 4479 .addTransportType(TRANSPORT_WIFI) 4480 .build(), 4481 networkCallbackListener); 4482 // now wait for callback 4483 mLock.wait(TEST_WAIT_DURATION_MS); 4484 } catch (InterruptedException e) { 4485 } 4486 } 4487 assertTrue(networkCallbackListener.onAvailableCalled); 4488 Network connectivityCurrentNetwork = networkCallbackListener.network; 4489 assertEquals(connectivityCurrentNetwork, wifiCurrentNetwork); 4490 4491 if (shouldDisableWifi) { 4492 setWifiEnabled(false); 4493 PollingCheck.check( 4494 "Wifi not disabled!", 4495 20000, 4496 () -> !sWifiManager.isWifiEnabled()); 4497 } else { 4498 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.disconnect()); 4499 } 4500 PollingCheck.check( 4501 "Wifi not disconnected! Connection info network id still valid", 4502 20000, 4503 () -> sWifiManager.getConnectionInfo().getNetworkId() == -1); 4504 4505 PollingCheck.check( 4506 "Wifi not disconnected! Current network is not null", 4507 WIFI_CONNECT_TIMEOUT_MILLIS, 4508 () -> ShellIdentityUtils.invokeWithShellPermissions(sWifiManager::getCurrentNetwork) 4509 == null); 4510 } 4511 4512 /** 4513 * Test that {@link WifiManager#getCurrentNetwork()} returns a Network object consistent 4514 * with {@link ConnectivityManager#registerNetworkCallback} when connected to a Wifi network, 4515 * and returns null when disconnected. 4516 */ 4517 @Test testGetCurrentNetworkWifiDisconnected()4518 public void testGetCurrentNetworkWifiDisconnected() throws Exception { 4519 testGetCurrentNetwork(false); 4520 } 4521 4522 /** 4523 * Test that {@link WifiManager#getCurrentNetwork()} returns a Network object consistent 4524 * with {@link ConnectivityManager#registerNetworkCallback} when connected to a Wifi network, 4525 * and returns null when wifi disabled. 4526 */ 4527 @Test testGetCurrentNetworkWifiDisabled()4528 public void testGetCurrentNetworkWifiDisabled() throws Exception { 4529 testGetCurrentNetwork(true); 4530 } 4531 4532 /** 4533 * Tests {@link WifiManager#isWpa3SaeSupported()} does not crash. 4534 */ 4535 @Test testIsWpa3SaeSupported()4536 public void testIsWpa3SaeSupported() throws Exception { 4537 sWifiManager.isWpa3SaeSupported(); 4538 } 4539 4540 /** 4541 * Tests {@link WifiManager#isWpa3SuiteBSupported()} does not crash. 4542 */ 4543 @Test testIsWpa3SuiteBSupported()4544 public void testIsWpa3SuiteBSupported() throws Exception { 4545 sWifiManager.isWpa3SuiteBSupported(); 4546 } 4547 4548 /** 4549 * Tests {@link WifiManager#isEnhancedOpenSupported()} does not crash. 4550 */ 4551 @Test testIsEnhancedOpenSupported()4552 public void testIsEnhancedOpenSupported() throws Exception { 4553 sWifiManager.isEnhancedOpenSupported(); 4554 } 4555 4556 /** 4557 * Test that {@link WifiManager#is5GHzBandSupported()} returns successfully in 4558 * both WiFi enabled/disabled states. 4559 * Note that the response depends on device support and hence both true/false 4560 * are valid responses. 4561 */ 4562 @Test testIs5GhzBandSupported()4563 public void testIs5GhzBandSupported() throws Exception { 4564 // Check for 5GHz support with wifi enabled 4565 setWifiEnabled(true); 4566 PollingCheck.check( 4567 "Wifi not enabled!", 4568 20000, 4569 () -> sWifiManager.isWifiEnabled()); 4570 boolean isSupportedEnabled = sWifiManager.is5GHzBandSupported(); 4571 4572 // Check for 5GHz support with wifi disabled 4573 setWifiEnabled(false); 4574 PollingCheck.check( 4575 "Wifi not disabled!", 4576 20000, 4577 () -> !sWifiManager.isWifiEnabled()); 4578 boolean isSupportedDisabled = sWifiManager.is5GHzBandSupported(); 4579 4580 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 4581 // Note, the reverse is a valid case. 4582 if (isSupportedDisabled) { 4583 assertTrue(isSupportedEnabled); 4584 } 4585 } 4586 4587 /** 4588 * Test that {@link WifiManager#is6GHzBandSupported()} returns successfully in 4589 * both Wifi enabled/disabled states. 4590 * Note that the response depends on device support and hence both true/false 4591 * are valid responses. 4592 */ 4593 @Test testIs6GhzBandSupported()4594 public void testIs6GhzBandSupported() throws Exception { 4595 // Check for 6GHz support with wifi enabled 4596 setWifiEnabled(true); 4597 PollingCheck.check( 4598 "Wifi not enabled!", 4599 20000, 4600 () -> sWifiManager.isWifiEnabled()); 4601 boolean isSupportedEnabled = sWifiManager.is6GHzBandSupported(); 4602 4603 // Check for 6GHz support with wifi disabled 4604 setWifiEnabled(false); 4605 PollingCheck.check( 4606 "Wifi not disabled!", 4607 20000, 4608 () -> !sWifiManager.isWifiEnabled()); 4609 boolean isSupportedDisabled = sWifiManager.is6GHzBandSupported(); 4610 4611 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 4612 // Note, the reverse is a valid case. 4613 if (isSupportedDisabled) { 4614 assertTrue(isSupportedEnabled); 4615 } 4616 } 4617 4618 /** 4619 * Test that {@link WifiManager#is60GHzBandSupported()} returns successfully in 4620 * both Wifi enabled/disabled states. 4621 * Note that the response depends on device support and hence both true/false 4622 * are valid responses. 4623 */ 4624 @Test testIs60GhzBandSupported()4625 public void testIs60GhzBandSupported() throws Exception { 4626 if (!(WifiFeature.isWifiSupported(sContext) 4627 && ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S))) { 4628 // skip the test if WiFi is not supported 4629 return; 4630 } 4631 4632 // Check for 60GHz support with wifi enabled 4633 setWifiEnabled(true); 4634 PollingCheck.check( 4635 "Wifi not enabled!", 4636 20000, 4637 () -> sWifiManager.isWifiEnabled()); 4638 boolean isSupportedEnabled = sWifiManager.is60GHzBandSupported(); 4639 4640 // Check for 60GHz support with wifi disabled 4641 setWifiEnabled(false); 4642 PollingCheck.check( 4643 "Wifi not disabled!", 4644 20000, 4645 () -> !sWifiManager.isWifiEnabled()); 4646 boolean isSupportedDisabled = sWifiManager.is60GHzBandSupported(); 4647 4648 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 4649 // Note, the reverse is a valid case. 4650 if (isSupportedDisabled) { 4651 assertTrue(isSupportedEnabled); 4652 } 4653 } 4654 4655 /** 4656 * Test that {@link WifiManager#isWifiStandardSupported()} returns successfully in 4657 * both Wifi enabled/disabled states. The test is to be performed on 4658 * {@link WifiAnnotations}'s {@code WIFI_STANDARD_} 4659 * Note that the response depends on device support and hence both true/false 4660 * are valid responses. 4661 */ 4662 @Test testIsWifiStandardsSupported()4663 public void testIsWifiStandardsSupported() throws Exception { 4664 // Check for WiFi standards support with wifi enabled 4665 setWifiEnabled(true); 4666 PollingCheck.check( 4667 "Wifi not enabled!", 4668 20000, 4669 () -> sWifiManager.isWifiEnabled()); 4670 boolean isLegacySupportedEnabled = 4671 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY); 4672 boolean is11nSupporedEnabled = 4673 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N); 4674 boolean is11acSupportedEnabled = 4675 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC); 4676 boolean is11axSupportedEnabled = 4677 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX); 4678 boolean is11beSupportedEnabled = 4679 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE); 4680 4681 // Check for WiFi standards support with wifi disabled 4682 setWifiEnabled(false); 4683 PollingCheck.check( 4684 "Wifi not disabled!", 4685 20000, 4686 () -> !sWifiManager.isWifiEnabled()); 4687 4688 boolean isLegacySupportedDisabled = 4689 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY); 4690 boolean is11nSupportedDisabled = 4691 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N); 4692 boolean is11acSupportedDisabled = 4693 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC); 4694 boolean is11axSupportedDisabled = 4695 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX); 4696 boolean is11beSupportedDisabled = 4697 sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE); 4698 4699 if (isLegacySupportedDisabled) { 4700 assertTrue(isLegacySupportedEnabled); 4701 } 4702 4703 if (is11nSupportedDisabled) { 4704 assertTrue(is11nSupporedEnabled); 4705 } 4706 4707 if (is11acSupportedDisabled) { 4708 assertTrue(is11acSupportedEnabled); 4709 } 4710 4711 if (is11axSupportedDisabled) { 4712 assertTrue(is11axSupportedEnabled); 4713 } 4714 4715 if (is11beSupportedDisabled) { 4716 assertTrue(is11beSupportedEnabled); 4717 } 4718 } 4719 createPasspointConfiguration()4720 private static PasspointConfiguration createPasspointConfiguration() { 4721 PasspointConfiguration config = new PasspointConfiguration(); 4722 HomeSp homeSp = new HomeSp(); 4723 homeSp.setFqdn("test.com"); 4724 homeSp.setFriendlyName("friendly name"); 4725 homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66}); 4726 config.setHomeSp(homeSp); 4727 Credential.SimCredential simCred = new Credential.SimCredential(); 4728 simCred.setImsi("123456*"); 4729 simCred.setEapType(23 /* EAP_AKA */); 4730 Credential cred = new Credential(); 4731 cred.setRealm("realm"); 4732 cred.setSimCredential(simCred); 4733 config.setCredential(cred); 4734 4735 return config; 4736 } 4737 4738 /** 4739 * Tests {@link WifiManager#addOrUpdatePasspointConfiguration(PasspointConfiguration)} 4740 * adds a Passpoint configuration correctly by getting it once it is added, and comparing it 4741 * to the local copy of the configuration. 4742 */ 4743 @Test testAddOrUpdatePasspointConfiguration()4744 public void testAddOrUpdatePasspointConfiguration() throws Exception { 4745 // Create and install a Passpoint configuration 4746 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 4747 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4748 try { 4749 uiAutomation.adoptShellPermissionIdentity(); 4750 sWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 4751 4752 // Compare configurations 4753 List<PasspointConfiguration> configurations = sWifiManager.getPasspointConfigurations(); 4754 assertNotNull("The installed passpoint profile is missing", configurations); 4755 assertEquals(passpointConfiguration, getTargetPasspointConfiguration(configurations, 4756 passpointConfiguration.getUniqueId())); 4757 } finally { 4758 // Clean up 4759 sWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn()); 4760 uiAutomation.dropShellPermissionIdentity(); 4761 } 4762 } 4763 4764 /** 4765 * Tests {@link WifiManager#setPasspointMeteredOverride(String, int)} 4766 * adds a Passpoint configuration correctly, check the default metered setting. Use API change 4767 * metered override, verify Passpoint configuration changes with it. 4768 */ 4769 @Test testSetPasspointMeteredOverride()4770 public void testSetPasspointMeteredOverride() throws Exception { 4771 // Create and install a Passpoint configuration 4772 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 4773 String fqdn = passpointConfiguration.getHomeSp().getFqdn(); 4774 String uniqueId = passpointConfiguration.getUniqueId(); 4775 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4776 4777 try { 4778 uiAutomation.adoptShellPermissionIdentity(); 4779 sWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 4780 PasspointConfiguration saved = getTargetPasspointConfiguration( 4781 sWifiManager.getPasspointConfigurations(), uniqueId); 4782 assertNotNull("The installed passpoint profile is missing", saved); 4783 // Verify meter override setting. 4784 assertEquals("Metered overrider default should be none", 4785 WifiConfiguration.METERED_OVERRIDE_NONE, saved.getMeteredOverride()); 4786 // Change the meter override setting. 4787 sWifiManager.setPasspointMeteredOverride(fqdn, 4788 WifiConfiguration.METERED_OVERRIDE_METERED); 4789 // Verify passpoint config change with the new setting. 4790 saved = getTargetPasspointConfiguration( 4791 sWifiManager.getPasspointConfigurations(), uniqueId); 4792 assertNotNull("The installed passpoint profile is missing", saved); 4793 assertEquals("Metered override should be metered", 4794 WifiConfiguration.METERED_OVERRIDE_METERED, saved.getMeteredOverride()); 4795 } finally { 4796 // Clean up 4797 sWifiManager.removePasspointConfiguration(fqdn); 4798 uiAutomation.dropShellPermissionIdentity(); 4799 } 4800 } 4801 4802 /** 4803 * Tests that 4804 * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, Executor, ProvisioningCallback)} 4805 * starts a subscription provisioning, and confirm a status callback invoked once. 4806 */ 4807 @Test testStartSubscriptionProvisioning()4808 public void testStartSubscriptionProvisioning() throws Exception { 4809 // Using Java reflection to construct an OsuProvider instance because its constructor is 4810 // hidden and not available to apps. 4811 Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider"); 4812 Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class, 4813 Map.class, String.class, Uri.class, String.class, List.class); 4814 4815 OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID, 4816 TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, 4817 TEST_METHOD_LIST); 4818 TestProvisioningCallback callback = new TestProvisioningCallback(mLock); 4819 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 4820 try { 4821 uiAutomation.adoptShellPermissionIdentity(); 4822 synchronized (mLock) { 4823 // Start a subscription provisioning for a non-existent Passpoint R2 AP 4824 sWifiManager.startSubscriptionProvisioning(osuProvider, mExecutor, callback); 4825 mLock.wait(TEST_WAIT_DURATION_MS); 4826 } 4827 } finally { 4828 uiAutomation.dropShellPermissionIdentity(); 4829 } 4830 waitForDisconnection(); 4831 // Expect only a single callback event, connecting. Since AP doesn't exist, it ends here 4832 assertEquals(ProvisioningCallback.OSU_STATUS_AP_CONNECTING, callback.mProvisioningStatus); 4833 // No failure callbacks expected 4834 assertEquals(0, callback.mProvisioningFailureStatus); 4835 // No completion callback expected 4836 assertFalse(callback.mProvisioningComplete); 4837 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); 4838 PollingCheck.check("Wifi not disabled!", 20000, 4839 () -> !sWifiManager.isWifiEnabled()); 4840 } 4841 4842 /** 4843 * Tests {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} does not crash. 4844 */ 4845 @Test testSetTdlsEnabled()4846 public void testSetTdlsEnabled() throws Exception { 4847 InetAddress inetAddress = InetAddress.getByName(TEST_IP_ADDRESS); 4848 4849 sWifiManager.setTdlsEnabled(inetAddress, true); 4850 Thread.sleep(50); 4851 sWifiManager.setTdlsEnabled(inetAddress, false); 4852 } 4853 4854 /** 4855 * Tests {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} does not crash. 4856 */ 4857 @Test testSetTdlsEnabledWithMacAddress()4858 public void testSetTdlsEnabledWithMacAddress() throws Exception { 4859 sWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, true); 4860 Thread.sleep(50); 4861 sWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, false); 4862 } 4863 4864 /** 4865 * Verify the usage of {@code WifiManager#isTdlsOperationCurrentlyAvailable}. 4866 */ 4867 @Test testIsTdlsOperationCurrentlyAvailable()4868 public void testIsTdlsOperationCurrentlyAvailable() throws Exception { 4869 boolean expectedResult = sWifiManager.isTdlsSupported(); 4870 AtomicBoolean enabled = new AtomicBoolean(false); 4871 sWifiManager.isTdlsOperationCurrentlyAvailable(mExecutor, 4872 (enabledLocal) -> { 4873 synchronized (mLock) { 4874 enabled.set(enabledLocal); 4875 mLock.notify(); 4876 } 4877 }); 4878 synchronized (mLock) { 4879 mLock.wait(TEST_WAIT_DURATION_MS); 4880 } 4881 assertEquals(expectedResult, enabled.get()); 4882 } 4883 4884 /** 4885 * Verify the usage of {@code WifiManager#getMaxSupportedConcurrentTdlsSessions}. 4886 */ 4887 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 4888 @Test testGetMaxSupportedConcurrentTdlsSessions()4889 public void testGetMaxSupportedConcurrentTdlsSessions() throws Exception { 4890 if (!sWifiManager.isTdlsSupported()) { 4891 // skip the test if TDLS is not supported 4892 return; 4893 } 4894 4895 AtomicInteger maxNumOfTdlsSessions = new AtomicInteger(0); 4896 sWifiManager.getMaxSupportedConcurrentTdlsSessions(mExecutor, 4897 (maxNumOfTdlsSessionsLocal) -> { 4898 synchronized (mLock) { 4899 maxNumOfTdlsSessions.set(maxNumOfTdlsSessionsLocal); 4900 mLock.notify(); 4901 } 4902 }); 4903 synchronized (mLock) { 4904 mLock.wait(TEST_WAIT_DURATION_MS); 4905 } 4906 // {@code WifiManager#getMaxSupportedConcurrentTdlsSessions} returns -1 4907 // if HAL doesn't provide this TDLS capability. 4908 assertTrue(maxNumOfTdlsSessions.get() == -1 || maxNumOfTdlsSessions.get() > 0); 4909 } 4910 4911 /** 4912 * Verify the usage of 4913 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)}. 4914 */ 4915 @Test testSetTdlsEnabledWithIpAddressConsumerModel()4916 public void testSetTdlsEnabledWithIpAddressConsumerModel() throws Exception { 4917 if (!sWifiManager.isTdlsSupported()) { 4918 // skip the test if TDLS is not supported 4919 return; 4920 } 4921 4922 InetAddress inetAddress = InetAddress.getByName(TEST_IP_ADDRESS); 4923 sWifiManager.setTdlsEnabled(inetAddress, true, mExecutor, (e) -> {}); 4924 sWifiManager.setTdlsEnabled(inetAddress, false, mExecutor, (e) -> {}); 4925 } 4926 4927 /** 4928 * Verify the usage of 4929 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 4930 * and {@link WifiManager#getNumberOfEnabledTdlsSessions(Executor, Consumer)}. 4931 */ 4932 @Test testSetTdlsEnabledWithMacAddressConsumerModel()4933 public void testSetTdlsEnabledWithMacAddressConsumerModel() throws Exception { 4934 if (!sWifiManager.isTdlsSupported()) { 4935 // skip the test if TDLS is not supported 4936 return; 4937 } 4938 4939 AtomicBoolean enabled = new AtomicBoolean(false); 4940 AtomicInteger numOfTdlsSessions = new AtomicInteger(0); 4941 Consumer<Integer> listener2 = new Consumer<Integer>() { 4942 @Override 4943 public void accept(Integer value) { 4944 synchronized (mLock) { 4945 numOfTdlsSessions.set(value); 4946 mLock.notify(); 4947 } 4948 } 4949 }; 4950 4951 sWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, true, mExecutor, 4952 (enabledLocal) -> { 4953 synchronized (mLock) { 4954 enabled.set(enabledLocal); 4955 mLock.notify(); 4956 } 4957 }); 4958 synchronized (mLock) { 4959 mLock.wait(TEST_WAIT_DURATION_MS); 4960 } 4961 assertTrue(enabled.get()); 4962 sWifiManager.getNumberOfEnabledTdlsSessions(mExecutor, listener2); 4963 synchronized (mLock) { 4964 mLock.wait(TEST_WAIT_DURATION_MS); 4965 } 4966 assertEquals(1, numOfTdlsSessions.get()); 4967 4968 sWifiManager.setTdlsEnabledWithMacAddress(TEST_MAC_ADDRESS, false, mExecutor, (e) -> {}); 4969 sWifiManager.getNumberOfEnabledTdlsSessions(mExecutor, listener2); 4970 synchronized (mLock) { 4971 mLock.wait(TEST_WAIT_DURATION_MS); 4972 } 4973 assertEquals(0, numOfTdlsSessions.get()); 4974 } 4975 4976 /** 4977 * Verify WifiNetworkSuggestion.Builder.setMacRandomizationSetting(WifiNetworkSuggestion 4978 * .RANDOMIZATION_NON_PERSISTENT) creates a 4979 * WifiConfiguration with macRandomizationSetting == RANDOMIZATION_NON_PERSISTENT. 4980 * Then verify by default, a WifiConfiguration created by suggestions should have 4981 * macRandomizationSetting == RANDOMIZATION_PERSISTENT. 4982 */ 4983 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 4984 @Test testSuggestionBuilderNonPersistentRandomization()4985 public void testSuggestionBuilderNonPersistentRandomization() throws Exception { 4986 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 4987 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE) 4988 .setMacRandomizationSetting(WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT) 4989 .build(); 4990 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 4991 sWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 4992 verifySuggestionFoundWithMacRandomizationSetting(TEST_SSID, 4993 WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT); 4994 4995 suggestion = new WifiNetworkSuggestion.Builder() 4996 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE) 4997 .build(); 4998 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 4999 sWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 5000 verifySuggestionFoundWithMacRandomizationSetting(TEST_SSID, 5001 WifiNetworkSuggestion.RANDOMIZATION_PERSISTENT); 5002 } 5003 verifySuggestionFoundWithMacRandomizationSetting(String ssid, int macRandomizationSetting)5004 private void verifySuggestionFoundWithMacRandomizationSetting(String ssid, 5005 int macRandomizationSetting) { 5006 List<WifiNetworkSuggestion> retrievedSuggestions = sWifiManager.getNetworkSuggestions(); 5007 for (WifiNetworkSuggestion entry : retrievedSuggestions) { 5008 if (entry.getSsid().equals(ssid)) { 5009 assertEquals(macRandomizationSetting, entry.getMacRandomizationSetting()); 5010 return; // pass test after the MAC randomization setting is verified. 5011 } 5012 } 5013 fail("WifiNetworkSuggestion not found for SSID=" + ssid + ", macRandomizationSetting=" 5014 + macRandomizationSetting); 5015 } 5016 5017 /** 5018 * Tests {@link WifiManager#getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(List)} 5019 */ 5020 @Test testGetAllWifiConfigForMatchedNetworkSuggestion()5021 public void testGetAllWifiConfigForMatchedNetworkSuggestion() { 5022 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5023 ScanResult scanResult = new ScanResult(); 5024 scanResult.SSID = TEST_SSID; 5025 scanResult.capabilities = TEST_PSK_CAP; 5026 scanResult.BSSID = TEST_BSSID; 5027 List<ScanResult> testList = Arrays.asList(scanResult); 5028 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 5029 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE).build(); 5030 5031 assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, 5032 sWifiManager.addNetworkSuggestions(Arrays.asList(suggestion))); 5033 List<WifiConfiguration> matchedResult; 5034 try { 5035 uiAutomation.adoptShellPermissionIdentity(); 5036 matchedResult = sWifiManager 5037 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(testList); 5038 } finally { 5039 uiAutomation.dropShellPermissionIdentity(); 5040 } 5041 // As suggestion is not approved, will return empty list. 5042 assertTrue(matchedResult.isEmpty()); 5043 } 5044 5045 /** 5046 * Tests {@link WifiManager#getMatchingScanResults(List, List)} 5047 */ 5048 @Test testGetMatchingScanResults()5049 public void testGetMatchingScanResults() { 5050 // Create pair of ScanResult and WifiNetworkSuggestion 5051 ScanResult scanResult = new ScanResult(); 5052 scanResult.SSID = TEST_SSID; 5053 scanResult.capabilities = TEST_PSK_CAP; 5054 scanResult.BSSID = TEST_BSSID; 5055 5056 WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() 5057 .setSsid(TEST_SSID).setWpa2Passphrase(TEST_PASSPHRASE).build(); 5058 5059 Map<WifiNetworkSuggestion, List<ScanResult>> matchedResults = sWifiManager 5060 .getMatchingScanResults(Arrays.asList(suggestion), Arrays.asList(scanResult)); 5061 // Verify result is matched pair of ScanResult and WifiNetworkSuggestion 5062 assertEquals(scanResult.SSID, matchedResults.get(suggestion).get(0).SSID); 5063 5064 // Change ScanResult to unmatched should return empty result. 5065 scanResult.SSID = TEST_SSID_UNQUOTED; 5066 matchedResults = sWifiManager 5067 .getMatchingScanResults(Arrays.asList(suggestion), Arrays.asList(scanResult)); 5068 assertTrue(matchedResults.get(suggestion).isEmpty()); 5069 } 5070 5071 /** 5072 * Tests {@link WifiManager#disableEphemeralNetwork(String)}. 5073 */ 5074 @Test testDisableEphemeralNetwork()5075 public void testDisableEphemeralNetwork() throws Exception { 5076 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5077 List<WifiConfiguration> savedNetworks = null; 5078 try { 5079 uiAutomation.adoptShellPermissionIdentity(); 5080 // Temporarily disable on all networks. 5081 savedNetworks = sWifiManager.getConfiguredNetworks(); 5082 for (WifiConfiguration network : savedNetworks) { 5083 sWifiManager.disableEphemeralNetwork(network.SSID); 5084 } 5085 // trigger a disconnect and wait for disconnect. 5086 sWifiManager.disconnect(); 5087 waitForDisconnection(); 5088 5089 // Now trigger scan and ensure that the device does not connect to any networks. 5090 sWifiManager.startScan(); 5091 ensureNotConnected(); 5092 } finally { 5093 uiAutomation.dropShellPermissionIdentity(); 5094 setWifiEnabled(false); 5095 } 5096 } 5097 5098 /** 5099 * Tests {@link WifiManager#allowAutojoin(int, boolean)}. 5100 */ 5101 @Test testAllowAutojoin()5102 public void testAllowAutojoin() throws Exception { 5103 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5104 List<WifiConfiguration> savedNetworks = null; 5105 try { 5106 uiAutomation.adoptShellPermissionIdentity(); 5107 // disable autojoin on all networks. 5108 savedNetworks = sWifiManager.getConfiguredNetworks(); 5109 for (WifiConfiguration network : savedNetworks) { 5110 sWifiManager.allowAutojoin(network.networkId, false); 5111 } 5112 // trigger a disconnect and wait for disconnect. 5113 sWifiManager.disconnect(); 5114 waitForDisconnection(); 5115 5116 // Now trigger scan and ensure that the device does not connect to any networks. 5117 sWifiManager.startScan(); 5118 ensureNotConnected(); 5119 5120 // Now enable autojoin on all networks. 5121 for (WifiConfiguration network : savedNetworks) { 5122 sWifiManager.allowAutojoin(network.networkId, true); 5123 } 5124 5125 // Trigger a scan & wait for connection to one of the saved networks. 5126 sWifiManager.startScan(); 5127 waitForConnection(); 5128 } finally { 5129 // Restore auto join state. 5130 if (savedNetworks != null) { 5131 for (WifiConfiguration network : savedNetworks) { 5132 sWifiManager.allowAutojoin(network.networkId, network.allowAutojoin); 5133 } 5134 } 5135 uiAutomation.dropShellPermissionIdentity(); 5136 } 5137 } 5138 5139 /** 5140 * Tests {@link WifiManager#allowAutojoinPasspoint(String, boolean)}. 5141 */ 5142 @Test testAllowAutojoinPasspoint()5143 public void testAllowAutojoinPasspoint() throws Exception { 5144 PasspointConfiguration passpointConfiguration = createPasspointConfiguration(); 5145 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5146 try { 5147 uiAutomation.adoptShellPermissionIdentity(); 5148 sWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration); 5149 // Turn off auto-join 5150 sWifiManager.allowAutojoinPasspoint( 5151 passpointConfiguration.getHomeSp().getFqdn(), false); 5152 // Turn on auto-join 5153 sWifiManager.allowAutojoinPasspoint( 5154 passpointConfiguration.getHomeSp().getFqdn(), true); 5155 } finally { 5156 sWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn()); 5157 uiAutomation.dropShellPermissionIdentity(); 5158 } 5159 } 5160 5161 /** 5162 * Tests {@link WifiManager#allowAutojoinGlobal(boolean)}. 5163 */ 5164 @Test testAllowAutojoinGlobal()5165 public void testAllowAutojoinGlobal() throws Exception { 5166 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5167 try { 5168 uiAutomation.adoptShellPermissionIdentity(); 5169 // disable autojoin on all networks. 5170 sWifiManager.allowAutojoinGlobal(false); 5171 5172 // trigger a disconnect and wait for disconnect. 5173 sWifiManager.disconnect(); 5174 waitForDisconnection(); 5175 5176 // Now trigger scan and ensure that the device does not connect to any networks. 5177 sWifiManager.startScan(); 5178 ensureNotConnected(); 5179 5180 // verify null is returned when attempting to get current configured network. 5181 WifiConfiguration config = sWifiManager.getPrivilegedConnectedNetwork(); 5182 assertNull("config should be null because wifi is not connected", config); 5183 5184 // Now enable autojoin on all networks. 5185 sWifiManager.allowAutojoinGlobal(true); 5186 5187 // Trigger a scan & wait for connection to one of the saved networks. 5188 sWifiManager.startScan(); 5189 waitForConnection(); 5190 } finally { 5191 // Re-enable auto join if the test fails for some reason. 5192 sWifiManager.allowAutojoinGlobal(true); 5193 uiAutomation.dropShellPermissionIdentity(); 5194 } 5195 } 5196 5197 /** 5198 * Verify the invalid and valid usages of {@code WifiManager#queryAutojoinGlobal}. 5199 */ 5200 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 5201 @Test testQueryAutojoinGlobal()5202 public void testQueryAutojoinGlobal() throws Exception { 5203 AtomicBoolean enabled = new AtomicBoolean(false); 5204 Consumer<Boolean> listener = new Consumer<Boolean>() { 5205 @Override 5206 public void accept(Boolean value) { 5207 synchronized (mLock) { 5208 enabled.set(value); 5209 mLock.notify(); 5210 } 5211 } 5212 }; 5213 // Test invalid inputs trigger IllegalArgumentException 5214 assertThrows("null executor should trigger exception", NullPointerException.class, 5215 () -> sWifiManager.queryAutojoinGlobal(null, listener)); 5216 assertThrows("null listener should trigger exception", NullPointerException.class, 5217 () -> sWifiManager.queryAutojoinGlobal(mExecutor, null)); 5218 5219 // Test caller with no permission triggers SecurityException. 5220 assertThrows("No permission should trigger SecurityException", SecurityException.class, 5221 () -> sWifiManager.queryAutojoinGlobal(mExecutor, listener)); 5222 5223 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5224 try { 5225 uiAutomation.adoptShellPermissionIdentity(); 5226 // Test get/set autojoin global enabled 5227 sWifiManager.allowAutojoinGlobal(true); 5228 sWifiManager.queryAutojoinGlobal(mExecutor, listener); 5229 synchronized (mLock) { 5230 mLock.wait(TEST_WAIT_DURATION_MS); 5231 } 5232 assertTrue(enabled.get()); 5233 5234 // Test get/set autojoin global disabled 5235 sWifiManager.allowAutojoinGlobal(false); 5236 sWifiManager.queryAutojoinGlobal(mExecutor, listener); 5237 synchronized (mLock) { 5238 mLock.wait(TEST_WAIT_DURATION_MS); 5239 } 5240 assertFalse(enabled.get()); 5241 } finally { 5242 // Re-enable auto join if the test fails for some reason. 5243 sWifiManager.allowAutojoinGlobal(true); 5244 uiAutomation.dropShellPermissionIdentity(); 5245 } 5246 } 5247 5248 /** 5249 * Tests {@link WifiManager#setPerSsidRoamingMode(WifiSsid, int)}, 5250 * {@link WifiManager#getPerSsidRoamingModes(Executor, Consumer)}, 5251 * and {@link WifiManager#removePerSsidRoamingMode(WifiSsid)}. 5252 */ 5253 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 5254 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 5255 codeName = "VanillaIceCream") 5256 @Test testPerSsidRoamingMode()5257 public void testPerSsidRoamingMode() throws Exception { 5258 WifiSsid testSsid = WifiSsid.fromBytes("TEST_SSID_1".getBytes(StandardCharsets.UTF_8)); 5259 Map<String, Integer> roamingModes = new HashMap<>(); 5260 Consumer<Map<String, Integer>> listener = new Consumer<Map<String, Integer>>() { 5261 @Override 5262 public void accept(Map<String, Integer> value) { 5263 synchronized (mLock) { 5264 roamingModes.clear(); 5265 roamingModes.putAll(value); 5266 mLock.notify(); 5267 } 5268 } 5269 }; 5270 5271 // Test caller with no permission triggers SecurityException. 5272 assertThrows("No permission should trigger SecurityException", SecurityException.class, 5273 () -> sWifiManager.setPerSsidRoamingMode(testSsid, 5274 WifiManager.ROAMING_MODE_NORMAL)); 5275 assertThrows("No permission should trigger SecurityException", SecurityException.class, 5276 () -> sWifiManager.removePerSsidRoamingMode(testSsid)); 5277 assertThrows("No permission should trigger SecurityException", SecurityException.class, 5278 () -> sWifiManager.getPerSsidRoamingModes(mExecutor, listener)); 5279 5280 // Test that invalid inputs trigger an Exception. 5281 assertThrows("null WifiSsid should trigger exception", NullPointerException.class, 5282 () -> sWifiManager.setPerSsidRoamingMode(null, 5283 WifiManager.ROAMING_MODE_NORMAL)); 5284 assertThrows("null WifiSsid should trigger exception", NullPointerException.class, 5285 () -> sWifiManager.removePerSsidRoamingMode(null)); 5286 assertThrows("null executor should trigger exception", NullPointerException.class, 5287 () -> sWifiManager.getPerSsidRoamingModes(null, listener)); 5288 assertThrows("null listener should trigger exception", NullPointerException.class, 5289 () -> sWifiManager.getPerSsidRoamingModes(mExecutor, null)); 5290 5291 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5292 try { 5293 uiAutomation.adoptShellPermissionIdentity(); 5294 sWifiManager.setPerSsidRoamingMode(testSsid, WifiManager.ROAMING_MODE_NORMAL); 5295 sWifiManager.getPerSsidRoamingModes(mExecutor, listener); 5296 Thread.sleep(TEST_WAIT_DURATION_MS); 5297 assertTrue( 5298 roamingModes.get(testSsid.toString()) == WifiManager.ROAMING_MODE_NORMAL); 5299 sWifiManager.removePerSsidRoamingMode(testSsid); 5300 sWifiManager.getPerSsidRoamingModes(mExecutor, listener); 5301 Thread.sleep(TEST_WAIT_DURATION_MS); 5302 assertNull(roamingModes.get(testSsid.toString())); 5303 5304 if (sWifiManager.isAggressiveRoamingModeSupported()) { 5305 sWifiManager.setPerSsidRoamingMode(testSsid, WifiManager.ROAMING_MODE_AGGRESSIVE); 5306 sWifiManager.getPerSsidRoamingModes(mExecutor, listener); 5307 Thread.sleep(TEST_WAIT_DURATION_MS); 5308 assertTrue(roamingModes.get(testSsid.toString()) 5309 == WifiManager.ROAMING_MODE_AGGRESSIVE); 5310 sWifiManager.removePerSsidRoamingMode(testSsid); 5311 sWifiManager.getPerSsidRoamingModes(mExecutor, listener); 5312 Thread.sleep(TEST_WAIT_DURATION_MS); 5313 assertNull(roamingModes.get(testSsid.toString())); 5314 } else { 5315 assertThrows("Aggressive roaming mode not supported", 5316 UnsupportedOperationException.class, 5317 () -> sWifiManager.setPerSsidRoamingMode(testSsid, 5318 WifiManager.ROAMING_MODE_AGGRESSIVE)); 5319 } 5320 } finally { 5321 uiAutomation.dropShellPermissionIdentity(); 5322 } 5323 } 5324 5325 /** 5326 * Verify the invalid and valid usages of {@code WifiManager#setPnoScanState}. 5327 */ 5328 @Test 5329 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) testSetPnoScanState()5330 public void testSetPnoScanState() throws Exception { 5331 // Test caller with no permission triggers SecurityException. 5332 assertThrows("No permission should trigger SecurityException", SecurityException.class, 5333 () -> sWifiManager.setPnoScanState(WifiManager.PNO_SCAN_STATE_ENABLED)); 5334 5335 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5336 try { 5337 uiAutomation.adoptShellPermissionIdentity(); 5338 sWifiManager.setPnoScanState(WifiManager.PNO_SCAN_STATE_ENABLED); 5339 } finally { 5340 uiAutomation.dropShellPermissionIdentity(); 5341 } 5342 } 5343 5344 /** 5345 * Tests {@link WifiManager#isWapiSupported()} does not crash. 5346 */ 5347 @Test testIsWapiSupported()5348 public void testIsWapiSupported() throws Exception { 5349 sWifiManager.isWapiSupported(); 5350 } 5351 5352 /** 5353 * Tests {@link WifiManager#isWpa3SaePublicKeySupported()} does not crash. 5354 */ 5355 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5356 @Test testIsWpa3SaePublicKeySupported()5357 public void testIsWpa3SaePublicKeySupported() throws Exception { 5358 sWifiManager.isWpa3SaePublicKeySupported(); 5359 } 5360 5361 /** 5362 * Tests {@link WifiManager#isWpa3SaeH2eSupported()} does not crash. 5363 */ 5364 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5365 @Test testIsWpa3SaeH2eSupported()5366 public void testIsWpa3SaeH2eSupported() throws Exception { 5367 sWifiManager.isWpa3SaeH2eSupported(); 5368 } 5369 5370 /** 5371 * Tests {@link WifiManager#isWifiDisplayR2Supported()} does not crash. 5372 */ 5373 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5374 @Test testIsWifiDisplayR2Supported()5375 public void testIsWifiDisplayR2Supported() throws Exception { 5376 sWifiManager.isWifiDisplayR2Supported(); 5377 } 5378 5379 /** 5380 * Tests {@link WifiManager#isP2pSupported()} returns true 5381 * if this device supports it, otherwise, ensure no crash. 5382 */ 5383 @Test testIsP2pSupported()5384 public void testIsP2pSupported() throws Exception { 5385 if (WifiFeature.isP2pSupported(sContext)) { 5386 // if this device supports P2P, ensure hw capability is correct. 5387 assertTrue(sWifiManager.isP2pSupported()); 5388 } else { 5389 // ensure no crash. 5390 sWifiManager.isP2pSupported(); 5391 } 5392 5393 } 5394 5395 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5396 @Test testIsMultiStaConcurrencySupported()5397 public void testIsMultiStaConcurrencySupported() throws Exception { 5398 // ensure no crash. 5399 sWifiManager.isStaApConcurrencySupported(); 5400 } 5401 getTargetPasspointConfiguration( List<PasspointConfiguration> configurationList, String uniqueId)5402 private PasspointConfiguration getTargetPasspointConfiguration( 5403 List<PasspointConfiguration> configurationList, String uniqueId) { 5404 if (configurationList == null || configurationList.isEmpty()) { 5405 return null; 5406 } 5407 for (PasspointConfiguration config : configurationList) { 5408 if (TextUtils.equals(config.getUniqueId(), uniqueId)) { 5409 return config; 5410 } 5411 } 5412 return null; 5413 } 5414 5415 /** 5416 * Test that {@link WifiManager#is60GHzBandSupported()} throws UnsupportedOperationException 5417 * if the release is older than S. 5418 */ 5419 @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.R) 5420 @Test testIs60GhzBandSupportedOnROrOlder()5421 public void testIs60GhzBandSupportedOnROrOlder() throws Exception { 5422 // check for 60ghz support with wifi enabled 5423 try { 5424 sWifiManager.is60GHzBandSupported(); 5425 fail("Expected UnsupportedOperationException"); 5426 } catch (UnsupportedOperationException ex) { 5427 } 5428 } 5429 5430 /** 5431 * Test that {@link WifiManager#is60GHzBandSupported()} returns successfully in 5432 * both Wifi enabled/disabled states for release newer than R. 5433 * Note that the response depends on device support and hence both true/false 5434 * are valid responses. 5435 */ 5436 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5437 @Test testIs60GhzBandSupportedOnSOrNewer()5438 public void testIs60GhzBandSupportedOnSOrNewer() throws Exception { 5439 // check for 60ghz support with wifi enabled 5440 boolean isSupportedWhenWifiEnabled = sWifiManager.is60GHzBandSupported(); 5441 5442 // Check for 60GHz support with wifi disabled 5443 setWifiEnabled(false); 5444 PollingCheck.check( 5445 "Wifi not disabled!", 5446 20000, 5447 () -> !sWifiManager.isWifiEnabled()); 5448 boolean isSupportedWhenWifiDisabled = sWifiManager.is60GHzBandSupported(); 5449 5450 // If Support is true when WiFi is disable, then it has to be true when it is enabled. 5451 // Note, the reverse is a valid case. 5452 if (isSupportedWhenWifiDisabled) { 5453 assertTrue(isSupportedWhenWifiEnabled); 5454 } 5455 } 5456 5457 /** 5458 * Tests {@link WifiManager#isTrustOnFirstUseSupported()} does not crash. 5459 */ 5460 // TODO(b/196180536): Wait for T SDK finalization before changing 5461 // to `@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU)` 5462 @SdkSuppress(minSdkVersion = 31) 5463 @Test testIsTrustOnFirstUseSupported()5464 public void testIsTrustOnFirstUseSupported() throws Exception { 5465 sWifiManager.isTrustOnFirstUseSupported(); 5466 } 5467 5468 public class TestCoexCallback extends WifiManager.CoexCallback { 5469 private Object mCoexLock; 5470 private int mOnCoexUnsafeChannelChangedCount; 5471 private List<CoexUnsafeChannel> mCoexUnsafeChannels; 5472 private int mCoexRestrictions; 5473 TestCoexCallback(Object lock)5474 TestCoexCallback(Object lock) { 5475 mCoexLock = lock; 5476 } 5477 5478 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, int restrictions)5479 public void onCoexUnsafeChannelsChanged( 5480 @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) { 5481 synchronized (mCoexLock) { 5482 mCoexUnsafeChannels = unsafeChannels; 5483 mCoexRestrictions = restrictions; 5484 mOnCoexUnsafeChannelChangedCount++; 5485 mCoexLock.notify(); 5486 } 5487 } 5488 getOnCoexUnsafeChannelChangedCount()5489 public int getOnCoexUnsafeChannelChangedCount() { 5490 synchronized (mCoexLock) { 5491 return mOnCoexUnsafeChannelChangedCount; 5492 } 5493 } 5494 getCoexUnsafeChannels()5495 public List<CoexUnsafeChannel> getCoexUnsafeChannels() { 5496 return mCoexUnsafeChannels; 5497 } 5498 getCoexRestrictions()5499 public int getCoexRestrictions() { 5500 return mCoexRestrictions; 5501 } 5502 } 5503 5504 /** 5505 * Test that coex-related methods fail without the needed privileged permissions 5506 */ 5507 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5508 @Test testCoexMethodsShouldFailNoPermission()5509 public void testCoexMethodsShouldFailNoPermission() { 5510 try { 5511 sWifiManager.setCoexUnsafeChannels(Collections.emptyList(), 0); 5512 fail("setCoexUnsafeChannels should not succeed - privileged call"); 5513 } catch (SecurityException e) { 5514 // expected 5515 } 5516 final TestCoexCallback callback = new TestCoexCallback(mLock); 5517 try { 5518 sWifiManager.registerCoexCallback(mExecutor, callback); 5519 fail("registerCoexCallback should not succeed - privileged call"); 5520 } catch (SecurityException e) { 5521 // expected 5522 } 5523 try { 5524 sWifiManager.unregisterCoexCallback(callback); 5525 fail("unregisterCoexCallback should not succeed - privileged call"); 5526 } catch (SecurityException e) { 5527 // expected 5528 } 5529 } 5530 5531 /** 5532 * Test that coex-related methods succeed in setting the current unsafe channels and notifying 5533 * the listener. Since the default coex algorithm may be enabled, no-op is also valid behavior. 5534 */ 5535 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5536 @Test testListenOnCoexUnsafeChannels()5537 public void testListenOnCoexUnsafeChannels() { 5538 // These below API's only work with privileged permissions (obtained via shell identity 5539 // for test) 5540 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5541 List<CoexUnsafeChannel> prevUnsafeChannels = new ArrayList<>(); 5542 int prevRestrictions = -1; 5543 try { 5544 uiAutomation.adoptShellPermissionIdentity(); 5545 synchronized (mLock) { 5546 try { 5547 boolean defaultAlgoEnabled = false; 5548 final TestCoexCallback callback = new TestCoexCallback(mLock); 5549 sWifiManager.registerCoexCallback(mExecutor, callback); 5550 5551 // Callback should be called after registering 5552 mLock.wait(TEST_WAIT_DURATION_MS); 5553 assertEquals(1, callback.getOnCoexUnsafeChannelChangedCount()); 5554 5555 // Store the previous coex channels and try setting new coex channels 5 times. 5556 // 5557 // If the default algorithm is disabled, we'll get exactly 5 callbacks, and we 5558 // can verify that the update channels match what we inputted. 5559 // 5560 // If the default algorithm is enabled, then the callbacks will trigger 5561 // according to the algorithm, which may or may not trigger during the test. 5562 // Thus we try 5 times and see if the callbacks match the number of tries, since 5563 // it's highly unlikely that the default algorithm will update the channels 5564 // exactly 5 times during the test. 5565 prevUnsafeChannels = callback.getCoexUnsafeChannels(); 5566 prevRestrictions = callback.getCoexRestrictions(); 5567 List<CoexUnsafeChannel> testChannels = null; 5568 final int testRestrictions = COEX_RESTRICTION_WIFI_DIRECT 5569 | COEX_RESTRICTION_SOFTAP | COEX_RESTRICTION_WIFI_AWARE; 5570 for (int i = 0; i < 5; i++) { 5571 testChannels = List.of(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 1 + i)); 5572 sWifiManager.setCoexUnsafeChannels(testChannels, testRestrictions); 5573 mLock.wait(TEST_WAIT_DURATION_MS); 5574 if (callback.getOnCoexUnsafeChannelChangedCount() != i + 2) { 5575 defaultAlgoEnabled = true; 5576 break; 5577 } 5578 } 5579 5580 if (!defaultAlgoEnabled) { 5581 int currentCallbackCount = callback.getOnCoexUnsafeChannelChangedCount(); 5582 assertEquals(testChannels, callback.getCoexUnsafeChannels()); 5583 assertEquals(testRestrictions, callback.getCoexRestrictions()); 5584 // Unregister callback and try setting again 5585 sWifiManager.unregisterCoexCallback(callback); 5586 sWifiManager.setCoexUnsafeChannels( 5587 List.of(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 11)), 5588 testRestrictions); 5589 mLock.wait(TEST_WAIT_DURATION_MS); 5590 // Callback should not be called here since it was unregistered. 5591 assertThat(callback.getOnCoexUnsafeChannelChangedCount()) 5592 .isEqualTo(currentCallbackCount); 5593 } 5594 } catch (InterruptedException e) { 5595 fail("Thread interrupted unexpectedly while waiting on mLock"); 5596 } 5597 } 5598 } finally { 5599 // Reset the previous unsafe channels if we overrode them. 5600 if (prevRestrictions != -1) { 5601 sWifiManager.setCoexUnsafeChannels(prevUnsafeChannels, prevRestrictions); 5602 } 5603 uiAutomation.dropShellPermissionIdentity(); 5604 } 5605 } 5606 5607 /** 5608 * Verify that secure WPA-Enterprise network configurations can be added and updated. 5609 */ 5610 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5611 @Test testSecureEnterpriseConfigurationsAccepted()5612 public void testSecureEnterpriseConfigurationsAccepted() throws Exception { 5613 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 5614 wifiConfiguration.SSID = SSID1; 5615 wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); 5616 wifiConfiguration.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS); 5617 int networkId = INVALID_NETWORK_ID; 5618 5619 // These below API's only work with privileged permissions (obtained via shell identity 5620 // for test) 5621 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5622 try { 5623 uiAutomation.adoptShellPermissionIdentity(); 5624 5625 // Now configure it correctly with a Root CA cert and domain name 5626 wifiConfiguration.enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); 5627 wifiConfiguration.enterpriseConfig.setAltSubjectMatch(TEST_DOM_SUBJECT_MATCH); 5628 5629 // Verify that the network is added 5630 networkId = sWifiManager.addNetwork(wifiConfiguration); 5631 assertNotEquals(INVALID_NETWORK_ID, networkId); 5632 5633 // Verify that the update API accepts configurations configured securely 5634 wifiConfiguration.networkId = networkId; 5635 assertEquals(networkId, sWifiManager.updateNetwork(wifiConfiguration)); 5636 } finally { 5637 if (networkId != INVALID_NETWORK_ID) { 5638 // Clean up the previously added network 5639 sWifiManager.removeNetwork(networkId); 5640 } 5641 uiAutomation.dropShellPermissionIdentity(); 5642 } 5643 } 5644 5645 /** 5646 * Tests {@link WifiManager#isPasspointTermsAndConditionsSupported)} does not crash. 5647 */ 5648 @Test testIsPasspointTermsAndConditionsSupported()5649 public void testIsPasspointTermsAndConditionsSupported() throws Exception { 5650 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 5651 // Skip the test if wifi module version is older than S. 5652 return; 5653 } 5654 sWifiManager.isPasspointTermsAndConditionsSupported(); 5655 } 5656 5657 /** 5658 * Test that call to {@link WifiManager#setOverrideCountryCode()}, 5659 * {@link WifiManager#clearOverrideCountryCode()} and 5660 * {@link WifiManager#setDefaultCountryCode()} need privileged permission 5661 * and the permission is not even given to shell user. 5662 */ 5663 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5664 @Test testManageCountryCodeMethodsFailWithoutPermissions()5665 public void testManageCountryCodeMethodsFailWithoutPermissions() throws Exception { 5666 ShellIdentityUtils.invokeWithShellPermissions(() -> { 5667 try { 5668 sWifiManager.setOverrideCountryCode(TEST_COUNTRY_CODE); 5669 fail("setOverrideCountryCode() expected to fail - privileged call"); 5670 } catch (SecurityException e) { 5671 // expected 5672 } 5673 5674 try { 5675 sWifiManager.clearOverrideCountryCode(); 5676 fail("clearOverrideCountryCode() expected to fail - privileged call"); 5677 } catch (SecurityException e) { 5678 // expected 5679 } 5680 5681 try { 5682 sWifiManager.setDefaultCountryCode(TEST_COUNTRY_CODE); 5683 fail("setDefaultCountryCode() expected to fail - privileged call"); 5684 } catch (SecurityException e) { 5685 // expected 5686 } 5687 }); 5688 } 5689 5690 /** 5691 * Tests {@link WifiManager#flushPasspointAnqpCache)} does not crash. 5692 */ 5693 @Test testFlushPasspointAnqpCache()5694 public void testFlushPasspointAnqpCache() throws Exception { 5695 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 5696 // Skip the test if wifi module version is older than S. 5697 return; 5698 } 5699 // The below API only works with privileged permissions (obtained via shell identity 5700 // for test) 5701 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5702 try { 5703 uiAutomation.adoptShellPermissionIdentity(); 5704 sWifiManager.flushPasspointAnqpCache(); 5705 } finally { 5706 uiAutomation.dropShellPermissionIdentity(); 5707 } 5708 } 5709 5710 /** 5711 * Tests {@link WifiManager#setWifiPasspointEnabled)} raise security exception without 5712 * permission. 5713 */ 5714 // TODO(b/139192273): Wait for T SDK finalization before changing 5715 // to `@SdkSuppress(minSdkVersion = Build.VERSION_CODES.T)` 5716 @SdkSuppress(minSdkVersion = 31) 5717 @Test testEnablePasspointWithoutPermission()5718 public void testEnablePasspointWithoutPermission() throws Exception { 5719 try { 5720 sWifiManager.setWifiPasspointEnabled(true); 5721 fail("setWifiPasspointEnabled() expected to fail - privileged call"); 5722 } catch (SecurityException e) { 5723 // expected 5724 } 5725 } 5726 5727 /** 5728 * Tests {@link WifiManager#setWifiPasspointEnabled)} does not crash and returns success. 5729 */ 5730 // TODO(b/139192273): Wait for T SDK finalization before changing 5731 // to `@SdkSuppress(minSdkVersion = Build.VERSION_CODES.T)` 5732 @SdkSuppress(minSdkVersion = 31) 5733 @Test testEnablePasspoint()5734 public void testEnablePasspoint() throws Exception { 5735 // The below API only works with privileged permissions (obtained via shell identity 5736 // for test) 5737 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5738 try { 5739 uiAutomation.adoptShellPermissionIdentity(); 5740 // Check if passpoint is enabled by default. 5741 assertTrue(sWifiManager.isWifiPasspointEnabled()); 5742 // Try to disable passpoint 5743 sWifiManager.setWifiPasspointEnabled(false); 5744 PollingCheck.check("Wifi passpoint turn off failed!", 2_000, 5745 () -> !sWifiManager.isWifiPasspointEnabled()); 5746 // Try to enable passpoint 5747 sWifiManager.setWifiPasspointEnabled(true); 5748 PollingCheck.check("Wifi passpoint turn on failed!", 2_000, 5749 () -> sWifiManager.isWifiPasspointEnabled()); 5750 } finally { 5751 uiAutomation.dropShellPermissionIdentity(); 5752 } 5753 } 5754 5755 /** 5756 * Tests {@link WifiManager#isDecoratedIdentitySupported)} does not crash. 5757 */ 5758 @Test testIsDecoratedIdentitySupported()5759 public void testIsDecoratedIdentitySupported() throws Exception { 5760 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 5761 // Skip the test if wifi module version is older than S. 5762 return; 5763 } 5764 sWifiManager.isDecoratedIdentitySupported(); 5765 } 5766 5767 /** 5768 * Tests {@link WifiManager#setCarrierNetworkOffloadEnabled)} and 5769 * {@link WifiManager#isCarrierNetworkOffloadEnabled} work as expected. 5770 */ 5771 @Test testSetCarrierNetworkOffloadEnabled()5772 public void testSetCarrierNetworkOffloadEnabled() { 5773 if (!WifiFeature.isWifiSupported(sContext) 5774 || !WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 5775 // skip the test if WiFi is not supported 5776 return; 5777 } 5778 assertTrue(sWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 5779 // The below API only works with privileged permissions (obtained via shell identity 5780 // for test) 5781 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5782 try { 5783 uiAutomation.adoptShellPermissionIdentity(); 5784 sWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, false, false); 5785 assertFalse(sWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 5786 } finally { 5787 sWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, false, true); 5788 uiAutomation.dropShellPermissionIdentity(); 5789 } 5790 assertTrue(sWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); 5791 } 5792 5793 /** 5794 * Test that {@link WifiManager#getUsableChannels(int, int)}, 5795 * {@link WifiManager#getAllowedChannels(int, int)} 5796 * throws UnsupportedOperationException if the release is older than S. 5797 */ 5798 @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.R) 5799 @Test testGetAllowedUsableChannelsOnROrOlder()5800 public void testGetAllowedUsableChannelsOnROrOlder() throws Exception { 5801 try { 5802 sWifiManager.getAllowedChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 5803 fail("getAllowedChannels Expected to fail - UnsupportedOperationException"); 5804 } catch (UnsupportedOperationException ex) {} 5805 5806 try { 5807 sWifiManager.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 5808 fail("getUsableChannels Expected to fail - UnsupportedOperationException"); 5809 } catch (UnsupportedOperationException ex) {} 5810 } 5811 5812 /** 5813 * Tests {@link WifiManager#getAllowedChannels(int, int))} does not crash 5814 */ 5815 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5816 @Test testGetAllowedChannels()5817 public void testGetAllowedChannels() throws Exception { 5818 // The below API only works with privileged permissions (obtained via shell identity 5819 // for test) 5820 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5821 try { 5822 WifiAvailableChannel channel = new WifiAvailableChannel(2412, OP_MODE_SAP); 5823 assertEquals(channel.getFrequencyMhz(), 2412); 5824 assertEquals(channel.getOperationalModes(), OP_MODE_SAP); 5825 final List<Integer> valid24GhzFreqs = Arrays.asList( 5826 2412, 2417, 2422, 2427, 2432, 2437, 2442, 5827 2447, 2452, 2457, 2462, 2467, 2472, 2484); 5828 Set<Integer> supported24GhzFreqs = new HashSet<Integer>(); 5829 uiAutomation.adoptShellPermissionIdentity(); 5830 List<WifiAvailableChannel> allowedChannels = 5831 sWifiManager.getAllowedChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 5832 assertNotNull(allowedChannels); 5833 for (WifiAvailableChannel ch : allowedChannels) { 5834 //Must contain a valid 2.4GHz frequency 5835 assertTrue(valid24GhzFreqs.contains(ch.getFrequencyMhz())); 5836 if(ch.getFrequencyMhz() <= 2462) { 5837 //Channels 1-11 are supported for STA in all countries 5838 assertEquals(ch.getOperationalModes() & OP_MODE_STA, OP_MODE_STA); 5839 supported24GhzFreqs.add(ch.getFrequencyMhz()); 5840 } 5841 } 5842 //Channels 1-11 are supported for STA in all countries 5843 assertEquals(supported24GhzFreqs.size(), 11); 5844 } catch (UnsupportedOperationException ex) { 5845 //expected if the device does not support this API 5846 } catch (Exception ex) { 5847 fail("getAllowedChannels unexpected Exception " + ex); 5848 } finally { 5849 uiAutomation.dropShellPermissionIdentity(); 5850 } 5851 } 5852 5853 /** 5854 * Tests {@link WifiAvailableChannel#getChannelWidth()}. 5855 */ 5856 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5857 @RequiresFlagsEnabled(Flags.FLAG_GET_CHANNEL_WIDTH_API) 5858 @ApiTest(apis = {"android.net.wifi.WifiAvailableChannel#getChannelWidth"}) 5859 @Test testGetAllowedChannelsWidth()5860 public void testGetAllowedChannelsWidth() throws Exception { 5861 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5862 try { 5863 final List<Integer> valid24GhzFreqs = Arrays.asList(2412, 2417, 2422, 2427, 2432, 2437, 5864 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484); 5865 uiAutomation.adoptShellPermissionIdentity(); 5866 List<WifiAvailableChannel> allowedChannels = sWifiManager.getAllowedChannels( 5867 WIFI_BAND_24_GHZ, OP_MODE_STA); 5868 assertNotNull(allowedChannels); 5869 for (WifiAvailableChannel ch : allowedChannels) { 5870 //Must contain a valid 2.4GHz frequency 5871 assertTrue(valid24GhzFreqs.contains(ch.getFrequencyMhz())); 5872 if (ch.getFrequencyMhz() <= 2462) { 5873 //Channels 1-11 are supported for STA in all countries 5874 assertEquals(ch.getOperationalModes() & OP_MODE_STA, OP_MODE_STA); 5875 assertEquals(ch.getChannelWidth(), ScanResult.CHANNEL_WIDTH_20MHZ); 5876 } 5877 } 5878 } catch (UnsupportedOperationException ex) { 5879 //expected if the device does not support this API 5880 } catch (Exception ex) { 5881 fail("getAllowedChannels unexpected Exception " + ex); 5882 } finally { 5883 uiAutomation.dropShellPermissionIdentity(); 5884 } 5885 } 5886 5887 /** 5888 * Tests {@link WifiManager#getUsableChannels(int, int))} does not crash 5889 * and returns at least one 2G channel in STA and WFD GO modes (if WFD is supported) 5890 */ 5891 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 5892 @Test testGetUsableChannelsStaWfdMode()5893 public void testGetUsableChannelsStaWfdMode() throws Exception { 5894 // The below API only works with privileged permissions (obtained via shell identity 5895 // for test) 5896 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5897 try { 5898 uiAutomation.adoptShellPermissionIdentity(); 5899 List<WifiAvailableChannel> usableStaChannels = 5900 sWifiManager.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_STA); 5901 //There must be at least one usable STA channel in 2.4GHz band 5902 assertFalse(usableStaChannels.isEmpty()); 5903 if (sWifiManager.isP2pSupported()) { 5904 List<WifiAvailableChannel> usableGoChannels = 5905 sWifiManager.getUsableChannels(WIFI_BAND_24_GHZ, OP_MODE_WIFI_DIRECT_GO); 5906 //There must be at least one usable P2P channel in 2.4GHz band 5907 assertFalse(usableGoChannels.isEmpty()); 5908 } 5909 5910 } catch (UnsupportedOperationException ex) { 5911 //expected if the device does not support this API 5912 } catch (Exception ex) { 5913 fail("getUsableChannels unexpected Exception " + ex); 5914 } finally { 5915 uiAutomation.dropShellPermissionIdentity(); 5916 } 5917 } 5918 5919 /** 5920 * Tests {@link WifiManager#getChannelData(Executor, Consumer<List<Bundle>>)} 5921 * does not crash. 5922 */ 5923 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 5924 @Test testGetChannelData()5925 public void testGetChannelData() throws Exception { 5926 List<Bundle> dataList = new ArrayList<>(); 5927 Consumer<List<Bundle>> listener = new Consumer<List<Bundle>>() { 5928 @Override 5929 public void accept(List<Bundle> value) { 5930 synchronized (mLock) { 5931 dataList.addAll(value); 5932 mLock.notify(); 5933 } 5934 } 5935 }; 5936 // Test invalid inputs trigger IllegalArgumentException 5937 assertThrows("null executor should trigger exception", NullPointerException.class, 5938 () -> sWifiManager.getChannelData(null, listener)); 5939 assertThrows("null listener should trigger exception", NullPointerException.class, 5940 () -> sWifiManager.getChannelData(mExecutor, null)); 5941 5942 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 5943 try { 5944 uiAutomation.adoptShellPermissionIdentity(); 5945 // Start scan and wait for scan results 5946 startScan(); 5947 sWifiManager.getChannelData(mExecutor, listener); 5948 synchronized (mLock) { 5949 mLock.wait(TEST_WAIT_DURATION_MS); 5950 } 5951 if (sWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) { 5952 assertFalse(dataList.isEmpty()); 5953 } 5954 } catch (UnsupportedOperationException ex) { 5955 //expected if the device does not support this API 5956 } catch (Exception ex) { 5957 fail("getChannelData unexpected Exception " + ex); 5958 } finally { 5959 uiAutomation.dropShellPermissionIdentity(); 5960 } 5961 } 5962 5963 /** 5964 * Validate that the Passpoint feature is enabled on the device. 5965 */ 5966 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 5967 @Test testPasspointCapability()5968 public void testPasspointCapability() { 5969 if (PropertyUtil.getVsrApiLevel() < Build.VERSION_CODES.S) { 5970 return; 5971 } 5972 PackageManager packageManager = sContext.getPackageManager(); 5973 assertTrue("Passpoint must be supported", 5974 packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT)); 5975 } 5976 5977 /** 5978 * Validate add and remove SuggestionUserApprovalStatusListener. And verify the listener's 5979 * stickiness. 5980 */ 5981 @Test testAddRemoveSuggestionUserApprovalStatusListener()5982 public void testAddRemoveSuggestionUserApprovalStatusListener() throws Exception { 5983 if (!WifiFeature.isWifiSupported(sContext) 5984 || !WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(sContext)) { 5985 return; 5986 } 5987 CountDownLatch countDownLatch = new CountDownLatch(1); 5988 TestUserApprovalStatusListener listener = new TestUserApprovalStatusListener( 5989 countDownLatch); 5990 try { 5991 sWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, listener); 5992 assertTrue(countDownLatch.await(TEST_WAIT_DURATION_MS, TimeUnit.MILLISECONDS)); 5993 } finally { 5994 sWifiManager.removeSuggestionUserApprovalStatusListener(listener); 5995 } 5996 } 5997 5998 private static class TestUserApprovalStatusListener implements 5999 WifiManager.SuggestionUserApprovalStatusListener { 6000 private final CountDownLatch mBlocker; 6001 TestUserApprovalStatusListener(CountDownLatch countDownLatch)6002 public TestUserApprovalStatusListener(CountDownLatch countDownLatch) { 6003 mBlocker = countDownLatch; 6004 } 6005 @Override onUserApprovalStatusChange(int status)6006 public void onUserApprovalStatusChange(int status) { 6007 mBlocker.countDown(); 6008 } 6009 } 6010 6011 /** 6012 * Tests {@link WifiManager#setStaConcurrencyForMultiInternetMode)} raise security exception 6013 * without permission. 6014 */ 6015 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6016 @Test testIsStaConcurrencyForMultiInternetSupported()6017 public void testIsStaConcurrencyForMultiInternetSupported() throws Exception { 6018 // ensure no crash. 6019 sWifiManager.isStaConcurrencyForMultiInternetSupported(); 6020 } 6021 6022 /** 6023 * Tests {@link WifiManager#setStaConcurrencyForMultiInternetMode)} raise security exception 6024 * without permission. 6025 */ 6026 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6027 @Test testSetStaConcurrencyForMultiInternetModeWithoutPermission()6028 public void testSetStaConcurrencyForMultiInternetModeWithoutPermission() throws Exception { 6029 if (!WifiFeature.isWifiSupported(sContext) 6030 || !sWifiManager.isStaConcurrencyForMultiInternetSupported()) { 6031 // skip the test if WiFi is not supported or multi internet feature not supported. 6032 return; 6033 } 6034 try { 6035 sWifiManager.setStaConcurrencyForMultiInternetMode( 6036 WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED); 6037 fail("setWifiPasspointEnabled() expected to fail - privileged call"); 6038 } catch (SecurityException e) { 6039 // expected 6040 } 6041 } 6042 6043 /** 6044 * Tests {@link WifiManager#setStaConcurrencyForMultiInternetMode)} does not crash. 6045 */ 6046 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6047 @Test testSetStaConcurrencyForMultiInternetMode()6048 public void testSetStaConcurrencyForMultiInternetMode() throws Exception { 6049 if (!WifiFeature.isWifiSupported(sContext) 6050 || !sWifiManager.isStaConcurrencyForMultiInternetSupported()) { 6051 // skip the test if WiFi is not supported or multi internet feature not supported. 6052 return; 6053 } 6054 6055 // The below API only works with privileged permissions (obtained via shell identity 6056 // for test) 6057 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6058 try { 6059 uiAutomation.adoptShellPermissionIdentity(); 6060 // Try to disable multi internet 6061 sWifiManager.setStaConcurrencyForMultiInternetMode( 6062 WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED); 6063 PollingCheck.check( 6064 "Wifi multi internet disable failed!", 2_000, 6065 () -> sWifiManager.getStaConcurrencyForMultiInternetMode() 6066 == WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED); 6067 // Try to enable multi internet 6068 sWifiManager.setStaConcurrencyForMultiInternetMode( 6069 WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP); 6070 PollingCheck.check( 6071 "Wifi multi internet turn on failed!", 2_000, 6072 () -> sWifiManager.getStaConcurrencyForMultiInternetMode() 6073 == WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP); 6074 } finally { 6075 uiAutomation.dropShellPermissionIdentity(); 6076 } 6077 } 6078 6079 static class TestWifiNetworkStateChangeListener implements 6080 WifiManager.WifiNetworkStateChangedListener { 6081 final int mCmmRole; 6082 private List<Integer> mStateList = new ArrayList<>(); 6083 TestWifiNetworkStateChangeListener(int cmmRole)6084 TestWifiNetworkStateChangeListener(int cmmRole) { 6085 mCmmRole = cmmRole; 6086 } 6087 6088 @Override onWifiNetworkStateChanged(int cmmRole, int state)6089 public void onWifiNetworkStateChanged(int cmmRole, int state) { 6090 if (cmmRole != mCmmRole) { 6091 return; 6092 } 6093 if (mStateList.contains(state)) { 6094 // ignore duplicate state transitions 6095 return; 6096 } 6097 mStateList.add(state); 6098 } 6099 getStateList()6100 public List<Integer> getStateList() { 6101 return mStateList; 6102 } 6103 clear()6104 public void clear() { 6105 mStateList.clear(); 6106 } 6107 } 6108 6109 @Test testWifiNetworkStateChangeListener()6110 public void testWifiNetworkStateChangeListener() throws Exception { 6111 TestWifiNetworkStateChangeListener testListener = new TestWifiNetworkStateChangeListener( 6112 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY); 6113 // Verify permission check 6114 assertThrows(SecurityException.class, 6115 () -> sWifiManager.addWifiNetworkStateChangedListener(mExecutor, testListener)); 6116 6117 // Disable wifi 6118 setWifiEnabled(false); 6119 waitForDisconnection(); 6120 6121 try { 6122 // Register listener then enable wifi 6123 ShellIdentityUtils.invokeWithShellPermissions( 6124 () -> sWifiManager.addWifiNetworkStateChangedListener(mExecutor, testListener)); 6125 setWifiEnabled(true); 6126 6127 // Trigger a scan & wait for connection to one of the saved networks. 6128 sWifiManager.startScan(); 6129 waitForConnection(); 6130 6131 PollingCheck.check( 6132 "Wifi network state change listener did not receive connected!", 1_000, 6133 () -> testListener.getStateList().contains( 6134 WifiManager.WifiNetworkStateChangedListener 6135 .WIFI_NETWORK_STATUS_CONNECTED)); 6136 int firstState = testListener.getStateList().get(0); 6137 int lastState = testListener.getStateList().get(testListener.getStateList().size() - 1); 6138 assertEquals(WifiManager.WifiNetworkStateChangedListener 6139 .WIFI_NETWORK_STATUS_CONNECTING, firstState); 6140 assertEquals(WifiManager.WifiNetworkStateChangedListener 6141 .WIFI_NETWORK_STATUS_CONNECTED, lastState); 6142 6143 // Disable wifi and verify disconnect is reported. 6144 testListener.clear(); 6145 setWifiEnabled(false); 6146 waitForDisconnection(); 6147 PollingCheck.check( 6148 "Wifi network state change listener did not receive disconnected!", 1_000, 6149 () -> testListener.getStateList().contains( 6150 WifiManager.WifiNetworkStateChangedListener 6151 .WIFI_NETWORK_STATUS_DISCONNECTED)); 6152 } finally { 6153 sWifiManager.removeWifiNetworkStateChangedListener(testListener); 6154 } 6155 } 6156 6157 /** 6158 * Tests {@link WifiConfiguration#setBssidAllowlist(List)}. 6159 */ 6160 @Test testBssidAllowlist()6161 public void testBssidAllowlist() throws Exception { 6162 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6163 List<WifiConfiguration> savedNetworks = null; 6164 try { 6165 uiAutomation.adoptShellPermissionIdentity(); 6166 6167 WifiInfo wifiInfo = sWifiManager.getConnectionInfo(); 6168 String connectedBssid = wifiInfo.getBSSID(); 6169 int networkId = wifiInfo.getNetworkId(); 6170 6171 // Set empty BSSID allow list to block all APs 6172 savedNetworks = sWifiManager.getConfiguredNetworks(); 6173 for (WifiConfiguration network : savedNetworks) { 6174 network.setBssidAllowlist(Collections.emptyList()); 6175 sWifiManager.updateNetwork(network); 6176 } 6177 6178 // Disable and re-enable Wifi to avoid reconnect to the secondary candidate 6179 sWifiManager.setWifiEnabled(false); 6180 waitForDisconnection(); 6181 sWifiManager.setWifiEnabled(true); 6182 // Now trigger scan and ensure that the device does not connect to any networks. 6183 sWifiManager.startScan(); 6184 ensureNotConnected(); 6185 6186 // Set the previous connected BSSID on that network. Other network set with a fake 6187 // (not visible) BSSID only 6188 for (WifiConfiguration network : savedNetworks) { 6189 if (network.networkId == networkId) { 6190 network.setBssidAllowlist(List.of(MacAddress.fromString(connectedBssid))); 6191 sWifiManager.updateNetwork(network); 6192 } else { 6193 network.setBssidAllowlist(List.of(MacAddress.fromString(TEST_BSSID))); 6194 sWifiManager.updateNetwork(network); 6195 } 6196 } 6197 6198 // Trigger a scan & wait for connection to one of the saved networks. 6199 sWifiManager.startScan(); 6200 waitForConnection(); 6201 wifiInfo = sWifiManager.getConnectionInfo(); 6202 assertEquals(networkId, wifiInfo.getNetworkId()); 6203 } finally { 6204 // Reset BSSID allow list to accept all APs 6205 for (WifiConfiguration network : savedNetworks) { 6206 assertNotNull(network.getBssidAllowlist()); 6207 network.setBssidAllowlist(null); 6208 sWifiManager.updateNetwork(network); 6209 } 6210 uiAutomation.dropShellPermissionIdentity(); 6211 } 6212 } 6213 6214 /** 6215 * Tests {@link WifiManager#notifyMinimumRequiredWifiSecurityLevelChanged(int)} 6216 * raise security exception without permission. 6217 */ 6218 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6219 @Test testNotifyMinimumRequiredWifiSecurityLevelChangedWithoutPermission()6220 public void testNotifyMinimumRequiredWifiSecurityLevelChangedWithoutPermission() 6221 throws Exception { 6222 if (!WifiFeature.isWifiSupported(sContext)) { 6223 // skip the test if WiFi is not supported. 6224 return; 6225 } 6226 assertThrows(SecurityException.class, 6227 () -> sWifiManager.notifyMinimumRequiredWifiSecurityLevelChanged( 6228 DevicePolicyManager.WIFI_SECURITY_PERSONAL)); 6229 } 6230 6231 /** 6232 * Tests {@link WifiManager#notifyMinimumRequiredWifiSecurityLevelChanged(int)} 6233 * raise security exception without permission. 6234 */ 6235 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6236 @Test testNotifyWifiSsidPolicyChangedWithoutPermission()6237 public void testNotifyWifiSsidPolicyChangedWithoutPermission() throws Exception { 6238 if (!WifiFeature.isWifiSupported(sContext)) { 6239 // skip the test if WiFi is not supported. 6240 return; 6241 } 6242 WifiSsidPolicy policy = new WifiSsidPolicy( 6243 WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST, new ArraySet<>(Arrays.asList( 6244 WifiSsid.fromBytes("ssid".getBytes(StandardCharsets.UTF_8))))); 6245 try { 6246 sWifiManager.notifyWifiSsidPolicyChanged(policy); 6247 fail("Expected security exception due to lack of permission"); 6248 } catch (SecurityException e) { 6249 // expected 6250 } 6251 } 6252 6253 /** 6254 * Verifies that 6255 * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)} raises 6256 * a security exception without permission. 6257 */ 6258 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6259 @Test testIsItPossibleToCreateInterfaceNotAllowed()6260 public void testIsItPossibleToCreateInterfaceNotAllowed() throws Exception { 6261 assertThrows(SecurityException.class, () -> sWifiManager.reportCreateInterfaceImpact( 6262 WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor, 6263 (canBeCreatedLocal, interfacesWhichWillBeDeletedLocal) -> { 6264 // should not get here (security exception!) 6265 })); 6266 } 6267 6268 /** 6269 * Verifies 6270 * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)} . 6271 */ 6272 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6273 @Test testIsItPossibleToCreateInterface()6274 public void testIsItPossibleToCreateInterface() throws Exception { 6275 AtomicBoolean called = new AtomicBoolean(false); 6276 AtomicBoolean canBeCreated = new AtomicBoolean(false); 6277 AtomicReference<Set<WifiManager.InterfaceCreationImpact>> 6278 interfacesWhichWillBeDeleted = new AtomicReference<>(null); 6279 ShellIdentityUtils.invokeWithShellPermissions( 6280 () -> sWifiManager.reportCreateInterfaceImpact( 6281 WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor, 6282 (canBeCreatedLocal, interfacesWhichWillBeDeletedLocal) -> { 6283 synchronized (mLock) { 6284 canBeCreated.set(canBeCreatedLocal); 6285 called.set(true); 6286 interfacesWhichWillBeDeleted.set(interfacesWhichWillBeDeletedLocal); 6287 mLock.notify(); 6288 } 6289 })); 6290 synchronized (mLock) { 6291 mLock.wait(TEST_WAIT_DURATION_MS); 6292 } 6293 assertTrue(called.get()); 6294 if (canBeCreated.get()) { 6295 for (WifiManager.InterfaceCreationImpact entry : interfacesWhichWillBeDeleted.get()) { 6296 int interfaceType = entry.getInterfaceType(); 6297 assertTrue(interfaceType == WifiManager.WIFI_INTERFACE_TYPE_STA 6298 || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_AP 6299 || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_DIRECT 6300 || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_AWARE); 6301 Set<String> packages = entry.getPackages(); 6302 for (String p : packages) { 6303 assertNotNull(p); 6304 } 6305 } 6306 } 6307 6308 // verify the WifiManager.InterfaceCreationImpact APIs 6309 int interfaceType = WifiManager.WIFI_INTERFACE_TYPE_STA; 6310 Set<String> packages = Set.of("package1", "packages2"); 6311 WifiManager.InterfaceCreationImpact element = new WifiManager.InterfaceCreationImpact( 6312 interfaceType, packages); 6313 assertEquals(interfaceType, element.getInterfaceType()); 6314 assertEquals(packages, element.getPackages()); 6315 } 6316 6317 /** 6318 * Tests {@link WifiManager#isEasyConnectDppAkmSupported)} does not crash. 6319 */ 6320 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6321 @Test testIsEasyConnectDppAkmSupported()6322 public void testIsEasyConnectDppAkmSupported() throws Exception { 6323 sWifiManager.isEasyConnectDppAkmSupported(); 6324 } 6325 6326 /** 6327 * Tests {@link WifiManager#getMaxNumberOfChannelsPerNetworkSpecifierRequest)} works 6328 */ 6329 @Test testGetMaxNumberOfChannelsPerNetworkSpecifierRequest()6330 public void testGetMaxNumberOfChannelsPerNetworkSpecifierRequest() { 6331 assertTrue(sWifiManager.getMaxNumberOfChannelsPerNetworkSpecifierRequest() > 0); 6332 } 6333 6334 /** 6335 * Tests {@link WifiManager#isTlsV13Supported)} does not crash. 6336 */ 6337 @Test testIsTlsV13Supported()6338 public void testIsTlsV13Supported() throws Exception { 6339 sWifiManager.isTlsV13Supported(); 6340 } 6341 6342 /** 6343 * Tests {@link WifiManager#isTlsMinimumVersionSupported)} does not crash. 6344 */ 6345 @Test testIsTlsMinimumVersionSupported()6346 public void testIsTlsMinimumVersionSupported() throws Exception { 6347 sWifiManager.isTlsMinimumVersionSupported(); 6348 } 6349 fillQosPolicyParamsList(List<QosPolicyParams> policyParamsList, int size, boolean uniqueIds)6350 private void fillQosPolicyParamsList(List<QosPolicyParams> policyParamsList, 6351 int size, boolean uniqueIds) { 6352 policyParamsList.clear(); 6353 for (int i = 0; i < size; i++) { 6354 int policyId = uniqueIds ? i + 2 : 5; 6355 policyParamsList.add(new QosPolicyParams.Builder( 6356 policyId, QosPolicyParams.DIRECTION_DOWNLINK) 6357 .setUserPriority(QosPolicyParams.USER_PRIORITY_VIDEO_LOW) 6358 .setIpVersion(QosPolicyParams.IP_VERSION_4) 6359 .build()); 6360 } 6361 } 6362 6363 /** 6364 * Check whether the application QoS feature is enabled. 6365 * 6366 * The feature is enabled if the overlay is true, the experiment feature flag 6367 * is true, and the supplicant service implements V2 of the AIDL interface. 6368 */ applicationQosFeatureEnabled()6369 private boolean applicationQosFeatureEnabled() { 6370 boolean overlayEnabled; 6371 try { 6372 WifiResourceUtil resourceUtil = new WifiResourceUtil(sContext); 6373 overlayEnabled = resourceUtil 6374 .getWifiBoolean("config_wifiApplicationCentricQosPolicyFeatureEnabled"); 6375 } catch (Exception e) { 6376 Log.i(TAG, "Unable to retrieve the QoS overlay value"); 6377 return false; 6378 } 6379 6380 // Supplicant V2 is supported if the vendor partition indicates API > T. 6381 boolean halSupport = PropertyUtil.isVndkApiLevelNewerThan(Build.VERSION_CODES.TIRAMISU); 6382 boolean featureFlagEnabled = DeviceConfig.getBoolean(DEVICE_CONFIG_NAMESPACE, 6383 "application_qos_policy_api_enabled", true); 6384 6385 return overlayEnabled && featureFlagEnabled && halSupport; 6386 } 6387 6388 /** 6389 * Tests that {@link WifiManager#addQosPolicies(List, Executor, Consumer)}, 6390 * {@link WifiManager#removeQosPolicies(int[])}, and 6391 * {@link WifiManager#removeAllQosPolicies()} do not crash. 6392 */ 6393 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6394 @Test testAddAndRemoveQosPolicies()6395 public void testAddAndRemoveQosPolicies() throws Exception { 6396 final Mutable<Boolean> callbackReceived = new Mutable<Boolean>(false); 6397 final Mutable<Boolean> policiesRejected = new Mutable<Boolean>(true); 6398 Consumer<List<Integer>> listener = new Consumer<List<Integer>>() { 6399 @Override 6400 public void accept(List value) { 6401 synchronized (mLock) { 6402 callbackReceived.value = true; 6403 List<Integer> statusList = value; 6404 for (Integer status : statusList) { 6405 if (status != WifiManager.QOS_REQUEST_STATUS_FAILURE_UNKNOWN) { 6406 policiesRejected.value = false; 6407 break; 6408 } 6409 } 6410 Log.i(TAG, "Callback received for QoS add request, size=" + statusList.size() 6411 + ", rejected=" + policiesRejected.value); 6412 mLock.notify(); 6413 } 6414 } 6415 }; 6416 6417 // Test that invalid inputs trigger an Exception. 6418 final List<QosPolicyParams> policyParamsList = new ArrayList<>(); 6419 assertThrows("null executor should trigger exception", NullPointerException.class, 6420 () -> sWifiManager.addQosPolicies(policyParamsList, null, listener)); 6421 assertThrows("null listener should trigger exception", NullPointerException.class, 6422 () -> sWifiManager.addQosPolicies(policyParamsList, mExecutor, null)); 6423 assertThrows("null policy list should trigger exception", NullPointerException.class, 6424 () -> sWifiManager.addQosPolicies(null, mExecutor, listener)); 6425 6426 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6427 try { 6428 uiAutomation.adoptShellPermissionIdentity(); 6429 boolean enabled = applicationQosFeatureEnabled(); 6430 6431 // If the feature is disabled, verify that all policies are rejected. 6432 if (!enabled) { 6433 Log.i(TAG, "QoS policy APIs are not enabled"); 6434 fillQosPolicyParamsList(policyParamsList, 4, true); 6435 sWifiManager.addQosPolicies(policyParamsList, mExecutor, listener); 6436 synchronized (mLock) { 6437 mLock.wait(TEST_WAIT_DURATION_MS); 6438 } 6439 assertTrue(callbackReceived.value); 6440 assertTrue(policiesRejected.value); 6441 return; 6442 } 6443 6444 // Empty params list 6445 assertThrows("empty list should trigger exception", IllegalArgumentException.class, 6446 () -> sWifiManager.addQosPolicies(new ArrayList<>(), mExecutor, listener)); 6447 6448 // More than {@link WifiManager#getMaxNumberOfPoliciesPerQosRequest()} 6449 // policies in the list 6450 fillQosPolicyParamsList(policyParamsList, 6451 sWifiManager.getMaxNumberOfPoliciesPerQosRequest() + 1, true); 6452 assertThrows("large list should trigger exception", IllegalArgumentException.class, 6453 () -> sWifiManager.addQosPolicies(policyParamsList, mExecutor, listener)); 6454 6455 // Params list contains duplicate policy ids 6456 fillQosPolicyParamsList(policyParamsList, 4, false); 6457 assertThrows("duplicate ids should trigger exception", IllegalArgumentException.class, 6458 () -> sWifiManager.addQosPolicies(policyParamsList, mExecutor, listener)); 6459 6460 // Valid list 6461 fillQosPolicyParamsList(policyParamsList, 4, true); 6462 sWifiManager.addQosPolicies(policyParamsList, mExecutor, listener); 6463 6464 // sleep to wait for a response from supplicant 6465 synchronized (mLock) { 6466 mLock.wait(TEST_WAIT_DURATION_MS); 6467 } 6468 6469 int[] policyIds = new int[policyParamsList.size()]; 6470 for (int i = 0; i < policyParamsList.size(); i++) { 6471 policyIds[i] = policyParamsList.get(i).getPolicyId(); 6472 } 6473 sWifiManager.removeQosPolicies(policyIds); 6474 6475 // sleep to wait for a response from supplicant 6476 synchronized (mLock) { 6477 mLock.wait(TEST_WAIT_DURATION_MS); 6478 } 6479 sWifiManager.removeAllQosPolicies(); 6480 } catch (Exception e) { 6481 fail("addAndRemoveQosPolicy unexpected Exception " + e); 6482 } finally { 6483 uiAutomation.dropShellPermissionIdentity(); 6484 } 6485 } 6486 qosR3Supported()6487 private boolean qosR3Supported() { 6488 return SdkLevel.isAtLeastV() && Flags.androidVWifiApi(); 6489 } 6490 6491 /** 6492 * Tests the builder and get methods for {@link QosPolicyParams}. 6493 */ 6494 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6495 @Test testQosPolicyParamsBuilder()6496 public void testQosPolicyParamsBuilder() throws Exception { 6497 final int policyId = 5; 6498 final int direction = QosPolicyParams.DIRECTION_DOWNLINK; 6499 final int ipVersion = QosPolicyParams.IP_VERSION_6; 6500 final int dscp = 12; 6501 final int userPriority = QosPolicyParams.USER_PRIORITY_VIDEO_LOW; 6502 final String ipv6Address = "2001:db8:3333:4444:5555:6666:7777:8888"; 6503 final InetAddress srcAddr = InetAddress.getByName(ipv6Address); 6504 final InetAddress dstAddr = InetAddress.getByName(ipv6Address); 6505 final int srcPort = 123; 6506 final int protocol = QosPolicyParams.PROTOCOL_TCP; 6507 final int dstPort = 17; 6508 final int[] dstPortRange = new int[]{15, 22}; 6509 final byte[] flowLabel = new byte[]{17, 18, 19}; 6510 6511 int minServiceIntervalMicros = 2000; 6512 int maxServiceIntervalMicros = 5000; 6513 int minDataRateKbps = 500; 6514 int delayBoundMicros = 200; 6515 QosCharacteristics qosCharacteristics = new QosCharacteristics.Builder( 6516 minServiceIntervalMicros, maxServiceIntervalMicros, 6517 minDataRateKbps, delayBoundMicros).build(); 6518 6519 // Invalid parameter 6520 assertThrows("Invalid dscp should trigger an exception", IllegalArgumentException.class, 6521 () -> new QosPolicyParams.Builder(policyId, direction) 6522 .setDscp(70) 6523 .build()); 6524 6525 // Valid downlink parameters 6526 QosPolicyParams.Builder builder = 6527 new QosPolicyParams.Builder(policyId, QosPolicyParams.DIRECTION_DOWNLINK) 6528 .setSourceAddress(srcAddr) 6529 .setDestinationAddress(dstAddr) 6530 .setUserPriority(userPriority) 6531 .setIpVersion(ipVersion) 6532 .setSourcePort(srcPort) 6533 .setProtocol(protocol) 6534 .setDestinationPort(dstPort) 6535 .setFlowLabel(flowLabel); 6536 if (qosR3Supported()) { 6537 // Optional field for downlink policies 6538 builder.setQosCharacteristics(qosCharacteristics); 6539 } 6540 QosPolicyParams downlinkParams = builder.build(); 6541 6542 assertEquals(policyId, downlinkParams.getPolicyId()); 6543 assertEquals(QosPolicyParams.DIRECTION_DOWNLINK, downlinkParams.getDirection()); 6544 assertEquals(srcAddr, downlinkParams.getSourceAddress()); 6545 assertEquals(dstAddr, downlinkParams.getDestinationAddress()); 6546 assertEquals(userPriority, downlinkParams.getUserPriority()); 6547 assertEquals(ipVersion, downlinkParams.getIpVersion()); 6548 assertEquals(srcPort, downlinkParams.getSourcePort()); 6549 assertEquals(protocol, downlinkParams.getProtocol()); 6550 assertEquals(dstPort, downlinkParams.getDestinationPort()); 6551 assertArrayEquals(flowLabel, downlinkParams.getFlowLabel()); 6552 if (qosR3Supported()) { 6553 assertEquals(qosCharacteristics, downlinkParams.getQosCharacteristics()); 6554 } 6555 6556 if (ApiLevelUtil.getApiLevel() == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 6557 Log.i(TAG, "Uplink policies were not tested, since they are not supported before V"); 6558 return; 6559 } 6560 6561 // Valid uplink parameters 6562 if (qosR3Supported()) { 6563 QosPolicyParams uplinkParams = 6564 new QosPolicyParams.Builder(policyId, QosPolicyParams.DIRECTION_UPLINK) 6565 .setSourceAddress(srcAddr) 6566 .setDestinationAddress(dstAddr) 6567 .setDscp(dscp) 6568 .setSourcePort(srcPort) 6569 .setProtocol(protocol) 6570 .setDestinationPortRange(dstPortRange[0], dstPortRange[1]) 6571 .setQosCharacteristics(qosCharacteristics) 6572 .build(); 6573 assertEquals(policyId, uplinkParams.getPolicyId()); 6574 assertEquals(QosPolicyParams.DIRECTION_UPLINK, uplinkParams.getDirection()); 6575 assertEquals(srcAddr, uplinkParams.getSourceAddress()); 6576 assertEquals(dstAddr, uplinkParams.getDestinationAddress()); 6577 assertEquals(dscp, uplinkParams.getDscp()); 6578 assertEquals(srcPort, uplinkParams.getSourcePort()); 6579 assertEquals(protocol, uplinkParams.getProtocol()); 6580 assertArrayEquals(dstPortRange, uplinkParams.getDestinationPortRange()); 6581 assertEquals(qosCharacteristics, uplinkParams.getQosCharacteristics()); 6582 } 6583 } 6584 6585 /** 6586 * Verifies when the link layer stats polling interval is overridden by 6587 * {@link WifiManager#setLinkLayerStatsPollingInterval(int)}, 6588 * the new interval is set correctly by checking 6589 * {@link WifiManager#getLinkLayerStatsPollingInterval(Executor, Consumer)} 6590 */ 6591 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6592 @Test testSetAndGetLinkLayerStatsPollingInterval()6593 public void testSetAndGetLinkLayerStatsPollingInterval() throws Exception { 6594 AtomicInteger currentInterval = new AtomicInteger(-1); 6595 Consumer<Integer> listener = new Consumer<Integer>() { 6596 @Override 6597 public void accept(Integer value) { 6598 synchronized (mLock) { 6599 currentInterval.set(value); 6600 mLock.notify(); 6601 } 6602 } 6603 }; 6604 6605 // SecurityException 6606 assertThrows(SecurityException.class, 6607 () -> sWifiManager.setLinkLayerStatsPollingInterval( 6608 TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS)); 6609 assertThrows(SecurityException.class, 6610 () -> sWifiManager.getLinkLayerStatsPollingInterval(mExecutor, listener)); 6611 // null executor 6612 assertThrows("null executor should trigger exception", NullPointerException.class, 6613 () -> sWifiManager.getLinkLayerStatsPollingInterval(null, listener)); 6614 // null listener 6615 assertThrows("null listener should trigger exception", NullPointerException.class, 6616 () -> sWifiManager.getLinkLayerStatsPollingInterval(mExecutor, null)); 6617 6618 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6619 6620 try { 6621 uiAutomation.adoptShellPermissionIdentity(); 6622 assertThrows(IllegalArgumentException.class, 6623 () -> sWifiManager.setLinkLayerStatsPollingInterval( 6624 -TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS)); 6625 sWifiManager.setLinkLayerStatsPollingInterval( 6626 TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS); 6627 sWifiManager.getLinkLayerStatsPollingInterval(mExecutor, listener); 6628 synchronized (mLock) { 6629 mLock.wait(TEST_WAIT_DURATION_MS); 6630 } 6631 assertEquals(TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS, currentInterval.get()); 6632 // set the interval to automatic handling after the test 6633 sWifiManager.setLinkLayerStatsPollingInterval(0); 6634 } catch (UnsupportedOperationException ex) { 6635 // Expected if the device does not support this API 6636 } catch (Exception e) { 6637 fail("setLinkLayerStatsPollingInterval / getLinkLayerStatsPollingInterval " 6638 + "unexpected Exception " + e); 6639 } finally { 6640 uiAutomation.dropShellPermissionIdentity(); 6641 } 6642 } 6643 6644 /** 6645 * Tests {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)} and 6646 * {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)}. 6647 */ 6648 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6649 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6650 @Test testMloCapabilities()6651 public void testMloCapabilities() throws Exception { 6652 AtomicInteger linkCount = new AtomicInteger(); 6653 Consumer<Integer> getListener = new Consumer<Integer>() { 6654 @Override 6655 public void accept(Integer value) { 6656 synchronized (mLock) { 6657 linkCount.set(value); 6658 mLock.notify(); 6659 } 6660 } 6661 }; 6662 6663 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6664 try { 6665 uiAutomation.adoptShellPermissionIdentity(); 6666 // Test that invalid inputs trigger an exception. 6667 assertThrows("null executor should trigger exception", NullPointerException.class, 6668 () -> sWifiManager.getMaxMloAssociationLinkCount(null, getListener)); 6669 assertThrows("null listener should trigger exception", NullPointerException.class, 6670 () -> sWifiManager.getMaxMloAssociationLinkCount(mExecutor, null)); 6671 assertThrows("null executor should trigger exception", NullPointerException.class, 6672 () -> sWifiManager.getMaxMloStrLinkCount(null, getListener)); 6673 assertThrows("null listener should trigger exception", NullPointerException.class, 6674 () -> sWifiManager.getMaxMloStrLinkCount(mExecutor, null)); 6675 6676 linkCount.set(Integer.MIN_VALUE); 6677 sWifiManager.getMaxMloStrLinkCount(mExecutor, getListener); 6678 PollingCheck.check("getMaxMloStrLinkCount failed", TEST_WAIT_DURATION_MS, 6679 () -> (linkCount.get() >= -1)); 6680 6681 linkCount.set(Integer.MIN_VALUE); 6682 sWifiManager.getMaxMloAssociationLinkCount(mExecutor, getListener); 6683 PollingCheck.check("getMaxMloAssociationLinkCount failed", TEST_WAIT_DURATION_MS, 6684 () -> (linkCount.get() >= -1)); 6685 } catch (Exception e) { 6686 fail("Unexpected exception " + e); 6687 } finally { 6688 uiAutomation.dropShellPermissionIdentity(); 6689 } 6690 } 6691 /** 6692 * Tests {@link WifiManager#setLinkMode} and {@link WifiManager#getLinkMode} works 6693 */ 6694 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6695 @Test testMloMode()6696 public void testMloMode() { 6697 // Get listener. 6698 AtomicInteger getMode = new AtomicInteger(); 6699 Consumer<Integer> getListener = new Consumer<Integer>() { 6700 @Override 6701 public void accept(Integer value) { 6702 synchronized (mLock) { 6703 getMode.set(value); 6704 mLock.notify(); 6705 } 6706 } 6707 }; 6708 // Set listener. 6709 AtomicBoolean setStatus = new AtomicBoolean(); 6710 Consumer<Boolean> setListener = new Consumer<Boolean>() { 6711 @Override 6712 public void accept(Boolean value) { 6713 synchronized (mLock) { 6714 setStatus.set(value); 6715 mLock.notify(); 6716 } 6717 } 6718 }; 6719 // Test that invalid inputs trigger an exception. 6720 assertThrows("null executor should trigger exception", NullPointerException.class, 6721 () -> sWifiManager.setMloMode(WifiManager.MLO_MODE_DEFAULT, null, setListener)); 6722 assertThrows("null listener should trigger exception", NullPointerException.class, 6723 () -> sWifiManager.setMloMode(WifiManager.MLO_MODE_DEFAULT, mExecutor, null)); 6724 assertThrows("null executor should trigger exception", NullPointerException.class, 6725 () -> sWifiManager.getMloMode(null, getListener)); 6726 assertThrows("null listener should trigger exception", NullPointerException.class, 6727 () -> sWifiManager.getMloMode(mExecutor, null)); 6728 6729 // Test that invalid inputs trigger an IllegalArgumentException. 6730 assertThrows("Invalid mode", IllegalArgumentException.class, 6731 () -> sWifiManager.setMloMode(-1, mExecutor, setListener)); 6732 assertThrows("Invalid mode", IllegalArgumentException.class, 6733 () -> sWifiManager.setMloMode(1000, mExecutor, setListener)); 6734 6735 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6736 // Test set if supported. 6737 try { 6738 uiAutomation.adoptShellPermissionIdentity(); 6739 // Check getMloMode() returns values in range. 6740 sWifiManager.getMloMode(mExecutor, getListener); 6741 assertThat(getMode.get()).isIn(Range.closed(WifiManager.MLO_MODE_DEFAULT, 6742 WifiManager.MLO_MODE_LOW_POWER)); 6743 // Try to set default MLO mode and get. 6744 sWifiManager.setMloMode(WifiManager.MLO_MODE_DEFAULT, mExecutor, setListener); 6745 if (setStatus.get()) { 6746 sWifiManager.getMloMode(mExecutor, getListener); 6747 assertTrue(getMode.get() == WifiManager.MLO_MODE_DEFAULT); 6748 } 6749 // Try to set low latency MLO mode and get. 6750 sWifiManager.setMloMode(WifiManager.MLO_MODE_LOW_LATENCY, mExecutor, setListener); 6751 if (setStatus.get()) { 6752 sWifiManager.getMloMode(mExecutor, getListener); 6753 assertTrue(getMode.get() == WifiManager.MLO_MODE_LOW_LATENCY); 6754 } 6755 // Try to set high throughput MLO mode and get. 6756 sWifiManager.setMloMode(WifiManager.MLO_MODE_HIGH_THROUGHPUT, mExecutor, setListener); 6757 if (setStatus.get()) { 6758 sWifiManager.getMloMode(mExecutor, getListener); 6759 assertTrue(getMode.get() == WifiManager.MLO_MODE_DEFAULT); 6760 } 6761 // Try to set low power MLO mode and get. 6762 sWifiManager.setMloMode(WifiManager.MLO_MODE_LOW_POWER, mExecutor, setListener); 6763 if (setStatus.get()) { 6764 sWifiManager.getMloMode(mExecutor, getListener); 6765 assertTrue(getMode.get() == WifiManager.MLO_MODE_DEFAULT); 6766 } 6767 } catch (Exception e) { 6768 fail("Unexpected exception " + e); 6769 } finally { 6770 uiAutomation.dropShellPermissionIdentity(); 6771 } 6772 } 6773 6774 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6775 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6776 @Test testGetSupportedSimultaneousBandCombinations()6777 public void testGetSupportedSimultaneousBandCombinations() { 6778 AtomicInteger nEntries = new AtomicInteger(); 6779 Consumer<List<int[]>> getListener = new Consumer<List<int[]>>() { 6780 @Override 6781 public void accept(List<int[]> bands) { 6782 synchronized (mLock) { 6783 nEntries.set(bands.size()); 6784 mLock.notify(); 6785 } 6786 } 6787 }; 6788 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6789 try { 6790 uiAutomation.adoptShellPermissionIdentity(); 6791 6792 assertThrows("null executor should trigger exception", NullPointerException.class, 6793 () -> sWifiManager.getSupportedSimultaneousBandCombinations(null, getListener)); 6794 assertThrows("null listener should trigger exception", NullPointerException.class, 6795 () -> sWifiManager.getSupportedSimultaneousBandCombinations(mExecutor, null)); 6796 6797 nEntries.set(-1); 6798 sWifiManager.getSupportedSimultaneousBandCombinations(mExecutor, getListener); 6799 PollingCheck.check("getSupportedSimultaneousBandCombinations failed", 6800 TEST_WAIT_DURATION_MS, 6801 () -> (nEntries.get() > -1)); 6802 } catch (Exception e) { 6803 fail("Unexpected exception " + e); 6804 } finally { 6805 uiAutomation.dropShellPermissionIdentity(); 6806 } 6807 } 6808 6809 /** 6810 * Tests {@link WifiManager#isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} 6811 * and {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} 6812 */ 6813 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 6814 @Test testGetAndSetThirdPartyAppEnablingWifiConfirmationDialogEnabled()6815 public void testGetAndSetThirdPartyAppEnablingWifiConfirmationDialogEnabled() { 6816 // Expect a SecurityException without the required permissions. 6817 assertThrows(SecurityException.class, 6818 () -> sWifiManager.isThirdPartyAppEnablingWifiConfirmationDialogEnabled()); 6819 assertThrows(SecurityException.class, 6820 () -> sWifiManager.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(true)); 6821 6822 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 6823 try { 6824 uiAutomation.adoptShellPermissionIdentity(); 6825 6826 // Store a new value. 6827 boolean defaultVal = 6828 sWifiManager.isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); 6829 boolean newVal = !defaultVal; 6830 sWifiManager.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(newVal); 6831 assertEquals(newVal, 6832 sWifiManager.isThirdPartyAppEnablingWifiConfirmationDialogEnabled()); 6833 6834 // Restore the original value. 6835 sWifiManager.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(defaultVal); 6836 assertEquals(defaultVal, 6837 sWifiManager.isThirdPartyAppEnablingWifiConfirmationDialogEnabled()); 6838 } catch (Exception e) { 6839 fail("Unexpected exception " + e); 6840 } finally { 6841 uiAutomation.dropShellPermissionIdentity(); 6842 } 6843 } 6844 6845 static class TestWifiLowLatencyLockListener implements WifiManager.WifiLowLatencyLockListener { 6846 private boolean mIsActivated = false; 6847 private int[] mOwnerUids = null; 6848 private int[] mActiveUids = null; 6849 clear()6850 public void clear() { 6851 mIsActivated = false; 6852 mOwnerUids = null; 6853 mActiveUids = null; 6854 } 6855 6856 @Override onActivatedStateChanged(boolean activated)6857 public void onActivatedStateChanged(boolean activated) { 6858 mIsActivated = activated; 6859 } 6860 6861 @Override onOwnershipChanged(@onNull int[] ownerUids)6862 public void onOwnershipChanged(@NonNull int[] ownerUids) { 6863 mOwnerUids = ownerUids; 6864 } 6865 6866 @Override onActiveUsersChanged(@onNull int[] activeUids)6867 public void onActiveUsersChanged(@NonNull int[] activeUids) { 6868 mActiveUids = activeUids; 6869 } 6870 isActivated()6871 public boolean isActivated() { 6872 return mIsActivated; 6873 } 6874 isLockOwned(int myUid)6875 public boolean isLockOwned(int myUid) { 6876 if (mOwnerUids == null) return false; 6877 for (int uid : mOwnerUids) { 6878 if (uid == myUid) return true; 6879 } 6880 return false; 6881 } 6882 isActiveLockUser(int myUid)6883 public boolean isActiveLockUser(int myUid) { 6884 if (mActiveUids == null) return false; 6885 for (int uid : mActiveUids) { 6886 if (uid == myUid) return true; 6887 } 6888 return false; 6889 } 6890 } 6891 6892 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 6893 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6894 @Test testWifiLowLatencyLockListener()6895 public void testWifiLowLatencyLockListener() throws Exception { 6896 TestWifiLowLatencyLockListener testListener = new TestWifiLowLatencyLockListener(); 6897 // Verify permission check 6898 assertThrows(SecurityException.class, 6899 () -> sWifiManager.addWifiLowLatencyLockListener(mExecutor, testListener)); 6900 6901 // Disable wifi 6902 setWifiEnabled(false); 6903 waitForDisconnection(); 6904 6905 WifiLock wifiLowLatencyLock = sWifiManager.createWifiLock( 6906 WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 6907 TAG); 6908 6909 try { 6910 // Register listener then enable wifi 6911 ShellIdentityUtils.invokeWithShellPermissions( 6912 () -> sWifiManager.addWifiLowLatencyLockListener(mExecutor, testListener)); 6913 setWifiEnabled(true); 6914 6915 // Trigger a scan & wait for connection to one of the saved networks. 6916 sWifiManager.startScan(); 6917 waitForConnection(); 6918 6919 // TODO: b/281356259 - Move this to a foreground activity. 6920 ShellIdentityUtils.invokeWithShellPermissions(() -> wifiLowLatencyLock.acquire()); 6921 6922 if (sWifiManager.isLowLatencyModeSupported()) { 6923 PollingCheck.check("Lock is not activated!", 1_000, 6924 () -> testListener.isActivated()); 6925 } 6926 6927 PollingCheck.check("Lock is not owned!", 1_000, 6928 () -> testListener.isLockOwned(myUid())); 6929 6930 if (sWifiManager.isLowLatencyModeSupported()) { 6931 PollingCheck.check("Not an active Lock user!", 1_000, 6932 () -> testListener.isActiveLockUser(myUid())); 6933 } 6934 6935 ShellIdentityUtils.invokeWithShellPermissions(() -> wifiLowLatencyLock.release()); 6936 6937 // Note: The lock cannot be tested for deactivation after release because other 6938 // applications can still keep it active. 6939 6940 PollingCheck.check("Still owns the Lock after release!", 1_000, 6941 () -> !testListener.isLockOwned(myUid())); 6942 } catch (Exception e) { 6943 fail("Unexpected exception " + e); 6944 } finally { 6945 testListener.clear(); 6946 sWifiManager.removeWifiLowLatencyLockListener(testListener); 6947 } 6948 } 6949 6950 /** 6951 * Tests the builder and get methods for {@link OuiKeyedData}. 6952 */ 6953 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6954 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 6955 codeName = "VanillaIceCream") 6956 @Test testOuiKeyedDataBuilder()6957 public void testOuiKeyedDataBuilder() throws Exception { 6958 int oui = 0x00112233; 6959 PersistableBundle data = new PersistableBundle(); 6960 String key = "intField"; 6961 data.putInt(key, 12345); 6962 6963 assertThrows("Zero OUI should trigger an exception", IllegalArgumentException.class, 6964 () -> new OuiKeyedData.Builder(0, data).build()); 6965 assertThrows(">24-bit OUI should trigger an exception", IllegalArgumentException.class, 6966 () -> new OuiKeyedData.Builder(0x11223344, data).build()); 6967 assertThrows("Null data should trigger an exception", IllegalArgumentException.class, 6968 () -> new OuiKeyedData.Builder(oui, null).build()); 6969 6970 OuiKeyedData ouiKeyedData = new OuiKeyedData.Builder(oui, data).build(); 6971 assertEquals(oui, ouiKeyedData.getOui()); 6972 assertTrue(data.keySet().equals(ouiKeyedData.getData().keySet())); 6973 assertEquals(data.getInt(key), ouiKeyedData.getData().getInt(key)); 6974 } 6975 6976 /** 6977 * Tests {@link WifiManager#isWepSupported()} does not crash. 6978 */ 6979 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6980 @Test testIsWepSupported()6981 public void testIsWepSupported() throws Exception { 6982 sWifiManager.isWepSupported(); 6983 } 6984 6985 /** 6986 * Tests {@link WifiManager#isWpaPersonalSupported()} does not crash. 6987 */ 6988 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6989 @Test testIsWpaPersonalSupported()6990 public void testIsWpaPersonalSupported() throws Exception { 6991 sWifiManager.isWpaPersonalSupported(); 6992 } 6993 6994 /** 6995 * Tests {@link WifiManager#setWepAllowed()} and 6996 * {@link WifiManager#queryWepAllowed()}. 6997 */ 6998 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 6999 @Test testSetAndQueryWepAllowed()7000 public void testSetAndQueryWepAllowed() throws Exception { 7001 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7002 Mutable<Boolean> isQuerySucceeded = new Mutable<Boolean>(false); 7003 boolean currentWepAllowed = false; 7004 boolean isRestoreRequired = false; 7005 long now, deadline; 7006 try { 7007 uiAutomation.adoptShellPermissionIdentity(); 7008 Mutable<Boolean> isWepAllowed = new Mutable<Boolean>(false); 7009 sWifiManager.queryWepAllowed(mExecutor, 7010 new Consumer<Boolean>() { 7011 @Override 7012 public void accept(Boolean value) { 7013 synchronized (mLock) { 7014 isWepAllowed.value = value; 7015 isQuerySucceeded.value = true; 7016 mLock.notify(); 7017 } 7018 } 7019 }); 7020 synchronized (mLock) { 7021 now = System.currentTimeMillis(); 7022 deadline = now + TEST_WAIT_DURATION_MS; 7023 while (!isQuerySucceeded.value && now < deadline) { 7024 mLock.wait(deadline - now); 7025 now = System.currentTimeMillis(); 7026 } 7027 } 7028 assertTrue(isQuerySucceeded.value); 7029 // Reset for next query 7030 isQuerySucceeded.value = false; 7031 currentWepAllowed = isWepAllowed.value; 7032 isRestoreRequired = true; 7033 sWifiManager.setWepAllowed(!currentWepAllowed); 7034 sWifiManager.queryWepAllowed(mExecutor, 7035 new Consumer<Boolean>() { 7036 @Override 7037 public void accept(Boolean value) { 7038 synchronized (mLock) { 7039 isWepAllowed.value = value; 7040 isQuerySucceeded.value = true; 7041 mLock.notify(); 7042 } 7043 } 7044 }); 7045 synchronized (mLock) { 7046 now = System.currentTimeMillis(); 7047 deadline = now + TEST_WAIT_DURATION_MS; 7048 while (!isQuerySucceeded.value && now < deadline) { 7049 mLock.wait(deadline - now); 7050 now = System.currentTimeMillis(); 7051 } 7052 } 7053 assertEquals(isWepAllowed.value, !currentWepAllowed); 7054 } finally { 7055 if (isRestoreRequired) { 7056 sWifiManager.setWepAllowed(currentWepAllowed); 7057 } 7058 uiAutomation.dropShellPermissionIdentity(); 7059 } 7060 } 7061 7062 /** 7063 * Tests {@link WifiManager#enableMscs(MscsParams)}, {@link WifiManager#disableMscs()}, 7064 * and all get/set methods in {@link MscsParams}. 7065 */ 7066 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7067 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 7068 codeName = "VanillaIceCream") 7069 @Test testEnableAndDisableMscs()7070 public void testEnableAndDisableMscs() { 7071 int frameClassifierFields = MscsParams.FRAME_CLASSIFIER_IP_VERSION; 7072 int userPriorityBitmap = 0; // don't match any user priorities using MSCS 7073 int userPriorityLimit = 7; 7074 int streamTimeoutUs = 30000000; // 30 seconds (value is longer than TEST_WAIT_DURATION_MS) 7075 MscsParams params = new MscsParams.Builder() 7076 .setFrameClassifierFields(frameClassifierFields) 7077 .setUserPriorityBitmap(userPriorityBitmap) 7078 .setUserPriorityLimit(userPriorityLimit) 7079 .setStreamTimeoutUs(streamTimeoutUs) 7080 .build(); 7081 assertEquals(frameClassifierFields, params.getFrameClassifierFields()); 7082 assertEquals(userPriorityBitmap, params.getUserPriorityBitmap()); 7083 assertEquals(userPriorityLimit, params.getUserPriorityLimit()); 7084 assertEquals(streamTimeoutUs, params.getStreamTimeoutUs()); 7085 7086 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7087 try { 7088 uiAutomation.adoptShellPermissionIdentity(); 7089 sWifiManager.enableMscs(params); 7090 synchronized (mLock) { 7091 // Wait for the request to get sent to the AP. 7092 mLock.wait(TEST_WAIT_DURATION_MS); 7093 } 7094 sWifiManager.disableMscs(); 7095 } catch (Exception e) { 7096 fail("testEnableAndDisableMscs encountered an exception: " + e); 7097 } finally { 7098 uiAutomation.dropShellPermissionIdentity(); 7099 } 7100 } 7101 7102 /** 7103 * Tests the result from {@link WifiUriParser#parseUri(String)} can be added. 7104 */ 7105 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7106 @Test testZxingNetworkFromUriParserCanBeAdded()7107 public void testZxingNetworkFromUriParserCanBeAdded() throws Exception { 7108 String testUriZx = "WIFI:S:testAbC;T:nopass"; 7109 UriParserResults result = WifiUriParser.parseUri(testUriZx); 7110 assertNotNull(result); 7111 assertEquals(result.getUriScheme(), UriParserResults.URI_SCHEME_ZXING_WIFI_NETWORK_CONFIG); 7112 WifiConfiguration config = result.getWifiConfiguration(); 7113 assertNotNull(config); 7114 // These below API's only work with privileged permissions (obtained via shell identity 7115 // for test) 7116 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation() 7117 .getUiAutomation(); 7118 int networkId = INVALID_NETWORK_ID; 7119 try { 7120 uiAutomation.adoptShellPermissionIdentity(); 7121 // Verify that the network is added 7122 networkId = sWifiManager.addNetwork(config); 7123 assertNotEquals(INVALID_NETWORK_ID, networkId); 7124 } finally { 7125 if (networkId != INVALID_NETWORK_ID) { 7126 // Clean up the previously added network 7127 sWifiManager.removeNetwork(networkId); 7128 } 7129 uiAutomation.dropShellPermissionIdentity(); 7130 } 7131 } 7132 7133 /* 7134 * Tests the builder and get methods for {@link QosCharacteristics}. 7135 */ 7136 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7137 @Test testQosCharacteristicsBuilder()7138 public void testQosCharacteristicsBuilder() { 7139 int minServiceIntervalMicros = 2000; 7140 int maxServiceIntervalMicros = 5000; 7141 int minDataRateKbps = 500; 7142 int delayBoundMicros = 200; 7143 int maxMsduSizeOctets = 4; 7144 int serviceStartTimeMicros = 250; 7145 int serviceStartTimeLinkId = 0x5; 7146 int meanDataRateKbps = 1500; 7147 int burstSizeOctets = 2; 7148 int msduLifetimeMillis = 400; 7149 int deliveryRatio = QosCharacteristics.DELIVERY_RATIO_99; 7150 int countExponent = 5; 7151 7152 QosCharacteristics qosCharacteristics = new QosCharacteristics.Builder( 7153 minServiceIntervalMicros, maxServiceIntervalMicros, 7154 minDataRateKbps, delayBoundMicros) 7155 .setBurstSizeOctets(burstSizeOctets) 7156 .setMaxMsduSizeOctets(maxMsduSizeOctets) 7157 .setServiceStartTimeInfo(serviceStartTimeMicros, serviceStartTimeLinkId) 7158 .setMeanDataRateKbps(meanDataRateKbps) 7159 .setMsduLifetimeMillis(msduLifetimeMillis) 7160 .setMsduDeliveryInfo(deliveryRatio, countExponent) 7161 .build(); 7162 7163 assertEquals(minServiceIntervalMicros, qosCharacteristics.getMinServiceIntervalMicros()); 7164 assertEquals(maxServiceIntervalMicros, qosCharacteristics.getMaxServiceIntervalMicros()); 7165 assertEquals(minDataRateKbps, qosCharacteristics.getMinDataRateKbps()); 7166 assertEquals(delayBoundMicros, qosCharacteristics.getDelayBoundMicros()); 7167 assertEquals(maxMsduSizeOctets, qosCharacteristics.getMaxMsduSizeOctets()); 7168 assertEquals(serviceStartTimeMicros, qosCharacteristics.getServiceStartTimeMicros()); 7169 assertEquals(serviceStartTimeLinkId, qosCharacteristics.getServiceStartTimeLinkId()); 7170 assertEquals(meanDataRateKbps, qosCharacteristics.getMeanDataRateKbps()); 7171 assertEquals(burstSizeOctets, qosCharacteristics.getBurstSizeOctets()); 7172 assertEquals(msduLifetimeMillis, qosCharacteristics.getMsduLifetimeMillis()); 7173 assertEquals(deliveryRatio, qosCharacteristics.getDeliveryRatio()); 7174 assertEquals(countExponent, qosCharacteristics.getCountExponent()); 7175 } 7176 querySendDhcpHostnameRestrictionSynchronous()7177 private int querySendDhcpHostnameRestrictionSynchronous() throws Exception { 7178 Mutable<Integer> queriedRestriction = new Mutable<>(0); 7179 Mutable<Boolean> isQuerySucceeded = new Mutable<>(false); 7180 sWifiManager.querySendDhcpHostnameRestriction(mExecutor, (value) -> { 7181 synchronized (mLock) { 7182 queriedRestriction.value = value; 7183 isQuerySucceeded.value = true; 7184 mLock.notify(); 7185 } 7186 }); 7187 synchronized (mLock) { 7188 long now = System.currentTimeMillis(); 7189 long deadline = now + TEST_WAIT_DURATION_MS; 7190 while (!isQuerySucceeded.value && now < deadline) { 7191 mLock.wait(deadline - now); 7192 now = System.currentTimeMillis(); 7193 } 7194 } 7195 assertTrue(isQuerySucceeded.value); 7196 return queriedRestriction.value; 7197 } 7198 7199 /** 7200 * Tests {@link WifiManager#setSendDhcpHostnameRestriction(int)} and 7201 * {@link WifiManager#querySendDhcpHostnameRestriction(Executor, IntConsumer)}. 7202 */ 7203 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7204 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 7205 codeName = "VanillaIceCream") 7206 @Test testSetAndQuerySendDhcpHostnameRestriction()7207 public void testSetAndQuerySendDhcpHostnameRestriction() throws Exception { 7208 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7209 int previousRestriction = 0; 7210 boolean isRestoreRequired = false; 7211 try { 7212 uiAutomation.adoptShellPermissionIdentity(); 7213 previousRestriction = querySendDhcpHostnameRestrictionSynchronous(); 7214 7215 sWifiManager.setSendDhcpHostnameRestriction( 7216 WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN); 7217 isRestoreRequired = true; 7218 assertEquals(querySendDhcpHostnameRestrictionSynchronous(), 7219 WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN); 7220 7221 sWifiManager.setSendDhcpHostnameRestriction( 7222 WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN 7223 | WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE); 7224 assertEquals(querySendDhcpHostnameRestrictionSynchronous(), 7225 WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN 7226 | WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE); 7227 } finally { 7228 if (isRestoreRequired) { 7229 sWifiManager.setSendDhcpHostnameRestriction(previousRestriction); 7230 } 7231 uiAutomation.dropShellPermissionIdentity(); 7232 } 7233 } 7234 7235 /** 7236 * Tests {@link WifiConfiguration#setWifi7Enabled(boolean)}. Validate default behavior, disable 7237 * Wi-Fi 7 and Enable Wi-Fi 7. 7238 */ 7239 @ApiTest(apis = {"android.net.wifi.WifiConfiguration#setWifi7Enabled", 7240 "android.net.wifi.WifiConfiguration#isWifi7Enabled"}) 7241 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7242 @Test testEnableWifi7()7243 public void testEnableWifi7() throws Exception { 7244 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7245 TestActionListener actionListener = new TestActionListener(mLock); 7246 setWifiEnabled(true); 7247 WifiConfiguration wifi7Network = null; 7248 try { 7249 uiAutomation.adoptShellPermissionIdentity(); 7250 // Make sure device supports Wi-Fi 7 7251 assumeTrue(sWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)); 7252 7253 List<WifiConfiguration> savedNetworks = sWifiManager.getConfiguredNetworks(); 7254 wifi7Network = TestHelper.findFirstAvailableSavedNetwork(sWifiManager, 7255 savedNetworks, TestHelper.AP_CAPABILITY_BIT_WIFI7); 7256 // TODO: b/322011012 7257 assumeTrue("Unable to locate Wi-Fi 7 networks in range.\n", wifi7Network != null); 7258 7259 // Default behavior: check new connection is Wi-Fi 7 7260 sWifiManager.disconnect(); 7261 waitForDisconnection(); 7262 assertTrue(wifi7Network.isWifi7Enabled()); 7263 sWifiManager.connect(wifi7Network.networkId, actionListener); 7264 waitForConnection(); 7265 assertTrue(sWifiManager.getConnectionInfo().getWifiStandard() 7266 == ScanResult.WIFI_STANDARD_11BE); 7267 7268 // Disable Wi-Fi 7 while connected: check new connection is not Wi-Fi 7 7269 wifi7Network.setWifi7Enabled(false); 7270 assertFalse(wifi7Network.isWifi7Enabled()); 7271 sWifiManager.updateNetwork(wifi7Network); 7272 waitForConnection(); 7273 assertTrue(sWifiManager.getConnectionInfo().getWifiStandard() 7274 != ScanResult.WIFI_STANDARD_11BE); 7275 7276 // Enable Wi-Fi 7: check new connection is Wi-Fi 7 7277 sWifiManager.disconnect(); 7278 waitForDisconnection(); 7279 wifi7Network.setWifi7Enabled(true); 7280 assertTrue(wifi7Network.isWifi7Enabled()); 7281 sWifiManager.connect(wifi7Network.networkId, actionListener); 7282 waitForConnection(); 7283 assertTrue(sWifiManager.getConnectionInfo().getWifiStandard() 7284 == ScanResult.WIFI_STANDARD_11BE); 7285 7286 } finally { 7287 // Restore 7288 if (wifi7Network != null) { 7289 wifi7Network.setWifi7Enabled(true); 7290 } 7291 uiAutomation.dropShellPermissionIdentity(); 7292 } 7293 } 7294 7295 class TestTwtSessionCallback implements TwtSessionCallback { 7296 final AtomicReference<TwtSession> mTwtSession = new AtomicReference<>(); 7297 final AtomicInteger mTwtTeardownReasonCode = new AtomicInteger(-1); 7298 final AtomicInteger mTwtErrorCode = new AtomicInteger(-1); 7299 7300 @Override onFailure(int errorCode)7301 public void onFailure(int errorCode) { 7302 synchronized (mLock) { 7303 mTwtErrorCode.set(errorCode); 7304 mLock.notify(); 7305 } 7306 } 7307 7308 @Override onTeardown(int reasonCode)7309 public void onTeardown(int reasonCode) { 7310 synchronized (mLock) { 7311 mTwtTeardownReasonCode.set(reasonCode); 7312 mLock.notify(); 7313 } 7314 } 7315 7316 @Override onCreate(TwtSession twtSession)7317 public void onCreate(TwtSession twtSession) { 7318 synchronized (mLock) { 7319 mTwtSession.set(twtSession); 7320 mLock.notify(); 7321 } 7322 } 7323 } 7324 7325 /** 7326 * Validate setting up a TWT session if device supports and get stats and finally close. If the 7327 * connection is multi-link, pick the first link and set up the TWT session. 7328 */ 7329 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7330 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = 7331 "VanillaIceCream") 7332 @Test 7333 @ApiTest(apis = {"android.net.wifi.WifiManager#getTwtCapabilities", 7334 "android.net.wifi.WifiManager#twtSessionSetup", 7335 "android.net.wifi.twt.TwtSession#getStats", 7336 "android.net.wifi.twt.TwtSession#teardown", 7337 "android.net.wifi.twt.TwtSession#getWakeDurationMicros", 7338 "android.net.wifi.twt.TwtSession#getWakeIntervalMicros", 7339 "android.net.wifi.twt.TwtSession#getMloLinkId", 7340 "android.net.wifi.twt.TwtRequest#Builder", 7341 "android.net.wifi.twt.TwtRequest.Builder#setLinkId", 7342 "android.net.wifi.twt.TwtRequest#getMinWakeDurationMicros", 7343 "android.net.wifi.twt.TwtRequest#getMaxWakeDurationMicros", 7344 "android.net.wifi.twt.TwtRequest#getMinWakeIntervalMicros", 7345 "android.net.wifi.twt.TwtRequest#getMaxWakeIntervalMicros", 7346 "android.net.wifi.twt.TwtRequest#getLinkId"}) testTwt()7347 public void testTwt() throws Exception { 7348 AtomicReference<Bundle> twtCapabilities = new AtomicReference<>(); 7349 AtomicReference<Bundle> twtStats = new AtomicReference<>(); 7350 long now, deadline; 7351 Consumer<Bundle> twtCapabilityCallback = capabilities -> { 7352 synchronized (mLock) { 7353 twtCapabilities.set(capabilities); 7354 mLock.notify(); 7355 } 7356 }; 7357 Consumer<Bundle> twtStatsCallback = stats -> { 7358 synchronized (mLock) { 7359 twtStats.set(stats); 7360 mLock.notify(); 7361 } 7362 }; 7363 TestTwtSessionCallback testTwtSessionCallback = new TestTwtSessionCallback(); 7364 TestActionListener actionListener = new TestActionListener(mLock); 7365 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7366 7367 try { 7368 uiAutomation.adoptShellPermissionIdentity(); 7369 sWifiManager.getTwtCapabilities(mExecutor, twtCapabilityCallback); 7370 synchronized (mLock) { 7371 now = System.currentTimeMillis(); 7372 deadline = now + TEST_WAIT_DURATION_MS; 7373 while (twtCapabilities.get() == null && now < deadline) { 7374 mLock.wait(deadline - now); 7375 now = System.currentTimeMillis(); 7376 } 7377 } 7378 assertNotNull("getTwtCapabilities() timed out !", twtCapabilities.get()); 7379 // Assume device is a TWT requester 7380 assumeTrue(twtCapabilities.get().getBoolean( 7381 WifiManager.TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER)); 7382 assertTrue(twtCapabilities.get().getInt( 7383 WifiManager.TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS) >= 0); 7384 assertTrue(twtCapabilities.get().getInt( 7385 WifiManager.TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS) >= 0); 7386 assertTrue(twtCapabilities.get().getLong( 7387 WifiManager.TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS) >= 0); 7388 assertTrue(twtCapabilities.get().getLong( 7389 WifiManager.TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS) >= 0); 7390 7391 // Connect to an available TWT responder network 7392 List<WifiConfiguration> savedNetworks = sWifiManager.getConfiguredNetworks(); 7393 WifiConfiguration twtNetwork = TestHelper.findFirstAvailableSavedNetwork(sWifiManager, 7394 savedNetworks, TestHelper.AP_CAPABILITY_BIT_TWT_RESPONDER); 7395 // TODO: Make it an assert once the TWT setup is available for CTS test 7396 assumeTrue("Unable to locate TWT capable networks in range.\n", twtNetwork != null); 7397 sWifiManager.disconnect(); 7398 waitForDisconnection(); 7399 sWifiManager.connect(twtNetwork.networkId, actionListener); 7400 waitForConnection(); 7401 7402 // Get the first link id, if the connection is multi-link 7403 List<MloLink> mloLinks = sWifiManager.getConnectionInfo().getAssociatedMloLinks(); 7404 int linkId = MloLink.INVALID_MLO_LINK_ID; 7405 if (!mloLinks.isEmpty()) { 7406 linkId = mloLinks.getFirst().getLinkId(); 7407 } 7408 7409 // Build and validate twtRequest 7410 int minWakeDuration = twtCapabilities.get().getInt( 7411 WifiManager.TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS); 7412 int maxWakeDuration = twtCapabilities.get().getInt( 7413 WifiManager.TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS); 7414 long minWakeInterval = twtCapabilities.get().getLong( 7415 WifiManager.TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS); 7416 long maxWakeInterval = twtCapabilities.get().getLong( 7417 WifiManager.TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS); 7418 TwtRequest.Builder builder = new TwtRequest.Builder(minWakeDuration, maxWakeDuration, 7419 minWakeInterval, maxWakeInterval); 7420 if (linkId != MloLink.INVALID_MLO_LINK_ID) { 7421 builder.setLinkId(linkId); 7422 } 7423 TwtRequest twtRequest = builder.build(); 7424 assertEquals(twtRequest.getMinWakeDurationMicros(), minWakeDuration); 7425 assertEquals(twtRequest.getMaxWakeDurationMicros(), maxWakeDuration); 7426 assertEquals(twtRequest.getMinWakeIntervalMicros(), minWakeInterval); 7427 assertEquals(twtRequest.getMaxWakeIntervalMicros(), maxWakeInterval); 7428 assertEquals(twtRequest.getLinkId(), linkId); 7429 7430 // Verify TWT session setup 7431 sWifiManager.setupTwtSession(twtRequest, mExecutor, testTwtSessionCallback); 7432 synchronized (mLock) { 7433 now = System.currentTimeMillis(); 7434 deadline = now + TEST_WAIT_DURATION_MS; 7435 while (testTwtSessionCallback.mTwtSession.get() == null && now < deadline) { 7436 mLock.wait(deadline - now); 7437 now = System.currentTimeMillis(); 7438 } 7439 } 7440 assertNotNull("setupTwtSession() timed out !", 7441 testTwtSessionCallback.mTwtSession.get()); 7442 assertTrue(testTwtSessionCallback.mTwtSession.get().getWakeDurationMicros() > 0); 7443 assertTrue(testTwtSessionCallback.mTwtSession.get().getWakeIntervalMicros() > 0); 7444 assertTrue(testTwtSessionCallback.mTwtSession.get().getMloLinkId() == linkId); 7445 7446 // Verify TWT session get stats 7447 testTwtSessionCallback.mTwtSession.get().getStats(mExecutor, twtStatsCallback); 7448 synchronized (mLock) { 7449 now = System.currentTimeMillis(); 7450 deadline = now + TEST_WAIT_DURATION_MS; 7451 while (twtStats.get() == null && now < deadline) { 7452 mLock.wait(deadline - now); 7453 now = System.currentTimeMillis(); 7454 } 7455 } 7456 assertNotNull("TwtSession#getStats() timed out !", twtStats.get()); 7457 assertTrue(twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_AVERAGE_TX_PACKET_COUNT) 7458 >= 0); 7459 assertTrue(twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_AVERAGE_RX_PACKET_COUNT) 7460 >= 0); 7461 assertTrue(twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_AVERAGE_TX_PACKET_SIZE) 7462 >= 0); 7463 assertTrue(twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_AVERAGE_RX_PACKET_SIZE) 7464 >= 0); 7465 assertTrue( 7466 twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_AVERAGE_EOSP_DURATION_MICROS) 7467 >= 0); 7468 assertTrue(twtStats.get().getInt(TwtSession.TWT_STATS_KEY_INT_EOSP_COUNT) >= 0); 7469 7470 // Verify TWT session teardown 7471 testTwtSessionCallback.mTwtSession.get().teardown(); 7472 synchronized (mLock) { 7473 now = System.currentTimeMillis(); 7474 deadline = now + TEST_WAIT_DURATION_MS; 7475 while (testTwtSessionCallback.mTwtTeardownReasonCode.get() == -1 7476 && now < deadline) { 7477 mLock.wait(deadline - now); 7478 now = System.currentTimeMillis(); 7479 } 7480 } 7481 assertNotEquals("TwtSession#teardown() timed out !", -1, 7482 testTwtSessionCallback.mTwtTeardownReasonCode.get()); 7483 assertTrue(testTwtSessionCallback.mTwtTeardownReasonCode.get() 7484 == TwtSessionCallback.TWT_REASON_CODE_LOCALLY_REQUESTED); 7485 } finally { 7486 uiAutomation.dropShellPermissionIdentity(); 7487 } 7488 } 7489 7490 /** 7491 * Tests {@link WifiManager#isD2dSupportedWhenInfraStaDisabled()}, 7492 * {@link WifiManager#setD2dAllowedWhenInfraStaDisabled()} and 7493 * {@link WifiManager#queryD2dAllowedWhenInfraStaDisabled()}. 7494 */ 7495 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7496 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 7497 @Test testD2dAllowedWhenInfraStaDisabled()7498 public void testD2dAllowedWhenInfraStaDisabled() throws Exception { 7499 if (!sWifiManager.isD2dSupportedWhenInfraStaDisabled()) { 7500 // skip the test if feature is not supported. 7501 return; 7502 } 7503 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7504 Mutable<Boolean> isQuerySucceeded = new Mutable<Boolean>(false); 7505 boolean currentD2dAllowed = false; 7506 boolean isRestoreRequired = false; 7507 long now, deadline; 7508 try { 7509 uiAutomation.adoptShellPermissionIdentity(); 7510 Mutable<Boolean> isD2dAllowed = new Mutable<Boolean>(false); 7511 sWifiManager.queryD2dAllowedWhenInfraStaDisabled(mExecutor, 7512 new Consumer<Boolean>() { 7513 @Override 7514 public void accept(Boolean value) { 7515 synchronized (mLock) { 7516 isD2dAllowed.value = value; 7517 isQuerySucceeded.value = true; 7518 mLock.notify(); 7519 } 7520 } 7521 }); 7522 synchronized (mLock) { 7523 now = System.currentTimeMillis(); 7524 deadline = now + TEST_WAIT_DURATION_MS; 7525 while (!isQuerySucceeded.value && now < deadline) { 7526 mLock.wait(deadline - now); 7527 now = System.currentTimeMillis(); 7528 } 7529 } 7530 assertTrue("d2d allowed query fail", isQuerySucceeded.value); 7531 // Reset for next query 7532 isQuerySucceeded.value = false; 7533 currentD2dAllowed = isD2dAllowed.value; 7534 isRestoreRequired = true; 7535 sWifiManager.setD2dAllowedWhenInfraStaDisabled(!currentD2dAllowed); 7536 sWifiManager.queryD2dAllowedWhenInfraStaDisabled(mExecutor, 7537 new Consumer<Boolean>() { 7538 @Override 7539 public void accept(Boolean value) { 7540 synchronized (mLock) { 7541 isD2dAllowed.value = value; 7542 isQuerySucceeded.value = true; 7543 mLock.notify(); 7544 } 7545 } 7546 }); 7547 synchronized (mLock) { 7548 now = System.currentTimeMillis(); 7549 deadline = now + TEST_WAIT_DURATION_MS; 7550 while (!isQuerySucceeded.value && now < deadline) { 7551 mLock.wait(deadline - now); 7552 now = System.currentTimeMillis(); 7553 } 7554 } 7555 assertEquals("set/query d2d allowed should match", 7556 isD2dAllowed.value, !currentD2dAllowed); 7557 } finally { 7558 if (isRestoreRequired) { 7559 sWifiManager.setD2dAllowedWhenInfraStaDisabled(currentD2dAllowed); 7560 } 7561 uiAutomation.dropShellPermissionIdentity(); 7562 } 7563 } 7564 7565 @RequiresFlagsEnabled(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API) 7566 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 7567 @Test 7568 @ApiTest(apis = {"android.net.wifi.WifiManager#setAutojoinDisallowedSecurityTypes", 7569 "android.net.wifi.WifiManager#getAutojoinDisallowedSecurityTypes"}) testAutojoinDisallowed()7570 public void testAutojoinDisallowed() throws Exception { 7571 Mutable<Boolean> isQuerySucceeded = new Mutable<Boolean>(false); 7572 long now, deadline; 7573 int[] restrictionTypes = { WifiInfo.SECURITY_TYPE_OPEN, WifiInfo.SECURITY_TYPE_OWE }; 7574 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7575 try { 7576 uiAutomation.adoptShellPermissionIdentity(); 7577 sWifiManager.setAutojoinDisallowedSecurityTypes(restrictionTypes); 7578 sWifiManager.getAutojoinDisallowedSecurityTypes(mExecutor, 7579 new Consumer<int[]>() { 7580 @Override 7581 public void accept(int[] values) { 7582 synchronized (mLock) { 7583 isQuerySucceeded.value = true; 7584 assertArrayEquals("Set and get results mismatch", restrictionTypes, 7585 values); 7586 } 7587 } 7588 }); 7589 synchronized (mLock) { 7590 now = System.currentTimeMillis(); 7591 deadline = now + TEST_WAIT_DURATION_MS; 7592 while (!isQuerySucceeded.value && now < deadline) { 7593 mLock.wait(deadline - now); 7594 now = System.currentTimeMillis(); 7595 } 7596 } 7597 assertTrue("get autojoin restrictions query fail", isQuerySucceeded.value); 7598 } finally { 7599 sWifiManager.setAutojoinDisallowedSecurityTypes(new int[0]); 7600 uiAutomation.dropShellPermissionIdentity(); 7601 } 7602 } 7603 7604 /** 7605 * Tests {@link WifiManager#getBssidBlocklist(List, Executor, Consumer)} 7606 */ 7607 @RequiresFlagsEnabled(Flags.FLAG_GET_BSSID_BLOCKLIST_API) 7608 @Test 7609 @ApiTest(apis = {"android.net.wifi.WifiManager#getBssidBlocklist"}) testGetBssidBlocklist()7610 public void testGetBssidBlocklist() throws Exception { 7611 Mutable<Boolean> isQuerySucceeded = new Mutable<Boolean>(false); 7612 Mutable<Boolean> isResultNonNull = new Mutable<Boolean>(false); 7613 long now, deadline; 7614 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7615 try { 7616 uiAutomation.adoptShellPermissionIdentity(); 7617 sWifiManager.getBssidBlocklist(Collections.EMPTY_LIST, mExecutor, 7618 new Consumer<List<MacAddress>>() { 7619 @Override 7620 public void accept(List<MacAddress> value) { 7621 synchronized (mLock) { 7622 isQuerySucceeded.value = true; 7623 if (value != null) { 7624 isResultNonNull.value = true; 7625 } 7626 mLock.notify(); 7627 } 7628 } 7629 }); 7630 synchronized (mLock) { 7631 now = System.currentTimeMillis(); 7632 deadline = now + TEST_WAIT_DURATION_MS; 7633 while (!isQuerySucceeded.value && now < deadline) { 7634 mLock.wait(deadline - now); 7635 now = System.currentTimeMillis(); 7636 } 7637 } 7638 assertTrue("getBssidBlocklist fail", isQuerySucceeded.value); 7639 assertTrue("getBssidBlocklist returned null list", isResultNonNull.value); 7640 } finally { 7641 uiAutomation.dropShellPermissionIdentity(); 7642 } 7643 } 7644 7645 /** 7646 * Tests {@link WifiManager#retrieveWifiBackupData()}, 7647 * {@link WifiManager#restoreWifiBackupData()}. 7648 */ 7649 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 7650 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 7651 codeName = "VanillaIceCream") 7652 @Test testWifiBackupRestore()7653 public void testWifiBackupRestore() throws Exception { 7654 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7655 Mutable<Boolean> isQuerySucceeded = new Mutable<Boolean>(false); 7656 Mutable<byte[]> backupWifiData = new Mutable<byte[]>(); 7657 long now, deadline; 7658 try { 7659 uiAutomation.adoptShellPermissionIdentity(); 7660 sWifiManager.retrieveWifiBackupData(mExecutor, 7661 new Consumer<byte[]>() { 7662 @Override 7663 public void accept(byte[] value) { 7664 synchronized (mLock) { 7665 isQuerySucceeded.value = true; 7666 backupWifiData.value = value; 7667 mLock.notify(); 7668 } 7669 } 7670 }); 7671 // Test no crash when calling backup/restore api 7672 synchronized (mLock) { 7673 now = System.currentTimeMillis(); 7674 deadline = now + TEST_WAIT_DURATION_MS; 7675 while (!isQuerySucceeded.value && now < deadline) { 7676 mLock.wait(deadline - now); 7677 now = System.currentTimeMillis(); 7678 } 7679 } 7680 assertTrue("retrieve Wi-Fi backup data fail", isQuerySucceeded.value); 7681 sWifiManager.restoreWifiBackupData(backupWifiData.value); 7682 } finally { 7683 uiAutomation.dropShellPermissionIdentity(); 7684 } 7685 } 7686 7687 /** 7688 * Tests {@link WifiManager#getAvailableAdvancedProtectionFeatures()}. 7689 */ 7690 @RequiresFlagsEnabled(android.security.Flags.FLAG_AAPM_API) 7691 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, 7692 codeName = "Baklava") 7693 @Test testGetSupportedAdvancedProtectionFeaturesOverWifi()7694 public void testGetSupportedAdvancedProtectionFeaturesOverWifi() throws Exception { 7695 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 7696 try { 7697 uiAutomation.adoptShellPermissionIdentity(); 7698 List<AdvancedProtectionFeature> features = 7699 sWifiManager.getAvailableAdvancedProtectionFeatures(); 7700 assertNotNull(features); 7701 if (Flags.wepDisabledInApm()) { 7702 // Should have the WEP disabled feature at least. 7703 assertFalse(features.isEmpty()); 7704 } 7705 } finally { 7706 uiAutomation.dropShellPermissionIdentity(); 7707 } 7708 } 7709 7710 @RequiresFlagsEnabled(Flags.FLAG_BSSID_BLOCKLIST_FOR_SUGGESTION) 7711 @Test testBlockingOption()7712 public void testBlockingOption() { 7713 BlockingOption option = new BlockingOption 7714 .Builder(100) 7715 .setBlockingBssidOnly(true) 7716 .build(); 7717 assertEquals(100, option.getBlockingTimeSeconds()); 7718 assertTrue(option.isBlockingBssidOnly()); 7719 sWifiManager.disallowCurrentSuggestedNetwork(option); 7720 } 7721 } 7722