Loading packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt +123 −2 Original line number Diff line number Diff line Loading @@ -396,7 +396,7 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest : .onDozeAmountChanged( eq(.3f), eq(.3f), eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF) eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) transitionRepository.sendTransitionStep( Loading @@ -413,9 +413,130 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest : .onDozeAmountChanged( eq(1f), eq(1f), eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF) eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) job.cancel() } @Test fun aodToOccluded_dozeAmountChanged() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForAodToOccludedTransitions(this) // WHEN transitioning from aod to occluded transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.OCCLUDED, value = .3f, transitionState = TransitionState.RUNNING ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged(eq(.7f), eq(.7f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.OCCLUDED, value = 1f, transitionState = TransitionState.FINISHED ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) job.cancel() } @Test fun occludedToAod_dozeAmountChanged() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForOccludedToAodTransition(this) // WHEN transitioning from occluded to aod transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.OCCLUDED, to = KeyguardState.AOD, value = .3f, transitionState = TransitionState.RUNNING ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged( eq(.3f), eq(.3f), eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.OCCLUDED, to = KeyguardState.AOD, value = 1f, transitionState = TransitionState.FINISHED ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged( eq(1f), eq(1f), eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) job.cancel() } @Test fun cancelledAodToLockscreen_dozeAmountChangedToZero() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForLockscreenAodTransitions(this) // WHEN aod to lockscreen transition is cancelled transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, value = 1f, transitionState = TransitionState.CANCELED ) ) runCurrent() // ... and WHEN the next transition is from lockscreen => occluded transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.LOCKSCREEN, to = KeyguardState.OCCLUDED, value = .4f, transitionState = TransitionState.STARTED ) ) runCurrent() // THEN doze amount is updated to zero verify(mView) .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) job.cancel() } } packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt +55 −8 Original line number Diff line number Diff line Loading @@ -26,11 +26,13 @@ import com.android.app.animation.Interpolators import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.adapter.UdfpsKeyguardViewControllerAdapter import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.statusbar.StatusBarStateController Loading @@ -49,7 +51,7 @@ import java.io.PrintWriter import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch /** Class that coordinates non-HBM animations during keyguard authentication. */ Loading Loading @@ -191,8 +193,38 @@ open class UdfpsKeyguardViewControllerLegacy( repeatOnLifecycle(Lifecycle.State.CREATED) { listenForBouncerExpansion(this) listenForAlternateBouncerVisibility(this) listenForOccludedToAodTransition(this) listenForGoneToAodTransition(this) listenForLockscreenAodTransitions(this) listenForAodToOccludedTransitions(this) } } } @VisibleForTesting suspend fun listenForAodToOccludedTransitions(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED).collect { transitionStep -> view.onDozeAmountChanged( 1f - transitionStep.value, 1f - transitionStep.value, UdfpsKeyguardViewLegacy.ANIMATION_NONE, ) } } } @VisibleForTesting suspend fun listenForOccludedToAodTransition(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.transition(KeyguardState.OCCLUDED, KeyguardState.AOD).collect { transitionStep -> view.onDozeAmountChanged( transitionStep.value, transitionStep.value, ANIMATE_APPEAR_ON_SCREEN_OFF, ) } } } Loading @@ -204,7 +236,7 @@ open class UdfpsKeyguardViewControllerLegacy( view.onDozeAmountChanged( transitionStep.value, transitionStep.value, ANIMATION_UNLOCKED_SCREEN_OFF, ANIMATE_APPEAR_ON_SCREEN_OFF, ) } } Loading @@ -214,6 +246,20 @@ open class UdfpsKeyguardViewControllerLegacy( suspend fun listenForLockscreenAodTransitions(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.dozeAmountTransition.collect { transitionStep -> if (transitionStep.transitionState == TransitionState.CANCELED) { if ( transitionInteractor.startedKeyguardTransitionStep.first().to != KeyguardState.AOD ) { // If the next started transition isn't transitioning back to AOD, force // doze amount to be 0f (as if the transition to the lockscreen completed). view.onDozeAmountChanged( 0f, 0f, UdfpsKeyguardViewLegacy.ANIMATION_NONE, ) } } else { view.onDozeAmountChanged( transitionStep.value, transitionStep.value, Loading @@ -222,6 +268,7 @@ open class UdfpsKeyguardViewControllerLegacy( } } } } @VisibleForTesting override suspend fun listenForBouncerExpansion(scope: CoroutineScope): Job { Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java +4 −4 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { // if we're animating from screen off, we can immediately place the icon in the // AoD-burn in location, else we need to translate the icon from LS => AoD. final float darkAmountForAnimation = mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF final float darkAmountForAnimation = mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF ? 1f : mInterpolatedDarkAmount; final float burnInOffsetX = MathUtils.lerp(0f, getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */) Loading Loading @@ -171,7 +171,7 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { mAnimationType == ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN && (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f); final boolean doneAnimatingUnlockedScreenOff = mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF && (mInterpolatedDarkAmount == 1f); if (doneAnimatingBetweenAodAndLS || doneAnimatingUnlockedScreenOff) { mAnimationType = ANIMATION_NONE; Loading Loading @@ -243,10 +243,10 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { static final int ANIMATION_NONE = 0; static final int ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN = 1; static final int ANIMATION_UNLOCKED_SCREEN_OFF = 2; static final int ANIMATE_APPEAR_ON_SCREEN_OFF = 2; @Retention(RetentionPolicy.SOURCE) @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATION_UNLOCKED_SCREEN_OFF}) @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATE_APPEAR_ON_SCREEN_OFF}) private @interface AnimationType {} void onDozeAmountChanged(float linear, float eased, @AnimationType int animationType) { Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt +123 −2 Original line number Diff line number Diff line Loading @@ -396,7 +396,7 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest : .onDozeAmountChanged( eq(.3f), eq(.3f), eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF) eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) transitionRepository.sendTransitionStep( Loading @@ -413,9 +413,130 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest : .onDozeAmountChanged( eq(1f), eq(1f), eq(UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF) eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) job.cancel() } @Test fun aodToOccluded_dozeAmountChanged() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForAodToOccludedTransitions(this) // WHEN transitioning from aod to occluded transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.OCCLUDED, value = .3f, transitionState = TransitionState.RUNNING ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged(eq(.7f), eq(.7f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.OCCLUDED, value = 1f, transitionState = TransitionState.FINISHED ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) job.cancel() } @Test fun occludedToAod_dozeAmountChanged() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForOccludedToAodTransition(this) // WHEN transitioning from occluded to aod transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.OCCLUDED, to = KeyguardState.AOD, value = .3f, transitionState = TransitionState.RUNNING ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged( eq(.3f), eq(.3f), eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.OCCLUDED, to = KeyguardState.AOD, value = 1f, transitionState = TransitionState.FINISHED ) ) runCurrent() // THEN doze amount is updated verify(mView) .onDozeAmountChanged( eq(1f), eq(1f), eq(UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF) ) job.cancel() } @Test fun cancelledAodToLockscreen_dozeAmountChangedToZero() = testScope.runTest { // GIVEN view is attached mController.onViewAttached() Mockito.reset(mView) val job = mController.listenForLockscreenAodTransitions(this) // WHEN aod to lockscreen transition is cancelled transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, value = 1f, transitionState = TransitionState.CANCELED ) ) runCurrent() // ... and WHEN the next transition is from lockscreen => occluded transitionRepository.sendTransitionStep( TransitionStep( from = KeyguardState.LOCKSCREEN, to = KeyguardState.OCCLUDED, value = .4f, transitionState = TransitionState.STARTED ) ) runCurrent() // THEN doze amount is updated to zero verify(mView) .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE)) job.cancel() } }
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt +55 −8 Original line number Diff line number Diff line Loading @@ -26,11 +26,13 @@ import com.android.app.animation.Interpolators import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATION_UNLOCKED_SCREEN_OFF import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.adapter.UdfpsKeyguardViewControllerAdapter import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.statusbar.StatusBarStateController Loading @@ -49,7 +51,7 @@ import java.io.PrintWriter import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch /** Class that coordinates non-HBM animations during keyguard authentication. */ Loading Loading @@ -191,8 +193,38 @@ open class UdfpsKeyguardViewControllerLegacy( repeatOnLifecycle(Lifecycle.State.CREATED) { listenForBouncerExpansion(this) listenForAlternateBouncerVisibility(this) listenForOccludedToAodTransition(this) listenForGoneToAodTransition(this) listenForLockscreenAodTransitions(this) listenForAodToOccludedTransitions(this) } } } @VisibleForTesting suspend fun listenForAodToOccludedTransitions(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED).collect { transitionStep -> view.onDozeAmountChanged( 1f - transitionStep.value, 1f - transitionStep.value, UdfpsKeyguardViewLegacy.ANIMATION_NONE, ) } } } @VisibleForTesting suspend fun listenForOccludedToAodTransition(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.transition(KeyguardState.OCCLUDED, KeyguardState.AOD).collect { transitionStep -> view.onDozeAmountChanged( transitionStep.value, transitionStep.value, ANIMATE_APPEAR_ON_SCREEN_OFF, ) } } } Loading @@ -204,7 +236,7 @@ open class UdfpsKeyguardViewControllerLegacy( view.onDozeAmountChanged( transitionStep.value, transitionStep.value, ANIMATION_UNLOCKED_SCREEN_OFF, ANIMATE_APPEAR_ON_SCREEN_OFF, ) } } Loading @@ -214,6 +246,20 @@ open class UdfpsKeyguardViewControllerLegacy( suspend fun listenForLockscreenAodTransitions(scope: CoroutineScope): Job { return scope.launch { transitionInteractor.dozeAmountTransition.collect { transitionStep -> if (transitionStep.transitionState == TransitionState.CANCELED) { if ( transitionInteractor.startedKeyguardTransitionStep.first().to != KeyguardState.AOD ) { // If the next started transition isn't transitioning back to AOD, force // doze amount to be 0f (as if the transition to the lockscreen completed). view.onDozeAmountChanged( 0f, 0f, UdfpsKeyguardViewLegacy.ANIMATION_NONE, ) } } else { view.onDozeAmountChanged( transitionStep.value, transitionStep.value, Loading @@ -222,6 +268,7 @@ open class UdfpsKeyguardViewControllerLegacy( } } } } @VisibleForTesting override suspend fun listenForBouncerExpansion(scope: CoroutineScope): Job { Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java +4 −4 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { // if we're animating from screen off, we can immediately place the icon in the // AoD-burn in location, else we need to translate the icon from LS => AoD. final float darkAmountForAnimation = mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF final float darkAmountForAnimation = mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF ? 1f : mInterpolatedDarkAmount; final float burnInOffsetX = MathUtils.lerp(0f, getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */) Loading Loading @@ -171,7 +171,7 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { mAnimationType == ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN && (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f); final boolean doneAnimatingUnlockedScreenOff = mAnimationType == ANIMATION_UNLOCKED_SCREEN_OFF mAnimationType == ANIMATE_APPEAR_ON_SCREEN_OFF && (mInterpolatedDarkAmount == 1f); if (doneAnimatingBetweenAodAndLS || doneAnimatingUnlockedScreenOff) { mAnimationType = ANIMATION_NONE; Loading Loading @@ -243,10 +243,10 @@ public class UdfpsKeyguardViewLegacy extends UdfpsAnimationView { static final int ANIMATION_NONE = 0; static final int ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN = 1; static final int ANIMATION_UNLOCKED_SCREEN_OFF = 2; static final int ANIMATE_APPEAR_ON_SCREEN_OFF = 2; @Retention(RetentionPolicy.SOURCE) @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATION_UNLOCKED_SCREEN_OFF}) @IntDef({ANIMATION_NONE, ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN, ANIMATE_APPEAR_ON_SCREEN_OFF}) private @interface AnimationType {} void onDozeAmountChanged(float linear, float eased, @AnimationType int animationType) { Loading