Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c9d588e authored by Steve Elliott's avatar Steve Elliott
Browse files

[kairos] Tests for KairosAdapters

Flag: com.android.systemui.status_bar_mobile_icon_kairos
Bug: 383172066
Test: atest
Change-Id: Icd4206176c8ad92467eb61bb7b33ace534ac27a7
parent f9cb4e1d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -220,6 +220,7 @@ filegroup {
        "tests/src/**/systemui/statusbar/phone/StatusBarBoundsProviderTest.kt",
        "tests/src/**/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryKairosAdapterTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt",
@@ -356,7 +357,9 @@ filegroup {
        "tests/src/**/systemui/qs/tiles/AlarmTileTest.kt",
        "tests/src/**/systemui/qs/tiles/BluetoothTileTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryKairosAdapterTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionKairosAdapterTelephonySmokeTests.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt",
        "tests/src/**/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt",
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.activated
import com.android.systemui.kairos.ExperimentalKairosApi
import com.android.systemui.kairos.launchKairosNetwork
import com.android.systemui.kairos.stateOf
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.data.model.testCarrierConfig
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runCurrent
import org.junit.runner.RunWith
import org.mockito.Mockito

@OptIn(ExperimentalKairosApi::class, ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class CarrierMergedConnectionRepositoryKairosAdapterTest :
    CarrierMergedConnectionRepositoryTestBase() {

    var job: Job? = null
    val kairosNetwork = testScope.backgroundScope.launchKairosNetwork()

    override fun recreateRepo(): MobileConnectionRepositoryKairosAdapter {
        lateinit var adapter: MobileConnectionRepositoryKairosAdapter
        job?.cancel()
        Mockito.clearInvocations(telephonyManager)
        job =
            testScope.backgroundScope.launch {
                kairosNetwork.activateSpec {
                    val repo = activated {
                        CarrierMergedConnectionRepositoryKairos(
                            SUB_ID,
                            logger,
                            telephonyManager,
                            wifiRepository,
                            isInEcmMode = stateOf(false),
                        )
                    }
                    adapter =
                        MobileConnectionRepositoryKairosAdapter(
                            repo,
                            SystemUiCarrierConfig(SUB_ID, testCarrierConfig()),
                        )
                    Unit
                }
            }
        testScope.runCurrent() // ensure the lateinit is set
        return adapter
    }
}
+37 −49
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -43,16 +44,30 @@ import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidJUnit4::class)
class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
class CarrierMergedConnectionRepositoryTest : CarrierMergedConnectionRepositoryTestBase() {
    override fun recreateRepo() =
        CarrierMergedConnectionRepository(
            SUB_ID,
            logger,
            telephonyManager,
            testScope.backgroundScope.coroutineContext,
            testScope.backgroundScope,
            wifiRepository,
        )
}

abstract class CarrierMergedConnectionRepositoryTestBase : SysuiTestCase() {

    protected lateinit var underTest: MobileConnectionRepository

    private lateinit var underTest: CarrierMergedConnectionRepository
    protected lateinit var wifiRepository: FakeWifiRepository
    @Mock protected lateinit var logger: TableLogBuffer
    @Mock protected lateinit var telephonyManager: TelephonyManager

    private lateinit var wifiRepository: FakeWifiRepository
    @Mock private lateinit var logger: TableLogBuffer
    @Mock private lateinit var telephonyManager: TelephonyManager
    protected val testDispatcher = UnconfinedTestDispatcher()
    protected val testScope = TestScope(testDispatcher)

    private val testDispatcher = UnconfinedTestDispatcher()
    private val testScope = TestScope(testDispatcher)
    abstract fun recreateRepo(): MobileConnectionRepository

    @Before
    fun setUp() {
@@ -62,15 +77,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {

        wifiRepository = FakeWifiRepository()

        underTest =
            CarrierMergedConnectionRepository(
                SUB_ID,
                logger,
                telephonyManager,
                testScope.backgroundScope.coroutineContext,
                testScope.backgroundScope,
                wifiRepository,
            )
        underTest = recreateRepo()
    }

    @Test
@@ -121,10 +128,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            wifiRepository.setIsWifiDefault(true)

            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID, level = 3)
            )

            assertThat(latest).isEqualTo(3)
@@ -141,26 +145,17 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            wifiRepository.setIsWifiEnabled(true)
            wifiRepository.setIsWifiDefault(true)
            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID, level = 3)
            )
            wifiRepository.setWifiActivity(
                DataActivityModel(
                    hasActivityIn = true,
                    hasActivityOut = false,
                )
                DataActivityModel(hasActivityIn = true, hasActivityOut = false)
            )

            assertThat(latest!!.hasActivityIn).isTrue()
            assertThat(latest!!.hasActivityOut).isFalse()

            wifiRepository.setWifiActivity(
                DataActivityModel(
                    hasActivityIn = false,
                    hasActivityOut = true,
                )
                DataActivityModel(hasActivityIn = false, hasActivityOut = true)
            )

            assertThat(latest!!.hasActivityIn).isFalse()
