diff options
| author | 2024-05-07 15:31:35 +0200 | |
|---|---|---|
| committer | 2024-05-16 17:49:16 +0200 | |
| commit | 4b439508338c01d72f748cc27043eced64d9f462 (patch) | |
| tree | 21a226d7b1acddbe5905b9157111e54f2056cb77 | |
| parent | 7175951f38781d82349a1f47c72b09944c05c7e6 (diff) | |
Fix wildcard scene edges
When scene container is flipped wildcard edges with UNDEFINED are not
allowed because KTF will not track all edges in or out of e.g.
Scenes.Gone but rather only the edges between Lockscreen and Gone.
This CL fixes some occurrences but not yet all.
Test: None
Bug: b/330311871
Flag: com.android.systemui.scene_container
Change-Id: Ia09d95fdf15768b24d5e6c2103697574b9458d47
8 files changed, 225 insertions, 40 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt index 6e364d180ebf..3cbcb2cb4a0b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt @@ -33,12 +33,16 @@ import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.utils.GlobalWindowManager import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -60,6 +64,7 @@ constructor( @Application private val applicationScope: CoroutineScope, @Background private val bgDispatcher: CoroutineDispatcher, private val featureFlags: FeatureFlags, + private val sceneInteractor: SceneInteractor, ) : CoreStartable, WakefulnessLifecycle.Observer { override fun start() { @@ -85,9 +90,15 @@ constructor( applicationScope.launch(bgDispatcher) { // We drop 1 to avoid triggering on initial collect(). - keyguardTransitionInteractor.transition(Edge.create(to = GONE)).collect { transition -> - if (transition.transitionState == TransitionState.FINISHED) { - onKeyguardGone() + if (SceneContainerFlag.isEnabled) { + sceneInteractor.transitionState + .filter { it.isIdle(Scenes.Gone) } + .collect { onKeyguardGone() } + } else { + keyguardTransitionInteractor.transition(Edge.create(to = GONE)).collect { + if (it.transitionState == TransitionState.FINISHED) { + onKeyguardGone() + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt index 08d29d4fc0a6..1aac1c5940b3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt @@ -25,6 +25,9 @@ import com.android.systemui.keyguard.shared.model.KeyguardDone import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -48,6 +51,7 @@ constructor( transitionInteractor: KeyguardTransitionInteractor, val dismissInteractor: KeyguardDismissInteractor, @Application private val applicationScope: CoroutineScope, + sceneInteractor: SceneInteractor, ) { val dismissAction: Flow<DismissAction> = repository.dismissAction @@ -72,7 +76,12 @@ constructor( ) private val finishedTransitionToGone: Flow<Unit> = - transitionInteractor.finishedKeyguardState.filter { it == GONE }.map {} // map to Unit + if (SceneContainerFlag.isEnabled) { + sceneInteractor.transitionState.filter { it.isIdle(Scenes.Gone) }.map {} + } else { + transitionInteractor.finishedKeyguardState.filter { it == GONE }.map {} + } + val executeDismissAction: Flow<() -> KeyguardDone> = merge( finishedTransitionToGone, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index 188516cc7e36..229e592a6a0c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -74,6 +74,9 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PageIndicator import com.android.systemui.res.R +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.shared.system.SysUiStatsLog.SMARTSPACE_CARD_REPORTED import com.android.systemui.shared.system.SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD @@ -143,6 +146,7 @@ constructor( private val secureSettings: SecureSettings, private val mediaCarouselViewModel: MediaCarouselViewModel, private val mediaViewControllerFactory: Provider<MediaViewController>, + private val sceneInteractor: SceneInteractor, ) : Dumpable { /** The current width of the carousel */ var currentCarouselWidth: Int = 0 @@ -641,9 +645,13 @@ constructor( @VisibleForTesting internal fun listenForAnyStateToGoneKeyguardTransition(scope: CoroutineScope): Job { return scope.launch { - keyguardTransitionInteractor - .transition(Edge.create(to = GONE)) - .filter { it.transitionState == TransitionState.FINISHED } + if (SceneContainerFlag.isEnabled) { + sceneInteractor.transitionState.filter { it.isIdle(Scenes.Gone) } + } else { + keyguardTransitionInteractor.transition(Edge.create(to = GONE)).filter { + it.transitionState == TransitionState.FINISHED + } + } .collect { showMediaCarousel() updateHostVisibility() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt index 7afed9db8604..977116e812ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt @@ -8,6 +8,8 @@ import android.platform.test.flag.junit.SetFlagsRule import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository @@ -19,7 +21,10 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.scene.data.repository.Idle +import com.android.systemui.scene.data.repository.setSceneTransition import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.utils.GlobalWindowManager @@ -70,12 +75,13 @@ class ResourceTrimmerTest : SysuiTestCase() { resourceTrimmer = ResourceTrimmer( keyguardInteractor, - powerInteractor, - kosmos.keyguardTransitionInteractor, - globalWindowManager, - testScope.backgroundScope, - kosmos.testDispatcher, - featureFlags, + powerInteractor = powerInteractor, + keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor, + globalWindowManager = globalWindowManager, + applicationScope = testScope.backgroundScope, + bgDispatcher = kosmos.testDispatcher, + featureFlags = featureFlags, + sceneInteractor = kosmos.sceneInteractor, ) resourceTrimmer.start() } @@ -204,6 +210,7 @@ class ResourceTrimmerTest : SysuiTestCase() { @Test @EnableFlags(com.android.systemui.Flags.FLAG_TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) + @DisableSceneContainer fun keyguardTransitionsToGone_trimsFontCache() = testScope.runTest { keyguardTransitionRepository.sendTransitionSteps( @@ -219,6 +226,20 @@ class ResourceTrimmerTest : SysuiTestCase() { @Test @EnableFlags(com.android.systemui.Flags.FLAG_TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) + @EnableSceneContainer + fun keyguardTransitionsToGone_trimsFontCache_scene_container() = + testScope.runTest { + kosmos.setSceneTransition(Idle(Scenes.Gone)) + + verify(globalWindowManager, times(1)) + .trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) + verify(globalWindowManager, times(1)).trimCaches(HardwareRenderer.CACHE_TRIM_FONT) + verifyNoMoreInteractions(globalWindowManager) + } + + @Test + @EnableFlags(com.android.systemui.Flags.FLAG_TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) + @DisableSceneContainer fun keyguardTransitionsToGone_flagDisabled_doesNotTrimFontCache() = testScope.runTest { featureFlags.set(Flags.TRIM_FONT_CACHES_AT_UNLOCK, false) @@ -232,4 +253,18 @@ class ResourceTrimmerTest : SysuiTestCase() { .trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) verify(globalWindowManager, times(0)).trimCaches(any()) } + + @Test + @EnableFlags(com.android.systemui.Flags.FLAG_TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) + @EnableSceneContainer + fun keyguardTransitionsToGone_flagDisabled_doesNotTrimFontCache_scene_container() = + testScope.runTest { + featureFlags.set(Flags.TRIM_FONT_CACHES_AT_UNLOCK, false) + kosmos.setSceneTransition(Idle(Scenes.Gone)) + + // Memory hidden should still be called. + verify(globalWindowManager, times(1)) + .trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) + verify(globalWindowManager, times(0)).trimCaches(any()) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt index 62855d79c052..974e3bb133d8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt @@ -21,12 +21,18 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.DismissAction import com.android.systemui.keyguard.shared.model.KeyguardDone import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.data.repository.Idle +import com.android.systemui.scene.data.repository.setSceneTransition +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -65,10 +71,11 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() { underTest = KeyguardDismissActionInteractor( - keyguardRepository, - kosmos.keyguardTransitionInteractor, - dismissInteractorWithDependencies.interactor, - testScope.backgroundScope, + repository = keyguardRepository, + transitionInteractor = kosmos.keyguardTransitionInteractor, + dismissInteractor = dismissInteractorWithDependencies.interactor, + applicationScope = testScope.backgroundScope, + sceneInteractor = kosmos.sceneInteractor, ) } @@ -153,6 +160,7 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() { } @Test + @DisableSceneContainer fun executeDismissAction_dismissKeyguardRequestWithoutImmediateDismissAction() = testScope.runTest { val executeDismissAction by collectLastValue(underTest.executeDismissAction) @@ -179,6 +187,29 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() { } @Test + @EnableSceneContainer + fun executeDismissAction_dismissKeyguardRequestWithoutImmediateDismissAction_scene_container() = + testScope.runTest { + val executeDismissAction by collectLastValue(underTest.executeDismissAction) + + // WHEN a keyguard action will run after the keyguard is gone + val onDismissAction = {} + keyguardRepository.setDismissAction( + DismissAction.RunAfterKeyguardGone( + dismissAction = onDismissAction, + onCancelAction = {}, + message = "message", + willAnimateOnLockscreen = true, + ) + ) + assertThat(executeDismissAction).isNull() + + kosmos.setSceneTransition(Idle(Scenes.Gone)) + + assertThat(executeDismissAction).isNotNull() + } + + @Test fun resetDismissAction() = testScope.runTest { val resetDismissAction by collectLastValue(underTest.resetDismissAction) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt index d3952f047215..85cfacc0f87b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt @@ -33,6 +33,8 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -54,7 +56,10 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PageIndicator import com.android.systemui.res.R +import com.android.systemui.scene.data.repository.Idle +import com.android.systemui.scene.data.repository.setSceneTransition import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider import com.android.systemui.statusbar.policy.ConfigurationController @@ -153,29 +158,30 @@ class MediaCarouselControllerTest : SysuiTestCase() { testDispatcher = UnconfinedTestDispatcher() mediaCarouselController = MediaCarouselController( - context, - mediaControlPanelFactory, - visualStabilityProvider, - mediaHostStatesManager, - activityStarter, - clock, - kosmos.testDispatcher, - executor, - bgExecutor, - testDispatcher, - mediaDataManager, - configurationController, - falsingManager, - dumpManager, - logger, - debugLogger, - mediaFlags, - keyguardUpdateMonitor, - kosmos.keyguardTransitionInteractor, - globalSettings, - secureSettings, - kosmos.mediaCarouselViewModel, - mediaViewControllerFactory, + context = context, + mediaControlPanelFactory = mediaControlPanelFactory, + visualStabilityProvider = visualStabilityProvider, + mediaHostStatesManager = mediaHostStatesManager, + activityStarter = activityStarter, + systemClock = clock, + mainDispatcher = kosmos.testDispatcher, + executor = executor, + bgExecutor = bgExecutor, + backgroundDispatcher = testDispatcher, + mediaManager = mediaDataManager, + configurationController = configurationController, + falsingManager = falsingManager, + dumpManager = dumpManager, + logger = logger, + debugLogger = debugLogger, + mediaFlags = mediaFlags, + keyguardUpdateMonitor = keyguardUpdateMonitor, + keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor, + globalSettings = globalSettings, + secureSettings = secureSettings, + mediaCarouselViewModel = kosmos.mediaCarouselViewModel, + mediaViewControllerFactory = mediaViewControllerFactory, + sceneInteractor = kosmos.sceneInteractor, ) verify(configurationController).addCallback(capture(configListener)) verify(mediaDataManager).addListener(capture(listener)) @@ -835,6 +841,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { verify(mediaCarousel).visibility = View.VISIBLE } + @DisableSceneContainer @ExperimentalCoroutinesApi @Test fun testKeyguardGone_showMediaCarousel() = @@ -858,6 +865,25 @@ class MediaCarouselControllerTest : SysuiTestCase() { job.cancel() } + @EnableSceneContainer + @ExperimentalCoroutinesApi + @Test + fun testKeyguardGone_showMediaCarousel_scene_container() = + kosmos.testScope.runTest { + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + var updatedVisibility = false + mediaCarouselController.updateHostVisibility = { updatedVisibility = true } + mediaCarouselController.mediaCarousel = mediaCarousel + + val job = mediaCarouselController.listenForAnyStateToGoneKeyguardTransition(this) + kosmos.setSceneTransition(Idle(Scenes.Gone)) + + verify(mediaCarousel).visibility = View.VISIBLE + assertEquals(true, updatedVisibility) + + job.cancel() + } + @ExperimentalCoroutinesApi @Test fun keyguardShowing_notAllowedOnLockscreen_updateVisibility() { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt index 2c6d44f10152..03e5a90c9f7d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt @@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.domain.interactor.sceneInteractor import kotlinx.coroutines.ExperimentalCoroutinesApi @ExperimentalCoroutinesApi @@ -29,5 +30,6 @@ val Kosmos.keyguardDismissActionInteractor by transitionInteractor = keyguardTransitionInteractor, dismissInteractor = keyguardDismissInteractor, applicationScope = testScope.backgroundScope, + sceneInteractor = sceneInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryUtil.kt new file mode 100644 index 000000000000..641a75716ea0 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryUtil.kt @@ -0,0 +1,63 @@ +/* + * 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.data.repository + +import com.android.compose.animation.scene.ObservableTransitionState +import com.android.compose.animation.scene.SceneKey +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.shared.model.Scenes +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent + +private val mutableTransitionState = + MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(Scenes.Lockscreen)) + +fun Kosmos.setSceneTransition( + transition: ObservableTransitionState, + scope: TestScope = testScope, + repository: SceneContainerRepository = sceneContainerRepository +) { + repository.setTransitionState(mutableTransitionState) + mutableTransitionState.value = transition + scope.runCurrent() +} + +fun Transition( + from: SceneKey, + to: SceneKey, + currentScene: Flow<SceneKey> = flowOf(to), + progress: Flow<Float> = flowOf(0f), + isInitiatedByUserInput: Boolean = false, + isUserInputOngoing: Flow<Boolean> = flowOf(false), +): ObservableTransitionState.Transition { + return ObservableTransitionState.Transition( + fromScene = from, + toScene = to, + currentScene = currentScene, + progress = progress, + isInitiatedByUserInput = isInitiatedByUserInput, + isUserInputOngoing = isUserInputOngoing + ) +} + +fun Idle(currentScene: SceneKey): ObservableTransitionState.Idle { + return ObservableTransitionState.Idle(currentScene) +} |