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