@@ -178,10 +173,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            val typeJob = underTest.resolvedNetworkType.onEach { latestType = it }.launchIn(this)

            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID + 10,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID + 10, level = 3)
            )

            assertThat(latestLevel).isNotEqualTo(3)
@@ -199,10 +191,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)

            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID, level = 3)
            )
            wifiRepository.setIsWifiEnabled(false)

@@ -219,10 +208,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)

            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID, level = 3)
            )
            wifiRepository.setIsWifiDefault(false)

@@ -280,6 +266,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
    fun networkName_usesSimOperatorNameAsInitial() =
        testScope.runTest {
            whenever(telephonyManager.simOperatorName).thenReturn("Test SIM name")
            underTest = recreateRepo()

            var latest: NetworkNameModel? = null
            val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -293,6 +280,10 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
    fun networkName_updatesOnNetworkUpdate() =
        testScope.runTest {
            whenever(telephonyManager.simOperatorName).thenReturn("Test SIM name")
            underTest = recreateRepo()

            wifiRepository.setIsWifiEnabled(true)
            wifiRepository.setIsWifiDefault(true)

            var latest: NetworkNameModel? = null
            val job = underTest.networkName.onEach { latest = it }.launchIn(this)
@@ -301,10 +292,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {

            whenever(telephonyManager.simOperatorName).thenReturn("New SIM name")
            wifiRepository.setWifiNetwork(
                WifiNetworkModel.CarrierMerged.of(
                    subscriptionId = SUB_ID,
                    level = 3,
                )
                WifiNetworkModel.CarrierMerged.of(subscriptionId = SUB_ID, level = 3)
            )

            assertThat(latest).isEqualTo(NetworkNameModel.SimDerived("New SIM name"))
@@ -320,7 +308,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
            assertThat(latest).isTrue()
        }

    private companion object {
    companion object {
        const val SUB_ID = 123
    }
}
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.pipeline.mobile.domain.interactor

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
import com.android.systemui.activated
import com.android.systemui.kairos.BuildScope
import com.android.systemui.kairos.ExperimentalKairosApi
import com.android.systemui.kairos.Incremental
import com.android.systemui.kairos.State
import com.android.systemui.kairos.asIncremental
import com.android.systemui.kairos.buildSpec
import com.android.systemui.kairos.combine
import com.android.systemui.kairos.launchKairosNetwork
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorKairosAdapterTest.Companion.wrapRepo
import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runCurrent
import org.junit.runner.RunWith

@OptIn(ExperimentalKairosApi::class, ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconInteractorKairosAdapterTest : MobileIconInteractorTestBase() {

    var job: Job? = null
    val kairosNetwork = testScope.backgroundScope.launchKairosNetwork()

    override fun createInteractor(overrides: MobileIconCarrierIdOverrides): MobileIconInteractor {
        lateinit var result: MobileIconInteractor
        job?.cancel()
        job =
            testScope.backgroundScope.launch {
                kairosNetwork.activateSpec {
                    val wrapped = wrap(mobileIconsInteractor)
                    result =
                        MobileIconInteractorKairosAdapter(
                            kairosImpl =
                                activated {
                                    MobileIconInteractorKairosImpl(
                                        defaultSubscriptionHasDataEnabled =
                                            wrapped.activeDataConnectionHasDataEnabled,
                                        alwaysShowDataRatIcon = wrapped.alwaysShowDataRatIcon,
                                        alwaysUseCdmaLevel = wrapped.alwaysUseCdmaLevel,
                                        isSingleCarrier = wrapped.isSingleCarrier,
                                        mobileIsDefault = wrapped.mobileIsDefault,
                                        defaultMobileIconMapping = wrapped.defaultMobileIconMapping,
                                        defaultMobileIconGroup = wrapped.defaultMobileIconGroup,
                                        isDefaultConnectionFailed =
                                            wrapped.isDefaultConnectionFailed,
                                        isForceHidden = wrapped.isForceHidden,
                                        connectionRepository = wrapRepo(connectionRepository),
                                        context = context,
                                        carrierIdOverrides = overrides,
                                    )
                                }
                        )
                    Unit
                }
            }
        testScope.runCurrent() // ensure the lateinit is set
        return result
    }

    /** Allows us to wrap a (likely fake) MobileIconsInteractor into a Kairos version. */
    private fun BuildScope.wrap(interactor: MobileIconsInteractor): MobileIconsInteractorKairos {
        val filteredSubscriptions = interactor.filteredSubscriptions.toState(emptyList())
        val icons = interactor.icons.toState()
        return InteractorWrapper(
            mobileIsDefault = interactor.mobileIsDefault.toState(),
            filteredSubscriptions = filteredSubscriptions,
            icons =
                combine(filteredSubscriptions, icons) { subs, icons ->
                        subs.zip(icons).associate { (subModel, icon) ->
                            subModel.subscriptionId to buildSpec { wrap(icon) }
                        }
                    }
                    .asIncremental()
                    .applyLatestSpecForKey(),
            isStackable = interactor.isStackable.toState(),
            activeDataConnectionHasDataEnabled =
                interactor.activeDataConnectionHasDataEnabled.toState(),
            activeDataIconInteractor =
                interactor.activeDataIconInteractor.toState().mapLatestBuild {
                    it?.let { wrap(it) }
                },
            alwaysShowDataRatIcon = interactor.alwaysShowDataRatIcon.toState(),
            alwaysUseCdmaLevel = interactor.alwaysUseCdmaLevel.toState(),
            isSingleCarrier = interactor.isSingleCarrier.toState(),
            defaultMobileIconMapping = interactor.defaultMobileIconMapping.toState(),
            defaultMobileIconGroup = interactor.defaultMobileIconGroup.toState(),
            isDefaultConnectionFailed = interactor.isDefaultConnectionFailed.toState(),
            isUserSetUp = interactor.isUserSetUp.toState(),
            isForceHidden = interactor.isForceHidden.toState(false),
            isDeviceInEmergencyCallsOnlyMode =
                interactor.isDeviceInEmergencyCallsOnlyMode.toState(false),
        )
    }

    private fun BuildScope.wrap(interactor: MobileIconInteractor): MobileIconInteractorKairos =
        // unused in tests
        mock()

    private class InteractorWrapper(
        override val mobileIsDefault: State<Boolean>,
        override val filteredSubscriptions: State<List<SubscriptionModel>>,
        override val icons: Incremental<Int, MobileIconInteractorKairos>,
        override val isStackable: State<Boolean>,
        override val activeDataConnectionHasDataEnabled: State<Boolean>,
        override val activeDataIconInteractor: State<MobileIconInteractorKairos?>,
        override val alwaysShowDataRatIcon: State<Boolean>,
        override val alwaysUseCdmaLevel: State<Boolean>,
        override val isSingleCarrier: State<Boolean>,
        override val defaultMobileIconMapping: State<Map<String, SignalIcon.MobileIconGroup>>,
        override val defaultMobileIconGroup: State<SignalIcon.MobileIconGroup>,
        override val isDefaultConnectionFailed: State<Boolean>,
        override val isUserSetUp: State<Boolean>,
        override val isForceHidden: State<Boolean>,
        override val isDeviceInEmergencyCallsOnlyMode: State<Boolean>,
    ) : MobileIconsInteractorKairos
}
+30 −25
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.telephony.CellSignalStrength
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.telephony.flags.Flags
import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl
import com.android.settingslib.mobile.TelephonyIcons
@@ -58,21 +59,40 @@ import org.mockito.ArgumentMatchers.anyString

@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconInteractorTest : SysuiTestCase() {
    private val kosmos = testKosmos()
class MobileIconInteractorTest : MobileIconInteractorTestBase() {
    override fun createInteractor(overrides: MobileIconCarrierIdOverrides) =
        MobileIconInteractorImpl(
            testScope.backgroundScope,
            mobileIconsInteractor.activeDataConnectionHasDataEnabled,
            mobileIconsInteractor.alwaysShowDataRatIcon,
            mobileIconsInteractor.alwaysUseCdmaLevel,
            mobileIconsInteractor.isSingleCarrier,
            mobileIconsInteractor.mobileIsDefault,
            mobileIconsInteractor.defaultMobileIconMapping,
            mobileIconsInteractor.defaultMobileIconGroup,
            mobileIconsInteractor.isDefaultConnectionFailed,
            mobileIconsInteractor.isForceHidden,
            connectionRepository,
            context,
            overrides,
        )
}

    private lateinit var underTest: MobileIconInteractor
    private val mobileMappingsProxy = FakeMobileMappingsProxy()
    private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())
abstract class MobileIconInteractorTestBase : SysuiTestCase() {
    protected val kosmos = testKosmos()

    private val connectionRepository =
    protected lateinit var underTest: MobileIconInteractor
    protected val mobileMappingsProxy = FakeMobileMappingsProxy()
    protected val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())

    protected val connectionRepository =
        FakeMobileConnectionRepository(
            SUB_1_ID,
            logcatTableLogBuffer(kosmos, "MobileIconInteractorTest"),
        )

    private val testDispatcher = UnconfinedTestDispatcher()
    private val testScope = TestScope(testDispatcher)
    protected val testDispatcher = UnconfinedTestDispatcher()
    protected val testScope = TestScope(testDispatcher)

    @Before
    fun setUp() {
@@ -835,24 +855,9 @@ class MobileIconInteractorTest : SysuiTestCase() {
            assertThat(latest!!.level).isEqualTo(0)
        }

    private fun createInteractor(
    abstract fun createInteractor(
        overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl()
    ) =
        MobileIconInteractorImpl(
            testScope.backgroundScope,
            mobileIconsInteractor.activeDataConnectionHasDataEnabled,
            mobileIconsInteractor.alwaysShowDataRatIcon,
            mobileIconsInteractor.alwaysUseCdmaLevel,
            mobileIconsInteractor.isSingleCarrier,
            mobileIconsInteractor.mobileIsDefault,
            mobileIconsInteractor.defaultMobileIconMapping,
            mobileIconsInteractor.defaultMobileIconGroup,
            mobileIconsInteractor.isDefaultConnectionFailed,
            mobileIconsInteractor.isForceHidden,
            connectionRepository,
            context,
            overrides,
        )
    ): MobileIconInteractor

    companion object {
        private const val GSM_LEVEL = 1
Loading