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