summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt21
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt26
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt1
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt97
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt114
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt115
-rw-r--r--packages/SystemUI/res/values/dimens.xml7
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt96
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt71
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt27
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt3
30 files changed, 864 insertions, 167 deletions
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
index aa567364d130..76931a2b4d41 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -22,12 +22,15 @@ import android.view.View
import android.view.WindowInsets
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.LifecycleOwner
+import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.theme.PlatformTheme
import com.android.compose.ui.platform.DensityAwareComposeView
import com.android.internal.policy.ScreenDecorationsUtils
@@ -89,12 +92,18 @@ object ComposeFacade : BaseComposeFacade {
) {
activity.setContent {
PlatformTheme {
- CommunalHub(
- viewModel = viewModel,
- onOpenWidgetPicker = onOpenWidgetPicker,
- widgetConfigurator = widgetConfigurator,
- onEditDone = onEditDone,
- )
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ .background(LocalAndroidColorScheme.current.outlineVariant),
+ ) {
+ CommunalHub(
+ viewModel = viewModel,
+ onOpenWidgetPicker = onOpenWidgetPicker,
+ widgetConfigurator = widgetConfigurator,
+ onEditDone = onEditDone,
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index bc85513ae296..be5aa8a4c3b9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -1,6 +1,7 @@
package com.android.systemui.communal.ui.compose
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
@@ -12,6 +13,7 @@ import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.FixedSizeEdgeDetector
+import com.android.compose.animation.scene.LowestZIndexScenePicker
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
@@ -21,6 +23,7 @@ import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.observableTransitionState
import com.android.compose.animation.scene.transitions
import com.android.compose.animation.scene.updateSceneTransitionLayoutState
+import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
import com.android.systemui.communal.ui.compose.extensions.allowGestures
@@ -31,16 +34,25 @@ import kotlinx.coroutines.flow.transform
object Communal {
object Elements {
+ val Scrim = ElementKey("Scrim", scenePicker = LowestZIndexScenePicker)
val Content = ElementKey("CommunalContent")
}
}
val sceneTransitions = transitions {
- from(TransitionSceneKey.Blank, to = TransitionSceneKey.Communal) {
- spec = tween(durationMillis = 500)
-
+ to(TransitionSceneKey.Communal) {
+ spec = tween(durationMillis = 1000)
+ translate(Communal.Elements.Content, Edge.Right)
+ timestampRange(startMillis = 167, endMillis = 334) {
+ fade(Communal.Elements.Scrim)
+ fade(Communal.Elements.Content)
+ }
+ }
+ to(TransitionSceneKey.Blank) {
+ spec = tween(durationMillis = 1000)
translate(Communal.Elements.Content, Edge.Right)
- fade(Communal.Elements.Content)
+ timestampRange(endMillis = 167) { fade(Communal.Elements.Content) }
+ timestampRange(startMillis = 167, endMillis = 334) { fade(Communal.Elements.Scrim) }
}
}
@@ -111,6 +123,12 @@ private fun SceneScope.CommunalScene(
viewModel: BaseCommunalViewModel,
modifier: Modifier = Modifier,
) {
+ Box(
+ modifier =
+ Modifier.element(Communal.Elements.Scrim)
+ .fillMaxSize()
+ .background(LocalAndroidColorScheme.current.outlineVariant),
+ )
Box(modifier.element(Communal.Elements.Content)) { CommunalHub(viewModel = viewModel) }
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 090750e046a7..cddd4fa1c33d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -141,7 +141,6 @@ fun CommunalHub(
modifier =
modifier
.fillMaxSize()
- .background(LocalAndroidColorScheme.current.outlineVariant)
.pointerInput(gridState, contentOffset, contentListState) {
// If not in edit mode, don't allow selecting items.
if (!viewModel.isEditMode) return@pointerInput
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 8a35ef11a364..a6715dfcec24 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -8,7 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.complication.ComplicationHostViewController
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
+import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel
import com.android.systemui.log.core.FakeLogBuffer
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -47,7 +47,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
@Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController
@Mock private lateinit var stateController: DreamOverlayStateController
@Mock private lateinit var configController: ConfigurationController
- @Mock private lateinit var transitionViewModel: DreamingToLockscreenTransitionViewModel
+ @Mock private lateinit var transitionViewModel: DreamOverlayViewModel
private val logBuffer = FakeLogBuffer.Factory.create()
private lateinit var controller: DreamOverlayAnimationsController
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt
new file mode 100644
index 000000000000..4defe8a08d3d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelTest.kt
@@ -0,0 +1,97 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DreamingToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val underTest by lazy { kosmos.dreamingToGlanceableHubTransitionViewModel }
+
+ @Test
+ fun dreamOverlayAlpha() =
+ testScope.runTest {
+ val values by collectValues(underTest.dreamOverlayAlpha)
+ assertThat(values).isEmpty()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ // Should start running here...
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.5f),
+ // Up to here...
+ step(1f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(4)
+ values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+ }
+
+ @Test
+ fun dreamOverlayTranslationX() =
+ testScope.runTest {
+ val values by collectValues(underTest.dreamOverlayTranslationX(100))
+ assertThat(values).isEmpty()
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0.3f),
+ step(0.6f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(3)
+ values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = value,
+ transitionState = state,
+ ownerName = "DreamingToGlanceableHubTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt
new file mode 100644
index 000000000000..64125f139a2e
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelTest.kt
@@ -0,0 +1,114 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GlanceableHubToLockscreenTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val underTest by lazy { kosmos.glanceableHubToLockscreenTransitionViewModel }
+
+ @Test
+ fun lockscreenFadeIn() =
+ testScope.runTest {
+ val values by collectValues(underTest.keyguardAlpha)
+ assertThat(values).containsExactly(0f)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ // Should start running here...
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(0.4f),
+ // ...up to here
+ step(0.5f),
+ step(0.6f),
+ step(0.7f),
+ step(0.8f),
+ step(1f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(5)
+ values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+ }
+
+ @Test
+ fun lockscreenTranslationX() =
+ testScope.runTest {
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x,
+ 100
+ )
+ val values by collectValues(underTest.keyguardTranslationX)
+ assertThat(values).isEmpty()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ step(1f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(5)
+ values.forEach { assertThat(it.value).isIn(Range.closed(-100f, 0f)) }
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.LOCKSCREEN,
+ value = value,
+ transitionState = state,
+ ownerName = this::class.java.simpleName
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt
new file mode 100644
index 000000000000..241d0b818193
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelTest.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LockscreenToGlanceableHubTransitionViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+
+ val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val underTest by lazy { kosmos.lockscreenToGlanceableHubTransitionViewModel }
+
+ @Test
+ fun lockscreenFadeOut() =
+ testScope.runTest {
+ val values by collectValues(underTest.keyguardAlpha)
+ assertThat(values).containsExactly(1f)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ // Should start running here
+ step(0f, TransitionState.STARTED),
+ step(0.1f),
+ step(0.2f),
+ // ...up to here
+ step(0.3f),
+ step(0.4f),
+ step(0.5f),
+ step(0.6f),
+ step(0.7f),
+ step(0.8f),
+ // ...up to here
+ step(1f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(4)
+ values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+ }
+
+ @Test
+ fun lockscreenTranslationX() =
+ testScope.runTest {
+ configurationRepository.setDimensionPixelSize(
+ R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x,
+ -100
+ )
+ val values by collectValues(underTest.keyguardTranslationX)
+ assertThat(values).isEmpty()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.3f),
+ step(0.5f),
+ step(1f),
+ ),
+ testScope,
+ )
+
+ assertThat(values).hasSize(5)
+ values.forEach { assertThat(it.value).isIn(Range.closed(-100f, 0f)) }
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GLANCEABLE_HUB,
+ value = value,
+ transitionState = state,
+ ownerName = this::class.java.simpleName
+ )
+ }
+}
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a681da3adc4e..65120a99a6b5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1514,6 +1514,12 @@
<!-- The amount of vertical offset for the keyguard during the full shade transition. -->
<dimen name="lockscreen_shade_keyguard_transition_vertical_offset">0dp</dimen>
+ <!-- LOCKSCREEN -> GLANCEABLE_HUB transition: Amount to shift lockscreen content on entering -->
+ <dimen name="lockscreen_to_hub_transition_lockscreen_translation_x">-824dp</dimen>
+
+ <!-- GLANCEABLE_HUB -> LOCKSCREEN transition: Amount to shift lockscreen content on entering -->
+ <dimen name="hub_to_lockscreen_transition_lockscreen_translation_x">824dp</dimen>
+
<!-- Distance that the full shade transition takes in order for media to fully transition to
the shade -->
<dimen name="lockscreen_shade_media_transition_distance">120dp</dimen>
@@ -1857,6 +1863,7 @@
<dimen name="dream_overlay_y_offset">80dp</dimen>
<dimen name="dream_overlay_entry_y_offset">40dp</dimen>
<dimen name="dream_overlay_exit_y_offset">40dp</dimen>
+ <dimen name="dream_overlay_exit_x_offset">824dp</dimen>
<dimen name="status_view_margin_horizontal">0dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index 557ad132bc9f..9000da33312c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -33,20 +33,16 @@ import com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTO
import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP
import com.android.systemui.complication.ComplicationLayoutParams.Position
import com.android.systemui.dreams.dagger.DreamOverlayModule
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
+import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.DreamLog
-import com.android.systemui.res.R
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.CrossFadeHelper
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
import javax.inject.Inject
import javax.inject.Named
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
/** Controller for dream overlay animations. */
@@ -58,7 +54,7 @@ constructor(
private val mStatusBarViewController: DreamOverlayStatusBarViewController,
private val mOverlayStateController: DreamOverlayStateController,
@Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int,
- private val transitionViewModel: DreamingToLockscreenTransitionViewModel,
+ private val dreamOverlayViewModel: DreamOverlayViewModel,
private val configController: ConfigurationController,
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
private val mDreamInBlurAnimDurationMs: Long,
@@ -91,59 +87,45 @@ constructor(
this.view = view
view.repeatWhenAttached {
- val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
- val configCallback =
- object : ConfigurationListener {
- override fun onDensityOrFontScaleChanged() {
- configurationBasedDimensions.value = loadFromResources(view)
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ launch {
+ dreamOverlayViewModel.dreamOverlayTranslationY.collect { px ->
+ ComplicationLayoutParams.iteratePositions(
+ { position: Int -> setElementsTranslationYAtPosition(px, position) },
+ POSITION_TOP or POSITION_BOTTOM
+ )
}
}
- configController.addCallback(configCallback)
-
- try {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- /* Translation animations, when moving from DREAMING->LOCKSCREEN state */
- launch {
- configurationBasedDimensions
- .flatMapLatest {
- transitionViewModel.dreamOverlayTranslationY(it.translationYPx)
- }
- .collect { px ->
- ComplicationLayoutParams.iteratePositions(
- { position: Int ->
- setElementsTranslationYAtPosition(px, position)
- },
- POSITION_TOP or POSITION_BOTTOM
- )
- }
+ launch {
+ dreamOverlayViewModel.dreamOverlayTranslationX.collect { px ->
+ ComplicationLayoutParams.iteratePositions(
+ { position: Int -> setElementsTranslationXAtPosition(px, position) },
+ POSITION_TOP or POSITION_BOTTOM
+ )
}
+ }
- /* Alpha animations, when moving from DREAMING->LOCKSCREEN state */
- launch {
- transitionViewModel.dreamOverlayAlpha.collect { alpha ->
- ComplicationLayoutParams.iteratePositions(
- { position: Int ->
- setElementsAlphaAtPosition(
- alpha = alpha,
- position = position,
- fadingOut = true,
- )
- },
- POSITION_TOP or POSITION_BOTTOM
- )
- }
+ launch {
+ dreamOverlayViewModel.dreamOverlayAlpha.collect { alpha ->
+ ComplicationLayoutParams.iteratePositions(
+ { position: Int ->
+ setElementsAlphaAtPosition(
+ alpha = alpha,
+ position = position,
+ fadingOut = true,
+ )
+ },
+ POSITION_TOP or POSITION_BOTTOM
+ )
}
+ }
- launch {
- transitionViewModel.transitionEnded.collect { _ ->
- mOverlayStateController.setExitAnimationsRunning(false)
- }
+ launch {
+ dreamOverlayViewModel.transitionEnded.collect { _ ->
+ mOverlayStateController.setExitAnimationsRunning(false)
}
}
- } finally {
- // Ensure the callback is removed when cancellation happens
- configController.removeCallback(configCallback)
}
}
}
@@ -373,14 +355,10 @@ constructor(
}
}
- private fun loadFromResources(view: View): ConfigurationBasedDimensions {
- return ConfigurationBasedDimensions(
- translationYPx =
- view.resources.getDimensionPixelSize(R.dimen.dream_overlay_exit_y_offset),
- )
+ /** Sets x translation of complications at the specified position. */
+ private fun setElementsTranslationXAtPosition(translationX: Float, position: Int) {
+ mComplicationHostViewController.getViewsAtPosition(position).forEach { v ->
+ v.translationX = translationX
+ }
}
-
- private data class ConfigurationBasedDimensions(
- val translationYPx: Int,
- )
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt
new file mode 100644
index 000000000000..dd67a4c8706c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.dreams.ui.viewmodel
+
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.merge
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class DreamOverlayViewModel
+@Inject
+constructor(
+ configurationInteractor: ConfigurationInteractor,
+ private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
+ private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
+) {
+
+ val dreamOverlayTranslationX: Flow<Float> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.dream_overlay_exit_x_offset)
+ .flatMapLatest { px: Int ->
+ toGlanceableHubTransitionViewModel.dreamOverlayTranslationX(px)
+ }
+
+ val dreamOverlayTranslationY: Flow<Float> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.dream_overlay_exit_y_offset)
+ .flatMapLatest { px: Int ->
+ toLockscreenTransitionViewModel.dreamOverlayTranslationY(px)
+ }
+
+ val dreamOverlayAlpha: Flow<Float> =
+ merge(
+ toLockscreenTransitionViewModel.dreamOverlayAlpha,
+ toGlanceableHubTransitionViewModel.dreamOverlayAlpha,
+ )
+
+ val transitionEnded = toLockscreenTransitionViewModel.transitionEnded
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 13ffd6396cda..c6594ef317d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import com.android.app.animation.Interpolators
+import com.android.systemui.Flags.communalHub
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -44,6 +45,7 @@ constructor(
@Background bgDispatcher: CoroutineDispatcher,
@Main mainDispatcher: CoroutineDispatcher,
private val keyguardInteractor: KeyguardInteractor,
+ private val glanceableHubTransitions: GlanceableHubTransitions,
) :
TransitionInteractor(
fromState = KeyguardState.DREAMING,
@@ -57,6 +59,17 @@ constructor(
listenForDreamingToGone()
listenForDreamingToAodOrDozing()
listenForTransitionToCamera(scope, keyguardInteractor)
+ listenForDreamingToGlanceableHub()
+ }
+
+ private fun listenForDreamingToGlanceableHub() {
+ if (!communalHub()) return
+ glanceableHubTransitions.listenForGlanceableHubTransition(
+ transitionName = "listenForDreamingToGlanceableHub",
+ transitionOwnerName = TAG,
+ fromState = KeyguardState.DREAMING,
+ toState = KeyguardState.GLANCEABLE_HUB,
+ )
}
fun startToLockscreenTransition() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 71d941ad8d22..fbf195eb0952 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -20,7 +20,6 @@ import android.animation.ValueAnimator
import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launch
import com.android.systemui.Flags
-import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -31,7 +30,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleMultiple
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
-import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -71,7 +70,11 @@ constructor(
override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator {
return ValueAnimator().apply {
interpolator = Interpolators.LINEAR
- duration = DEFAULT_DURATION.inWholeMilliseconds
+ duration =
+ when (toState) {
+ KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
+ else -> DEFAULT_DURATION
+ }.inWholeMilliseconds
}
}
@@ -80,10 +83,11 @@ constructor(
* transition.
*/
private fun listenForHubToLockscreen() {
- glanceableHubTransitions.listenForLockscreenAndHubTransition(
+ glanceableHubTransitions.listenForGlanceableHubTransition(
transitionName = "listenForHubToLockscreen",
transitionOwnerName = TAG,
- toScene = CommunalSceneKey.Blank,
+ fromState = KeyguardState.GLANCEABLE_HUB,
+ toState = KeyguardState.LOCKSCREEN,
)
}
@@ -175,7 +179,7 @@ constructor(
companion object {
const val TAG = "FromGlanceableHubTransitionInteractor"
- val DEFAULT_DURATION = 400.milliseconds
+ val DEFAULT_DURATION = 1.seconds
val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 57e9ac707965..40b2c638823d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -19,7 +19,6 @@ package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import android.util.MathUtils
import com.android.app.animation.Interpolators
-import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -39,6 +38,7 @@ import com.android.systemui.util.kotlin.sample
import java.util.UUID
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -361,10 +361,11 @@ constructor(
return
}
- glanceableHubTransitions.listenForLockscreenAndHubTransition(
+ glanceableHubTransitions.listenForGlanceableHubTransition(
transitionName = "listenForLockscreenToGlanceableHub",
transitionOwnerName = TAG,
- toScene = CommunalSceneKey.Communal
+ fromState = KeyguardState.LOCKSCREEN,
+ toState = KeyguardState.GLANCEABLE_HUB,
)
}
@@ -380,6 +381,7 @@ constructor(
KeyguardState.AOD -> TO_AOD_DURATION
KeyguardState.DOZING -> TO_DOZING_DURATION
KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> TO_DREAMING_HOSTED_DURATION
+ KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -395,6 +397,6 @@ constructor(
val TO_AOD_DURATION = 500.milliseconds
val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
val TO_GONE_DURATION = DEFAULT_DURATION
- val TO_GLANCEABLE_HUB_DURATION = DEFAULT_DURATION
+ val TO_GLANCEABLE_HUB_DURATION = 1.seconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt
index ca661536d988..809c0aee9882 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt
@@ -52,20 +52,18 @@ constructor(
* externally. The progress is used for both transitions caused by user touch input or by
* programmatic changes.
*/
- fun listenForLockscreenAndHubTransition(
+ fun listenForGlanceableHubTransition(
transitionName: String,
transitionOwnerName: String,
- toScene: CommunalSceneKey
+ fromState: KeyguardState,
+ toState: KeyguardState,
) {
- val fromState: KeyguardState
- val toState: KeyguardState
- if (toScene == CommunalSceneKey.Blank) {
- fromState = KeyguardState.GLANCEABLE_HUB
- toState = KeyguardState.LOCKSCREEN
- } else {
- fromState = KeyguardState.LOCKSCREEN
- toState = KeyguardState.GLANCEABLE_HUB
- }
+ val toScene =
+ if (toState == KeyguardState.GLANCEABLE_HUB) {
+ CommunalSceneKey.Communal
+ } else {
+ CommunalSceneKey.Blank
+ }
var transitionId: UUID? = null
scope.launch("$transitionOwnerName#$transitionName") {
communalInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index 8b278cdb9a6c..b8ba09801ee8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -185,13 +185,16 @@ constructor(
return getOrCreateFlow(edge)
.map { step ->
StateToValue(
- step.transitionState,
- when (step.transitionState) {
- STARTED -> stepToValue(step)
- RUNNING -> stepToValue(step)
- CANCELED -> onCancel?.invoke()
- FINISHED -> onFinish?.invoke()
- }
+ from = step.from,
+ to = step.to,
+ transitionState = step.transitionState,
+ value =
+ when (step.transitionState) {
+ STARTED -> stepToValue(step)
+ RUNNING -> stepToValue(step)
+ CANCELED -> onCancel?.invoke()
+ FINISHED -> onFinish?.invoke()
+ }
)
.also { logger.logTransitionStep(name, step, it.value) }
}
@@ -208,6 +211,10 @@ constructor(
}
data class StateToValue(
+ val from: KeyguardState? = null,
+ val to: KeyguardState? = null,
val transitionState: TransitionState = TransitionState.FINISHED,
val value: Float? = 0f,
-)
+) {
+ fun isToOrFrom(state: KeyguardState) = from == state || to == state
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index c58a03c05a09..ed488487f524 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -43,6 +43,7 @@ import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.shared.model.TintedIcon
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
@@ -101,6 +102,10 @@ object KeyguardRootViewBinder {
val burnInLayerId = R.id.burn_in_layer
val aodNotificationIconContainerId = R.id.aod_notification_icon_container
val largeClockId = R.id.lockscreen_clock_view_large
+ val indicationArea = R.id.keyguard_indication_area
+ val startButton = R.id.start_button
+ val endButton = R.id.end_button
+ val lockIcon = R.id.lock_icon_view
if (keyguardBottomAreaRefactor()) {
view.setOnTouchListener { _, event ->
@@ -200,10 +205,29 @@ object KeyguardRootViewBinder {
launch {
burnInParams
.flatMapLatest { params -> viewModel.translationX(params) }
- .collect { x ->
- childViews[burnInLayerId]?.translationX = x
- childViews[largeClockId]?.translationX = x
- childViews[aodNotificationIconContainerId]?.translationX = x
+ .collect { state ->
+ val px = state.value ?: return@collect
+ when {
+ state.isToOrFrom(KeyguardState.AOD) -> {
+ childViews[largeClockId]?.translationX = px
+ childViews[burnInLayerId]?.translationX = px
+ childViews[aodNotificationIconContainerId]
+ ?.translationX = px
+ }
+ state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> {
+ for ((key, childView) in childViews.entries) {
+ when (key) {
+ indicationArea,
+ startButton,
+ endButton,
+ lockIcon -> {
+ // Do not move these views
+ }
+ else -> childView.translationX = px
+ }
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
new file mode 100644
index 000000000000..374a93275ff2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import com.android.app.animation.Interpolators.EMPHASIZED
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.flow.Flow
+
+@SysUISingleton
+class DreamingToGlanceableHubTransitionViewModel
+@Inject
+constructor(animationFlow: KeyguardTransitionAnimationFlow) {
+
+ private val transitionAnimation =
+ animationFlow.setup(
+ duration = TO_GLANCEABLE_HUB_DURATION,
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ )
+
+ fun dreamOverlayTranslationX(translatePx: Int): Flow<Float> {
+ return transitionAnimation.sharedFlow(
+ duration = TO_GLANCEABLE_HUB_DURATION,
+ onStep = { it * -translatePx },
+ interpolator = EMPHASIZED,
+ name = "DREAMING->GLANCEABLE_HUB: overlayTranslationX",
+ )
+ }
+
+ val dreamOverlayAlpha: Flow<Float> =
+ transitionAnimation.sharedFlow(
+ duration = 167.milliseconds,
+ onStep = { 1f - it },
+ name = "DREAMING->GLANCEABLE_HUB: dreamOverlayAlpha",
+ )
+
+ private companion object {
+ val TO_GLANCEABLE_HUB_DURATION = 1.seconds
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
index 6aa2ecabae75..e5b596419efe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt
@@ -16,13 +16,22 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.app.animation.Interpolators.EMPHASIZED
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.StateToValue
+import com.android.systemui.res.R
import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
/**
* Breaks down GLANCEABLE_HUB->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -33,32 +42,43 @@ import kotlinx.coroutines.flow.Flow
class GlanceableHubToLockscreenTransitionViewModel
@Inject
constructor(
+ configurationInteractor: ConfigurationInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
animationFlow.setup(
- duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION,
+ duration = TO_LOCKSCREEN_DURATION,
from = KeyguardState.GLANCEABLE_HUB,
to = KeyguardState.LOCKSCREEN,
)
- // TODO(b/315205222): implement full animation spec instead of just a simple fade.
val keyguardAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION,
- onStep = { it },
- onFinish = { 1f },
- onCancel = { 0f },
- name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardAlpha",
- )
+ transitionAnimation
+ .sharedFlow(
+ duration = 167.milliseconds,
+ startTime = 167.milliseconds,
+ onStep = { it },
+ onFinish = { 1f },
+ onCancel = { 0f },
+ name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardAlpha",
+ )
+ .onStart { emit(0f) }
- // TODO(b/315205216): implement full animation spec instead of just a simple fade.
- val notificationAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION,
- onStep = { it },
- onFinish = { 1f },
- onCancel = { 0f },
- name = "GLANCEABLE_HUB->LOCKSCREEN: notificationAlpha",
- )
+ val keyguardTranslationX: Flow<StateToValue> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x)
+ .flatMapLatest { translatePx: Int ->
+ transitionAnimation.sharedFlowWithState(
+ duration = TO_LOCKSCREEN_DURATION,
+ onStep = { value -> -translatePx + value * translatePx },
+ interpolator = EMPHASIZED,
+ onCancel = { -translatePx.toFloat() },
+ name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardTranslationX"
+ )
+ }
+
+ val notificationAlpha: Flow<Float> = keyguardAlpha
+
+ val notificationTranslationX: Flow<Float> =
+ keyguardTranslationX.map { it.value }.filterNotNull()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index f790d356620d..35119338fb32 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -32,6 +32,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
+import com.android.systemui.keyguard.ui.StateToValue
import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
@@ -165,8 +166,12 @@ constructor(
return aodBurnInViewModel.translationY(params)
}
- fun translationX(params: BurnInParameters): Flow<Float> {
- return aodBurnInViewModel.translationX(params)
+ fun translationX(params: BurnInParameters): Flow<StateToValue> {
+ return merge(
+ aodBurnInViewModel.translationX(params).map { StateToValue(to = AOD, value = it) },
+ lockscreenToGlanceableHubTransitionViewModel.keyguardTranslationX,
+ glanceableHubToLockscreenTransitionViewModel.keyguardTranslationX,
+ )
}
fun scale(params: BurnInParameters): Flow<BurnInScaleViewModel> {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
index 3afa49e50167..978e71e2a825 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt
@@ -16,13 +16,22 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.app.animation.Interpolators.EMPHASIZED
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.StateToValue
+import com.android.systemui.res.R
import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
/**
* Breaks down LOCKSCREEN->GLANCEABLE_HUB transition into discrete steps for corresponding views to
@@ -33,6 +42,7 @@ import kotlinx.coroutines.flow.Flow
class LockscreenToGlanceableHubTransitionViewModel
@Inject
constructor(
+ configurationInteractor: ConfigurationInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
) {
private val transitionAnimation =
@@ -42,23 +52,35 @@ constructor(
to = KeyguardState.GLANCEABLE_HUB,
)
- // TODO(b/315205222): implement full animation spec instead of just a simple fade.
val keyguardAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION,
- onStep = { 1f - it },
- onFinish = { 0f },
- onCancel = { 1f },
- name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardAlpha",
- )
+ transitionAnimation
+ .sharedFlow(
+ duration = 167.milliseconds,
+ onStep = { 1f - it },
+ onFinish = { 0f },
+ onCancel = { 1f },
+ name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardAlpha",
+ )
+ .onStart { emit(1f) }
- // TODO(b/315205216): implement full animation spec instead of just a simple fade.
- val notificationAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION,
- onStep = { 1f - it },
- onFinish = { 0f },
- onCancel = { 1f },
- name = "LOCKSCREEN->GLANCEABLE_HUB: notificationAlpha",
- )
+ val keyguardTranslationX: Flow<StateToValue> =
+ configurationInteractor
+ .dimensionPixelSize(R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x)
+ .flatMapLatest { translatePx: Int ->
+ transitionAnimation.sharedFlowWithState(
+ duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION,
+ onStep = { value -> value * translatePx },
+ // Move notifications back to their original position since they can be
+ // accessed from the shade.
+ onFinish = { 0f },
+ onCancel = { 0f },
+ interpolator = EMPHASIZED,
+ name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardTranslationX"
+ )
+ }
+
+ val notificationAlpha: Flow<Float> = keyguardAlpha
+
+ val notificationTranslationX: Flow<Float> =
+ keyguardTranslationX.map { it.value }.filterNotNull()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index d2ff266319d0..715505d81d71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1039,6 +1039,11 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.setTranslationY(translationY);
}
+ /** Set view x-translation */
+ public void setTranslationX(float translationX) {
+ mView.setTranslationX(translationX);
+ }
+
public int indexOfChild(View view) {
return mView.indexOfChild(view);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index daea8af8f334..77e146b98242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -144,6 +144,8 @@ object SharedNotificationContainerBinder {
.collect { y -> controller.setTranslationY(y) }
}
+ launch { viewModel.translationX.collect { x -> controller.translationX = x } }
+
if (!sceneContainerFlags.isEnabled()) {
launch {
viewModel.expansionAlpha(viewState).collect {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index f325157c598d..6b949a3461e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -363,14 +363,9 @@ constructor(
lockscreenToGlanceableHubRunning,
glanceableHubToLockscreenRunning,
merge(
- lockscreenToGlanceableHubTransitionViewModel.notificationAlpha,
- glanceableHubToLockscreenTransitionViewModel.notificationAlpha,
- )
- .onStart {
- // Transition flows don't emit a value on start, kick things off so the
- // combine starts.
- emit(1f)
- }
+ lockscreenToGlanceableHubTransitionViewModel.notificationAlpha,
+ glanceableHubToLockscreenTransitionViewModel.notificationAlpha,
+ )
) { lockscreenToGlanceableHubRunning, glanceableHubToLockscreenRunning, alpha ->
if (isOnGlanceableHubWithoutShade) {
// Notifications should not be visible on the glanceable hub.
@@ -409,6 +404,16 @@ constructor(
}
/**
+ * The container may need to be translated in the x direction as the keyguard fades out, such as
+ * when swiping open the glanceable hub from the lockscreen.
+ */
+ val translationX: Flow<Float> =
+ merge(
+ lockscreenToGlanceableHubTransitionViewModel.notificationTranslationX,
+ glanceableHubToLockscreenTransitionViewModel.notificationTranslationX,
+ )
+
+ /**
* When on keyguard, there is limited space to display notifications so calculate how many could
* be shown. Otherwise, there is no limit since the vertical space will be scrollable.
*
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 5b93df5a0bad..a5d577dceecb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
-import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -148,6 +147,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardInteractor = keyguardInteractor,
transitionRepository = transitionRepository,
transitionInteractor = transitionInteractor,
+ glanceableHubTransitions = glanceableHubTransitions,
)
.apply { start() }
@@ -1372,6 +1372,44 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
}
@Test
+ fun dreamingToGlanceableHub() =
+ testScope.runTest {
+ // GIVEN a prior transition has run to DREAMING
+ keyguardRepository.setDreaming(true)
+ runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING)
+ runCurrent()
+
+ // WHEN a transition to the glanceable hub starts
+ val currentScene = CommunalSceneKey.Blank
+ val targetScene = CommunalSceneKey.Communal
+
+ val progress = MutableStateFlow(0f)
+ val transitionState =
+ MutableStateFlow<ObservableCommunalTransitionState>(
+ ObservableCommunalTransitionState.Transition(
+ fromScene = currentScene,
+ toScene = targetScene,
+ progress = progress,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
+ )
+ )
+ communalInteractor.setTransitionState(transitionState)
+ progress.value = .1f
+ runCurrent()
+
+ assertThat(transitionRepository)
+ .startedTransition(
+ ownerName = FromDreamingTransitionInteractor::class.simpleName,
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ animatorAssertion = { it.isNull() }, // transition should be manually animated
+ )
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
fun lockscreenToOccluded() =
testScope.runTest {
// GIVEN a prior transition has run to LOCKSCREEN
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
index 0e9197ef8ac1..f0607f4b70e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
@@ -22,7 +22,8 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
@@ -51,8 +52,8 @@ class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
underTest =
animationFlow.setup(
duration = 1000.milliseconds,
- from = KeyguardState.GONE,
- to = KeyguardState.DREAMING,
+ from = GONE,
+ to = DREAMING,
)
}
@@ -192,17 +193,65 @@ class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
runCurrent()
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.STARTED, 0f))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.STARTED,
+ value = 0f
+ )
+ )
repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.RUNNING, 0.6f))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.RUNNING,
+ value = 0.6f
+ )
+ )
repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.RUNNING, 1.2f))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.RUNNING,
+ value = 1.2f
+ )
+ )
repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.RUNNING, 1.6f))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.RUNNING,
+ value = 1.6f
+ )
+ )
repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.RUNNING, 2f))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.RUNNING,
+ value = 2f
+ )
+ )
repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(animationValues).isEqualTo(StateToValue(TransitionState.FINISHED, null))
+ assertThat(animationValues)
+ .isEqualTo(
+ StateToValue(
+ from = GONE,
+ to = DREAMING,
+ transitionState = TransitionState.FINISHED,
+ value = null
+ )
+ )
}
@Test
@@ -251,8 +300,8 @@ class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
state: TransitionState = TransitionState.RUNNING
): TransitionStep {
return TransitionStep(
- from = KeyguardState.GONE,
- to = KeyguardState.DREAMING,
+ from = GONE,
+ to = DREAMING,
value = value,
transitionState = state,
ownerName = "GoneToDreamingTransitionViewModelTest"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
index bfa84335d670..716c40d59ccf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
@@ -59,7 +59,14 @@ class GoneToAodTransitionViewModelTest : SysuiTestCase() {
// The animation should only start > .4f way through
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
assertThat(enterFromTopTranslationY)
- .isEqualTo(StateToValue(TransitionState.STARTED, pixels))
+ .isEqualTo(
+ StateToValue(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ value = pixels
+ )
+ )
repository.sendTransitionStep(step(.55f))
assertThat(enterFromTopTranslationY!!.value ?: -1f).isIn(Range.closed(pixels, 0f))
@@ -70,7 +77,14 @@ class GoneToAodTransitionViewModelTest : SysuiTestCase() {
// At the end, the translation should be complete and set to zero
repository.sendTransitionStep(step(1f))
assertThat(enterFromTopTranslationY)
- .isEqualTo(StateToValue(TransitionState.RUNNING, 0f))
+ .isEqualTo(
+ StateToValue(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.RUNNING,
+ value = 0f
+ )
+ )
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index b9b872254b06..3e0082c5aed7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.policy.splitShadeStateController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
+import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -274,8 +275,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
)
)
runCurrent()
- // Expected alpha is inverse of progress as notifications are fading away
- assertThat(alpha).isEqualTo(1 - progress)
+ assertThat(alpha).isIn(Range.closed(0f, 1f))
// Finish transition to glanceable hub
keyguardTransitionRepository.sendTransitionStep(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
new file mode 100644
index 000000000000..b37085957d7e
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.dreamingToGlanceableHubTransitionViewModel by
+ Kosmos.Fixture {
+ DreamingToGlanceableHubTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
index 28fce77b75b7..b1c21b8fa6cf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModelKosmos.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -26,6 +27,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
@OptIn(ExperimentalCoroutinesApi::class)
val Kosmos.glanceableHubToLockscreenTransitionViewModel by Fixture {
GlanceableHubToLockscreenTransitionViewModel(
+ configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
index 9fe4ea347f63..471381f7a13f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModelKosmos.kt
@@ -18,13 +18,16 @@
package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
+@ExperimentalCoroutinesApi
val Kosmos.lockscreenToGlanceableHubTransitionViewModel by Fixture {
LockscreenToGlanceableHubTransitionViewModel(
+ configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
)
}