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

Commit b94073d3 authored by Evan Laird's avatar Evan Laird
Browse files

[mobile] stacked mobile icon roaming indicator

Matches the single SIM case. Also scale(-1) when RTL

Test: StackedMobileIconViewModelTest
Test: manual via demo mode
Bug: 399416492
Flag: com.android.settingslib.flags.new_status_bar_icons
Flag: com.android.systemui.status_bar_root_modernization
Change-Id: Ib274a6afc1e2e43674038efd9c64c14caf51cbe2
parent 88f4ccfb
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -213,6 +213,32 @@ class StackedMobileIconViewModelTest : SysuiTestCase() {
            assertThat(underTest.mobileContext).isEqualTo(contextSub2)
        }

    @Test
    @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    fun roaming_primaryConnectionIsRoaming_true() =
        kosmos.runTest {
            fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
            fakeMobileIconsInteractor.activeMobileDataSubscriptionId.value = SUB_1.subscriptionId
            val intr1 = fakeMobileIconsInteractor.getInteractorForSubId(SUB_1.subscriptionId)!!

            intr1.isRoaming.value = true

            assertThat(underTest.roaming).isTrue()
        }

    @Test
    @EnableFlags(NewStatusBarIcons.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    fun roaming_secondaryConnectionIsRoaming_false() =
        kosmos.runTest {
            fakeMobileIconsInteractor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
            fakeMobileIconsInteractor.activeMobileDataSubscriptionId.value = SUB_1.subscriptionId
            val intr2 = fakeMobileIconsInteractor.getInteractorForSubId(SUB_2.subscriptionId)!!

            intr2.isRoaming.value = true

            assertThat(underTest.roaming).isFalse()
        }

    private fun setIconLevel(subId: Int, level: Int) {
        with(kosmos.fakeMobileIconsInteractor.getInteractorForSubId(subId)!!) {
            signalLevelIcon.value =
+23 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ interface StackedMobileIconViewModel {
    val networkTypeIcon: Icon.Resource?
    /** [Context] to use when loading the [networkTypeIcon] */
    val mobileContext: Context?
    val roaming: Boolean
    val isIconVisible: Boolean
}

@@ -147,6 +148,27 @@ constructor(
            initialValue = null,
        )

    override val roaming: Boolean by
        hydrator.hydratedStateOf(
            traceName = "isRoaming",
            source =
                _isIconVisible.flatMapLatest { isVisible ->
                    if (isVisible) {
                            iconViewModelFlow.flatMapLatest { viewModels ->
                                viewModels.firstOrNull()?.roaming ?: flowOf(false)
                            }
                        } else {
                            flowOf(false)
                        }
                        .logDiffsForTable(
                            tableLogBuffer = tableLogger,
                            columnName = COL_ROAMING,
                            initialValue = false,
                        )
                },
            initialValue = false,
        )

    override val isIconVisible: Boolean by
        hydrator.hydratedStateOf(
            traceName = "isIconVisible",
@@ -180,5 +202,6 @@ constructor(

    private companion object {
        const val COL_IS_ICON_VISIBLE = "isIconVisible"
        const val COL_ROAMING = "roam"
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -102,6 +102,13 @@ constructor(
            initialValue = null,
        )

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

    override val isIconVisible: Boolean
        get() = isStackable && dualSim != null

+59 −35
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LocalContentColor
@@ -35,15 +36,19 @@ import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.LayoutDirection
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.model.DualSim
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.StackedMobileIconViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.BarBaseHeightFiveBarsSp
@@ -63,6 +68,8 @@ import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobil
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconWidthFiveBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.IconWidthFourBarsSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.RatIndicatorPaddingSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.RoamingIconHeightSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.RoamingIconPaddingTopSp
import com.android.systemui.statusbar.pipeline.shared.ui.composable.StackedMobileIconDimensions.SecondaryBarHeightSp
import kotlin.math.max

@@ -104,6 +111,18 @@ fun StackedMobileIcon(viewModel: StackedMobileIconViewModel, modifier: Modifier
            color = contentColor,
            contentDescription = viewModel.contentDescription,
        )

        if (viewModel.roaming) {
            val height = with(LocalDensity.current) { RoamingIconHeightSp.toDp() }
            val paddingTop = with(LocalDensity.current) { RoamingIconPaddingTopSp.toDp() }
            Image(
                painter = painterResource(R.drawable.stat_sys_roaming_updated),
                contentDescription = stringResource(R.string.data_connection_roaming),
                modifier = Modifier.height(height).offset(y = paddingTop),
                colorFilter = ColorFilter.tint(contentColor, BlendMode.SrcIn),
                contentScale = ContentScale.FillHeight,
            )
        }
    }
}

@@ -125,6 +144,8 @@ private fun StackedMobileIcon(
            contentDescription?.let { this.contentDescription = it }
        }
    ) {
        val rtl = layoutDirection == LayoutDirection.Rtl
        scale(if (rtl) -1f else 1f, 1f) {
            val verticalPaddingPx = BarsVerticalPaddingSp.roundToPx()
            val horizontalPaddingPx = dimensions.barsHorizontalPadding.roundToPx()
            val totalPaddingWidthPx = horizontalPaddingPx * (numberOfBars - 1)
@@ -168,6 +189,7 @@ private fun StackedMobileIcon(
            }
        }
    }
}

private fun DrawScope.drawMobileIconBar(
    level: Int,
@@ -248,6 +270,8 @@ private object StackedMobileIconDimensions {
    val BarsLevelIncrementSp = 1.sp
    val SecondaryBarHeightSp = 3.sp
    val RatIndicatorPaddingSp = 4.sp // 6.sp total between RAT and bars
    val RoamingIconHeightSp = 10.sp
    val RoamingIconPaddingTopSp = 1.sp

    // Exclamation cutout dimensions
    val ExclamationCutoutRadiusSp = 5.sp