Loading packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +1 −2 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.systemui.scene.shared.model.SceneDataSourceDelegator import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import javax.inject.Provider import kotlinx.coroutines.flow.collectLatest /** * Renders a container of a collection of "scenes" that the user can switch between using certain Loading Loading @@ -117,7 +116,7 @@ fun SceneContainer( ) { "invalid ContentKey: $actionableContentKey" } actionableContent.userActions.collectLatest { userActions -> viewModel.filteredUserActions(actionableContent.userActions).collect { userActions -> userActionsByContentKey[actionableContentKey] = viewModel.resolveSceneFamilies(userActions) } Loading packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +18 −51 Original line number Diff line number Diff line Loading @@ -130,10 +130,6 @@ fun SceneScope.CollapsedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("CollapsedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return } val cutoutWidth = LocalDisplayCutout.current.width() val cutoutHeight = LocalDisplayCutout.current.height() Loading Loading @@ -196,7 +192,7 @@ fun SceneScope.CollapsedShadeHeader( horizontalArrangement = Arrangement.End, modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) .padding(horizontal = horizontalPadding) .padding(horizontal = horizontalPadding), ) { if (isLargeScreenLayout) { ShadeCarrierGroup( Loading @@ -207,7 +203,7 @@ fun SceneScope.CollapsedShadeHeader( SystemIconContainer( viewModel = viewModel, isClickable = isLargeScreenLayout, modifier = Modifier.align(Alignment.CenterVertically) modifier = Modifier.align(Alignment.CenterVertically), ) { StatusIcons( viewModel = viewModel, Loading @@ -217,7 +213,7 @@ fun SceneScope.CollapsedShadeHeader( modifier = Modifier.align(Alignment.CenterVertically) .padding(end = 6.dp) .weight(1f, fill = false) .weight(1f, fill = false), ) BatteryIcon( createBatteryMeterViewController = Loading Loading @@ -252,27 +248,15 @@ fun SceneScope.CollapsedShadeHeader( CutoutLocation.NONE, CutoutLocation.RIGHT -> { startPlaceable.placeRelative(x = 0, y = 0) endPlaceable.placeRelative( x = startPlaceable.width, y = 0, ) endPlaceable.placeRelative(x = startPlaceable.width, y = 0) } CutoutLocation.CENTER -> { startPlaceable.placeRelative(x = 0, y = 0) endPlaceable.placeRelative( x = startPlaceable.width + cutoutWidthPx, y = 0, ) endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } CutoutLocation.LEFT -> { startPlaceable.placeRelative( x = cutoutWidthPx, y = 0, ) endPlaceable.placeRelative( x = startPlaceable.width + cutoutWidthPx, y = 0, ) startPlaceable.placeRelative(x = cutoutWidthPx, y = 0) endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } } } Loading @@ -288,10 +272,6 @@ fun SceneScope.ExpandedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("ExpandedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return } val useExpandedFormat by remember { derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) } Loading @@ -302,17 +282,14 @@ fun SceneScope.ExpandedShadeHeader( Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) { if (isPrivacyChipVisible) { Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) { PrivacyChip( viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd), ) PrivacyChip(viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd)) } } Column( verticalArrangement = Arrangement.Bottom, modifier = Modifier.fillMaxWidth() .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight) .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight), ) { Box(modifier = Modifier.fillMaxWidth()) { Box { Loading Loading @@ -362,11 +339,7 @@ fun SceneScope.ExpandedShadeHeader( } @Composable private fun SceneScope.Clock( scale: Float, viewModel: ShadeHeaderViewModel, modifier: Modifier, ) { private fun SceneScope.Clock(scale: Float, viewModel: ShadeHeaderViewModel, modifier: Modifier) { val layoutDirection = LocalLayoutDirection.current Element(key = ShadeHeader.Elements.Clock, modifier = modifier) { Loading @@ -391,10 +364,10 @@ private fun SceneScope.Clock( LayoutDirection.Ltr -> 0f LayoutDirection.Rtl -> 1f }, 0.5f 0.5f, ) } .clickable { viewModel.onClockClicked() } .clickable { viewModel.onClockClicked() }, ) } } Loading Loading @@ -447,10 +420,7 @@ private fun BatteryIcon( } @Composable private fun ShadeCarrierGroup( viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier, ) { private fun ShadeCarrierGroup(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { Row(modifier = modifier) { val subIds by viewModel.mobileSubIds.collectAsStateWithLifecycle() Loading @@ -465,11 +435,11 @@ private fun ShadeCarrierGroup( viewModel = (viewModel.mobileIconsViewModel.viewModelForSub( subId, StatusBarLocation.SHADE_CARRIER_GROUP StatusBarLocation.SHADE_CARRIER_GROUP, ) as ShadeCarrierGroupMobileIconViewModel), ) .also { it.setOnClickListener { viewModel.onShadeCarrierGroupClicked() } } }, } ) } } Loading Loading @@ -506,7 +476,7 @@ private fun SceneScope.StatusIcons( Utils.getColorAttrDefaultColor(themedContext, android.R.attr.textColorPrimary), Utils.getColorAttrDefaultColor( themedContext, android.R.attr.textColorPrimaryInverse android.R.attr.textColorPrimaryInverse, ), ) statusBarIconController.addIconGroup(iconManager) Loading Loading @@ -551,7 +521,7 @@ private fun SystemIconContainer( viewModel: ShadeHeaderViewModel, isClickable: Boolean, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit content: @Composable RowScope.() -> Unit, ) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() Loading @@ -578,10 +548,7 @@ private fun SystemIconContainer( } @Composable private fun SceneScope.PrivacyChip( viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier, ) { private fun SceneScope.PrivacyChip(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { val privacyList by viewModel.privacyItems.collectAsStateWithLifecycle() AndroidView( Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorTest.kt 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.scene.domain.interactor import android.app.StatusBarManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class DisabledContentInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val underTest = kosmos.disabledContentInteractor @Test fun isDisabled_notificationsShade() = kosmos.runTest { fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isFalse() fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isTrue() } @Test fun isDisabled_qsShade() = kosmos.runTest { fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isFalse() fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isTrue() } @Test fun repeatWhenDisabled() = kosmos.runTest { var notificationDisabledCount = 0 applicationCoroutineScope.launch { underTest.repeatWhenDisabled(Overlays.NotificationsShade) { notificationDisabledCount++ } } var qsDisabledCount = 0 applicationCoroutineScope.launch { underTest.repeatWhenDisabled(Overlays.QuickSettingsShade) { qsDisabledCount++ } } fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(notificationDisabledCount).isEqualTo(0) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel( disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE or StatusBarManager.DISABLE2_QUICK_SETTINGS ) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(2) } @Test fun filteredUserActions() = kosmos.runTest { val map = mapOf<UserAction, UserActionResult>( Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade), Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade), ) val unfiltered = MutableStateFlow(map) val filtered by collectLastValue(underTest.filteredUserActions(unfiltered)) assertThat(filtered).isEqualTo(map) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(filtered) .isEqualTo( mapOf(Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade)) ) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(filtered) .isEqualTo( mapOf(Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade)) ) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel( disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE or StatusBarManager.DISABLE2_QUICK_SETTINGS ) assertThat(filtered).isEqualTo(emptyMap<UserAction, UserActionResult>()) } } packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.scene.domain.interactor import android.app.StatusBarManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState Loading @@ -30,6 +31,8 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.Transition Loading @@ -43,6 +46,8 @@ import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.SceneFamilies import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi Loading Loading @@ -523,4 +528,51 @@ class SceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Gone) } @Test fun showOverlay_overlayDisabled_doesNothing() = kosmos.runTest { val currentOverlays by collectLastValue(underTest.currentOverlays) val disabledOverlay = Overlays.QuickSettingsShade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() assertThat(currentOverlays).doesNotContain(disabledOverlay) underTest.showOverlay(disabledOverlay, "reason") assertThat(currentOverlays).doesNotContain(disabledOverlay) } @Test fun replaceOverlay_withDisabledOverlay_doesNothing() = kosmos.runTest { val currentOverlays by collectLastValue(underTest.currentOverlays) val showingOverlay = Overlays.NotificationsShade underTest.showOverlay(showingOverlay, "reason") assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) val disabledOverlay = Overlays.QuickSettingsShade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() underTest.replaceOverlay(showingOverlay, disabledOverlay, "reason") assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) } @Test fun changeScene_toDisabledScene_doesNothing() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) val disabledScene = Scenes.Shade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(disabledContentInteractor.isDisabled(disabledScene)).isTrue() assertThat(currentScene).isNotEqualTo(disabledScene) underTest.changeScene(disabledScene, "reason") assertThat(currentScene).isNotEqualTo(disabledScene) } } packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +24 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ import com.android.systemui.keyguard.domain.interactor.scenetransition.lockscree import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runCurrent import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState import com.android.systemui.power.data.repository.fakePowerRepository Loading @@ -101,6 +104,8 @@ import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository Loading Loading @@ -2673,6 +2678,25 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(isAlternateBouncerVisible).isFalse() } @Test fun handleDisableFlags() = kosmos.runTest { underTest.start() val currentScene by collectLastValue(sceneInteractor.currentScene) val currentOverlays by collectLastValue(sceneInteractor.currentOverlays) sceneInteractor.changeScene(Scenes.Shade, "reason") sceneInteractor.showOverlay(Overlays.NotificationsShade, "reason") assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(currentOverlays).contains(Overlays.NotificationsShade) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) runCurrent() assertThat(currentScene).isNotEqualTo(Scenes.Shade) assertThat(currentOverlays).isEmpty() } private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +1 −2 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.systemui.scene.shared.model.SceneDataSourceDelegator import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import javax.inject.Provider import kotlinx.coroutines.flow.collectLatest /** * Renders a container of a collection of "scenes" that the user can switch between using certain Loading Loading @@ -117,7 +116,7 @@ fun SceneContainer( ) { "invalid ContentKey: $actionableContentKey" } actionableContent.userActions.collectLatest { userActions -> viewModel.filteredUserActions(actionableContent.userActions).collect { userActions -> userActionsByContentKey[actionableContentKey] = viewModel.resolveSceneFamilies(userActions) } Loading
packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +18 −51 Original line number Diff line number Diff line Loading @@ -130,10 +130,6 @@ fun SceneScope.CollapsedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("CollapsedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return } val cutoutWidth = LocalDisplayCutout.current.width() val cutoutHeight = LocalDisplayCutout.current.height() Loading Loading @@ -196,7 +192,7 @@ fun SceneScope.CollapsedShadeHeader( horizontalArrangement = Arrangement.End, modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) .padding(horizontal = horizontalPadding) .padding(horizontal = horizontalPadding), ) { if (isLargeScreenLayout) { ShadeCarrierGroup( Loading @@ -207,7 +203,7 @@ fun SceneScope.CollapsedShadeHeader( SystemIconContainer( viewModel = viewModel, isClickable = isLargeScreenLayout, modifier = Modifier.align(Alignment.CenterVertically) modifier = Modifier.align(Alignment.CenterVertically), ) { StatusIcons( viewModel = viewModel, Loading @@ -217,7 +213,7 @@ fun SceneScope.CollapsedShadeHeader( modifier = Modifier.align(Alignment.CenterVertically) .padding(end = 6.dp) .weight(1f, fill = false) .weight(1f, fill = false), ) BatteryIcon( createBatteryMeterViewController = Loading Loading @@ -252,27 +248,15 @@ fun SceneScope.CollapsedShadeHeader( CutoutLocation.NONE, CutoutLocation.RIGHT -> { startPlaceable.placeRelative(x = 0, y = 0) endPlaceable.placeRelative( x = startPlaceable.width, y = 0, ) endPlaceable.placeRelative(x = startPlaceable.width, y = 0) } CutoutLocation.CENTER -> { startPlaceable.placeRelative(x = 0, y = 0) endPlaceable.placeRelative( x = startPlaceable.width + cutoutWidthPx, y = 0, ) endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } CutoutLocation.LEFT -> { startPlaceable.placeRelative( x = cutoutWidthPx, y = 0, ) endPlaceable.placeRelative( x = startPlaceable.width + cutoutWidthPx, y = 0, ) startPlaceable.placeRelative(x = cutoutWidthPx, y = 0) endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } } } Loading @@ -288,10 +272,6 @@ fun SceneScope.ExpandedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("ExpandedShadeHeader") { viewModelFactory.create() } val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() if (isDisabled) { return } val useExpandedFormat by remember { derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) } Loading @@ -302,17 +282,14 @@ fun SceneScope.ExpandedShadeHeader( Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) { if (isPrivacyChipVisible) { Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) { PrivacyChip( viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd), ) PrivacyChip(viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd)) } } Column( verticalArrangement = Arrangement.Bottom, modifier = Modifier.fillMaxWidth() .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight) .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight), ) { Box(modifier = Modifier.fillMaxWidth()) { Box { Loading Loading @@ -362,11 +339,7 @@ fun SceneScope.ExpandedShadeHeader( } @Composable private fun SceneScope.Clock( scale: Float, viewModel: ShadeHeaderViewModel, modifier: Modifier, ) { private fun SceneScope.Clock(scale: Float, viewModel: ShadeHeaderViewModel, modifier: Modifier) { val layoutDirection = LocalLayoutDirection.current Element(key = ShadeHeader.Elements.Clock, modifier = modifier) { Loading @@ -391,10 +364,10 @@ private fun SceneScope.Clock( LayoutDirection.Ltr -> 0f LayoutDirection.Rtl -> 1f }, 0.5f 0.5f, ) } .clickable { viewModel.onClockClicked() } .clickable { viewModel.onClockClicked() }, ) } } Loading Loading @@ -447,10 +420,7 @@ private fun BatteryIcon( } @Composable private fun ShadeCarrierGroup( viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier, ) { private fun ShadeCarrierGroup(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { Row(modifier = modifier) { val subIds by viewModel.mobileSubIds.collectAsStateWithLifecycle() Loading @@ -465,11 +435,11 @@ private fun ShadeCarrierGroup( viewModel = (viewModel.mobileIconsViewModel.viewModelForSub( subId, StatusBarLocation.SHADE_CARRIER_GROUP StatusBarLocation.SHADE_CARRIER_GROUP, ) as ShadeCarrierGroupMobileIconViewModel), ) .also { it.setOnClickListener { viewModel.onShadeCarrierGroupClicked() } } }, } ) } } Loading Loading @@ -506,7 +476,7 @@ private fun SceneScope.StatusIcons( Utils.getColorAttrDefaultColor(themedContext, android.R.attr.textColorPrimary), Utils.getColorAttrDefaultColor( themedContext, android.R.attr.textColorPrimaryInverse android.R.attr.textColorPrimaryInverse, ), ) statusBarIconController.addIconGroup(iconManager) Loading Loading @@ -551,7 +521,7 @@ private fun SystemIconContainer( viewModel: ShadeHeaderViewModel, isClickable: Boolean, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit content: @Composable RowScope.() -> Unit, ) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() Loading @@ -578,10 +548,7 @@ private fun SystemIconContainer( } @Composable private fun SceneScope.PrivacyChip( viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier, ) { private fun SceneScope.PrivacyChip(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { val privacyList by viewModel.privacyItems.collectAsStateWithLifecycle() AndroidView( Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorTest.kt 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.scene.domain.interactor import android.app.StatusBarManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class DisabledContentInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val underTest = kosmos.disabledContentInteractor @Test fun isDisabled_notificationsShade() = kosmos.runTest { fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isFalse() fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isTrue() } @Test fun isDisabled_qsShade() = kosmos.runTest { fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isFalse() fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isTrue() } @Test fun repeatWhenDisabled() = kosmos.runTest { var notificationDisabledCount = 0 applicationCoroutineScope.launch { underTest.repeatWhenDisabled(Overlays.NotificationsShade) { notificationDisabledCount++ } } var qsDisabledCount = 0 applicationCoroutineScope.launch { underTest.repeatWhenDisabled(Overlays.QuickSettingsShade) { qsDisabledCount++ } } fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(notificationDisabledCount).isEqualTo(0) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel( disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE or StatusBarManager.DISABLE2_QUICK_SETTINGS ) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(1) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(notificationDisabledCount).isEqualTo(1) assertThat(qsDisabledCount).isEqualTo(2) } @Test fun filteredUserActions() = kosmos.runTest { val map = mapOf<UserAction, UserActionResult>( Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade), Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade), ) val unfiltered = MutableStateFlow(map) val filtered by collectLastValue(underTest.filteredUserActions(unfiltered)) assertThat(filtered).isEqualTo(map) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(filtered) .isEqualTo( mapOf(Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade)) ) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(filtered) .isEqualTo( mapOf(Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade)) ) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel( disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE or StatusBarManager.DISABLE2_QUICK_SETTINGS ) assertThat(filtered).isEqualTo(emptyMap<UserAction, UserActionResult>()) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +52 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.scene.domain.interactor import android.app.StatusBarManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState Loading @@ -30,6 +31,8 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.Transition Loading @@ -43,6 +46,8 @@ import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.SceneFamilies import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi Loading Loading @@ -523,4 +528,51 @@ class SceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Gone) } @Test fun showOverlay_overlayDisabled_doesNothing() = kosmos.runTest { val currentOverlays by collectLastValue(underTest.currentOverlays) val disabledOverlay = Overlays.QuickSettingsShade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() assertThat(currentOverlays).doesNotContain(disabledOverlay) underTest.showOverlay(disabledOverlay, "reason") assertThat(currentOverlays).doesNotContain(disabledOverlay) } @Test fun replaceOverlay_withDisabledOverlay_doesNothing() = kosmos.runTest { val currentOverlays by collectLastValue(underTest.currentOverlays) val showingOverlay = Overlays.NotificationsShade underTest.showOverlay(showingOverlay, "reason") assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) val disabledOverlay = Overlays.QuickSettingsShade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() underTest.replaceOverlay(showingOverlay, disabledOverlay, "reason") assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) } @Test fun changeScene_toDisabledScene_doesNothing() = kosmos.runTest { val currentScene by collectLastValue(underTest.currentScene) val disabledScene = Scenes.Shade fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) assertThat(disabledContentInteractor.isDisabled(disabledScene)).isTrue() assertThat(currentScene).isNotEqualTo(disabledScene) underTest.changeScene(disabledScene, "reason") assertThat(currentScene).isNotEqualTo(disabledScene) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +24 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ import com.android.systemui.keyguard.domain.interactor.scenetransition.lockscree import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runCurrent import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState import com.android.systemui.power.data.repository.fakePowerRepository Loading @@ -101,6 +104,8 @@ import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository Loading Loading @@ -2673,6 +2678,25 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(isAlternateBouncerVisible).isFalse() } @Test fun handleDisableFlags() = kosmos.runTest { underTest.start() val currentScene by collectLastValue(sceneInteractor.currentScene) val currentOverlays by collectLastValue(sceneInteractor.currentOverlays) sceneInteractor.changeScene(Scenes.Shade, "reason") sceneInteractor.showOverlay(Overlays.NotificationsShade, "reason") assertThat(currentScene).isEqualTo(Scenes.Shade) assertThat(currentOverlays).contains(Overlays.NotificationsShade) fakeDisableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) runCurrent() assertThat(currentScene).isNotEqualTo(Scenes.Shade) assertThat(currentOverlays).isEmpty() } private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, Loading