Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelTest.kt +80 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 = Loading @@ -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( Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/compose/MobileIcon.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt +42 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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", Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelKairos.kt +30 −0 Original line number Diff line number Diff line Loading @@ -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", Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelTest.kt +80 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 = Loading @@ -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( Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/compose/MobileIcon.kt +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModel.kt +42 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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", Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/StackedMobileIconViewModelKairos.kt +30 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StackedMobileIcon.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading