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

Commit f22eda35 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add the data transfer arrows for the dual sim icon" into main

parents 799b583c 13dc9a44
Loading
Loading
Loading
Loading
+80 −1
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.shared.connectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -48,7 +50,10 @@ import org.mockito.kotlin.whenever
@SmallTest
@RunWith(AndroidJUnit4::class)
class StackedMobileIconViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val kosmos =
        testKosmos().useUnconfinedTestDispatcher().apply {
            connectivityConstants.shouldShowActivityConfig = true
        }

    private val Kosmos.underTest: StackedMobileIconViewModelImpl by Fixture {
        stackedMobileIconViewModelImpl
@@ -239,6 +244,74 @@ class StackedMobileIconViewModelTest : SysuiTestCase() {
            assertThat(underTest.roaming).isFalse()
        }

    @Test
    @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    fun activityInVisible_tracksPrimaryConnection() =
        kosmos.runTest {
            fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
            fakeMobileIconsInteractor.activeMobileDataSubscriptionId.value = SUB_1.subscriptionId

            setActivity(
                SUB_1.subscriptionId,
                DataActivityModel(hasActivityIn = true, hasActivityOut = false),
            )

            assertThat(underTest.activityInVisible).isTrue()
            assertThat(underTest.activityContainerVisible).isTrue()

            setActivity(
                SUB_1.subscriptionId,
                DataActivityModel(hasActivityIn = false, hasActivityOut = false),
            )

            assertThat(underTest.activityInVisible).isFalse()
            assertThat(underTest.activityContainerVisible).isFalse()

            // Change the activity for the secondary connection
            setActivity(
                SUB_2.subscriptionId,
                DataActivityModel(hasActivityIn = true, hasActivityOut = false),
            )

            // Assert the stacked icon activity is unchanged
            assertThat(underTest.activityInVisible).isFalse()
            assertThat(underTest.activityContainerVisible).isFalse()
        }

    @Test
    @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    fun activityOutVisible_tracksPrimaryConnection() =
        kosmos.runTest {
            fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
            fakeMobileIconsInteractor.activeMobileDataSubscriptionId.value = SUB_1.subscriptionId

            setActivity(
                SUB_1.subscriptionId,
                DataActivityModel(hasActivityIn = false, hasActivityOut = true),
            )

            assertThat(underTest.activityOutVisible).isTrue()
            assertThat(underTest.activityContainerVisible).isTrue()

            setActivity(
                SUB_1.subscriptionId,
                DataActivityModel(hasActivityIn = false, hasActivityOut = false),
            )

            assertThat(underTest.activityOutVisible).isFalse()
            assertThat(underTest.activityContainerVisible).isFalse()

            // Change the activity for the secondary connection
            setActivity(
                SUB_2.subscriptionId,
                DataActivityModel(hasActivityIn = false, hasActivityOut = true),
            )

            // Assert the stacked icon activity is unchanged
            assertThat(underTest.activityOutVisible).isFalse()
            assertThat(underTest.activityContainerVisible).isFalse()
        }

    private fun setIconLevel(subId: Int, level: Int) {
        with(kosmos.fakeMobileIconsInteractor.getInteractorForSubId(subId)!!) {
            signalLevelIcon.value =
@@ -246,6 +319,12 @@ class StackedMobileIconViewModelTest : SysuiTestCase() {
        }
    }

    private fun setActivity(subId: Int, activity: DataActivityModel) {
        with(kosmos.fakeMobileIconsInteractor.getInteractorForSubId(subId)!!) {
            this.activity.value = activity
        }
    }

    companion object {
        private val SUB_1 =
            SubscriptionModel(
+1 −1
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ fun MobileIcon(viewModel: MobileIconViewModelCommon, modifier: Modifier = Modifi

/** Composable for activity indicators (data in/out arrows) */
@Composable
private fun ActivityIndicators(
fun ActivityIndicators(
    activityInVisible: Boolean,
    activityOutVisible: Boolean,
    color: Color,
+42 −0
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@ interface StackedMobileIconViewModel {
    val dualSim: DualSim?
    val contentDescription: String?
    val networkTypeIcon: Icon.Resource?
    val activityInVisible: Boolean
    val activityOutVisible: Boolean
    val activityContainerVisible: Boolean
    /** [Context] to use when loading the [networkTypeIcon] */
    val mobileContext: Context?
    val roaming: Boolean
@@ -133,6 +136,45 @@ constructor(
            initialValue = null,
        )

    override val activityInVisible: Boolean by
        hydrator.hydratedStateOf(
            traceName = "activityInVisible",
            source =
                flowIfIconIsVisible(
                        iconViewModelFlow.flatMapLatest { viewModels ->
                            viewModels.firstOrNull()?.activityInVisible ?: flowOf(false)
                        }
                    )
                    .map { it == true },
            initialValue = false,
        )

    override val activityOutVisible: Boolean by
        hydrator.hydratedStateOf(
            traceName = "activityOutVisible",
            source =
                flowIfIconIsVisible(
                        iconViewModelFlow.flatMapLatest { viewModels ->
                            viewModels.firstOrNull()?.activityOutVisible ?: flowOf(false)
                        }
                    )
                    .map { it == true },
            initialValue = false,
        )

    override val activityContainerVisible: Boolean by
        hydrator.hydratedStateOf(
            traceName = "activityContainerVisible",
            source =
                flowIfIconIsVisible(
                        iconViewModelFlow.flatMapLatest { viewModels ->
                            viewModels.firstOrNull()?.activityContainerVisible ?: flowOf(false)
                        }
                    )
                    .map { it == true },
            initialValue = false,
        )

    override val mobileContext: Context? by
        hydrator.hydratedStateOf(
            traceName = "mobileContext",
+30 −0
Original line number Diff line number Diff line
@@ -91,6 +91,36 @@ constructor(
            initialValue = null,
        )

    override val activityInVisible: Boolean by
        hydratedComposeStateOf(
            name = "activityInVisible",
            source =
                iconList.flatMap { icons ->
                    icons.firstOrNull()?.activityInVisible ?: stateOf(false)
                },
            initialValue = false,
        )

    override val activityOutVisible: Boolean by
        hydratedComposeStateOf(
            name = "activityOutVisible",
            source =
                iconList.flatMap { icons ->
                    icons.firstOrNull()?.activityOutVisible ?: stateOf(false)
                },
            initialValue = false,
        )

    override val activityContainerVisible: Boolean by
        hydratedComposeStateOf(
            name = "activityContainerVisible",
            source =
                iconList.flatMap { icons ->
                    icons.firstOrNull()?.activityContainerVisible ?: stateOf(false)
                },
            initialValue = false,
        )

    override val mobileContext: Context? by
        hydratedComposeStateOf(
            "StackedMobileIconViewModelKairos.mobileContext",
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import com.android.systemui.common.ui.compose.load
import com.android.systemui.res.R
import com.android.systemui.statusbar.pipeline.mobile.ui.compose.ActivityIndicators
import com.android.systemui.statusbar.pipeline.mobile.ui.model.DualSim
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.StackedMobileIconViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarBaseHeightFiveBarsSp
@@ -92,6 +93,14 @@ fun StackedMobileIcon(viewModel: StackedMobileIconViewModel, modifier: Modifier
        verticalAlignment = Alignment.CenterVertically,
        modifier = modifier.padding(horizontal = padding),
    ) {
        if (viewModel.activityContainerVisible) {
            ActivityIndicators(
                activityInVisible = viewModel.activityInVisible,
                activityOutVisible = viewModel.activityOutVisible,
                color = contentColor,
            )
        }

        viewModel.networkTypeIcon?.let {
            // Provide the RAT context needed for the resource overlays
            val ratContext = viewModel.mobileContext ?: LocalContext.current