1 package org.robolectric.shadows; 2 3 import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION; 4 import static android.os.Build.VERSION_CODES.Q; 5 import static android.os.Build.VERSION_CODES.R; 6 import static android.os.Build.VERSION_CODES.S; 7 import static android.os.Build.VERSION_CODES.TIRAMISU; 8 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 9 import static com.google.common.truth.Truth.assertThat; 10 import static com.google.common.util.concurrent.MoreExecutors.directExecutor; 11 import static java.util.concurrent.TimeUnit.MINUTES; 12 import static org.junit.Assert.assertThrows; 13 import static org.junit.Assert.fail; 14 import static org.mockito.ArgumentMatchers.eq; 15 import static org.mockito.Mockito.mock; 16 import static org.mockito.Mockito.verify; 17 import static org.mockito.Mockito.verifyNoMoreInteractions; 18 import static org.robolectric.Shadows.shadowOf; 19 20 import android.app.Application; 21 import android.app.admin.DeviceAdminService; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.net.ConnectivityManager; 27 import android.net.DhcpInfo; 28 import android.net.MacAddress; 29 import android.net.NetworkInfo; 30 import android.net.wifi.ScanResult; 31 import android.net.wifi.SoftApConfiguration; 32 import android.net.wifi.WifiConfiguration; 33 import android.net.wifi.WifiInfo; 34 import android.net.wifi.WifiManager; 35 import android.net.wifi.WifiManager.AddNetworkResult; 36 import android.net.wifi.WifiManager.LocalOnlyConnectionFailureListener; 37 import android.net.wifi.WifiManager.MulticastLock; 38 import android.net.wifi.WifiManager.PnoScanResultsCallback; 39 import android.net.wifi.WifiNetworkSpecifier; 40 import android.net.wifi.WifiNetworkSuggestion; 41 import android.net.wifi.WifiSsid; 42 import android.net.wifi.WifiUsabilityStatsEntry; 43 import android.util.Pair; 44 import androidx.test.ext.junit.runners.AndroidJUnit4; 45 import java.util.ArrayList; 46 import java.util.Collections; 47 import java.util.List; 48 import java.util.concurrent.BlockingQueue; 49 import java.util.concurrent.ExecutorService; 50 import java.util.concurrent.Executors; 51 import java.util.concurrent.LinkedBlockingQueue; 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.ArgumentCaptor; 56 import org.robolectric.RuntimeEnvironment; 57 import org.robolectric.annotation.Config; 58 import org.robolectric.shadow.api.Shadow; 59 import org.robolectric.util.ReflectionHelpers; 60 import org.robolectric.versioning.AndroidVersions.U; 61 62 @RunWith(AndroidJUnit4.class) 63 public class ShadowWifiManagerTest { 64 private WifiManager wifiManager; 65 66 @Before setUp()67 public void setUp() throws Exception { 68 wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); 69 } 70 71 @Test shouldReturnWifiInfo()72 public void shouldReturnWifiInfo() { 73 assertThat(wifiManager.getConnectionInfo().getClass()).isEqualTo(WifiInfo.class); 74 } 75 76 @Test setWifiInfo_shouldUpdateWifiInfo()77 public void setWifiInfo_shouldUpdateWifiInfo() { 78 WifiInfo wifiInfo = new WifiInfo(); 79 shadowOf(wifiManager).setConnectionInfo(wifiInfo); 80 assertThat(wifiManager.getConnectionInfo()).isSameInstanceAs(wifiInfo); 81 } 82 83 @Test setWifiEnabled_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted()84 public void setWifiEnabled_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted() { 85 shadowOf(wifiManager).setAccessWifiStatePermission(false); 86 try { 87 wifiManager.setWifiEnabled(true); 88 fail("SecurityException not thrown"); 89 } catch (SecurityException e) { 90 // expected 91 } 92 } 93 94 @Test isWifiEnabled_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted()95 public void isWifiEnabled_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted() { 96 shadowOf(wifiManager).setAccessWifiStatePermission(false); 97 try { 98 wifiManager.isWifiEnabled(); 99 fail("SecurityException not thrown"); 100 } catch (SecurityException e) { 101 // expected 102 } 103 } 104 105 @Test getWifiState_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted()106 public void getWifiState_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted() { 107 shadowOf(wifiManager).setAccessWifiStatePermission(false); 108 try { 109 wifiManager.getWifiState(); 110 fail("SecurityException not thrown"); 111 } catch (SecurityException e) { 112 // expected 113 } 114 } 115 116 @Test 117 public void getConnectionInfo_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted()118 getConnectionInfo_shouldThrowSecurityExceptionWhenAccessWifiStatePermissionNotGranted() { 119 shadowOf(wifiManager).setAccessWifiStatePermission(false); 120 try { 121 wifiManager.getConnectionInfo(); 122 fail("SecurityException not thrown"); 123 } catch (SecurityException e) { 124 // expected 125 } 126 } 127 128 @Test getWifiState()129 public void getWifiState() { 130 wifiManager.setWifiEnabled(true); 131 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); 132 133 wifiManager.setWifiEnabled(false); 134 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); 135 } 136 137 @Test startScan()138 public void startScan() { 139 // By default startScan() succeeds. 140 assertThat(wifiManager.startScan()).isTrue(); 141 142 shadowOf(wifiManager).setStartScanSucceeds(true); 143 assertThat(wifiManager.startScan()).isTrue(); 144 145 shadowOf(wifiManager).setStartScanSucceeds(false); 146 assertThat(wifiManager.startScan()).isFalse(); 147 } 148 149 @Test getIsScanAlwaysAvailable()150 public void getIsScanAlwaysAvailable() { 151 shadowOf(wifiManager).setIsScanAlwaysAvailable(true); 152 assertThat(wifiManager.isScanAlwaysAvailable()).isEqualTo(true); 153 154 shadowOf(wifiManager).setIsScanAlwaysAvailable(false); 155 assertThat(wifiManager.isScanAlwaysAvailable()).isEqualTo(false); 156 } 157 158 @Test shouldEnableNetworks()159 public void shouldEnableNetworks() { 160 wifiManager.enableNetwork(666, true); 161 Pair<Integer, Boolean> lastEnabled = shadowOf(wifiManager).getLastEnabledNetwork(); 162 assertThat(lastEnabled).isEqualTo(new Pair<>(666, true)); 163 164 wifiManager.enableNetwork(777, false); 165 lastEnabled = shadowOf(wifiManager).getLastEnabledNetwork(); 166 assertThat(lastEnabled).isEqualTo(new Pair<>(777, false)); 167 168 boolean enabledNetwork = shadowOf(wifiManager).isNetworkEnabled(666); 169 assertThat(enabledNetwork).isTrue(); 170 171 enabledNetwork = shadowOf(wifiManager).isNetworkEnabled(777); 172 assertThat(enabledNetwork).isTrue(); 173 } 174 175 @Test shouldDisableNetwork()176 public void shouldDisableNetwork() { 177 wifiManager.enableNetwork(666, true); 178 boolean enabledNetwork = shadowOf(wifiManager).isNetworkEnabled(666); 179 assertThat(enabledNetwork).isTrue(); 180 181 wifiManager.disableNetwork(666); 182 enabledNetwork = shadowOf(wifiManager).isNetworkEnabled(666); 183 assertThat(enabledNetwork).isFalse(); 184 } 185 186 @Test shouldReturnSetScanResults()187 public void shouldReturnSetScanResults() { 188 List<ScanResult> scanResults = new ArrayList<>(); 189 shadowOf(wifiManager).setScanResults(scanResults); 190 assertThat(wifiManager.getScanResults()).isSameInstanceAs(scanResults); 191 } 192 193 @Test shouldReturnDhcpInfo()194 public void shouldReturnDhcpInfo() { 195 DhcpInfo dhcpInfo = new DhcpInfo(); 196 shadowOf(wifiManager).setDhcpInfo(dhcpInfo); 197 assertThat(wifiManager.getDhcpInfo()).isSameInstanceAs(dhcpInfo); 198 } 199 200 @Test shouldRecordTheLastAddedNetwork()201 public void shouldRecordTheLastAddedNetwork() { 202 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 203 wifiConfiguration.networkId = -1; 204 int networkId = wifiManager.addNetwork(wifiConfiguration); 205 assertThat(networkId).isEqualTo(0); 206 assertThat(wifiManager.getConfiguredNetworks().get(0)).isNotSameInstanceAs(wifiConfiguration); 207 assertThat(wifiConfiguration.networkId).isEqualTo(-1); 208 assertThat(wifiManager.getConfiguredNetworks().get(0).networkId).isEqualTo(0); 209 assertThat(wifiManager.addNetwork(/* wifiConfiguration= */ null)).isEqualTo(-1); 210 211 WifiConfiguration anotherConfig = new WifiConfiguration(); 212 assertThat(wifiManager.addNetwork(anotherConfig)).isEqualTo(1); 213 assertThat(anotherConfig.networkId).isEqualTo(-1); 214 assertThat(wifiManager.getConfiguredNetworks().get(1).networkId).isEqualTo(1); 215 } 216 217 @Test updateNetwork_shouldReplaceNetworks()218 public void updateNetwork_shouldReplaceNetworks() { 219 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 220 wifiConfiguration.networkId = -1; 221 wifiManager.addNetwork(wifiConfiguration); 222 223 WifiConfiguration anotherConfig = new WifiConfiguration(); 224 int networkId = wifiManager.addNetwork(anotherConfig); 225 226 assertThat(networkId).isEqualTo(1); 227 WifiConfiguration configuration = new WifiConfiguration(); 228 configuration.networkId = networkId; 229 configuration.priority = 44; 230 231 assertThat(wifiManager.updateNetwork(configuration)).isEqualTo(networkId); 232 List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks(); 233 assertThat(configuredNetworks.size()).isEqualTo(2); 234 assertThat(configuration.priority).isEqualTo(44); 235 assertThat(configuredNetworks.get(1).priority).isEqualTo(44); 236 } 237 238 @Test updateNetworkTests_permissions()239 public void updateNetworkTests_permissions() { 240 int networkId = 1; 241 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 242 wifiConfiguration.networkId = networkId; 243 244 // By default we should have permission to update networks. 245 assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(networkId); 246 247 // If we don't have permission to update, updateNetwork will return -1. 248 shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission= */ false); 249 assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(-1); 250 251 // Ensure updates can occur if permission is restored. 252 shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission= */ true); 253 assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(networkId); 254 } 255 256 @Test removeNetwork()257 public void removeNetwork() { 258 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 259 wifiConfiguration.networkId = 123; 260 wifiManager.addNetwork(wifiConfiguration); 261 262 List<WifiConfiguration> list = wifiManager.getConfiguredNetworks(); 263 assertThat(list.size()).isEqualTo(1); 264 265 wifiManager.removeNetwork(0); 266 267 list = wifiManager.getConfiguredNetworks(); 268 assertThat(list.size()).isEqualTo(0); 269 } 270 271 @Test 272 @Config(minSdk = S) addNetworkPrivileged_nullConfig_shouldThrowIllegalArgumentException()273 public void addNetworkPrivileged_nullConfig_shouldThrowIllegalArgumentException() { 274 assertThrows(IllegalArgumentException.class, () -> wifiManager.addNetworkPrivileged(null)); 275 } 276 277 @Test 278 @Config(minSdk = S) addNetworkPrivileged_nonNullConfig_shouldAddNetworkSuccessfully()279 public void addNetworkPrivileged_nonNullConfig_shouldAddNetworkSuccessfully() { 280 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 281 282 AddNetworkResult addNetworkResult = wifiManager.addNetworkPrivileged(wifiConfiguration); 283 284 assertThat(addNetworkResult).isNotNull(); 285 assertThat(addNetworkResult.statusCode).isEqualTo(AddNetworkResult.STATUS_SUCCESS); 286 assertThat(wifiManager.getConfiguredNetworks()).hasSize(1); 287 } 288 289 @Test 290 @Config(minSdk = S) 291 public void getCallerConfiguredNetworks_noAccessWifiStatePermission_shouldThrowSecurityException()292 getCallerConfiguredNetworks_noAccessWifiStatePermission_shouldThrowSecurityException() { 293 shadowOf(wifiManager).setAccessWifiStatePermission(false); 294 295 assertThrows(SecurityException.class, () -> wifiManager.getCallerConfiguredNetworks()); 296 } 297 298 @Test 299 @Config(minSdk = S) getCallerConfiguredNetworks_noNetworksConfigured_returnsEmptyList()300 public void getCallerConfiguredNetworks_noNetworksConfigured_returnsEmptyList() { 301 assertThat(wifiManager.getCallerConfiguredNetworks()).isEmpty(); 302 } 303 304 @Test 305 @Config(minSdk = S) getCallerConfiguredNetworks_networksAddedAndRemoved_returnsConfiguredNetworks()306 public void getCallerConfiguredNetworks_networksAddedAndRemoved_returnsConfiguredNetworks() { 307 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 308 wifiManager.addNetwork(wifiConfiguration); 309 310 assertThat(wifiManager.getCallerConfiguredNetworks()).hasSize(1); 311 312 wifiManager.removeNetwork(0); 313 314 assertThat(wifiManager.getCallerConfiguredNetworks()).isEmpty(); 315 } 316 317 @Test 318 @Config(minSdk = S) 319 public void removeNonCallerConfiguredNetworks_noChangeWifiStatePermission_shouldThrowSecurityException()320 removeNonCallerConfiguredNetworks_noChangeWifiStatePermission_shouldThrowSecurityException() { 321 setDeviceOwner(); 322 shadowOf(wifiManager).setChangeWifiStatePermission(false); 323 324 assertThrows(SecurityException.class, () -> wifiManager.removeNonCallerConfiguredNetworks()); 325 } 326 327 @Test 328 @Config(minSdk = S) removeNonCallerConfiguredNetworks_notDeviceOwner_shouldThrowSecurityException()329 public void removeNonCallerConfiguredNetworks_notDeviceOwner_shouldThrowSecurityException() { 330 assertThrows(SecurityException.class, () -> wifiManager.removeNonCallerConfiguredNetworks()); 331 } 332 333 @Test 334 @Config(minSdk = S) removeNonCallerConfiguredNetworks_noConfiguredNetworks_returnsFalse()335 public void removeNonCallerConfiguredNetworks_noConfiguredNetworks_returnsFalse() { 336 setDeviceOwner(); 337 338 assertThat(wifiManager.removeNonCallerConfiguredNetworks()).isFalse(); 339 } 340 341 @Test 342 @Config(minSdk = S) removeNonCallerConfiguredNetworks_hasConfiguredNetworks_removesConfiguredNetworks()343 public void removeNonCallerConfiguredNetworks_hasConfiguredNetworks_removesConfiguredNetworks() { 344 setDeviceOwner(); 345 wifiManager.addNetwork(new WifiConfiguration()); 346 wifiManager.addNetwork(new WifiConfiguration()); 347 348 assertThat(wifiManager.removeNonCallerConfiguredNetworks()).isTrue(); 349 assertThat(wifiManager.getConfiguredNetworks()).isEmpty(); 350 } 351 352 @Test getPrivilegedConfiguredNetworks_shouldReturnConfiguredNetworks()353 public void getPrivilegedConfiguredNetworks_shouldReturnConfiguredNetworks() { 354 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 355 wifiConfiguration.networkId = 123; 356 wifiManager.addNetwork(wifiConfiguration); 357 358 List<WifiConfiguration> list = wifiManager.getPrivilegedConfiguredNetworks(); 359 assertThat(list.size()).isEqualTo(1); 360 361 wifiManager.removeNetwork(0); 362 363 list = wifiManager.getPrivilegedConfiguredNetworks(); 364 assertThat(list.size()).isEqualTo(0); 365 } 366 367 @Test updateNetwork_shouldRejectNullandNewConfigs()368 public void updateNetwork_shouldRejectNullandNewConfigs() { 369 WifiConfiguration config = new WifiConfiguration(); 370 config.networkId = -1; 371 assertThat(wifiManager.updateNetwork(config)).isEqualTo(-1); 372 assertThat(wifiManager.updateNetwork(null)).isEqualTo(-1); 373 assertThat(wifiManager.getConfiguredNetworks()).isEmpty(); 374 } 375 376 @Test shouldSaveConfigurations()377 public void shouldSaveConfigurations() { 378 assertThat(wifiManager.saveConfiguration()).isTrue(); 379 assertThat(shadowOf(wifiManager).wasConfigurationSaved()).isTrue(); 380 } 381 382 @Test shouldCreateWifiLock()383 public void shouldCreateWifiLock() { 384 assertThat(wifiManager.createWifiLock("TAG")).isNotNull(); 385 assertThat(wifiManager.createWifiLock(1, "TAG")).isNotNull(); 386 } 387 388 @Test wifiLockAcquireIncreasesActiveLockCount()389 public void wifiLockAcquireIncreasesActiveLockCount() { 390 WifiManager.WifiLock lock = wifiManager.createWifiLock("TAG"); 391 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(0); 392 lock.acquire(); 393 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(1); 394 lock.release(); 395 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(0); 396 } 397 398 @Test multicastLockAcquireIncreasesActiveLockCount()399 public void multicastLockAcquireIncreasesActiveLockCount() { 400 MulticastLock lock = wifiManager.createMulticastLock("TAG"); 401 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(0); 402 lock.acquire(); 403 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(1); 404 lock.release(); 405 assertThat(shadowOf(wifiManager).getActiveLockCount()).isEqualTo(0); 406 } 407 408 @Test shouldAcquireAndReleaseWifilockRefCounted()409 public void shouldAcquireAndReleaseWifilockRefCounted() { 410 WifiManager.WifiLock lock = wifiManager.createWifiLock("TAG"); 411 lock.acquire(); 412 lock.acquire(); 413 assertThat(lock.isHeld()).isTrue(); 414 lock.release(); 415 assertThat(lock.isHeld()).isTrue(); 416 lock.release(); 417 assertThat(lock.isHeld()).isFalse(); 418 } 419 420 @Test shouldAcquireAndReleaseWifilockNonRefCounted()421 public void shouldAcquireAndReleaseWifilockNonRefCounted() { 422 WifiManager.WifiLock lock = wifiManager.createWifiLock("TAG"); 423 lock.setReferenceCounted(false); 424 lock.acquire(); 425 assertThat(lock.isHeld()).isTrue(); 426 lock.acquire(); 427 assertThat(lock.isHeld()).isTrue(); 428 lock.release(); 429 assertThat(lock.isHeld()).isFalse(); 430 } 431 432 @Test shouldThrowRuntimeExceptionIfWifiLockisUnderlocked()433 public void shouldThrowRuntimeExceptionIfWifiLockisUnderlocked() { 434 WifiManager.WifiLock lock = wifiManager.createWifiLock("TAG"); 435 try { 436 lock.release(); 437 fail("RuntimeException not thrown"); 438 } catch (RuntimeException e) { 439 // expected 440 } 441 } 442 443 @Test shouldThrowUnsupportedOperationIfWifiLockisOverlocked()444 public void shouldThrowUnsupportedOperationIfWifiLockisOverlocked() { 445 WifiManager.WifiLock lock = wifiManager.createWifiLock("TAG"); 446 try { 447 for (int i = 0; i < ShadowWifiManager.ShadowWifiLock.MAX_ACTIVE_LOCKS; i++) { 448 lock.acquire(); 449 } 450 fail("UnsupportedOperationException not thrown"); 451 } catch (UnsupportedOperationException e) { 452 // expected 453 } 454 } 455 456 @Test shouldCreateMulticastLock()457 public void shouldCreateMulticastLock() { 458 assertThat(wifiManager.createMulticastLock("TAG")).isNotNull(); 459 } 460 461 @Test shouldAcquireAndReleaseMulticastLockRefCounted()462 public void shouldAcquireAndReleaseMulticastLockRefCounted() { 463 MulticastLock lock = wifiManager.createMulticastLock("TAG"); 464 lock.acquire(); 465 lock.acquire(); 466 assertThat(lock.isHeld()).isTrue(); 467 lock.release(); 468 assertThat(lock.isHeld()).isTrue(); 469 lock.release(); 470 assertThat(lock.isHeld()).isFalse(); 471 } 472 473 @Test shouldAcquireAndReleaseMulticastLockNonRefCounted()474 public void shouldAcquireAndReleaseMulticastLockNonRefCounted() { 475 MulticastLock lock = wifiManager.createMulticastLock("TAG"); 476 lock.setReferenceCounted(false); 477 lock.acquire(); 478 assertThat(lock.isHeld()).isTrue(); 479 lock.acquire(); 480 assertThat(lock.isHeld()).isTrue(); 481 lock.release(); 482 assertThat(lock.isHeld()).isFalse(); 483 } 484 485 @Test shouldThrowRuntimeExceptionIfMulticastLockisUnderlocked()486 public void shouldThrowRuntimeExceptionIfMulticastLockisUnderlocked() { 487 MulticastLock lock = wifiManager.createMulticastLock("TAG"); 488 try { 489 lock.release(); 490 fail("Expected exception"); 491 } catch (RuntimeException expected) { 492 } 493 ; 494 } 495 496 @Test shouldThrowUnsupportedOperationIfMulticastLockisOverlocked()497 public void shouldThrowUnsupportedOperationIfMulticastLockisOverlocked() { 498 MulticastLock lock = wifiManager.createMulticastLock("TAG"); 499 try { 500 for (int i = 0; i < ShadowWifiManager.ShadowMulticastLock.MAX_ACTIVE_LOCKS; i++) { 501 lock.acquire(); 502 } 503 fail("Expected exception"); 504 } catch (UnsupportedOperationException e) { 505 // expected 506 } 507 } 508 509 @Test shouldCalculateSignalLevelSetBefore()510 public void shouldCalculateSignalLevelSetBefore() { 511 ShadowWifiManager.setSignalLevelInPercent(0.5f); 512 assertThat(WifiManager.calculateSignalLevel(0, 5)).isEqualTo(2); 513 assertThat(WifiManager.calculateSignalLevel(2, 5)).isEqualTo(2); 514 515 ShadowWifiManager.setSignalLevelInPercent(0.9f); 516 assertThat(WifiManager.calculateSignalLevel(0, 5)).isEqualTo(3); 517 assertThat(WifiManager.calculateSignalLevel(2, 5)).isEqualTo(3); 518 519 ShadowWifiManager.setSignalLevelInPercent(1f); 520 assertThat(WifiManager.calculateSignalLevel(0, 4)).isEqualTo(3); 521 assertThat(WifiManager.calculateSignalLevel(2, 4)).isEqualTo(3); 522 523 ShadowWifiManager.setSignalLevelInPercent(0); 524 assertThat(WifiManager.calculateSignalLevel(0, 5)).isEqualTo(0); 525 assertThat(WifiManager.calculateSignalLevel(2, 5)).isEqualTo(0); 526 } 527 528 @Test(expected = IllegalArgumentException.class) shouldThrowIllegalArgumentExceptionWhenSignalLevelToLow()529 public void shouldThrowIllegalArgumentExceptionWhenSignalLevelToLow() { 530 ShadowWifiManager.setSignalLevelInPercent(-0.01f); 531 } 532 533 @Test(expected = IllegalArgumentException.class) shouldThrowIllegalArgumentExceptionWhenSignalLevelToHigh()534 public void shouldThrowIllegalArgumentExceptionWhenSignalLevelToHigh() { 535 ShadowWifiManager.setSignalLevelInPercent(1.01f); 536 } 537 538 @Test startScan_shouldNotThrowException()539 public void startScan_shouldNotThrowException() { 540 assertThat(wifiManager.startScan()).isTrue(); 541 } 542 543 @Test reconnect_shouldNotThrowException()544 public void reconnect_shouldNotThrowException() { 545 assertThat(wifiManager.reconnect()).isFalse(); 546 } 547 548 @Test reconnect_setsConnectionInfo()549 public void reconnect_setsConnectionInfo() { 550 // GIVEN 551 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 552 wifiConfiguration.SSID = "SSID"; 553 int netId = wifiManager.addNetwork(wifiConfiguration); 554 wifiManager.enableNetwork(netId, false); 555 556 // WHEN 557 wifiManager.reconnect(); 558 559 // THEN 560 assertThat(wifiManager.getConnectionInfo().getSSID()).contains("SSID"); 561 } 562 563 @Test reconnect_shouldEnableDhcp()564 public void reconnect_shouldEnableDhcp() { 565 // GIVEN 566 WifiConfiguration config = new WifiConfiguration(); 567 config.SSID = "SSID"; 568 int netId = wifiManager.addNetwork(config); 569 wifiManager.enableNetwork(netId, false); 570 571 // WHEN 572 wifiManager.reconnect(); 573 574 // THEN 575 assertThat(wifiManager.getDhcpInfo()).isNotNull(); 576 } 577 578 @Test reconnect_updatesConnectivityManager()579 public void reconnect_updatesConnectivityManager() { 580 // GIVEN 581 WifiConfiguration config = new WifiConfiguration(); 582 config.SSID = "SSID"; 583 int netId = wifiManager.addNetwork(config); 584 wifiManager.enableNetwork(netId, false); 585 586 // WHEN 587 wifiManager.reconnect(); 588 589 // THEN 590 NetworkInfo networkInfo = 591 ((ConnectivityManager) 592 getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE)) 593 .getActiveNetworkInfo(); 594 assertThat(networkInfo.getType()).isEqualTo(ConnectivityManager.TYPE_WIFI); 595 assertThat(networkInfo.isConnected()).isTrue(); 596 } 597 598 @Test connect_setsNetworkId_shouldHasNetworkId()599 public void connect_setsNetworkId_shouldHasNetworkId() { 600 // WHEN 601 wifiManager.connect(123, null); 602 603 // THEN 604 assertThat(wifiManager.getConnectionInfo().getNetworkId()).isEqualTo(123); 605 } 606 607 @Test connect_setsConnectionInfo()608 public void connect_setsConnectionInfo() { 609 // GIVEN 610 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 611 wifiConfiguration.SSID = "foo"; 612 613 // WHEN 614 wifiManager.connect(wifiConfiguration, null); 615 616 // THEN 617 assertThat(wifiManager.getConnectionInfo().getSSID()).contains("foo"); 618 } 619 620 @Test is5GhzBandSupportedAndConfigurable()621 public void is5GhzBandSupportedAndConfigurable() { 622 assertThat(wifiManager.is5GHzBandSupported()).isFalse(); 623 shadowOf(wifiManager).setIs5GHzBandSupported(true); 624 assertThat(wifiManager.is5GHzBandSupported()).isTrue(); 625 } 626 627 @Test 628 @Config(minSdk = R) isStaApConcurrencySupportedAndConfigurable()629 public void isStaApConcurrencySupportedAndConfigurable() { 630 assertThat(wifiManager.isStaApConcurrencySupported()).isFalse(); 631 shadowOf(wifiManager).setStaApConcurrencySupported(true); 632 assertThat(wifiManager.isStaApConcurrencySupported()).isTrue(); 633 } 634 635 @Test 636 @Config(minSdk = Q) isWpa3SaeSupportedAndConfigurable()637 public void isWpa3SaeSupportedAndConfigurable() { 638 assertThat(wifiManager.isWpa3SaeSupported()).isFalse(); 639 shadowOf(wifiManager).setWpa3SaeSupported(true); 640 assertThat(wifiManager.isWpa3SaeSupported()).isTrue(); 641 } 642 643 @Test 644 @Config(minSdk = S) isWpa3SaePublicKeySupportedAndConfigurable()645 public void isWpa3SaePublicKeySupportedAndConfigurable() { 646 assertThat(wifiManager.isWpa3SaePublicKeySupported()).isFalse(); 647 shadowOf(wifiManager).setWpa3SaePublicKeySupported(true); 648 assertThat(wifiManager.isWpa3SaePublicKeySupported()).isTrue(); 649 } 650 651 @Test 652 @Config(minSdk = S) isWpa3SaeH2eSupportedAndConfigurable()653 public void isWpa3SaeH2eSupportedAndConfigurable() { 654 assertThat(wifiManager.isWpa3SaeH2eSupported()).isFalse(); 655 shadowOf(wifiManager).setWpa3SaeH2eSupported(true); 656 assertThat(wifiManager.isWpa3SaeH2eSupported()).isTrue(); 657 } 658 659 @Test 660 @Config(minSdk = Q) isWpa3SuiteBSupportedAndConfigurable()661 public void isWpa3SuiteBSupportedAndConfigurable() { 662 assertThat(wifiManager.isWpa3SuiteBSupported()).isFalse(); 663 shadowOf(wifiManager).setWpa3SuiteBSupported(true); 664 assertThat(wifiManager.isWpa3SuiteBSupported()).isTrue(); 665 } 666 667 @Test 668 @Config(minSdk = Q) testAddOnWifiUsabilityStatsListener()669 public void testAddOnWifiUsabilityStatsListener() { 670 // GIVEN 671 WifiManager.OnWifiUsabilityStatsListener mockListener = 672 mock(WifiManager.OnWifiUsabilityStatsListener.class); 673 wifiManager.addOnWifiUsabilityStatsListener(directExecutor(), mockListener); 674 675 // WHEN 676 WifiUsabilityStatsEntryBuilder builder = new WifiUsabilityStatsEntryBuilder(); 677 builder 678 .setTimeStampMillis(1234567L) 679 .setRssi(23) 680 .setLinkSpeedMbps(998) 681 .setTotalTxSuccess(1) 682 .setTotalTxRetries(2) 683 .setTotalTxBad(3) 684 .setTotalRxSuccess(4) 685 .setTotalRadioOnTimeMillis(5) 686 .setTotalRadioTxTimeMillis(6) 687 .setTotalRadioRxTimeMillis(7) 688 .setTotalScanTimeMillis(8) 689 .setTotalNanScanTimeMillis(9) 690 .setTotalBackgroundScanTimeMillis(10) 691 .setTotalRoamScanTimeMillis(11) 692 .setTotalPnoScanTimeMillis(12) 693 .setTotalHotspot2ScanTimeMillis(13) 694 .setTotalCcaBusyFreqTimeMillis(14) 695 .setTotalRadioOnFreqTimeMillis(15) 696 .setTotalBeaconRx(16) 697 .setProbeStatusSinceLastUpdate(2) 698 .setProbeElapsedTimeSinceLastUpdateMillis(18) 699 .setProbeMcsRateSinceLastUpdate(19) 700 .setRxLinkSpeedMbps(20) 701 .setCellularDataNetworkType(1) 702 .setCellularSignalStrengthDbm(2) 703 .setCellularSignalStrengthDb(3) 704 .setSameRegisteredCell(false); 705 706 if (RuntimeEnvironment.getApiLevel() >= S) { 707 builder 708 .setTimeSliceDutyCycleInPercent(10) 709 .setIsCellularDataAvailable(false) 710 .setIsThroughputSufficient(false) 711 .setIsWifiScoringEnabled(false); 712 } 713 714 shadowOf(wifiManager) 715 .postUsabilityStats(/* seqNum= */ 10, /* isSameBssidAndFreq= */ false, builder); 716 // THEN 717 718 ArgumentCaptor<WifiUsabilityStatsEntry> usabilityStats = 719 ArgumentCaptor.forClass(WifiUsabilityStatsEntry.class); 720 verify(mockListener).onWifiUsabilityStats(eq(10), eq(false), usabilityStats.capture()); 721 assertThat(usabilityStats.getValue().getTimeStampMillis()).isEqualTo(1234567L); 722 assertThat(usabilityStats.getValue().getRssi()).isEqualTo(23); 723 assertThat(usabilityStats.getValue().getLinkSpeedMbps()).isEqualTo(998); 724 assertThat(usabilityStats.getValue().getTotalTxSuccess()).isEqualTo(1); 725 assertThat(usabilityStats.getValue().getTotalTxRetries()).isEqualTo(2); 726 assertThat(usabilityStats.getValue().getTotalTxBad()).isEqualTo(3); 727 assertThat(usabilityStats.getValue().getTotalRxSuccess()).isEqualTo(4); 728 assertThat(usabilityStats.getValue().getTotalRadioOnTimeMillis()).isEqualTo(5); 729 assertThat(usabilityStats.getValue().getTotalRadioTxTimeMillis()).isEqualTo(6); 730 assertThat(usabilityStats.getValue().getTotalRadioRxTimeMillis()).isEqualTo(7); 731 assertThat(usabilityStats.getValue().getTotalScanTimeMillis()).isEqualTo(8); 732 assertThat(usabilityStats.getValue().getTotalNanScanTimeMillis()).isEqualTo(9); 733 assertThat(usabilityStats.getValue().getTotalBackgroundScanTimeMillis()).isEqualTo(10); 734 assertThat(usabilityStats.getValue().getTotalRoamScanTimeMillis()).isEqualTo(11); 735 assertThat(usabilityStats.getValue().getTotalPnoScanTimeMillis()).isEqualTo(12); 736 assertThat(usabilityStats.getValue().getTotalHotspot2ScanTimeMillis()).isEqualTo(13); 737 assertThat(usabilityStats.getValue().getTotalCcaBusyFreqTimeMillis()).isEqualTo(14); 738 assertThat(usabilityStats.getValue().getTotalRadioOnFreqTimeMillis()).isEqualTo(15); 739 assertThat(usabilityStats.getValue().getTotalBeaconRx()).isEqualTo(16); 740 assertThat(usabilityStats.getValue().getProbeStatusSinceLastUpdate()).isEqualTo(2); 741 assertThat(usabilityStats.getValue().getProbeElapsedTimeSinceLastUpdateMillis()).isEqualTo(18); 742 assertThat(usabilityStats.getValue().getProbeMcsRateSinceLastUpdate()).isEqualTo(19); 743 assertThat(usabilityStats.getValue().getRxLinkSpeedMbps()).isEqualTo(20); 744 assertThat(usabilityStats.getValue().getCellularDataNetworkType()).isEqualTo(1); 745 assertThat(usabilityStats.getValue().getCellularSignalStrengthDbm()).isEqualTo(2); 746 assertThat(usabilityStats.getValue().getCellularSignalStrengthDb()).isEqualTo(3); 747 assertThat(usabilityStats.getValue().isSameRegisteredCell()).isFalse(); 748 if (RuntimeEnvironment.getApiLevel() >= S) { 749 assertThat(usabilityStats.getValue().getTimeSliceDutyCycleInPercent()).isEqualTo(10); 750 assertThat(usabilityStats.getValue().isCellularDataAvailable()).isFalse(); 751 assertThat(usabilityStats.getValue().isThroughputSufficient()).isFalse(); 752 assertThat(usabilityStats.getValue().isWifiScoringEnabled()).isFalse(); 753 } 754 verifyNoMoreInteractions(mockListener); 755 } 756 757 @Test 758 @Config(minSdk = Q) testRemoveOnWifiUsabilityStatsListener()759 public void testRemoveOnWifiUsabilityStatsListener() { 760 // GIVEN 761 WifiManager.OnWifiUsabilityStatsListener mockListener = 762 mock(WifiManager.OnWifiUsabilityStatsListener.class); 763 wifiManager.addOnWifiUsabilityStatsListener(directExecutor(), mockListener); 764 765 WifiUsabilityStatsEntryBuilder builder = new WifiUsabilityStatsEntryBuilder(); 766 builder 767 .setTimeStampMillis(1234567L) 768 .setRssi(23) 769 .setLinkSpeedMbps(998) 770 .setTotalTxSuccess(0) 771 .setTotalTxRetries(0) 772 .setTotalTxBad(0) 773 .setTotalRxSuccess(0) 774 .setTotalRadioOnTimeMillis(0) 775 .setTotalRadioTxTimeMillis(0) 776 .setTotalRadioRxTimeMillis(0) 777 .setTotalScanTimeMillis(0) 778 .setTotalNanScanTimeMillis(0) 779 .setTotalBackgroundScanTimeMillis(0) 780 .setTotalRoamScanTimeMillis(0) 781 .setTotalPnoScanTimeMillis(0) 782 .setTotalHotspot2ScanTimeMillis(0) 783 .setTotalCcaBusyFreqTimeMillis(0) 784 .setTotalRadioOnFreqTimeMillis(0) 785 .setTotalBeaconRx(0) 786 .setProbeStatusSinceLastUpdate(0) 787 .setProbeElapsedTimeSinceLastUpdateMillis(0) 788 .setProbeMcsRateSinceLastUpdate(0) 789 .setRxLinkSpeedMbps(0) 790 .setCellularDataNetworkType(0) 791 .setCellularSignalStrengthDbm(0) 792 .setCellularSignalStrengthDb(0) 793 .setSameRegisteredCell(false); 794 795 // WHEN 796 wifiManager.removeOnWifiUsabilityStatsListener(mockListener); 797 shadowOf(wifiManager) 798 .postUsabilityStats(/* seqNum= */ 10, /* isSameBssidAndFreq= */ true, builder); 799 800 // THEN 801 verifyNoMoreInteractions(mockListener); 802 } 803 804 @Test 805 @Config(minSdk = R) testSetClearWifiConnectedNetworkScorer()806 public void testSetClearWifiConnectedNetworkScorer() { 807 // GIVEN 808 WifiManager.WifiConnectedNetworkScorer mockScorer = 809 mock(WifiManager.WifiConnectedNetworkScorer.class); 810 // WHEN 811 wifiManager.setWifiConnectedNetworkScorer(directExecutor(), mockScorer); 812 assertThat(shadowOf(wifiManager).isWifiConnectedNetworkScorerEnabled()).isTrue(); 813 wifiManager.clearWifiConnectedNetworkScorer(); 814 815 // THEN 816 assertThat(shadowOf(wifiManager).isWifiConnectedNetworkScorerEnabled()).isFalse(); 817 } 818 819 @Test 820 @Config(minSdk = Q) testGetUsabilityScores()821 public void testGetUsabilityScores() { 822 // GIVEN 823 wifiManager.updateWifiUsabilityScore( 824 /* seqNum= */ 23, /* score= */ 50, /* predictionHorizonSec= */ 16); 825 wifiManager.updateWifiUsabilityScore( 826 /* seqNum= */ 24, /* score= */ 40, /* predictionHorizonSec= */ 16); 827 828 // WHEN 829 List<ShadowWifiManager.WifiUsabilityScore> scores = shadowOf(wifiManager).getUsabilityScores(); 830 831 // THEN 832 assertThat(scores).hasSize(2); 833 assertThat(scores.get(0).seqNum).isEqualTo(23); 834 assertThat(scores.get(0).score).isEqualTo(50); 835 assertThat(scores.get(0).predictionHorizonSec).isEqualTo(16); 836 assertThat(scores.get(1).seqNum).isEqualTo(24); 837 assertThat(scores.get(1).score).isEqualTo(40); 838 assertThat(scores.get(1).predictionHorizonSec).isEqualTo(16); 839 } 840 841 @Test 842 @Config(minSdk = Q) testClearUsabilityScores()843 public void testClearUsabilityScores() { 844 // GIVEN 845 wifiManager.updateWifiUsabilityScore( 846 /* seqNum= */ 23, /* score= */ 50, /* predictionHorizonSec= */ 16); 847 wifiManager.updateWifiUsabilityScore( 848 /* seqNum= */ 24, /* score= */ 40, /* predictionHorizonSec= */ 16); 849 850 // WHEN 851 shadowOf(wifiManager).clearUsabilityScores(); 852 List<ShadowWifiManager.WifiUsabilityScore> scores = shadowOf(wifiManager).getUsabilityScores(); 853 854 // THEN 855 assertThat(scores).isEmpty(); 856 } 857 858 @Test testSetWifiState()859 public void testSetWifiState() { 860 shadowOf(wifiManager).setWifiState(WifiManager.WIFI_STATE_ENABLED); 861 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED); 862 assertThat(wifiManager.isWifiEnabled()).isTrue(); 863 864 wifiManager.setWifiEnabled(false); 865 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); 866 assertThat(wifiManager.isWifiEnabled()).isFalse(); 867 868 shadowOf(wifiManager).setWifiState(WifiManager.WIFI_STATE_ENABLING); 869 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLING); 870 assertThat(wifiManager.isWifiEnabled()).isFalse(); 871 872 shadowOf(wifiManager).setWifiState(WifiManager.WIFI_STATE_DISABLING); 873 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLING); 874 assertThat(wifiManager.isWifiEnabled()).isFalse(); 875 876 shadowOf(wifiManager).setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 877 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_UNKNOWN); 878 assertThat(wifiManager.isWifiEnabled()).isFalse(); 879 880 shadowOf(wifiManager).setWifiState(WifiManager.WIFI_STATE_DISABLED); 881 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED); 882 assertThat(wifiManager.isWifiEnabled()).isFalse(); 883 } 884 885 @Test shouldRecordTheLastApConfiguration()886 public void shouldRecordTheLastApConfiguration() { 887 WifiConfiguration wifiConfiguration = new WifiConfiguration(); 888 wifiConfiguration.SSID = "foo"; 889 boolean status = shadowOf(wifiManager).setWifiApConfiguration(wifiConfiguration); 890 assertThat(status).isTrue(); 891 892 assertThat(shadowOf(wifiManager).getWifiApConfiguration().SSID).isEqualTo("foo"); 893 } 894 895 @Test 896 @Config(minSdk = R) shouldRecordTheLastSoftApConfiguration()897 public void shouldRecordTheLastSoftApConfiguration() { 898 SoftApConfiguration softApConfig = 899 new SoftApConfiguration.Builder() 900 .setSsid("foo") 901 .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN) 902 .build(); 903 904 boolean status = wifiManager.setSoftApConfiguration(softApConfig); 905 assertThat(status).isTrue(); 906 907 assertThat(shadowOf(wifiManager).getSoftApConfiguration().getSsid()).isEqualTo("foo"); 908 } 909 910 @Test 911 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_nullCallback_throwsIllegalArgumentException()912 public void setExternalPnoScanRequest_nullCallback_throwsIllegalArgumentException() { 913 assertThrows( 914 IllegalArgumentException.class, 915 () -> 916 wifiManager.setExternalPnoScanRequest( 917 List.of(WifiSsid.fromBytes(new byte[] {3, 2, 5})), 918 /* frequencies= */ null, 919 Executors.newSingleThreadExecutor(), 920 /* callback= */ null)); 921 } 922 923 @Test 924 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_nullExecutor_throwsIllegalArgumentException()925 public void setExternalPnoScanRequest_nullExecutor_throwsIllegalArgumentException() { 926 assertThrows( 927 IllegalArgumentException.class, 928 () -> 929 wifiManager.setExternalPnoScanRequest( 930 List.of(WifiSsid.fromBytes(new byte[] {3, 2, 5})), 931 /* frequencies= */ null, 932 /* executor= */ null, 933 ReflectionHelpers.createDelegatingProxy( 934 PnoScanResultsCallback.class, new TestPnoScanResultsCallbackDelegate()))); 935 } 936 937 @Test 938 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_nullSsidList_throwsIllegalStateException()939 public void setExternalPnoScanRequest_nullSsidList_throwsIllegalStateException() { 940 assertThrows( 941 IllegalStateException.class, 942 () -> 943 wifiManager.setExternalPnoScanRequest( 944 /* ssids= */ null, 945 /* frequencies= */ null, 946 Executors.newSingleThreadExecutor(), 947 ReflectionHelpers.createDelegatingProxy( 948 PnoScanResultsCallback.class, new TestPnoScanResultsCallbackDelegate()))); 949 } 950 951 @Test 952 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_emptySsidList_throwsIllegalStateException()953 public void setExternalPnoScanRequest_emptySsidList_throwsIllegalStateException() { 954 assertThrows( 955 IllegalStateException.class, 956 () -> 957 wifiManager.setExternalPnoScanRequest( 958 /* ssids= */ List.of(), 959 /* frequencies= */ null, 960 Executors.newSingleThreadExecutor(), 961 ReflectionHelpers.createDelegatingProxy( 962 PnoScanResultsCallback.class, new TestPnoScanResultsCallbackDelegate()))); 963 } 964 965 @Test 966 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_moreThan2Ssids_throwsIllegalArgumentException()967 public void setExternalPnoScanRequest_moreThan2Ssids_throwsIllegalArgumentException() { 968 assertThrows( 969 IllegalArgumentException.class, 970 () -> 971 wifiManager.setExternalPnoScanRequest( 972 List.of( 973 WifiSsid.fromBytes(new byte[] {1, 2, 3}), 974 WifiSsid.fromBytes(new byte[] {9, 8, 7, 6}), 975 WifiSsid.fromBytes(new byte[] {90, 81, 72, 63, 54})), 976 /* frequencies= */ null, 977 Executors.newSingleThreadExecutor(), 978 ReflectionHelpers.createDelegatingProxy( 979 PnoScanResultsCallback.class, new TestPnoScanResultsCallbackDelegate()))); 980 } 981 982 @Test 983 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_moreThan10Frequencies_throwsIllegalArgumentException()984 public void setExternalPnoScanRequest_moreThan10Frequencies_throwsIllegalArgumentException() { 985 assertThrows( 986 IllegalArgumentException.class, 987 () -> 988 wifiManager.setExternalPnoScanRequest( 989 List.of( 990 WifiSsid.fromBytes(new byte[] {1, 2, 3}), 991 WifiSsid.fromBytes(new byte[] {9, 8, 7, 6})), 992 new int[] {5160, 5180, 5200, 5220, 5240, 5260, 5280, 5300, 5320, 5340, 5360}, 993 Executors.newSingleThreadExecutor(), 994 ReflectionHelpers.createDelegatingProxy( 995 PnoScanResultsCallback.class, new TestPnoScanResultsCallbackDelegate()))); 996 } 997 998 @Test 999 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_validRequest_successCallbackInvoked()1000 public void setExternalPnoScanRequest_validRequest_successCallbackInvoked() throws Exception { 1001 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1002 PnoScanResultsCallback callback = 1003 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1004 1005 wifiManager.setExternalPnoScanRequest( 1006 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1007 /* frequencies= */ null, 1008 Executors.newSingleThreadExecutor(), 1009 callback); 1010 1011 assertThat(delegate.successfulRegistrations.take()).isNotNull(); 1012 } 1013 1014 @Test 1015 @Config(minSdk = TIRAMISU) 1016 public void setExternalPnoScanRequest_outstandingRequest_failureCallbackInvokedWithAlreadyRegisteredStatus()1017 setExternalPnoScanRequest_outstandingRequest_failureCallbackInvokedWithAlreadyRegisteredStatus() 1018 throws Exception { 1019 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1020 PnoScanResultsCallback callback = 1021 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1022 1023 wifiManager.setExternalPnoScanRequest( 1024 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1025 /* frequencies= */ null, 1026 Executors.newSingleThreadExecutor(), 1027 callback); 1028 1029 wifiManager.setExternalPnoScanRequest( 1030 List.of(WifiSsid.fromBytes(new byte[] {9, 2, 5})), 1031 new int[] {5280}, 1032 Executors.newSingleThreadExecutor(), 1033 callback); 1034 1035 assertThat(delegate.failedRegistrations.take()) 1036 .isEqualTo(PnoScanResultsCallback.REGISTER_PNO_CALLBACK_ALREADY_REGISTERED); 1037 } 1038 1039 @Test 1040 @Config(minSdk = TIRAMISU) setExternalPnoScanRequest_differentUid_failureCallbackInvokedWithBusyStatus()1041 public void setExternalPnoScanRequest_differentUid_failureCallbackInvokedWithBusyStatus() 1042 throws Exception { 1043 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1044 PnoScanResultsCallback callback = 1045 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1046 1047 wifiManager.setExternalPnoScanRequest( 1048 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1049 /* frequencies= */ null, 1050 Executors.newSingleThreadExecutor(), 1051 callback); 1052 1053 int firstAppUid = ShadowProcess.myUid(); 1054 int secondAppUid; 1055 do { 1056 secondAppUid = ShadowProcess.getRandomApplicationUid(); 1057 } while (firstAppUid == secondAppUid); 1058 ShadowProcess.setUid(secondAppUid); 1059 1060 wifiManager.setExternalPnoScanRequest( 1061 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1062 /* frequencies= */ null, 1063 Executors.newSingleThreadExecutor(), 1064 callback); 1065 1066 assertThat(delegate.failedRegistrations.take()) 1067 .isEqualTo(PnoScanResultsCallback.REGISTER_PNO_CALLBACK_RESOURCE_BUSY); 1068 } 1069 1070 @Test 1071 @Config(minSdk = TIRAMISU) clearExternalPnoScanRequest_outstandingRequest_callbackInvokedWithUnregisteredStatus()1072 public void clearExternalPnoScanRequest_outstandingRequest_callbackInvokedWithUnregisteredStatus() 1073 throws Exception { 1074 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1075 PnoScanResultsCallback callback = 1076 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1077 1078 wifiManager.setExternalPnoScanRequest( 1079 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1080 /* frequencies= */ null, 1081 Executors.newSingleThreadExecutor(), 1082 callback); 1083 wifiManager.clearExternalPnoScanRequest(); 1084 1085 assertThat(delegate.removedRegistrations.take()) 1086 .isEqualTo(PnoScanResultsCallback.REMOVE_PNO_CALLBACK_UNREGISTERED); 1087 } 1088 1089 @Test 1090 @Config(minSdk = TIRAMISU) clearExternalPnoScanRequest_wrongUid_callbackNotInvoked()1091 public void clearExternalPnoScanRequest_wrongUid_callbackNotInvoked() throws Exception { 1092 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1093 PnoScanResultsCallback callback = 1094 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1095 ExecutorService executor = Executors.newSingleThreadExecutor(); 1096 1097 wifiManager.setExternalPnoScanRequest( 1098 List.of(WifiSsid.fromBytes(new byte[] {1, 2, 3})), 1099 /* frequencies= */ null, 1100 executor, 1101 callback); 1102 1103 int firstAppUid = ShadowProcess.myUid(); 1104 int secondAppUid; 1105 do { 1106 secondAppUid = ShadowProcess.getRandomApplicationUid(); 1107 } while (firstAppUid == secondAppUid); 1108 ShadowProcess.setUid(secondAppUid); 1109 1110 wifiManager.clearExternalPnoScanRequest(); 1111 1112 executor.shutdown(); 1113 1114 assertThat(executor.awaitTermination(5, MINUTES)).isTrue(); 1115 assertThat(delegate.removedRegistrations).isEmpty(); 1116 } 1117 1118 @Test 1119 @Config(minSdk = TIRAMISU) networksFoundFromPnoScan_matchingSsid_availableCallbackInvoked()1120 public void networksFoundFromPnoScan_matchingSsid_availableCallbackInvoked() throws Exception { 1121 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1122 PnoScanResultsCallback callback = 1123 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1124 WifiSsid wifiSsid = WifiSsid.fromBytes(new byte[] {1, 2, 3}); 1125 ScanResult scanResult = new ScanResult(); 1126 scanResult.setWifiSsid(wifiSsid); 1127 1128 wifiManager.setExternalPnoScanRequest( 1129 List.of(wifiSsid), /* frequencies= */ null, Executors.newSingleThreadExecutor(), callback); 1130 shadowOf(wifiManager).networksFoundFromPnoScan(List.of(scanResult)); 1131 1132 assertThat(delegate.incomingScanResults.take()).containsExactly(scanResult); 1133 } 1134 1135 @Test 1136 @Config(minSdk = TIRAMISU) networksFoundFromPnoScan_matchingSsid_removedCallbackInvokedWithDeliveredStatus()1137 public void networksFoundFromPnoScan_matchingSsid_removedCallbackInvokedWithDeliveredStatus() 1138 throws Exception { 1139 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1140 PnoScanResultsCallback callback = 1141 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1142 WifiSsid wifiSsid = WifiSsid.fromBytes(new byte[] {1, 2, 3}); 1143 ScanResult scanResult = new ScanResult(); 1144 scanResult.setWifiSsid(wifiSsid); 1145 1146 wifiManager.setExternalPnoScanRequest( 1147 List.of(wifiSsid), /* frequencies= */ null, Executors.newSingleThreadExecutor(), callback); 1148 shadowOf(wifiManager).networksFoundFromPnoScan(List.of(scanResult)); 1149 1150 assertThat(delegate.removedRegistrations.take()) 1151 .isEqualTo(PnoScanResultsCallback.REMOVE_PNO_CALLBACK_RESULTS_DELIVERED); 1152 } 1153 1154 @Test 1155 @Config(minSdk = TIRAMISU) networksFoundFromPnoScan_matchingSsid_scanResultsAvailableBroadcastSent()1156 public void networksFoundFromPnoScan_matchingSsid_scanResultsAvailableBroadcastSent() { 1157 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1158 PnoScanResultsCallback callback = 1159 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1160 WifiSsid wifiSsid = WifiSsid.fromBytes(new byte[] {1, 2, 3}); 1161 ScanResult scanResult = new ScanResult(); 1162 scanResult.setWifiSsid(wifiSsid); 1163 1164 wifiManager.setExternalPnoScanRequest( 1165 List.of(wifiSsid), /* frequencies= */ null, Executors.newSingleThreadExecutor(), callback); 1166 shadowOf(wifiManager).networksFoundFromPnoScan(List.of(scanResult)); 1167 1168 Intent expectedIntent = new Intent(SCAN_RESULTS_AVAILABLE_ACTION); 1169 expectedIntent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true); 1170 expectedIntent.setPackage(getApplicationContext().getPackageName()); 1171 1172 assertThat( 1173 shadowOf((Application) getApplicationContext()).getBroadcastIntents().stream() 1174 .anyMatch(expectedIntent::filterEquals)) 1175 .isTrue(); 1176 } 1177 1178 @Test 1179 @Config(minSdk = TIRAMISU) networksFoundFromPnoScan_noMatchingSsid_availableCallbackNotInvoked()1180 public void networksFoundFromPnoScan_noMatchingSsid_availableCallbackNotInvoked() 1181 throws Exception { 1182 TestPnoScanResultsCallbackDelegate delegate = new TestPnoScanResultsCallbackDelegate(); 1183 PnoScanResultsCallback callback = 1184 ReflectionHelpers.createDelegatingProxy(PnoScanResultsCallback.class, delegate); 1185 ExecutorService executor = Executors.newSingleThreadExecutor(); 1186 WifiSsid wifiSsid = WifiSsid.fromBytes(new byte[] {1, 2, 3}); 1187 WifiSsid otherWifiSsid = WifiSsid.fromBytes(new byte[] {9, 8, 7, 6}); 1188 ScanResult scanResult = new ScanResult(); 1189 scanResult.setWifiSsid(otherWifiSsid); 1190 1191 wifiManager.setExternalPnoScanRequest( 1192 List.of(wifiSsid), /* frequencies= */ null, executor, callback); 1193 shadowOf(wifiManager).networksFoundFromPnoScan(List.of(scanResult)); 1194 1195 executor.shutdown(); 1196 1197 assertThat(executor.awaitTermination(5, MINUTES)).isTrue(); 1198 assertThat(delegate.incomingScanResults).isEmpty(); 1199 } 1200 1201 @Test 1202 @Config(minSdk = U.SDK_INT) addLocalOnlyConnectionFailureListener_nullExecutor_throwsIllegalArgumentException()1203 public void addLocalOnlyConnectionFailureListener_nullExecutor_throwsIllegalArgumentException() { 1204 assertThrows( 1205 IllegalArgumentException.class, 1206 () -> 1207 wifiManager.addLocalOnlyConnectionFailureListener( 1208 /* executor= */ null, /* listener= */ (unused1, unused2) -> {})); 1209 } 1210 1211 @Test 1212 @Config(minSdk = U.SDK_INT) addLocalOnlyConnectionFailureListener_nullListener_throwsIllegalArgumentException()1213 public void addLocalOnlyConnectionFailureListener_nullListener_throwsIllegalArgumentException() { 1214 assertThrows( 1215 IllegalArgumentException.class, 1216 () -> 1217 wifiManager.addLocalOnlyConnectionFailureListener( 1218 Executors.newSingleThreadExecutor(), /* listener= */ null)); 1219 } 1220 1221 @Test 1222 @Config(minSdk = U.SDK_INT) 1223 public void removeLocalOnlyConnectionFailureListener_nullListener_throwsIllegalArgumentException()1224 removeLocalOnlyConnectionFailureListener_nullListener_throwsIllegalArgumentException() { 1225 assertThrows( 1226 IllegalArgumentException.class, 1227 () -> wifiManager.removeLocalOnlyConnectionFailureListener(/* listener= */ null)); 1228 } 1229 1230 @Test 1231 @Config(minSdk = U.SDK_INT) triggerLocalConnectionFailure_callbackTriggered()1232 public void triggerLocalConnectionFailure_callbackTriggered() throws Exception { 1233 ExecutorService executor = Executors.newSingleThreadExecutor(); 1234 TestFailureListener listener = new TestFailureListener(); 1235 WifiNetworkSpecifier wifiNetworkSpecifier = 1236 new WifiNetworkSpecifier.Builder() 1237 .setSsid("icanhazinternet") 1238 .setBssid(MacAddress.fromString("01:92:83:74:65:AB")) 1239 .setWpa3Passphrase("r3@l gud pa$$w0rd") 1240 .build(); 1241 1242 wifiManager.addLocalOnlyConnectionFailureListener(executor, listener); 1243 ((ShadowWifiManager) Shadow.extract(wifiManager)) 1244 .triggerLocalConnectionFailure( 1245 wifiNetworkSpecifier, WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1246 executor.shutdown(); 1247 1248 IncomingFailure incomingFailure = listener.incomingFailures.take(); 1249 assertThat(incomingFailure.wifiNetworkSpecifier).isEqualTo(wifiNetworkSpecifier); 1250 assertThat(incomingFailure.failureReason) 1251 .isEqualTo(WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1252 } 1253 1254 @Test 1255 @Config(minSdk = U.SDK_INT) triggerLocalConnectionFailure_multipleCallbacksRegistered_allCallbacksTriggered()1256 public void triggerLocalConnectionFailure_multipleCallbacksRegistered_allCallbacksTriggered() 1257 throws Exception { 1258 ExecutorService executor = Executors.newSingleThreadExecutor(); 1259 TestFailureListener listener1 = new TestFailureListener(); 1260 TestFailureListener listener2 = new TestFailureListener(); 1261 WifiNetworkSpecifier wifiNetworkSpecifier = 1262 new WifiNetworkSpecifier.Builder() 1263 .setSsid("icanhazinternet") 1264 .setBssid(MacAddress.fromString("01:92:83:74:65:AB")) 1265 .setWpa3Passphrase("r3@l gud pa$$w0rd") 1266 .build(); 1267 1268 wifiManager.addLocalOnlyConnectionFailureListener(executor, listener1); 1269 wifiManager.addLocalOnlyConnectionFailureListener(executor, listener2); 1270 ((ShadowWifiManager) Shadow.extract(wifiManager)) 1271 .triggerLocalConnectionFailure( 1272 wifiNetworkSpecifier, WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1273 executor.shutdown(); 1274 1275 IncomingFailure incomingFailure = listener1.incomingFailures.take(); 1276 assertThat(incomingFailure.wifiNetworkSpecifier).isEqualTo(wifiNetworkSpecifier); 1277 assertThat(incomingFailure.failureReason) 1278 .isEqualTo(WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1279 incomingFailure = listener2.incomingFailures.take(); 1280 assertThat(incomingFailure.wifiNetworkSpecifier).isEqualTo(wifiNetworkSpecifier); 1281 assertThat(incomingFailure.failureReason) 1282 .isEqualTo(WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1283 } 1284 1285 @Test 1286 @Config(minSdk = U.SDK_INT) 1287 public void triggerLocalConnectionFailure_multipleCallbacksRegisteredOnDifferentExecutors_allCallbacksTriggered()1288 triggerLocalConnectionFailure_multipleCallbacksRegisteredOnDifferentExecutors_allCallbacksTriggered() 1289 throws Exception { 1290 ExecutorService executor1 = Executors.newSingleThreadExecutor(); 1291 ExecutorService executor2 = Executors.newSingleThreadExecutor(); 1292 TestFailureListener listener1 = new TestFailureListener(); 1293 TestFailureListener listener2 = new TestFailureListener(); 1294 WifiNetworkSpecifier wifiNetworkSpecifier = 1295 new WifiNetworkSpecifier.Builder() 1296 .setSsid("icanhazinternet") 1297 .setBssid(MacAddress.fromString("01:92:83:74:65:AB")) 1298 .setWpa3Passphrase("r3@l gud pa$$w0rd") 1299 .build(); 1300 1301 wifiManager.addLocalOnlyConnectionFailureListener(executor1, listener1); 1302 wifiManager.addLocalOnlyConnectionFailureListener(executor2, listener2); 1303 ((ShadowWifiManager) Shadow.extract(wifiManager)) 1304 .triggerLocalConnectionFailure( 1305 wifiNetworkSpecifier, WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1306 executor1.shutdown(); 1307 executor2.shutdown(); 1308 1309 IncomingFailure incomingFailure = listener1.incomingFailures.take(); 1310 assertThat(incomingFailure.wifiNetworkSpecifier).isEqualTo(wifiNetworkSpecifier); 1311 assertThat(incomingFailure.failureReason) 1312 .isEqualTo(WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1313 incomingFailure = listener2.incomingFailures.take(); 1314 assertThat(incomingFailure.wifiNetworkSpecifier).isEqualTo(wifiNetworkSpecifier); 1315 assertThat(incomingFailure.failureReason) 1316 .isEqualTo(WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1317 } 1318 1319 @Test 1320 @Config(minSdk = U.SDK_INT) triggerLocalConnectionFailure_listenerRemovedBeforeTrigger_callbackNotInvoked()1321 public void triggerLocalConnectionFailure_listenerRemovedBeforeTrigger_callbackNotInvoked() { 1322 ExecutorService executor = Executors.newSingleThreadExecutor(); 1323 TestFailureListener listener = new TestFailureListener(); 1324 WifiNetworkSpecifier wifiNetworkSpecifier = 1325 new WifiNetworkSpecifier.Builder() 1326 .setSsid("icanhazinternet") 1327 .setBssid(MacAddress.fromString("01:92:83:74:65:AB")) 1328 .setWpa3Passphrase("r3@l gud pa$$w0rd") 1329 .build(); 1330 1331 wifiManager.addLocalOnlyConnectionFailureListener(executor, listener); 1332 wifiManager.removeLocalOnlyConnectionFailureListener(listener); 1333 ((ShadowWifiManager) Shadow.extract(wifiManager)) 1334 .triggerLocalConnectionFailure( 1335 wifiNetworkSpecifier, WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION); 1336 executor.shutdown(); 1337 1338 assertThat(listener.incomingFailures).isEmpty(); 1339 } 1340 1341 @Test 1342 @Config(minSdk = R) addNetworkSuggestions_returnsSuccess()1343 public void addNetworkSuggestions_returnsSuccess() { 1344 assertThat(wifiManager.getNetworkSuggestions()).isEmpty(); 1345 WifiNetworkSuggestion suggestion = 1346 new WifiNetworkSuggestion.Builder() 1347 .setSsid("TestWifi") 1348 .setBssid(MacAddress.fromString("11:22:33:44:55:66")) 1349 .build(); 1350 1351 assertThat(wifiManager.addNetworkSuggestions(Collections.singletonList(suggestion))) 1352 .isEqualTo(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); 1353 1354 assertThat(wifiManager.getNetworkSuggestions()).containsExactly(suggestion); 1355 } 1356 1357 @Test 1358 @Config(minSdk = R) addNetworkSuggestions_returnsError()1359 public void addNetworkSuggestions_returnsError() { 1360 assertThat(wifiManager.getNetworkSuggestions()).isEmpty(); 1361 WifiNetworkSuggestion suggestion = 1362 new WifiNetworkSuggestion.Builder() 1363 .setSsid("TestWifi") 1364 .setBssid(MacAddress.fromString("11:22:33:44:55:66")) 1365 .build(); 1366 ((ShadowWifiManager) Shadow.extract(wifiManager)) 1367 .setAddNetworkSuggestionsResult( 1368 WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED); 1369 1370 assertThat(wifiManager.addNetworkSuggestions(Collections.singletonList(suggestion))) 1371 .isEqualTo(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED); 1372 1373 assertThat(wifiManager.getNetworkSuggestions()).isEmpty(); 1374 } 1375 1376 private static final class IncomingFailure { 1377 private final WifiNetworkSpecifier wifiNetworkSpecifier; 1378 private final int failureReason; 1379 IncomingFailure(WifiNetworkSpecifier wifiNetworkSpecifier, int failureReason)1380 IncomingFailure(WifiNetworkSpecifier wifiNetworkSpecifier, int failureReason) { 1381 this.wifiNetworkSpecifier = wifiNetworkSpecifier; 1382 this.failureReason = failureReason; 1383 } 1384 } 1385 1386 private static final class TestFailureListener implements LocalOnlyConnectionFailureListener { 1387 private final BlockingQueue<IncomingFailure> incomingFailures = new LinkedBlockingQueue<>(); 1388 1389 @Override onConnectionFailed(WifiNetworkSpecifier wifiNetworkSpecifier, int i)1390 public void onConnectionFailed(WifiNetworkSpecifier wifiNetworkSpecifier, int i) { 1391 incomingFailures.add(new IncomingFailure(wifiNetworkSpecifier, i)); 1392 } 1393 } 1394 1395 private static class TestPnoScanResultsCallbackDelegate { 1396 LinkedBlockingQueue<List<ScanResult>> incomingScanResults = new LinkedBlockingQueue<>(); 1397 LinkedBlockingQueue<Object> successfulRegistrations = new LinkedBlockingQueue<>(); 1398 LinkedBlockingQueue<Integer> failedRegistrations = new LinkedBlockingQueue<>(); 1399 LinkedBlockingQueue<Integer> removedRegistrations = new LinkedBlockingQueue<>(); 1400 onScanResultsAvailable(List<ScanResult> scanResults)1401 public void onScanResultsAvailable(List<ScanResult> scanResults) { 1402 incomingScanResults.add(scanResults); 1403 } 1404 onRegisterSuccess()1405 public void onRegisterSuccess() { 1406 successfulRegistrations.add(new Object()); 1407 } 1408 onRegisterFailed(int reason)1409 public void onRegisterFailed(int reason) { 1410 failedRegistrations.add(reason); 1411 } 1412 onRemoved(int reason)1413 public void onRemoved(int reason) { 1414 removedRegistrations.add(reason); 1415 } 1416 } 1417 setDeviceOwner()1418 private void setDeviceOwner() { 1419 shadowOf( 1420 (DevicePolicyManager) 1421 getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE)) 1422 .setDeviceOwner(new ComponentName(getApplicationContext(), DeviceAdminService.class)); 1423 } 1424 } 1425