summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Matt Pietal <mpietal@google.com> 2024-06-17 19:53:51 +0000
committer Matt Pietal <mpietal@google.com> 2024-06-17 20:08:22 +0000
commitbb945dbb0aac262d0a3f8610a361d8a685e9612f (patch)
tree6649b5e3aaf59a15f505fd6407e9be41038ec974
parent725aed7a8339e2b02f39004decd7b160a7d070c3 (diff)
Add AOD fold animation
When folding the device and entering AOD, keyguard should fade in from the side and not the top as is the default. Bug: 346325723 Test: atest GoneToAodTransitionViewModelTest Flag: com.android.systemui.migrate_clocks_to_blueprint Change-Id: Ie754bf839c7121a3bd5a85a878c379021804e47c
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt)87
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt76
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelKosmos.kt1
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt4
12 files changed, 258 insertions, 56 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
index 519bb6eb7834..63d06a409522 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
@@ -55,6 +55,8 @@ class AodBurnInViewModelTest : SysuiTestCase() {
@Mock private lateinit var burnInInteractor: BurnInInteractor
@Mock private lateinit var goneToAodTransitionViewModel: GoneToAodTransitionViewModel
+ @Mock
+ private lateinit var lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var clockController: ClockController
private val kosmos = testKosmos()
@@ -76,7 +78,12 @@ class AodBurnInViewModelTest : SysuiTestCase() {
kosmos.burnInInteractor = burnInInteractor
whenever(goneToAodTransitionViewModel.enterFromTopTranslationY(anyInt()))
.thenReturn(emptyFlow())
+ whenever(goneToAodTransitionViewModel.enterFromSideTranslationX(anyInt()))
+ .thenReturn(emptyFlow())
+ whenever(lockscreenToAodTransitionViewModel.enterFromSideTranslationX(anyInt()))
+ .thenReturn(emptyFlow())
kosmos.goneToAodTransitionViewModel = goneToAodTransitionViewModel
+ kosmos.lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel
kosmos.fakeKeyguardClockRepository.setCurrentClock(clockController)
underTest = kosmos.aodBurnInViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
index 716c40d59ccf..bab466a6c1d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
@@ -28,6 +28,9 @@ import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.StateToValue
import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.powerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.testKosmos
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
@@ -47,10 +50,18 @@ class GoneToAodTransitionViewModelTest : SysuiTestCase() {
private val underTest = kosmos.goneToAodTransitionViewModel
private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
private val biometricSettingsRepository = kosmos.biometricSettingsRepository
+ private val powerRepository = kosmos.powerRepository
@Test
- fun enterFromTopTranslationY() =
+ fun enterFromTopTranslationY_whenNotOnFold() =
testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.POWER_BUTTON,
+ powerButtonLaunchGestureTriggered = false
+ )
+
val pixels = -100f
val enterFromTopTranslationY by
collectLastValue(underTest.enterFromTopTranslationY(pixels.toInt()))
@@ -88,6 +99,80 @@ class GoneToAodTransitionViewModelTest : SysuiTestCase() {
}
@Test
+ fun enterFromTopTranslationY_whenOnFold_emitsNothing() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.FOLD,
+ powerButtonLaunchGestureTriggered = false
+ )
+
+ val pixels = -100f
+ val enterFromTopTranslationY by
+ collectLastValue(underTest.enterFromTopTranslationY(pixels.toInt()))
+ runCurrent()
+
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(enterFromTopTranslationY).isNull()
+
+ repository.sendTransitionStep(step(.55f))
+ assertThat(enterFromTopTranslationY).isNull()
+
+ repository.sendTransitionStep(step(.85f))
+ assertThat(enterFromTopTranslationY).isNull()
+
+ repository.sendTransitionStep(step(1f))
+ assertThat(enterFromTopTranslationY).isNull()
+ }
+
+ @Test
+ fun enterFromSideTranslationX_onFold() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.FOLD,
+ powerButtonLaunchGestureTriggered = false
+ )
+
+ val pixels = -100f
+ val enterFromSideTranslationX by
+ collectLastValue(underTest.enterFromSideTranslationX(pixels.toInt()))
+ runCurrent()
+
+ // The animation should only start > .4f way through
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(enterFromSideTranslationX)
+ .isEqualTo(
+ StateToValue(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ value = pixels
+ )
+ )
+
+ repository.sendTransitionStep(step(.55f))
+ assertThat(enterFromSideTranslationX!!.value ?: -1f).isIn(Range.closed(pixels, 0f))
+
+ repository.sendTransitionStep(step(.85f))
+ assertThat(enterFromSideTranslationX!!.value ?: -1f).isIn(Range.closed(pixels, 0f))
+
+ // At the end, the translation should be complete and set to zero
+ repository.sendTransitionStep(step(1f))
+ assertThat(enterFromSideTranslationX)
+ .isEqualTo(
+ StateToValue(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.RUNNING,
+ value = 0f
+ )
+ )
+ }
+
+ @Test
fun enterFromTopAnimationAlpha() =
testScope.runTest {
val enterFromTopAnimationAlpha by collectLastValue(underTest.enterFromTopAnimationAlpha)
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index cf91326a4b76..40bdc3eb50f8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -810,6 +810,8 @@
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
<!-- The amount to translate lockscreen elements on the GONE->AOD transition -->
<dimen name="keyguard_enter_from_top_translation_y">-100dp</dimen>
+ <!-- The amount to translate lockscreen elements on the GONE->AOD transition, on device fold -->
+ <dimen name="keyguard_enter_from_side_translation_x">-100dp</dimen>
<dimen name="notification_scrim_corner_radius">32dp</dimen>
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 f30eef080ede..35a2d58816b4 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
@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason.FOLD
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.ShadeRepository
@@ -368,7 +369,12 @@ constructor(
// being delayed in KeyguardViewMediator
KeyguardState.DREAMING -> TO_DREAMING_DURATION + 100.milliseconds
KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
- KeyguardState.AOD -> TO_AOD_DURATION
+ KeyguardState.AOD ->
+ if (powerInteractor.detailedWakefulness.value.lastSleepReason == FOLD) {
+ TO_AOD_FOLD_DURATION
+ } else {
+ TO_AOD_DURATION
+ }
KeyguardState.DOZING -> TO_DOZING_DURATION
KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> TO_DREAMING_HOSTED_DURATION
KeyguardState.GLANCEABLE_HUB -> TO_GLANCEABLE_HUB_DURATION
@@ -385,6 +391,7 @@ constructor(
val TO_DREAMING_HOSTED_DURATION = 933.milliseconds
val TO_OCCLUDED_DURATION = 450.milliseconds
val TO_AOD_DURATION = 500.milliseconds
+ val TO_AOD_FOLD_DURATION = 1100.milliseconds
val TO_PRIMARY_BOUNCER_DURATION = DEFAULT_DURATION
val TO_GONE_DURATION = 633.milliseconds
val TO_GLANCEABLE_HUB_DURATION = 1.seconds
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
index 6729246dcb7a..21b9e537cc18 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
@@ -16,30 +16,17 @@
package com.android.systemui.keyguard.domain.interactor
-import android.animation.ValueAnimator
import android.view.ViewGroup
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.TransitionInfo
-import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.ShadeFoldAnimator
import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
@SysUISingleton
class ToAodFoldTransitionInteractor
@Inject
constructor(
private val keyguardClockInteractor: KeyguardClockInteractor,
- private val transitionInteractor: KeyguardTransitionInteractor,
- private val transitionRepository: KeyguardTransitionRepository,
- @Application private val mainScope: CoroutineScope,
- @Main private val mainDispatcher: CoroutineDispatcher,
) {
private var parentAnimator: NotificationPanelViewController.ShadeFoldAnimatorImpl? = null
@@ -50,7 +37,6 @@ constructor(
get() = throw NotImplementedError("Deprecated. Do not call.")
override fun prepareFoldToAodAnimation() {
- forceToAod()
parentAnimator?.prepareFoldToAodAnimation()
}
@@ -78,21 +64,6 @@ constructor(
parentAnimator as? NotificationPanelViewController.ShadeFoldAnimatorImpl?
}
- /** Forces the keyguard into AOD or Doze */
- private fun forceToAod() {
- mainScope.launch(mainDispatcher) {
- transitionRepository.startTransition(
- TransitionInfo(
- "$TAG (Fold transition triggered)",
- transitionInteractor.getCurrentState(),
- transitionInteractor.asleepKeyguardState.value,
- ValueAnimator().apply { duration = 0 },
- TransitionModeOnCanceled.LAST_VALUE,
- )
- )
- }
- }
-
companion object {
private val TAG = ToAodFoldTransitionInteractor::class.simpleName!!
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
index d9a6d6401d64..62b47827fe8a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
@@ -55,6 +55,7 @@ constructor(
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
+ private val lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
private val keyguardClockViewModel: KeyguardClockViewModel,
@@ -74,13 +75,30 @@ constructor(
burnInParams
}
return configurationInteractor
- .dimensionPixelSize(R.dimen.keyguard_enter_from_top_translation_y)
- .flatMapLatest { enterFromTopAmount ->
+ .dimensionPixelSize(
+ setOf(
+ R.dimen.keyguard_enter_from_top_translation_y,
+ R.dimen.keyguard_enter_from_side_translation_x,
+ )
+ )
+ .flatMapLatest { dimens ->
combine(
keyguardInteractor.keyguardTranslationY.onStart { emit(0f) },
burnIn(params).onStart { emit(BurnInModel()) },
goneToAodTransitionViewModel
- .enterFromTopTranslationY(enterFromTopAmount)
+ .enterFromTopTranslationY(
+ dimens[R.dimen.keyguard_enter_from_top_translation_y]!!
+ )
+ .onStart { emit(StateToValue()) },
+ goneToAodTransitionViewModel
+ .enterFromSideTranslationX(
+ dimens[R.dimen.keyguard_enter_from_side_translation_x]!!
+ )
+ .onStart { emit(StateToValue()) },
+ lockscreenToAodTransitionViewModel
+ .enterFromSideTranslationX(
+ dimens[R.dimen.keyguard_enter_from_side_translation_x]!!
+ )
.onStart { emit(StateToValue()) },
occludedToLockscreenTransitionViewModel.lockscreenTranslationY.onStart {
emit(0f)
@@ -88,21 +106,31 @@ constructor(
aodToLockscreenTransitionViewModel.translationY(params.translationY).onStart {
emit(StateToValue())
},
- ) {
- keyguardTranslationY,
- burnInModel,
- goneToAod,
- occludedToLockscreen,
- aodToLockscreen ->
+ ) { flows ->
+ val keyguardTranslationY = flows[0] as Float
+ val burnInModel = flows[1] as BurnInModel
+ val goneToAodTranslationY = flows[2] as StateToValue
+ val goneToAodTranslationX = flows[3] as StateToValue
+ val lockscreenToAodTranslationX = flows[4] as StateToValue
+ val occludedToLockscreen = flows[5] as Float
+ val aodToLockscreen = flows[6] as StateToValue
+
val translationY =
if (aodToLockscreen.transitionState.isTransitioning()) {
aodToLockscreen.value ?: 0f
- } else if (goneToAod.transitionState.isTransitioning()) {
- (goneToAod.value ?: 0f) + burnInModel.translationY
+ } else if (goneToAodTranslationY.transitionState.isTransitioning()) {
+ (goneToAodTranslationY.value ?: 0f) + burnInModel.translationY
} else {
burnInModel.translationY + occludedToLockscreen + keyguardTranslationY
}
- burnInModel.copy(translationY = translationY.toInt())
+ val translationX =
+ burnInModel.translationX +
+ (goneToAodTranslationX.value ?: 0f) +
+ (lockscreenToAodTranslationX.value ?: 0f)
+ burnInModel.copy(
+ translationX = translationX.toInt(),
+ translationY = translationY.toInt(),
+ )
}
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
index 74f7d75fa326..2bc8e51a64f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
@@ -26,13 +26,17 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.StateToValue
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason.FOLD
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.transform
/** Breaks down GONE->AOD transition into discrete steps for corresponding views to consume. */
@ExperimentalCoroutinesApi
@@ -41,6 +45,7 @@ class GoneToAodTransitionViewModel
@Inject
constructor(
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ private val powerInteractor: PowerInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
@@ -56,13 +61,38 @@ constructor(
/** y-translation from the top of the screen for AOD */
fun enterFromTopTranslationY(translatePx: Int): Flow<StateToValue> {
- return transitionAnimation.sharedFlowWithState(
- startTime = 600.milliseconds,
- duration = 500.milliseconds,
- onStep = { translatePx + it * -translatePx },
- onFinish = { 0f },
- interpolator = EMPHASIZED_DECELERATE,
- )
+ return transitionAnimation
+ .sharedFlowWithState(
+ startTime = 600.milliseconds,
+ duration = 500.milliseconds,
+ onStep = { translatePx + it * -translatePx },
+ onFinish = { 0f },
+ interpolator = EMPHASIZED_DECELERATE,
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (stateToValue, wakefulness) ->
+ if (wakefulness.lastSleepReason != FOLD) {
+ emit(stateToValue)
+ }
+ }
+ }
+
+ /** x-translation from the side of the screen for fold animation */
+ fun enterFromSideTranslationX(translatePx: Int): Flow<StateToValue> {
+ return transitionAnimation
+ .sharedFlowWithState(
+ startTime = 500.milliseconds,
+ duration = 600.milliseconds,
+ onStep = { translatePx + it * -translatePx },
+ onFinish = { 0f },
+ interpolator = EMPHASIZED_DECELERATE,
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (stateToValue, wakefulness) ->
+ if (wakefulness.lastSleepReason == FOLD) {
+ emit(stateToValue)
+ }
+ }
}
val notificationAlpha: Flow<Float> =
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 aefff7d0f79b..d7ac976ec00f 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
@@ -251,6 +251,7 @@ constructor(
goneToDreamingTransitionViewModel.lockscreenAlpha,
goneToLockscreenTransitionViewModel.lockscreenAlpha,
lockscreenToAodTransitionViewModel.lockscreenAlpha(viewState),
+ lockscreenToAodTransitionViewModel.lockscreenAlphaOnFold,
lockscreenToDozingTransitionViewModel.lockscreenAlpha,
lockscreenToDreamingTransitionViewModel.lockscreenAlpha,
lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
index 8b5b347a763d..5408428c7072 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel
import android.util.MathUtils
+import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
@@ -24,12 +25,17 @@ import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.StateToValue
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason.FOLD
+import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.transform
/**
* Breaks down LOCKSCREEN->AOD transition into discrete steps for corresponding views to consume.
@@ -40,6 +46,7 @@ class LockscreenToAodTransitionViewModel
@Inject
constructor(
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ private val powerInteractor: PowerInteractor,
shadeDependentFlows: ShadeDependentFlows,
animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
@@ -50,6 +57,12 @@ constructor(
edge = Edge.create(from = LOCKSCREEN, to = AOD),
)
+ private val transitionAnimationOnFold =
+ animationFlow.setup(
+ duration = FromLockscreenTransitionInteractor.TO_AOD_FOLD_DURATION,
+ edge = Edge.create(from = LOCKSCREEN, to = AOD),
+ )
+
val deviceEntryBackgroundViewAlpha: Flow<Float> =
shadeDependentFlows.transitionFlow(
flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
@@ -71,11 +84,64 @@ constructor(
fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> {
var startAlpha = 1f
- return transitionAnimation.sharedFlow(
- duration = 500.milliseconds,
- onStart = { startAlpha = viewState.alpha() },
- onStep = { MathUtils.lerp(startAlpha, 1f, it) },
- )
+ return transitionAnimation
+ .sharedFlow(
+ duration = 500.milliseconds,
+ onStart = { startAlpha = viewState.alpha() },
+ onStep = { MathUtils.lerp(startAlpha, 1f, it) },
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (alpha, wakefulness) ->
+ if (wakefulness.lastSleepReason != FOLD) {
+ emit(alpha)
+ }
+ }
+ }
+
+ val lockscreenAlphaOnFold: Flow<Float> =
+ transitionAnimationOnFold
+ .sharedFlow(
+ startTime = 600.milliseconds,
+ duration = 500.milliseconds,
+ onStep = { it },
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (alpha, wakefulness) ->
+ if (wakefulness.lastSleepReason == FOLD) {
+ emit(alpha)
+ }
+ }
+
+ val notificationAlphaOnFold: Flow<Float> =
+ transitionAnimationOnFold
+ .sharedFlow(
+ duration = 1100.milliseconds,
+ onStep = { 0f },
+ onFinish = { 1f },
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (alpha, wakefulness) ->
+ if (wakefulness.lastSleepReason == FOLD) {
+ emit(alpha)
+ }
+ }
+
+ /** x-translation from the side of the screen for fold animation */
+ fun enterFromSideTranslationX(translatePx: Int): Flow<StateToValue> {
+ return transitionAnimationOnFold
+ .sharedFlowWithState(
+ startTime = 600.milliseconds,
+ duration = 500.milliseconds,
+ onStep = { translatePx + it * -translatePx },
+ onFinish = { 0f },
+ interpolator = EMPHASIZED_DECELERATE,
+ )
+ .sample(powerInteractor.detailedWakefulness, ::Pair)
+ .transform { (stateToValue, wakefulness) ->
+ if (wakefulness.lastSleepReason == FOLD) {
+ emit(stateToValue)
+ }
+ }
}
override val deviceEntryParentViewAlpha: Flow<Float> =
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelKosmos.kt
index 6f168d47038d..6cf668c50fa4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelKosmos.kt
@@ -33,6 +33,7 @@ var Kosmos.aodBurnInViewModel by Fixture {
keyguardInteractor = keyguardInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
goneToAodTransitionViewModel = goneToAodTransitionViewModel,
+ lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel,
aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
keyguardClockViewModel = keyguardClockViewModel,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
index 19e4241c62fa..8549a30c346e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelKosmos.kt
@@ -22,11 +22,13 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsIntera
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.power.domain.interactor.powerInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
var Kosmos.goneToAodTransitionViewModel by Fixture {
GoneToAodTransitionViewModel(
deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ powerInteractor = powerInteractor,
animationFlow = keyguardTransitionAnimationFlow,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt
index 07b4cd4f3251..f45e33bf6865 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelKosmos.kt
@@ -22,11 +22,13 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsIntera
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.power.domain.interactor.powerInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
-val Kosmos.lockscreenToAodTransitionViewModel by Fixture {
+var Kosmos.lockscreenToAodTransitionViewModel by Fixture {
LockscreenToAodTransitionViewModel(
deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ powerInteractor = powerInteractor,
shadeDependentFlows = shadeDependentFlows,
animationFlow = keyguardTransitionAnimationFlow,
)