diff options
4 files changed, 304 insertions, 302 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt index 7aa90336e2bf..49de5a232f30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt @@ -160,7 +160,7 @@ abstract class StatusBarPipelineModule { @SysUISingleton @SharedConnectivityInputLog fun provideSharedConnectivityTableLogBuffer(factory: LogBufferFactory): LogBuffer { - return factory.create("SharedConnectivityInputLog", 30) + return factory.create("SharedConnectivityInputLog", 60) } @Provides diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt index 0e9b6c56437e..81a068d10a14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt @@ -38,6 +38,7 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel @@ -88,6 +89,7 @@ constructor( private val context: Context, @Background private val bgDispatcher: CoroutineDispatcher, @Application private val scope: CoroutineScope, + airplaneModeRepository: AirplaneModeRepository, // Some "wifi networks" should be rendered as a mobile connection, which is why the wifi // repository is an input to the mobile repository. // See [CarrierMergedConnectionRepository] for details. @@ -106,10 +108,20 @@ constructor( context.getString(R.string.status_bar_network_name_separator) private val carrierMergedSubId: StateFlow<Int?> = - wifiRepository.wifiNetwork - .mapLatest { - if (it is WifiNetworkModel.CarrierMerged) { - it.subscriptionId + combine( + wifiRepository.wifiNetwork, + connectivityRepository.defaultConnections, + airplaneModeRepository.isAirplaneMode, + ) { wifiNetwork, defaultConnections, isAirplaneMode -> + // The carrier merged connection should only be used if it's also the default + // connection or mobile connections aren't available because of airplane mode. + val defaultConnectionIsNonMobile = + defaultConnections.carrierMerged.isDefault || + defaultConnections.wifi.isDefault || + isAirplaneMode + + if (wifiNetwork is WifiNetworkModel.CarrierMerged && defaultConnectionIsNonMobile) { + wifiNetwork.subscriptionId } else { null } @@ -269,12 +281,8 @@ constructor( .stateIn(scope, SharingStarted.WhileSubscribed(), false) override val hasCarrierMergedConnection: StateFlow<Boolean> = - combine( - connectivityRepository.defaultConnections, - carrierMergedSubId, - ) { defaultConnections, carrierMergedSubId -> - defaultConnections.carrierMerged.isDefault || carrierMergedSubId != null - } + carrierMergedSubId + .map { it != null } .distinctUntilChanged() .logDiffsForTable( tableLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt index bde05b9f499e..5a887ebcee80 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory +import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository @@ -131,6 +132,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() { context, IMMEDIATE, scope, + FakeAirplaneModeRepository(), wifiRepository, mock(), ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index 7cc59b67414b..38c7432eb288 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -34,13 +34,16 @@ import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import android.telephony.TelephonyCallback import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener import android.telephony.TelephonyManager +import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.telephony.PhoneConstants import com.android.settingslib.R import com.android.settingslib.mobile.MobileMappings import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory +import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository @@ -51,25 +54,25 @@ import com.android.systemui.statusbar.pipeline.mobile.util.FakeSubscriptionManag import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl -import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository -import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository +import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl +import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import java.util.UUID -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.yield -import org.junit.After +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue import org.junit.Before @@ -83,6 +86,9 @@ import org.mockito.MockitoAnnotations @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +// This is required because our [SubscriptionManager.OnSubscriptionsChangedListener] uses a looper +// to run the callback and this makes the looper place nicely with TestScope etc. +@TestableLooper.RunWithLooper class MobileConnectionsRepositoryTest : SysuiTestCase() { private lateinit var underTest: MobileConnectionsRepositoryImpl @@ -90,7 +96,8 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory private lateinit var fullConnectionFactory: FullMobileConnectionRepository.Factory private lateinit var connectivityRepository: ConnectivityRepository - private lateinit var wifiRepository: FakeWifiRepository + private lateinit var airplaneModeRepository: FakeAirplaneModeRepository + private lateinit var wifiRepository: WifiRepository private lateinit var carrierConfigRepository: CarrierConfigRepository @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var subscriptionManager: SubscriptionManager @@ -102,7 +109,8 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { private val mobileMappings = FakeMobileMappingsProxy() private val subscriptionManagerProxy = FakeSubscriptionManagerProxy() - private val scope = CoroutineScope(IMMEDIATE) + private val dispatcher = StandardTestDispatcher() + private val testScope = TestScope(dispatcher) @Before fun setUp() { @@ -138,11 +146,23 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { context, mock(), mock(), - scope, + testScope.backgroundScope, mock(), ) - wifiRepository = FakeWifiRepository() + airplaneModeRepository = FakeAirplaneModeRepository() + + wifiRepository = + WifiRepositoryImpl( + fakeBroadcastDispatcher, + connectivityManager, + connectivityRepository, + mock(), + mock(), + FakeExecutor(FakeSystemClock()), + testScope.backgroundScope, + mock(), + ) carrierConfigRepository = CarrierConfigRepository( @@ -150,28 +170,28 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { mock(), mock(), logger, - scope, + testScope.backgroundScope, ) connectionFactory = MobileConnectionRepositoryImpl.Factory( fakeBroadcastDispatcher, telephonyManager = telephonyManager, - bgDispatcher = IMMEDIATE, + bgDispatcher = dispatcher, logger = logger, mobileMappingsProxy = mobileMappings, - scope = scope, + scope = testScope.backgroundScope, carrierConfigRepository = carrierConfigRepository, ) carrierMergedFactory = CarrierMergedConnectionRepository.Factory( telephonyManager, - scope, + testScope.backgroundScope, wifiRepository, ) fullConnectionFactory = FullMobileConnectionRepository.Factory( - scope = scope, + scope = testScope.backgroundScope, logFactory = logBufferFactory, mobileRepoFactory = connectionFactory, carrierMergedRepoFactory = carrierMergedFactory, @@ -188,46 +208,38 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { mobileMappings, fakeBroadcastDispatcher, context, - IMMEDIATE, - scope, + dispatcher, + testScope.backgroundScope, + airplaneModeRepository, wifiRepository, fullConnectionFactory, ) - } - @After - fun tearDown() { - scope.cancel() + testScope.runCurrent() } @Test fun testSubscriptions_initiallyEmpty() = - runBlocking(IMMEDIATE) { + testScope.runTest { assertThat(underTest.subscriptions.value).isEqualTo(listOf<SubscriptionModel>()) } @Test fun testSubscriptions_listUpdates() = - runBlocking(IMMEDIATE) { - var latest: List<SubscriptionModel>? = null - - val job = underTest.subscriptions.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.subscriptions) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2)) getSubscriptionCallback().onSubscriptionsChanged() assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2)) - - job.cancel() } @Test fun testSubscriptions_removingSub_updatesList() = - runBlocking(IMMEDIATE) { - var latest: List<SubscriptionModel>? = null - - val job = underTest.subscriptions.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.subscriptions) // WHEN 2 networks show up whenever(subscriptionManager.completeActiveSubscriptionInfoList) @@ -241,71 +253,55 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { // THEN the subscriptions list represents the newest change assertThat(latest).isEqualTo(listOf(MODEL_2)) - - job.cancel() } @Test fun testSubscriptions_carrierMergedOnly_listHasCarrierMerged() = - runBlocking(IMMEDIATE) { - var latest: List<SubscriptionModel>? = null + testScope.runTest { + val latest by collectLastValue(underTest.subscriptions) - val job = underTest.subscriptions.onEach { latest = it }.launchIn(this) - - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() assertThat(latest).isEqualTo(listOf(MODEL_CM)) - - job.cancel() } @Test fun testSubscriptions_carrierMergedAndOther_listHasBothWithCarrierMergedLast() = - runBlocking(IMMEDIATE) { - var latest: List<SubscriptionModel>? = null + testScope.runTest { + val latest by collectLastValue(underTest.subscriptions) - val job = underTest.subscriptions.onEach { latest = it }.launchIn(this) - - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2, SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2, MODEL_CM)) - - job.cancel() } @Test fun testActiveDataSubscriptionId_initialValueIsNull() = - runBlocking(IMMEDIATE) { + testScope.runTest { assertThat(underTest.activeMobileDataSubscriptionId.value).isEqualTo(null) } @Test fun testActiveDataSubscriptionId_updates() = - runBlocking(IMMEDIATE) { - var active: Int? = null - - val job = underTest.activeMobileDataSubscriptionId.onEach { active = it }.launchIn(this) + testScope.runTest { + val active by collectLastValue(underTest.activeMobileDataSubscriptionId) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) assertThat(active).isEqualTo(SUB_2_ID) - - job.cancel() } @Test fun activeSubId_nullIfInvalidSubIdIsReceived() = - runBlocking(IMMEDIATE) { - var latest: Int? = null - - val job = underTest.activeMobileDataSubscriptionId.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.activeMobileDataSubscriptionId) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) @@ -316,8 +312,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { .onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID) assertThat(latest).isNull() - - job.cancel() } @Test @@ -327,23 +321,19 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Test fun activeRepo_updatesWithActiveDataId() = - runBlocking(IMMEDIATE) { - var latest: MobileConnectionRepository? = null - val job = underTest.activeMobileDataRepository.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.activeMobileDataRepository) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) assertThat(latest?.subId).isEqualTo(SUB_2_ID) - - job.cancel() } @Test fun activeRepo_nullIfActiveDataSubIdBecomesInvalid() = - runBlocking(IMMEDIATE) { - var latest: MobileConnectionRepository? = null - val job = underTest.activeMobileDataRepository.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.activeMobileDataRepository) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) @@ -354,64 +344,49 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { .onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID) assertThat(latest).isNull() - - job.cancel() } @Test /** Regression test for b/268146648. */ fun activeSubIdIsSetBeforeSubscriptionsAreUpdated_doesNotThrow() = - runBlocking(IMMEDIATE) { - var activeRepo: MobileConnectionRepository? = null - var subscriptions: List<SubscriptionModel>? = null - - val activeRepoJob = - underTest.activeMobileDataRepository.onEach { activeRepo = it }.launchIn(this) - val subscriptionsJob = - underTest.subscriptions.onEach { subscriptions = it }.launchIn(this) + testScope.runTest { + val activeRepo by collectLastValue(underTest.activeMobileDataRepository) + val subscriptions by collectLastValue(underTest.subscriptions) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) assertThat(subscriptions).isEmpty() assertThat(activeRepo).isNotNull() - - activeRepoJob.cancel() - subscriptionsJob.cancel() } @Test fun getRepoForSubId_activeDataSubIdIsRequestedBeforeSubscriptionsUpdate() = - runBlocking(IMMEDIATE) { - var latest: MobileConnectionRepository? = null - var subscriptions: List<SubscriptionModel>? = null - val activeSubIdJob = - underTest.activeMobileDataSubscriptionId - .filterNotNull() - .onEach { latest = underTest.getRepoForSubId(it) } - .launchIn(this) - val subscriptionsJob = - underTest.subscriptions.onEach { subscriptions = it }.launchIn(this) + testScope.runTest { + var latestActiveRepo: MobileConnectionRepository? = null + collectLastValue( + underTest.activeMobileDataSubscriptionId.filterNotNull().onEach { + latestActiveRepo = underTest.getRepoForSubId(it) + } + ) + + val latestSubscriptions by collectLastValue(underTest.subscriptions) // Active data subscription id is sent, but no subscription change has been posted yet getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_2_ID) // Subscriptions list is empty - assertThat(subscriptions).isEmpty() + assertThat(latestSubscriptions).isEmpty() // getRepoForSubId does not throw - assertThat(latest).isNotNull() - - activeSubIdJob.cancel() - subscriptionsJob.cancel() + assertThat(latestActiveRepo).isNotNull() } @Test fun activeDataSentBeforeSubscriptionList_subscriptionReusesActiveDataRepo() = - runBlocking(IMMEDIATE) { - var activeRepo: MobileConnectionRepository? = null - val job = underTest.activeMobileDataRepository.onEach { activeRepo = it }.launchIn(this) - val subscriptionsJob = underTest.subscriptions.launchIn(this) + testScope.runTest { + val activeRepo by collectLastValue(underTest.activeMobileDataRepository) + collectLastValue(underTest.subscriptions) // GIVEN active repo is updated before the subscription list updates getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() @@ -429,15 +404,12 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { // THEN the newly request repo has been cached and reused assertThat(activeRepo).isSameInstanceAs(newRepo) - - job.cancel() - subscriptionsJob.cancel() } @Test fun testConnectionRepository_validSubId_isCached() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1)) @@ -447,16 +419,15 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { val repo2 = underTest.getRepoForSubId(SUB_1_ID) assertThat(repo1).isSameInstanceAs(repo2) - - job.cancel() } @Test fun testConnectionRepository_carrierMergedSubId_isCached() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() @@ -465,16 +436,15 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { val repo2 = underTest.getRepoForSubId(SUB_CM_ID) assertThat(repo1).isSameInstanceAs(repo2) - - job.cancel() } @Test fun testConnectionRepository_carrierMergedAndMobileSubs_usesCorrectRepos() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() @@ -483,16 +453,15 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { val mobileRepo = underTest.getRepoForSubId(SUB_1_ID) assertThat(carrierMergedRepo.getIsCarrierMerged()).isTrue() assertThat(mobileRepo.getIsCarrierMerged()).isFalse() - - job.cancel() } @Test fun testSubscriptions_subNoLongerCarrierMerged_repoUpdates() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() @@ -503,26 +472,28 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(mobileRepo.getIsCarrierMerged()).isFalse() // WHEN the wifi network updates to be not carrier merged - wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 4, level = 1)) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE) + runCurrent() // THEN the repos update val noLongerCarrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID) mobileRepo = underTest.getRepoForSubId(SUB_1_ID) assertThat(noLongerCarrierMergedRepo.getIsCarrierMerged()).isFalse() assertThat(mobileRepo.getIsCarrierMerged()).isFalse() - - job.cancel() } @Test fun testSubscriptions_subBecomesCarrierMerged_repoUpdates() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) - wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_ACTIVE) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() + runCurrent() val notYetCarrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID) var mobileRepo = underTest.getRepoForSubId(SUB_1_ID) @@ -530,21 +501,21 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(mobileRepo.getIsCarrierMerged()).isFalse() // WHEN the wifi network updates to be carrier merged - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + runCurrent() // THEN the repos update val carrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID) mobileRepo = underTest.getRepoForSubId(SUB_1_ID) assertThat(carrierMergedRepo.getIsCarrierMerged()).isTrue() assertThat(mobileRepo.getIsCarrierMerged()).isFalse() - - job.cancel() } @Test fun testConnectionCache_clearsInvalidSubscriptions() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2)) @@ -563,16 +534,15 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { getSubscriptionCallback().onSubscriptionsChanged() assertThat(underTest.getSubIdRepoCache()).containsExactly(SUB_1_ID, repo1) - - job.cancel() } @Test fun testConnectionCache_clearsInvalidSubscriptions_includingCarrierMerged() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2, SUB_CM)) getSubscriptionCallback().onSubscriptionsChanged() @@ -591,15 +561,13 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { getSubscriptionCallback().onSubscriptionsChanged() assertThat(underTest.getSubIdRepoCache()).containsExactly(SUB_1_ID, repo1) - - job.cancel() } /** Regression test for b/261706421 */ @Test fun testConnectionsCache_clearMultipleSubscriptionsAtOnce_doesNotThrow() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2)) @@ -617,26 +585,20 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { getSubscriptionCallback().onSubscriptionsChanged() assertThat(underTest.getSubIdRepoCache()).isEmpty() - - job.cancel() } @Test fun testConnectionRepository_invalidSubId_throws() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) - + testScope.runTest { assertThrows(IllegalArgumentException::class.java) { underTest.getRepoForSubId(SUB_1_ID) } - - job.cancel() } @Test fun connectionRepository_logBufferContainsSubIdInItsName() = - runBlocking(IMMEDIATE) { - val job = underTest.subscriptions.launchIn(this) + testScope.runTest { + collectLastValue(underTest.subscriptions) whenever(subscriptionManager.completeActiveSubscriptionInfoList) .thenReturn(listOf(SUB_1, SUB_2)) @@ -655,15 +617,12 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { eq(tableBufferLogName(SUB_2_ID)), anyInt(), ) - - job.cancel() } @Test fun testDefaultDataSubId_updatesOnBroadcast() = - runBlocking(IMMEDIATE) { - var latest: Int? = null - val job = underTest.defaultDataSubId.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.defaultDataSubId) assertThat(latest).isEqualTo(INVALID_SUBSCRIPTION_ID) @@ -686,28 +645,24 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } assertThat(latest).isEqualTo(SUB_1_ID) - - job.cancel() } @Test fun defaultDataSubId_fetchesInitialValueOnStart() = - runBlocking(IMMEDIATE) { + testScope.runTest { subscriptionManagerProxy.defaultDataSubId = 2 - var latest: Int? = null - val job = underTest.defaultDataSubId.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.defaultDataSubId) assertThat(latest).isEqualTo(2) - - job.cancel() } @Test fun defaultDataSubId_fetchesCurrentOnRestart() = - runBlocking(IMMEDIATE) { + testScope.runTest { subscriptionManagerProxy.defaultDataSubId = 2 var latest: Int? = null var job = underTest.defaultDataSubId.onEach { latest = it }.launchIn(this) + runCurrent() assertThat(latest).isEqualTo(2) @@ -720,6 +675,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { subscriptionManagerProxy.defaultDataSubId = 1 job = underTest.defaultDataSubId.onEach { latest = it }.launchIn(this) + runCurrent() assertThat(latest).isEqualTo(1) @@ -733,43 +689,37 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Test fun mobileIsDefault_capsHaveCellular_isDefault() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) } - var latest: Boolean? = null - val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.mobileIsDefault) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun mobileIsDefault_capsDoNotHaveCellular_isNotDefault() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false) } - var latest: Boolean? = null - val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.mobileIsDefault) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isFalse() - - job.cancel() } @Test fun mobileIsDefault_carrierMergedViaMobile_isDefault() = - runBlocking(IMMEDIATE) { + testScope.runTest { val carrierMergedInfo = mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } val caps = @@ -778,151 +728,144 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { whenever(it.transportInfo).thenReturn(carrierMergedInfo) } - var latest: Boolean? = null - val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.mobileIsDefault) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun mobileIsDefault_wifiDefault_mobileNotDefault() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) } - var latest: Boolean? = null - val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.mobileIsDefault) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isFalse() - - job.cancel() } @Test fun mobileIsDefault_ethernetDefault_mobileNotDefault() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true) } - var latest: Boolean? = null - val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.mobileIsDefault) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isFalse() - - job.cancel() } /** Regression test for b/272586234. */ @Test fun hasCarrierMergedConnection_carrierMergedViaWifi_isTrue() = - runBlocking(IMMEDIATE) { + testScope.runTest { val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) whenever(it.transportInfo).thenReturn(carrierMergedInfo) } - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.hasCarrierMergedConnection) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun hasCarrierMergedConnection_carrierMergedViaMobile_isTrue() = - runBlocking(IMMEDIATE) { + testScope.runTest { val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) whenever(it.transportInfo).thenReturn(carrierMergedInfo) } - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.hasCarrierMergedConnection) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } /** Regression test for b/272586234. */ @Test fun hasCarrierMergedConnection_carrierMergedViaWifiWithVcnTransport_isTrue() = - runBlocking(IMMEDIATE) { + testScope.runTest { val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo)) } - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.hasCarrierMergedConnection) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun hasCarrierMergedConnection_carrierMergedViaMobileWithVcnTransport_isTrue() = - runBlocking(IMMEDIATE) { + testScope.runTest { val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val caps = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo)) } - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.hasCarrierMergedConnection) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun hasCarrierMergedConnection_isCarrierMergedViaUnderlyingWifi_isTrue() = - runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.hasCarrierMergedConnection) val underlyingNetwork = mock<Network>() val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val underlyingWifiCapabilities = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) @@ -941,23 +884,23 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities) // THEN there's a carrier merged connection assertThat(latest).isTrue() - - job.cancel() } @Test fun hasCarrierMergedConnection_isCarrierMergedViaUnderlyingCellular_isTrue() = - runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.hasCarrierMergedConnection) val underlyingCarrierMergedNetwork = mock<Network>() val carrierMergedInfo = - mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) } + mock<WifiInfo>().apply { + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.isPrimary).thenReturn(true) + } val underlyingCapabilities = mock<NetworkCapabilities>().also { whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) @@ -977,22 +920,19 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities) // THEN there's a carrier merged connection assertThat(latest).isTrue() - - job.cancel() } /** Regression test for b/272586234. */ @Test - fun hasCarrierMergedConnection_defaultNotCarrierMerged_butWifiRepoHasCarrierMerged_isTrue() = - runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this) + fun hasCarrierMergedConnection_defaultIsWifiNotCarrierMerged_wifiRepoIsCarrierMerged_isTrue() = + testScope.runTest { + val latest by collectLastValue(underTest.hasCarrierMergedConnection) - // WHEN the default callback isn't carrier merged + // WHEN the default callback is TRANSPORT_WIFI but not carrier merged val carrierMergedInfo = mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(false) } val caps = @@ -1001,16 +941,57 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { whenever(it.transportInfo).thenReturn(carrierMergedInfo) } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) - yield() // BUT the wifi repo has gotten updates that it *is* carrier merged - wifiRepository.setWifiNetwork(WIFI_NETWORK_CM) - yield() + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) // THEN hasCarrierMergedConnection is true assertThat(latest).isTrue() + } - job.cancel() + /** Regression test for b/278618530. */ + @Test + fun hasCarrierMergedConnection_defaultIsCellular_wifiRepoIsCarrierMerged_isFalse() = + testScope.runTest { + val latest by collectLastValue(underTest.hasCarrierMergedConnection) + + // WHEN the default callback is TRANSPORT_CELLULAR and not carrier merged + val caps = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(it.transportInfo).thenReturn(null) + } + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) + + // BUT the wifi repo has gotten updates that it *is* carrier merged + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + + // THEN hasCarrierMergedConnection is **false** (The default network being CELLULAR + // takes precedence over the wifi network being carrier merged.) + assertThat(latest).isFalse() + } + + /** Regression test for b/278618530. */ + @Test + fun hasCarrierMergedConnection_defaultCellular_wifiIsCarrierMerged_airplaneMode_isTrue() = + testScope.runTest { + val latest by collectLastValue(underTest.hasCarrierMergedConnection) + + // WHEN the default callback is TRANSPORT_CELLULAR and not carrier merged + val caps = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(it.transportInfo).thenReturn(null) + } + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) + + // BUT the wifi repo has gotten updates that it *is* carrier merged + getNormalNetworkCallback().onCapabilitiesChanged(NETWORK, WIFI_NETWORK_CAPS_CM) + // AND we're in airplane mode + airplaneModeRepository.setIsAirplaneMode(true) + + // THEN hasCarrierMergedConnection is true. + assertThat(latest).isTrue() } @Test @@ -1020,43 +1001,37 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Test fun defaultConnectionIsValidated_capsHaveValidated_isValidated() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(true) } - var latest: Boolean? = null - val job = underTest.defaultConnectionIsValidated.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.defaultConnectionIsValidated) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isTrue() - - job.cancel() } @Test fun defaultConnectionIsValidated_capsHaveNotValidated_isNotValidated() = - runBlocking(IMMEDIATE) { + testScope.runTest { val caps = mock<NetworkCapabilities>().also { whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(false) } - var latest: Boolean? = null - val job = underTest.defaultConnectionIsValidated.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.defaultConnectionIsValidated) getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps) assertThat(latest).isFalse() - - job.cancel() } @Test fun config_initiallyFromContext() = - runBlocking(IMMEDIATE) { + testScope.runTest { overrideResource(R.bool.config_showMin3G, true) val configFromContext = MobileMappings.Config.readConfig(context) assertThat(configFromContext.showAtLeast3G).isTrue() @@ -1074,26 +1049,24 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { mobileMappings, fakeBroadcastDispatcher, context, - IMMEDIATE, - scope, + dispatcher, + testScope.backgroundScope, + airplaneModeRepository, wifiRepository, fullConnectionFactory, ) - var latest: MobileMappings.Config? = null - val job = underTest.defaultDataSubRatConfig.onEach { latest = it }.launchIn(this) + val latest by collectLastValue(underTest.defaultDataSubRatConfig) assertTrue(latest!!.areEqual(configFromContext)) assertTrue(latest!!.showAtLeast3G) - - job.cancel() } @Test fun config_subIdChangeEvent_updated() = - runBlocking(IMMEDIATE) { - var latest: MobileMappings.Config? = null - val job = underTest.defaultDataSubRatConfig.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.defaultDataSubRatConfig) + assertThat(latest!!.showAtLeast3G).isFalse() overrideResource(R.bool.config_showMin3G, true) @@ -1112,15 +1085,13 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { // THEN the config is updated assertTrue(latest!!.areEqual(configFromContext)) assertTrue(latest!!.showAtLeast3G) - - job.cancel() } @Test fun config_carrierConfigChangeEvent_updated() = - runBlocking(IMMEDIATE) { - var latest: MobileMappings.Config? = null - val job = underTest.defaultDataSubRatConfig.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.defaultDataSubRatConfig) + assertThat(latest!!.showAtLeast3G).isFalse() overrideResource(R.bool.config_showMin3G, true) @@ -1138,15 +1109,12 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { // THEN the config is updated assertThat(latest!!.areEqual(configFromContext)).isTrue() assertThat(latest!!.showAtLeast3G).isTrue() - - job.cancel() } @Test fun activeDataChange_inSameGroup_emitsUnit() = - runBlocking(IMMEDIATE) { - var latest: Unit? = null - val job = underTest.activeSubChangedInGroupEvent.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.activeSubChangedInGroupEvent) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_3_ID_GROUPED) @@ -1154,15 +1122,12 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { .onActiveDataSubscriptionIdChanged(SUB_4_ID_GROUPED) assertThat(latest).isEqualTo(Unit) - - job.cancel() } @Test fun activeDataChange_notInSameGroup_doesNotEmit() = - runBlocking(IMMEDIATE) { - var latest: Unit? = null - val job = underTest.activeSubChangedInGroupEvent.onEach { latest = it }.launchIn(this) + testScope.runTest { + val latest by collectLastValue(underTest.activeSubChangedInGroupEvent) getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>() .onActiveDataSubscriptionIdChanged(SUB_3_ID_GROUPED) @@ -1170,38 +1135,46 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { .onActiveDataSubscriptionIdChanged(SUB_1_ID) assertThat(latest).isEqualTo(null) - - job.cancel() } - private fun getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback { + private fun TestScope.getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback { + runCurrent() val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>() verify(connectivityManager).registerDefaultNetworkCallback(callbackCaptor.capture()) return callbackCaptor.value!! } - private fun getSubscriptionCallback(): SubscriptionManager.OnSubscriptionsChangedListener { + // Note: This is used to update the [WifiRepository]. + private fun TestScope.getNormalNetworkCallback(): ConnectivityManager.NetworkCallback { + runCurrent() + val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>() + verify(connectivityManager).registerNetworkCallback(any(), callbackCaptor.capture()) + return callbackCaptor.value!! + } + + private fun TestScope.getSubscriptionCallback(): + SubscriptionManager.OnSubscriptionsChangedListener { + runCurrent() val callbackCaptor = argumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener>() verify(subscriptionManager) .addOnSubscriptionsChangedListener(any(), callbackCaptor.capture()) return callbackCaptor.value!! } - private fun getTelephonyCallbacks(): List<TelephonyCallback> { + private fun TestScope.getTelephonyCallbacks(): List<TelephonyCallback> { + runCurrent() val callbackCaptor = argumentCaptor<TelephonyCallback>() verify(telephonyManager).registerTelephonyCallback(any(), callbackCaptor.capture()) return callbackCaptor.allValues } - private inline fun <reified T> getTelephonyCallbackForType(): T { - val cbs = getTelephonyCallbacks().filterIsInstance<T>() + private inline fun <reified T> TestScope.getTelephonyCallbackForType(): T { + val cbs = this.getTelephonyCallbacks().filterIsInstance<T>() assertThat(cbs.size).isEqualTo(1) return cbs[0] } companion object { - private val IMMEDIATE = Dispatchers.Main.immediate - // Subscription 1 private const val SUB_1_ID = 1 private val GROUP_1 = ParcelUuid(UUID.randomUUID()) @@ -1259,11 +1232,30 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { private val SUB_CM = mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_CM_ID) } private val MODEL_CM = SubscriptionModel(subscriptionId = SUB_CM_ID) - private val WIFI_NETWORK_CM = - WifiNetworkModel.CarrierMerged( - networkId = 3, - subscriptionId = SUB_CM_ID, - level = 1, - ) + + private val WIFI_INFO_CM = + mock<WifiInfo>().apply { + whenever(this.isPrimary).thenReturn(true) + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.subscriptionId).thenReturn(SUB_CM_ID) + } + private val WIFI_NETWORK_CAPS_CM = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) + whenever(it.transportInfo).thenReturn(WIFI_INFO_CM) + whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(true) + } + + private val WIFI_INFO_ACTIVE = + mock<WifiInfo>().apply { + whenever(this.isPrimary).thenReturn(true) + whenever(this.isCarrierMerged).thenReturn(false) + } + private val WIFI_NETWORK_CAPS_ACTIVE = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) + whenever(it.transportInfo).thenReturn(WIFI_INFO_ACTIVE) + whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(true) + } } } |