1 /* 2 * Copyright (C) 2023 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 com.android.systemui.statusbar.pipeline.wifi.data.repository.prod 18 19 import android.net.wifi.ScanResult 20 import android.net.wifi.WifiManager 21 import android.net.wifi.WifiManager.UNKNOWN_SSID 22 import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo 23 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID 24 import android.testing.TestableLooper 25 import androidx.test.filters.SmallTest 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.coroutines.collectLastValue 28 import com.android.systemui.flags.FakeFeatureFlags 29 import com.android.systemui.flags.Flags 30 import com.android.systemui.log.LogBuffer 31 import com.android.systemui.log.table.TableLogBuffer 32 import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory 33 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel 34 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT 35 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel 36 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry 37 import com.android.systemui.util.concurrency.FakeExecutor 38 import com.android.systemui.util.mockito.any 39 import com.android.systemui.util.mockito.argumentCaptor 40 import com.android.systemui.util.mockito.capture 41 import com.android.systemui.util.mockito.mock 42 import com.android.systemui.util.mockito.whenever 43 import com.android.systemui.util.time.FakeSystemClock 44 import com.android.wifitrackerlib.HotspotNetworkEntry 45 import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType 46 import com.android.wifitrackerlib.MergedCarrierEntry 47 import com.android.wifitrackerlib.WifiEntry 48 import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX 49 import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN 50 import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE 51 import com.android.wifitrackerlib.WifiPickerTracker 52 import com.google.common.truth.Truth.assertThat 53 import kotlinx.coroutines.ExperimentalCoroutinesApi 54 import kotlinx.coroutines.test.StandardTestDispatcher 55 import kotlinx.coroutines.test.TestScope 56 import kotlinx.coroutines.test.runCurrent 57 import kotlinx.coroutines.test.runTest 58 import org.junit.Before 59 import org.junit.Test 60 import org.mockito.Mockito.verify 61 62 /** 63 * Note: Most of these tests are duplicates of [WifiRepositoryImplTest] tests. 64 * 65 * Any new tests added here may also need to be added to [WifiRepositoryImplTest]. 66 */ 67 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") 68 @OptIn(ExperimentalCoroutinesApi::class) 69 @SmallTest 70 @TestableLooper.RunWithLooper(setAsMainLooper = true) 71 class WifiRepositoryViaTrackerLibTest : SysuiTestCase() { 72 73 // Using lazy means that the class will only be constructed once it's fetched. Because the 74 // repository internally sets some values on construction, we need to set up some test 75 // parameters (like feature flags) *before* construction. Using lazy allows us to do that setup 76 // inside each test case without needing to manually recreate the repository. 77 private val underTest: WifiRepositoryViaTrackerLib by lazy { 78 WifiRepositoryViaTrackerLib( 79 featureFlags, 80 testScope.backgroundScope, 81 executor, 82 dispatcher, 83 wifiPickerTrackerFactory, 84 wifiManager, 85 logger, 86 tableLogger, 87 ) 88 } 89 90 private val executor = FakeExecutor(FakeSystemClock()) 91 private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock()) 92 private val featureFlags = FakeFeatureFlags() 93 private val tableLogger = mock<TableLogBuffer>() 94 private val wifiManager = 95 mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) } 96 private val wifiPickerTrackerFactory = mock<WifiPickerTrackerFactory>() 97 private val wifiPickerTracker = mock<WifiPickerTracker>() 98 99 private val callbackCaptor = argumentCaptor<WifiPickerTracker.WifiPickerTrackerCallback>() 100 101 private val dispatcher = StandardTestDispatcher() 102 private val testScope = TestScope(dispatcher) 103 104 @Before 105 fun setUp() { 106 featureFlags.set(Flags.INSTANT_TETHER, false) 107 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false) 108 whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor))) 109 .thenReturn(wifiPickerTracker) 110 } 111 112 @Test 113 fun wifiPickerTrackerCreation_scansDisabled() = 114 testScope.runTest { 115 collectLastValue(underTest.wifiNetwork) 116 testScope.runCurrent() 117 118 verify(wifiPickerTracker).disableScanning() 119 } 120 121 @Test 122 fun isWifiEnabled_enabled_true() = 123 testScope.runTest { 124 val latest by collectLastValue(underTest.isWifiEnabled) 125 126 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED) 127 getCallback().onWifiStateChanged() 128 129 assertThat(latest).isTrue() 130 } 131 132 @Test 133 fun isWifiEnabled_enabling_false() = 134 testScope.runTest { 135 val latest by collectLastValue(underTest.isWifiEnabled) 136 137 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLING) 138 getCallback().onWifiStateChanged() 139 140 assertThat(latest).isFalse() 141 } 142 143 @Test 144 fun isWifiEnabled_disabling_true() = 145 testScope.runTest { 146 val latest by collectLastValue(underTest.isWifiEnabled) 147 148 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLING) 149 getCallback().onWifiStateChanged() 150 151 assertThat(latest).isFalse() 152 } 153 154 @Test 155 fun isWifiEnabled_disabled_false() = 156 testScope.runTest { 157 val latest by collectLastValue(underTest.isWifiEnabled) 158 159 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED) 160 getCallback().onWifiStateChanged() 161 162 assertThat(latest).isFalse() 163 } 164 165 @Test 166 fun isWifiEnabled_respondsToUpdates() = 167 testScope.runTest { 168 val latest by collectLastValue(underTest.isWifiEnabled) 169 executor.runAllReady() 170 171 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_ENABLED) 172 getCallback().onWifiStateChanged() 173 174 assertThat(latest).isTrue() 175 176 whenever(wifiPickerTracker.wifiState).thenReturn(WifiManager.WIFI_STATE_DISABLED) 177 getCallback().onWifiStateChanged() 178 179 assertThat(latest).isFalse() 180 } 181 182 @Test 183 fun isWifiDefault_initiallyGetsDefault() = 184 testScope.runTest { assertThat(underTest.isWifiDefault.value).isFalse() } 185 186 @Test 187 fun isWifiDefault_wifiNetwork_isTrue() = 188 testScope.runTest { 189 val latest by collectLastValue(underTest.isWifiDefault) 190 191 val wifiEntry = 192 mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) } 193 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 194 getCallback().onWifiEntriesChanged() 195 196 assertThat(latest).isTrue() 197 } 198 199 @Test 200 fun isWifiDefault_carrierMerged_isTrue() = 201 testScope.runTest { 202 val latest by collectLastValue(underTest.isWifiDefault) 203 204 val wifiEntry = 205 mock<MergedCarrierEntry>().apply { 206 whenever(this.isDefaultNetwork).thenReturn(true) 207 } 208 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 209 getCallback().onWifiEntriesChanged() 210 211 assertThat(latest).isTrue() 212 } 213 214 @Test 215 fun isWifiDefault_wifiNetworkNotDefault_isFalse() = 216 testScope.runTest { 217 val latest by collectLastValue(underTest.isWifiDefault) 218 219 val wifiEntry = 220 mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(false) } 221 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 222 getCallback().onWifiEntriesChanged() 223 224 assertThat(latest).isFalse() 225 } 226 227 @Test 228 fun isWifiDefault_carrierMergedNotDefault_isFalse() = 229 testScope.runTest { 230 val latest by collectLastValue(underTest.isWifiDefault) 231 232 val wifiEntry = 233 mock<MergedCarrierEntry>().apply { 234 whenever(this.isDefaultNetwork).thenReturn(false) 235 } 236 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 237 getCallback().onWifiEntriesChanged() 238 239 assertThat(latest).isFalse() 240 } 241 242 @Test 243 fun isWifiDefault_noWifiNetwork_isFalse() = 244 testScope.runTest { 245 val latest by collectLastValue(underTest.isWifiDefault) 246 247 // First, add a network 248 val wifiEntry = 249 mock<WifiEntry>().apply { whenever(this.isDefaultNetwork).thenReturn(true) } 250 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 251 getCallback().onWifiEntriesChanged() 252 253 assertThat(latest).isTrue() 254 255 // WHEN the network is lost 256 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 257 getCallback().onWifiEntriesChanged() 258 259 // THEN we update to false 260 assertThat(latest).isFalse() 261 } 262 263 @Test 264 fun wifiNetwork_initiallyGetsDefault() = 265 testScope.runTest { 266 val latest by collectLastValue(underTest.wifiNetwork) 267 268 assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT) 269 } 270 271 @Test 272 fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() = 273 testScope.runTest { 274 val latest by collectLastValue(underTest.wifiNetwork) 275 276 val wifiEntry = 277 mock<WifiEntry>().apply { 278 whenever(this.isPrimaryNetwork).thenReturn(true) 279 whenever(this.level).thenReturn(3) 280 whenever(this.title).thenReturn(TITLE) 281 } 282 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 283 getCallback().onWifiEntriesChanged() 284 285 assertThat(latest is WifiNetworkModel.Active).isTrue() 286 val latestActive = latest as WifiNetworkModel.Active 287 assertThat(latestActive.level).isEqualTo(3) 288 assertThat(latestActive.ssid).isEqualTo(TITLE) 289 } 290 291 @Test 292 fun accessPointInfo_alwaysFalse() = 293 testScope.runTest { 294 val latest by collectLastValue(underTest.wifiNetwork) 295 296 val wifiEntry = 297 mock<WifiEntry>().apply { 298 whenever(this.isPrimaryNetwork).thenReturn(true) 299 whenever(this.level).thenReturn(3) 300 whenever(this.title).thenReturn(TITLE) 301 } 302 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 303 getCallback().onWifiEntriesChanged() 304 305 assertThat(latest is WifiNetworkModel.Active).isTrue() 306 val latestActive = latest as WifiNetworkModel.Active 307 assertThat(latestActive.isPasspointAccessPoint).isFalse() 308 assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse() 309 assertThat(latestActive.passpointProviderFriendlyName).isNull() 310 } 311 312 @Test 313 fun wifiNetwork_unreachableLevel_inactiveNetwork() = 314 testScope.runTest { 315 val latest by collectLastValue(underTest.wifiNetwork) 316 317 val wifiEntry = 318 mock<WifiEntry>().apply { 319 whenever(this.isPrimaryNetwork).thenReturn(true) 320 whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE) 321 } 322 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 323 getCallback().onWifiEntriesChanged() 324 325 assertThat(latest).isEqualTo(WifiNetworkModel.Inactive) 326 } 327 328 @Test 329 fun wifiNetwork_levelTooHigh_inactiveNetwork() = 330 testScope.runTest { 331 val latest by collectLastValue(underTest.wifiNetwork) 332 333 val wifiEntry = 334 mock<WifiEntry>().apply { 335 whenever(this.isPrimaryNetwork).thenReturn(true) 336 whenever(this.level).thenReturn(WIFI_LEVEL_MAX + 1) 337 } 338 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 339 getCallback().onWifiEntriesChanged() 340 341 assertThat(latest).isEqualTo(WifiNetworkModel.Inactive) 342 } 343 344 @Test 345 fun wifiNetwork_levelTooLow_inactiveNetwork() = 346 testScope.runTest { 347 val latest by collectLastValue(underTest.wifiNetwork) 348 349 val wifiEntry = 350 mock<WifiEntry>().apply { 351 whenever(this.isPrimaryNetwork).thenReturn(true) 352 whenever(this.level).thenReturn(WIFI_LEVEL_MIN - 1) 353 } 354 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 355 getCallback().onWifiEntriesChanged() 356 357 assertThat(latest).isEqualTo(WifiNetworkModel.Inactive) 358 } 359 360 @Test 361 fun wifiNetwork_levelIsMax_activeNetworkWithMaxLevel() = 362 testScope.runTest { 363 val latest by collectLastValue(underTest.wifiNetwork) 364 365 val wifiEntry = 366 mock<WifiEntry>().apply { 367 whenever(this.isPrimaryNetwork).thenReturn(true) 368 whenever(this.level).thenReturn(WIFI_LEVEL_MAX) 369 } 370 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 371 getCallback().onWifiEntriesChanged() 372 373 assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java) 374 assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MAX) 375 } 376 377 @Test 378 fun wifiNetwork_levelIsMin_activeNetworkWithMinLevel() = 379 testScope.runTest { 380 val latest by collectLastValue(underTest.wifiNetwork) 381 382 val wifiEntry = 383 mock<WifiEntry>().apply { 384 whenever(this.isPrimaryNetwork).thenReturn(true) 385 whenever(this.level).thenReturn(WIFI_LEVEL_MIN) 386 } 387 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 388 getCallback().onWifiEntriesChanged() 389 390 assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java) 391 assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MIN) 392 } 393 394 @Test 395 fun wifiNetwork_notHotspot_none() = 396 testScope.runTest { 397 featureFlags.set(Flags.INSTANT_TETHER, true) 398 val latest by collectLastValue(underTest.wifiNetwork) 399 400 val wifiEntry = 401 mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(true) } 402 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 403 getCallback().onWifiEntriesChanged() 404 405 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 406 .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE) 407 } 408 409 @Test 410 fun wifiNetwork_hotspot_unknown() = 411 testScope.runTest { 412 featureFlags.set(Flags.INSTANT_TETHER, true) 413 val latest by collectLastValue(underTest.wifiNetwork) 414 415 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN) 416 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 417 getCallback().onWifiEntriesChanged() 418 419 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 420 .isEqualTo(WifiNetworkModel.HotspotDeviceType.UNKNOWN) 421 } 422 423 @Test 424 fun wifiNetwork_hotspot_phone() = 425 testScope.runTest { 426 featureFlags.set(Flags.INSTANT_TETHER, true) 427 val latest by collectLastValue(underTest.wifiNetwork) 428 429 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE) 430 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 431 getCallback().onWifiEntriesChanged() 432 433 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 434 .isEqualTo(WifiNetworkModel.HotspotDeviceType.PHONE) 435 } 436 437 @Test 438 fun wifiNetwork_hotspot_tablet() = 439 testScope.runTest { 440 featureFlags.set(Flags.INSTANT_TETHER, true) 441 val latest by collectLastValue(underTest.wifiNetwork) 442 443 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET) 444 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 445 getCallback().onWifiEntriesChanged() 446 447 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 448 .isEqualTo(WifiNetworkModel.HotspotDeviceType.TABLET) 449 } 450 451 @Test 452 fun wifiNetwork_hotspot_laptop() = 453 testScope.runTest { 454 featureFlags.set(Flags.INSTANT_TETHER, true) 455 val latest by collectLastValue(underTest.wifiNetwork) 456 457 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP) 458 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 459 getCallback().onWifiEntriesChanged() 460 461 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 462 .isEqualTo(WifiNetworkModel.HotspotDeviceType.LAPTOP) 463 } 464 465 @Test 466 fun wifiNetwork_hotspot_watch() = 467 testScope.runTest { 468 featureFlags.set(Flags.INSTANT_TETHER, true) 469 val latest by collectLastValue(underTest.wifiNetwork) 470 471 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH) 472 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 473 getCallback().onWifiEntriesChanged() 474 475 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 476 .isEqualTo(WifiNetworkModel.HotspotDeviceType.WATCH) 477 } 478 479 @Test 480 fun wifiNetwork_hotspot_auto() = 481 testScope.runTest { 482 featureFlags.set(Flags.INSTANT_TETHER, true) 483 val latest by collectLastValue(underTest.wifiNetwork) 484 485 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO) 486 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 487 getCallback().onWifiEntriesChanged() 488 489 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 490 .isEqualTo(WifiNetworkModel.HotspotDeviceType.AUTO) 491 } 492 493 @Test 494 fun wifiNetwork_hotspot_invalid() = 495 testScope.runTest { 496 featureFlags.set(Flags.INSTANT_TETHER, true) 497 val latest by collectLastValue(underTest.wifiNetwork) 498 499 val wifiEntry = createHotspotWithType(1234) 500 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 501 getCallback().onWifiEntriesChanged() 502 503 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 504 .isEqualTo(WifiNetworkModel.HotspotDeviceType.INVALID) 505 } 506 507 @Test 508 fun wifiNetwork_hotspot_flagOff_valueNotUsed() = 509 testScope.runTest { 510 // WHEN the flag is off 511 featureFlags.set(Flags.INSTANT_TETHER, false) 512 513 val latest by collectLastValue(underTest.wifiNetwork) 514 515 val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH) 516 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 517 getCallback().onWifiEntriesChanged() 518 519 // THEN NONE is always used, even if the wifi entry does have a hotspot device type 520 assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) 521 .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE) 522 } 523 524 @Test 525 fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = 526 testScope.runTest { 527 val latest by collectLastValue(underTest.wifiNetwork) 528 529 val wifiEntry = 530 mock<MergedCarrierEntry>().apply { 531 whenever(this.isPrimaryNetwork).thenReturn(true) 532 whenever(this.level).thenReturn(3) 533 whenever(this.subscriptionId).thenReturn(567) 534 } 535 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 536 getCallback().onWifiEntriesChanged() 537 538 assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() 539 val latestMerged = latest as WifiNetworkModel.CarrierMerged 540 assertThat(latestMerged.level).isEqualTo(3) 541 assertThat(latestMerged.subscriptionId).isEqualTo(567) 542 } 543 544 @Test 545 fun wifiNetwork_isCarrierMerged_getsMaxSignalLevel() = 546 testScope.runTest { 547 val latest by collectLastValue(underTest.wifiNetwork) 548 549 val wifiEntry = 550 mock<MergedCarrierEntry>().apply { 551 whenever(this.isPrimaryNetwork).thenReturn(true) 552 } 553 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 554 whenever(wifiManager.maxSignalLevel).thenReturn(5) 555 556 getCallback().onWifiEntriesChanged() 557 558 assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() 559 val latestMerged = latest as WifiNetworkModel.CarrierMerged 560 // numberOfLevels = maxSignalLevel + 1 561 assertThat(latestMerged.numberOfLevels).isEqualTo(6) 562 } 563 564 @Test 565 fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() = 566 testScope.runTest { 567 val latest by collectLastValue(underTest.wifiNetwork) 568 569 val wifiEntry = 570 mock<MergedCarrierEntry>().apply { 571 whenever(this.isPrimaryNetwork).thenReturn(true) 572 whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID) 573 } 574 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 575 576 getCallback().onWifiEntriesChanged() 577 578 assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java) 579 } 580 581 @Test 582 fun wifiNetwork_notValidated_networkNotValidated() = 583 testScope.runTest { 584 val latest by collectLastValue(underTest.wifiNetwork) 585 586 val wifiEntry = 587 mock<WifiEntry>().apply { 588 whenever(this.isPrimaryNetwork).thenReturn(true) 589 whenever(this.hasInternetAccess()).thenReturn(false) 590 } 591 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 592 getCallback().onWifiEntriesChanged() 593 594 assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse() 595 } 596 597 @Test 598 fun wifiNetwork_validated_networkValidated() = 599 testScope.runTest { 600 val latest by collectLastValue(underTest.wifiNetwork) 601 602 val wifiEntry = 603 mock<WifiEntry>().apply { 604 whenever(this.isPrimaryNetwork).thenReturn(true) 605 whenever(this.hasInternetAccess()).thenReturn(true) 606 } 607 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 608 getCallback().onWifiEntriesChanged() 609 610 assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue() 611 } 612 613 @Test 614 fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() = 615 testScope.runTest { 616 val latest by collectLastValue(underTest.wifiNetwork) 617 618 val wifiEntry = 619 mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) } 620 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 621 getCallback().onWifiEntriesChanged() 622 623 assertThat(latest).isEqualTo(WifiNetworkModel.Inactive) 624 } 625 626 @Test 627 fun wifiNetwork_nonPrimaryCarrierMergedNetworkAdded_flowHasNoNetwork() = 628 testScope.runTest { 629 val latest by collectLastValue(underTest.wifiNetwork) 630 631 val wifiEntry = 632 mock<MergedCarrierEntry>().apply { 633 whenever(this.isPrimaryNetwork).thenReturn(false) 634 } 635 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 636 getCallback().onWifiEntriesChanged() 637 638 assertThat(latest).isEqualTo(WifiNetworkModel.Inactive) 639 } 640 641 @Test 642 fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() = 643 testScope.runTest { 644 val latest by collectLastValue(underTest.wifiNetwork) 645 646 // Start with the original network 647 val wifiEntry = 648 mock<WifiEntry>().apply { 649 whenever(this.isPrimaryNetwork).thenReturn(true) 650 whenever(this.level).thenReturn(3) 651 whenever(this.title).thenReturn("AB") 652 } 653 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 654 getCallback().onWifiEntriesChanged() 655 656 assertThat(latest is WifiNetworkModel.Active).isTrue() 657 var latestActive = latest as WifiNetworkModel.Active 658 assertThat(latestActive.level).isEqualTo(3) 659 assertThat(latestActive.ssid).isEqualTo("AB") 660 661 // WHEN we update to a new primary network 662 val newWifiEntry = 663 mock<WifiEntry>().apply { 664 whenever(this.isPrimaryNetwork).thenReturn(true) 665 whenever(this.level).thenReturn(4) 666 whenever(this.title).thenReturn("CD") 667 } 668 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(newWifiEntry) 669 getCallback().onWifiEntriesChanged() 670 671 // THEN we use the new network 672 assertThat(latest is WifiNetworkModel.Active).isTrue() 673 latestActive = latest as WifiNetworkModel.Active 674 assertThat(latestActive.level).isEqualTo(4) 675 assertThat(latestActive.ssid).isEqualTo("CD") 676 } 677 678 @Test 679 fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() = 680 testScope.runTest { 681 val latest by collectLastValue(underTest.wifiNetwork) 682 683 // WHEN we receive a null network without any networks beforehand 684 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 685 getCallback().onWifiEntriesChanged() 686 687 // THEN there's no crash and we still have no network 688 assertThat(latest is WifiNetworkModel.Inactive).isTrue() 689 } 690 691 @Test 692 fun wifiNetwork_currentActiveNetworkLost_flowHasNoNetwork() = 693 testScope.runTest { 694 val latest by collectLastValue(underTest.wifiNetwork) 695 696 val wifiEntry = 697 mock<WifiEntry>().apply { 698 whenever(this.isPrimaryNetwork).thenReturn(true) 699 whenever(this.title).thenReturn(TITLE) 700 } 701 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 702 getCallback().onWifiEntriesChanged() 703 704 assertThat((latest as WifiNetworkModel.Active).ssid).isEqualTo(TITLE) 705 706 // WHEN we lose our current network 707 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 708 getCallback().onWifiEntriesChanged() 709 710 // THEN we update to no network 711 assertThat(latest is WifiNetworkModel.Inactive).isTrue() 712 } 713 714 /** Possible regression test for b/278618530. */ 715 @Test 716 fun wifiNetwork_currentCarrierMergedNetworkLost_flowHasNoNetwork() = 717 testScope.runTest { 718 val latest by collectLastValue(underTest.wifiNetwork) 719 720 val wifiEntry = 721 mock<MergedCarrierEntry>().apply { 722 whenever(this.isPrimaryNetwork).thenReturn(true) 723 whenever(this.level).thenReturn(3) 724 } 725 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 726 getCallback().onWifiEntriesChanged() 727 728 assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() 729 assertThat((latest as WifiNetworkModel.CarrierMerged).level).isEqualTo(3) 730 731 // WHEN we lose our current network 732 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 733 getCallback().onWifiEntriesChanged() 734 735 // THEN we update to no network 736 assertThat(latest is WifiNetworkModel.Inactive).isTrue() 737 } 738 739 /** Regression test for b/244173280. */ 740 @Test 741 fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = 742 testScope.runTest { 743 val latest1 by collectLastValue(underTest.wifiNetwork) 744 745 val wifiEntry = 746 mock<WifiEntry>().apply { 747 whenever(this.isPrimaryNetwork).thenReturn(true) 748 whenever(this.level).thenReturn(1) 749 whenever(this.title).thenReturn(TITLE) 750 } 751 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 752 getCallback().onWifiEntriesChanged() 753 754 assertThat(latest1 is WifiNetworkModel.Active).isTrue() 755 val latest1Active = latest1 as WifiNetworkModel.Active 756 assertThat(latest1Active.level).isEqualTo(1) 757 assertThat(latest1Active.ssid).isEqualTo(TITLE) 758 759 // WHEN we add a second subscriber after having already emitted a value 760 val latest2 by collectLastValue(underTest.wifiNetwork) 761 762 // THEN the second subscribe receives the already-emitted value 763 assertThat(latest2 is WifiNetworkModel.Active).isTrue() 764 val latest2Active = latest2 as WifiNetworkModel.Active 765 assertThat(latest2Active.level).isEqualTo(1) 766 assertThat(latest2Active.ssid).isEqualTo(TITLE) 767 } 768 769 @Test 770 fun secondaryNetworks_activeEntriesEmpty_isEmpty() = 771 testScope.runTest { 772 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 773 val latest by collectLastValue(underTest.secondaryNetworks) 774 775 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf()) 776 777 getCallback().onWifiEntriesChanged() 778 779 assertThat(latest).isEmpty() 780 } 781 782 @Test 783 fun secondaryNetworks_oneActiveEntry_hasOne() = 784 testScope.runTest { 785 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 786 val latest by collectLastValue(underTest.secondaryNetworks) 787 788 val wifiEntry = mock<WifiEntry>() 789 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry)) 790 791 getCallback().onWifiEntriesChanged() 792 793 assertThat(latest).hasSize(1) 794 } 795 796 @Test 797 fun secondaryNetworks_multipleActiveEntries_hasMultiple() = 798 testScope.runTest { 799 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 800 val latest by collectLastValue(underTest.secondaryNetworks) 801 802 val wifiEntry1 = mock<WifiEntry>() 803 val wifiEntry2 = mock<WifiEntry>() 804 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry1, wifiEntry2)) 805 806 getCallback().onWifiEntriesChanged() 807 808 assertThat(latest).hasSize(2) 809 } 810 811 @Test 812 fun secondaryNetworks_mapsToInactive() = 813 testScope.runTest { 814 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 815 val latest by collectLastValue(underTest.secondaryNetworks) 816 817 val inactiveEntry = 818 mock<WifiEntry>().apply { whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE) } 819 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(inactiveEntry)) 820 821 getCallback().onWifiEntriesChanged() 822 823 assertThat(latest).hasSize(1) 824 assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Inactive::class.java) 825 } 826 827 @Test 828 fun secondaryNetworks_mapsToActive() = 829 testScope.runTest { 830 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 831 val latest by collectLastValue(underTest.secondaryNetworks) 832 833 val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) } 834 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(activeEntry)) 835 836 getCallback().onWifiEntriesChanged() 837 838 assertThat(latest).hasSize(1) 839 assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java) 840 assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2) 841 } 842 843 @Test 844 fun secondaryNetworks_mapsToCarrierMerged() = 845 testScope.runTest { 846 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 847 val latest by collectLastValue(underTest.secondaryNetworks) 848 849 val carrierMergedEntry = 850 mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) } 851 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(carrierMergedEntry)) 852 853 getCallback().onWifiEntriesChanged() 854 855 assertThat(latest).hasSize(1) 856 assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java) 857 assertThat((latest!![0] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3) 858 } 859 860 @Test 861 fun secondaryNetworks_mapsMultipleInOrder() = 862 testScope.runTest { 863 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 864 val latest by collectLastValue(underTest.secondaryNetworks) 865 866 val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) } 867 val carrierMergedEntry = 868 mock<MergedCarrierEntry>().apply { whenever(this.level).thenReturn(3) } 869 whenever(wifiPickerTracker.activeWifiEntries) 870 .thenReturn(listOf(activeEntry, carrierMergedEntry)) 871 872 getCallback().onWifiEntriesChanged() 873 874 assertThat(latest!![0]).isInstanceOf(WifiNetworkModel.Active::class.java) 875 assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2) 876 assertThat(latest!![1]).isInstanceOf(WifiNetworkModel.CarrierMerged::class.java) 877 assertThat((latest!![1] as WifiNetworkModel.CarrierMerged).level).isEqualTo(3) 878 } 879 880 @Test 881 fun secondaryNetworks_filtersOutConnectedEntry() = 882 testScope.runTest { 883 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 884 val latest by collectLastValue(underTest.secondaryNetworks) 885 886 val connectedEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(1) } 887 val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) } 888 val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) } 889 // WHEN the active list has both a primary and secondary networks 890 whenever(wifiPickerTracker.activeWifiEntries) 891 .thenReturn(listOf(connectedEntry, secondaryEntry1, secondaryEntry2)) 892 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(connectedEntry) 893 894 getCallback().onWifiEntriesChanged() 895 896 // THEN only the secondary networks are included 897 assertThat(latest).hasSize(2) 898 assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2) 899 assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3) 900 } 901 902 @Test 903 fun secondaryNetworks_noConnectedEntry_hasAllActiveEntries() = 904 testScope.runTest { 905 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 906 val latest by collectLastValue(underTest.secondaryNetworks) 907 908 val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) } 909 val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) } 910 whenever(wifiPickerTracker.activeWifiEntries) 911 .thenReturn(listOf(secondaryEntry1, secondaryEntry2)) 912 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 913 914 getCallback().onWifiEntriesChanged() 915 916 assertThat(latest).hasSize(2) 917 assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2) 918 assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3) 919 } 920 921 @Test 922 fun secondaryNetworks_filtersOutPrimaryNetwork() = 923 testScope.runTest { 924 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true) 925 val latest by collectLastValue(underTest.secondaryNetworks) 926 927 val primaryEntry = 928 mock<WifiEntry>().apply { 929 whenever(this.isPrimaryNetwork).thenReturn(true) 930 whenever(this.level).thenReturn(1) 931 } 932 val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) } 933 val secondaryEntry2 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(3) } 934 // WHEN the active list has both a primary and secondary networks 935 whenever(wifiPickerTracker.activeWifiEntries) 936 .thenReturn(listOf(secondaryEntry1, primaryEntry, secondaryEntry2)) 937 938 getCallback().onWifiEntriesChanged() 939 940 // THEN only the secondary networks are included 941 assertThat(latest).hasSize(2) 942 assertThat((latest!![0] as WifiNetworkModel.Active).level).isEqualTo(2) 943 assertThat((latest!![1] as WifiNetworkModel.Active).level).isEqualTo(3) 944 } 945 946 @Test 947 fun secondaryNetworks_flagOff_noNetworks() = 948 testScope.runTest { 949 featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false) 950 val latest by collectLastValue(underTest.secondaryNetworks) 951 952 val wifiEntry = mock<WifiEntry>() 953 whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry)) 954 955 getCallback().onWifiEntriesChanged() 956 957 assertThat(latest).isEmpty() 958 } 959 960 @Test 961 fun isWifiConnectedWithValidSsid_inactiveNetwork_false() = 962 testScope.runTest { 963 collectLastValue(underTest.wifiNetwork) 964 965 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 966 getCallback().onWifiEntriesChanged() 967 968 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 969 } 970 971 @Test 972 fun isWifiConnectedWithValidSsid_nonPrimaryNetwork_false() = 973 testScope.runTest { 974 collectLastValue(underTest.wifiNetwork) 975 976 val wifiEntry = 977 mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(false) } 978 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 979 getCallback().onWifiEntriesChanged() 980 testScope.runCurrent() 981 982 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 983 } 984 985 @Test 986 fun isWifiConnectedWithValidSsid_carrierMergedNetwork_false() = 987 testScope.runTest { 988 collectLastValue(underTest.wifiNetwork) 989 990 val wifiEntry = 991 mock<MergedCarrierEntry>().apply { 992 whenever(this.isPrimaryNetwork).thenReturn(true) 993 } 994 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 995 getCallback().onWifiEntriesChanged() 996 testScope.runCurrent() 997 998 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 999 } 1000 1001 @Test 1002 fun isWifiConnectedWithValidSsid_invalidNetwork_false() = 1003 testScope.runTest { 1004 collectLastValue(underTest.wifiNetwork) 1005 1006 val wifiEntry = 1007 mock<MergedCarrierEntry>().apply { 1008 whenever(this.isPrimaryNetwork).thenReturn(true) 1009 whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID) 1010 } 1011 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 1012 getCallback().onWifiEntriesChanged() 1013 testScope.runCurrent() 1014 1015 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 1016 } 1017 1018 @Test 1019 fun isWifiConnectedWithValidSsid_activeNetwork_nullTitle_false() = 1020 testScope.runTest { 1021 collectLastValue(underTest.wifiNetwork) 1022 1023 val wifiEntry = 1024 mock<WifiEntry>().apply { 1025 whenever(this.isPrimaryNetwork).thenReturn(true) 1026 whenever(this.title).thenReturn(null) 1027 } 1028 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 1029 getCallback().onWifiEntriesChanged() 1030 testScope.runCurrent() 1031 1032 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 1033 } 1034 1035 @Test 1036 fun isWifiConnectedWithValidSsid_activeNetwork_unknownTitle_false() = 1037 testScope.runTest { 1038 collectLastValue(underTest.wifiNetwork) 1039 1040 val wifiEntry = 1041 mock<WifiEntry>().apply { 1042 whenever(this.isPrimaryNetwork).thenReturn(true) 1043 whenever(this.title).thenReturn(UNKNOWN_SSID) 1044 } 1045 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 1046 getCallback().onWifiEntriesChanged() 1047 testScope.runCurrent() 1048 1049 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 1050 } 1051 1052 @Test 1053 fun isWifiConnectedWithValidSsid_activeNetwork_validTitle_true() = 1054 testScope.runTest { 1055 collectLastValue(underTest.wifiNetwork) 1056 1057 val wifiEntry = 1058 mock<WifiEntry>().apply { 1059 whenever(this.isPrimaryNetwork).thenReturn(true) 1060 whenever(this.title).thenReturn("fakeSsid") 1061 } 1062 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 1063 getCallback().onWifiEntriesChanged() 1064 testScope.runCurrent() 1065 1066 assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue() 1067 } 1068 1069 @Test 1070 fun isWifiConnectedWithValidSsid_activeToInactive_trueToFalse() = 1071 testScope.runTest { 1072 collectLastValue(underTest.wifiNetwork) 1073 1074 // Start with active 1075 val wifiEntry = 1076 mock<WifiEntry>().apply { 1077 whenever(this.isPrimaryNetwork).thenReturn(true) 1078 whenever(this.title).thenReturn("fakeSsid") 1079 } 1080 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) 1081 getCallback().onWifiEntriesChanged() 1082 testScope.runCurrent() 1083 1084 assertThat(underTest.isWifiConnectedWithValidSsid()).isTrue() 1085 1086 // WHEN the network is lost 1087 whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null) 1088 getCallback().onWifiEntriesChanged() 1089 testScope.runCurrent() 1090 1091 // THEN the isWifiConnected updates 1092 assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse() 1093 } 1094 1095 @Test 1096 fun wifiActivity_callbackGivesNone_activityFlowHasNone() = 1097 testScope.runTest { 1098 val latest by collectLastValue(underTest.wifiActivity) 1099 1100 getTrafficStateCallback() 1101 .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE) 1102 1103 assertThat(latest) 1104 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false)) 1105 } 1106 1107 @Test 1108 fun wifiActivity_callbackGivesIn_activityFlowHasIn() = 1109 testScope.runTest { 1110 val latest by collectLastValue(underTest.wifiActivity) 1111 1112 getTrafficStateCallback() 1113 .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN) 1114 1115 assertThat(latest) 1116 .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false)) 1117 } 1118 1119 @Test 1120 fun wifiActivity_callbackGivesOut_activityFlowHasOut() = 1121 testScope.runTest { 1122 val latest by collectLastValue(underTest.wifiActivity) 1123 1124 getTrafficStateCallback() 1125 .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT) 1126 1127 assertThat(latest) 1128 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true)) 1129 } 1130 1131 @Test 1132 fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() = 1133 testScope.runTest { 1134 val latest by collectLastValue(underTest.wifiActivity) 1135 1136 getTrafficStateCallback() 1137 .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT) 1138 1139 assertThat(latest) 1140 .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true)) 1141 } 1142 1143 @Test 1144 fun wifiScanResults_containsSsidList() = 1145 testScope.runTest { 1146 val latest by collectLastValue(underTest.wifiScanResults) 1147 1148 val scanResults = 1149 listOf( 1150 ScanResult().also { it.SSID = "ssid 1" }, 1151 ScanResult().also { it.SSID = "ssid 2" }, 1152 ScanResult().also { it.SSID = "ssid 3" }, 1153 ScanResult().also { it.SSID = "ssid 4" }, 1154 ScanResult().also { it.SSID = "ssid 5" }, 1155 ) 1156 whenever(wifiManager.scanResults).thenReturn(scanResults) 1157 getScanResultsCallback().onScanResultsAvailable() 1158 1159 val expected = 1160 listOf( 1161 WifiScanEntry(ssid = "ssid 1"), 1162 WifiScanEntry(ssid = "ssid 2"), 1163 WifiScanEntry(ssid = "ssid 3"), 1164 WifiScanEntry(ssid = "ssid 4"), 1165 WifiScanEntry(ssid = "ssid 5"), 1166 ) 1167 1168 assertThat(latest).isEqualTo(expected) 1169 } 1170 1171 @Test 1172 fun wifiScanResults_updates() = 1173 testScope.runTest { 1174 val latest by collectLastValue(underTest.wifiScanResults) 1175 1176 var scanResults = 1177 listOf( 1178 ScanResult().also { it.SSID = "ssid 1" }, 1179 ScanResult().also { it.SSID = "ssid 2" }, 1180 ScanResult().also { it.SSID = "ssid 3" }, 1181 ScanResult().also { it.SSID = "ssid 4" }, 1182 ScanResult().also { it.SSID = "ssid 5" }, 1183 ) 1184 whenever(wifiManager.scanResults).thenReturn(scanResults) 1185 getScanResultsCallback().onScanResultsAvailable() 1186 1187 // New scan representing no results 1188 scanResults = listOf() 1189 whenever(wifiManager.scanResults).thenReturn(scanResults) 1190 getScanResultsCallback().onScanResultsAvailable() 1191 1192 assertThat(latest).isEmpty() 1193 } 1194 1195 private fun getCallback(): WifiPickerTracker.WifiPickerTrackerCallback { 1196 testScope.runCurrent() 1197 return callbackCaptor.value 1198 } 1199 1200 private fun getTrafficStateCallback(): WifiManager.TrafficStateCallback { 1201 testScope.runCurrent() 1202 val callbackCaptor = argumentCaptor<WifiManager.TrafficStateCallback>() 1203 verify(wifiManager).registerTrafficStateCallback(any(), callbackCaptor.capture()) 1204 return callbackCaptor.value!! 1205 } 1206 1207 private fun createHotspotWithType(@DeviceType type: Int): HotspotNetworkEntry { 1208 return mock<HotspotNetworkEntry>().apply { 1209 whenever(this.isPrimaryNetwork).thenReturn(true) 1210 whenever(this.deviceType).thenReturn(type) 1211 } 1212 } 1213 1214 private fun getScanResultsCallback(): WifiManager.ScanResultsCallback { 1215 testScope.runCurrent() 1216 val callbackCaptor = argumentCaptor<WifiManager.ScanResultsCallback>() 1217 verify(wifiManager).registerScanResultsCallback(any(), callbackCaptor.capture()) 1218 return callbackCaptor.value!! 1219 } 1220 1221 private companion object { 1222 const val TITLE = "AB" 1223 } 1224 } 1225