Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8d6c64b authored by Aurélien Pomini's avatar Aurélien Pomini
Browse files

Introduce a lock screen fadeout, adjust timings

Instead of just fading in the home wallpaper in front of the lock
wallpaper, introduce a crossfade.

The "wallpaperTargets", representing the wallpaper on home screen, has
been renamed to "openingWallpaperTargets". A similar
"closingWallpaperTargets" has been added for the lock screen wallpaper
that goes away.

Also make a similar transition when the keyguard is dismissed with a
swipe.

Restore some constants that were (wrongly!) changed under the flag.

Flag: com.android.systemui.faster_unlock_transition
Bug: 298186160
Test: manual, keyguard tests
Change-Id: I8e53fbb6f4d9949c712862dd5a3519d722a3dc8e
parent 12ea3162
Loading
Loading
Loading
Loading
+68 −26
Original line number Diff line number Diff line
@@ -104,6 +104,13 @@ const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.3f
const val LEGACY_UNLOCK_ANIMATION_DURATION_MS = 200L
const val UNLOCK_ANIMATION_DURATION_MS = 167L

/**
 * If there are two different wallpapers on home and lock screen, duration and delay of the lock
 * wallpaper fade out.
 */
const val LOCK_WALLPAPER_FADE_OUT_DURATION = 140L
const val LOCK_WALLPAPER_FADE_OUT_START_DELAY = 0L

/**
 * How long the in-window launcher icon animation takes. This is used if the launcher is underneath
 * the lock screen and supports in-window animations.
@@ -115,23 +122,24 @@ const val LAUNCHER_ICONS_ANIMATION_DURATION_MS = 633L

/**
 * How long to wait for the shade to get out of the way before starting the canned unlock animation.
 * If there are two different wallpapers on home and lock screen, this is also the duration and
 * delay of the home wallpaper fade in.
 */
const val LEGACY_CANNED_UNLOCK_START_DELAY = 100L
const val CANNED_UNLOCK_START_DELAY = 67L
const val CANNED_UNLOCK_START_DELAY = 25L

/**
 * Duration for the alpha animation on the surface behind. This plays to fade in the surface during
 * a swipe to unlock (and to fade it back out if the swipe is cancelled).
 */
const val LEGACY_SURFACE_BEHIND_SWIPE_FADE_DURATION_MS = 175L
const val SURFACE_BEHIND_FADE_OUT_DURATION_MS = 83L
const val SURFACE_BEHIND_SWIPE_FADE_DURATION_MS = 175L

/**
 * Start delay for the surface behind animation, used so that the lockscreen can get out of the way
 * before the surface begins appearing.
 */
const val LEGACY_UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
const val SURFACE_BEHIND_FADE_OUT_START_DELAY_MS = 0L
const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 67L

/**
 * Initiates, controls, and ends the keyguard unlock animation.
@@ -268,7 +276,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
    @VisibleForTesting
    var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null
    private var surfaceBehindRemoteAnimationTargets: Array<RemoteAnimationTarget>? = null
    private var wallpaperTargets: Array<RemoteAnimationTarget>? = null
    private var openingWallpaperTargets: Array<RemoteAnimationTarget>? = null
    private var closingWallpaperTargets: Array<RemoteAnimationTarget>? = null
    private var surfaceBehindRemoteAnimationStartTime: Long = 0

    /**
@@ -286,6 +295,8 @@ class KeyguardUnlockAnimationController @Inject constructor(

    var wallpaperCannedUnlockAnimator = ValueAnimator.ofFloat(0f, 1f)

    var wallpaperFadeOutUnlockAnimator = ValueAnimator.ofFloat(1f, 0f)

    /**
     * Matrix applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the
     * app/launcher behind the keyguard.
@@ -335,7 +346,7 @@ class KeyguardUnlockAnimationController @Inject constructor(

    init {
        with(surfaceBehindAlphaAnimator) {
            duration = surfaceBehindFadeOutDurationMs()
            duration = SURFACE_BEHIND_SWIPE_FADE_DURATION_MS
            interpolator = Interpolators.LINEAR
            addUpdateListener { valueAnimator: ValueAnimator ->
                surfaceBehindAlpha = valueAnimator.animatedValue as Float
@@ -351,7 +362,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
                    if (surfaceBehindAlpha == 0f) {
                        Log.d(TAG, "surfaceBehindAlphaAnimator#onAnimationEnd")
                        surfaceBehindRemoteAnimationTargets = null
                        wallpaperTargets = null
                        openingWallpaperTargets = null
                        closingWallpaperTargets = null
                        keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation(
                            false /* cancelled */)
                    } else {
@@ -367,8 +379,10 @@ class KeyguardUnlockAnimationController @Inject constructor(
                    else LAUNCHER_ICONS_ANIMATION_DURATION_MS
            interpolator = if (fasterUnlockTransition()) Interpolators.LINEAR
                    else Interpolators.ALPHA_OUT
            if (fasterUnlockTransition()) startDelay = CANNED_UNLOCK_START_DELAY
            addUpdateListener { valueAnimator: ValueAnimator ->
                setWallpaperAppearAmount(valueAnimator.animatedValue as Float)
                setWallpaperAppearAmount(
                        valueAnimator.animatedValue as Float, openingWallpaperTargets)
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
@@ -379,6 +393,18 @@ class KeyguardUnlockAnimationController @Inject constructor(
            })
        }

        if (fasterUnlockTransition()) {
            with(wallpaperFadeOutUnlockAnimator) {
                duration = LOCK_WALLPAPER_FADE_OUT_DURATION
                startDelay = LOCK_WALLPAPER_FADE_OUT_START_DELAY
                interpolator = Interpolators.LINEAR
                addUpdateListener { valueAnimator: ValueAnimator ->
                    setWallpaperAppearAmount(
                            valueAnimator.animatedValue as Float, closingWallpaperTargets)
                }
            }
        }

        with(surfaceBehindEntryAnimator) {
            duration = unlockAnimationDurationMs()
            startDelay = surfaceBehindFadeOutStartDelayMs()
@@ -546,7 +572,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
     */
    fun notifyStartSurfaceBehindRemoteAnimation(
        targets: Array<RemoteAnimationTarget>,
        wallpapers: Array<RemoteAnimationTarget>,
        openingWallpapers: Array<RemoteAnimationTarget>,
        closingWallpapers: Array<RemoteAnimationTarget>,
        startTime: Long,
        requestedShowSurfaceBehindKeyguard: Boolean
    ) {
@@ -556,7 +583,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
        }

        surfaceBehindRemoteAnimationTargets = targets
        wallpaperTargets = wallpapers
        openingWallpaperTargets = openingWallpapers
        closingWallpaperTargets = closingWallpapers
        surfaceBehindRemoteAnimationStartTime = startTime

        // If we specifically requested that the surface behind be made visible (vs. it being made
@@ -720,8 +748,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
                return@postDelayed
            }

            if ((wallpaperTargets?.isNotEmpty() == true)) {
            if ((openingWallpaperTargets?.isNotEmpty() == true)) {
                fadeInWallpaper()
                if (fasterUnlockTransition()) fadeOutWallpaper()
                hideKeyguardViewAfterRemoteAnimation()
            } else {
                keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
@@ -855,7 +884,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
    /**
     * Scales in and translates up the surface behind the keyguard. This is used during unlock
     * animations and swipe gestures to animate the surface's entry (and exit, if the swipe is
     * cancelled).
     * cancelled). When called with [wallpapers]=true, if there are different home and lock screen
     * wallpapers, this transitions between the two wallpapers
     */
    fun setSurfaceBehindAppearAmount(amount: Float, wallpapers: Boolean = true) {
        val animationAlpha = when {
@@ -923,13 +953,27 @@ class KeyguardUnlockAnimationController @Inject constructor(
        }

        if (wallpapers) {
            setWallpaperAppearAmount(amount)
            if (!fasterUnlockTransition()) setWallpaperAppearAmount(amount, openingWallpaperTargets)
            else {
                // Use the amount to compute the fadeInAmount and fadeOutAmount of the home and lock
                // screen wallpapers to manually imitate the canned unlock animation.
                val total = (UNLOCK_ANIMATION_DURATION_MS + CANNED_UNLOCK_START_DELAY).toFloat()
                val fadeInStart = CANNED_UNLOCK_START_DELAY / total
                val fadeInAmount = maxOf(0f, (amount - fadeInStart) / (1f - fadeInStart))

                val fadeOutStart = LOCK_WALLPAPER_FADE_OUT_START_DELAY / total
                val fadeOutEnd = fadeOutStart + LOCK_WALLPAPER_FADE_OUT_DURATION / total
                val fadeOutAmount = ((amount - fadeOutStart) / (fadeOutEnd - fadeOutStart))
                        .coerceIn(0f, 1f)

                setWallpaperAppearAmount(fadeInAmount, openingWallpaperTargets)
                setWallpaperAppearAmount(1 - fadeOutAmount, closingWallpaperTargets)
            }
        }
    }

    fun setWallpaperAppearAmount(amount: Float) {
    fun setWallpaperAppearAmount(amount: Float, wallpaperTargets: Array<RemoteAnimationTarget>?) {
        val animationAlpha = amount

        wallpaperTargets?.forEach { wallpaper ->
            // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
            // unable to draw
@@ -991,7 +1035,8 @@ class KeyguardUnlockAnimationController @Inject constructor(

        // That target is no longer valid since the animation finished, null it out.
        surfaceBehindRemoteAnimationTargets = null
        wallpaperTargets = null
        openingWallpaperTargets = null
        if (fasterUnlockTransition()) closingWallpaperTargets = null

        playingCannedUnlockAnimation = false
        dismissAmountThresholdsReached = false
@@ -1035,6 +1080,12 @@ class KeyguardUnlockAnimationController @Inject constructor(
        wallpaperCannedUnlockAnimator.start()
    }

    private fun fadeOutWallpaper() {
        Log.d(TAG, "fadeOutWallpaper")
        wallpaperFadeOutUnlockAnimator.cancel()
        wallpaperFadeOutUnlockAnimator.start()
    }

    private fun fadeOutSurfaceBehind() {
        Log.d(TAG, "fadeOutSurfaceBehind")
        surfaceBehindAlphaAnimator.cancel()
@@ -1161,21 +1212,12 @@ class KeyguardUnlockAnimationController @Inject constructor(
                else LEGACY_UNLOCK_ANIMATION_DURATION_MS
    }

    /**
     * Temporary method for b/298186160
     * TODO (b/298186160) replace references with the constant itself when flag is removed
     */
    private fun surfaceBehindFadeOutDurationMs(): Long {
        return if (fasterUnlockTransition()) SURFACE_BEHIND_FADE_OUT_DURATION_MS
                else LEGACY_SURFACE_BEHIND_SWIPE_FADE_DURATION_MS
    }

    /**
     * Temporary method for b/298186160
     * TODO (b/298186160) replace references with the constant itself when flag is removed
     */
    private fun surfaceBehindFadeOutStartDelayMs(): Long {
        return if (fasterUnlockTransition()) SURFACE_BEHIND_FADE_OUT_START_DELAY_MS
        return if (fasterUnlockTransition()) UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS
                else LEGACY_UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS
    }

+5 −1
Original line number Diff line number Diff line
@@ -3143,9 +3143,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                        w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray(
                        RemoteAnimationTarget[]::new);

                RemoteAnimationTarget[] closingWallpapers = Arrays.stream(wallpapers).filter(
                        w -> w.mode == RemoteAnimationTarget.MODE_CLOSING).toArray(
                        RemoteAnimationTarget[]::new);

                mKeyguardUnlockAnimationControllerLazy.get()
                        .notifyStartSurfaceBehindRemoteAnimation(
                                openingApps, openingWallpapers, startTime,
                                openingApps, openingWallpapers, closingWallpapers, startTime,
                                mSurfaceBehindRemoteAnimationRequested);
            } else {
                mInteractionJankMonitor.begin(
+72 −4
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import android.graphics.Point
import android.graphics.Rect
import android.os.PowerManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import android.view.RemoteAnimationTarget
import android.view.SurfaceControl
@@ -99,6 +100,13 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
            mock(ActivityManager.RunningTaskInfo::class.java), false)
    private lateinit var wallpaperTargets: Array<RemoteAnimationTarget>

    private var surfaceControlLockWp = mock(SurfaceControl::class.java)
    private var lockWallpaperTarget = RemoteAnimationTarget(
            3 /* taskId */, 0, surfaceControlLockWp, false, Rect(), Rect(), 0, Point(), Rect(),
            Rect(), mock(WindowConfiguration::class.java), false, surfaceControlLockWp,
            Rect(), mock(ActivityManager.RunningTaskInfo::class.java), false)
    private lateinit var lockWallpaperTargets: Array<RemoteAnimationTarget>

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
@@ -118,6 +126,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        // appear amount setter doesn't short circuit.
        remoteAnimationTargets = arrayOf(remoteTarget1)
        wallpaperTargets = arrayOf(wallpaperTarget)
        lockWallpaperTargets = arrayOf(lockWallpaperTarget)

        // Set the surface applier to our mock so that we can verify the arguments passed to it.
        // This applier does not have any side effects within the unlock animation controller, so
@@ -144,6 +153,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            arrayOf(),
            arrayOf(),
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -177,6 +187,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -199,6 +210,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -219,6 +231,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -242,6 +255,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -265,6 +279,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -286,6 +301,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -301,6 +317,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
            wallpaperTargets,
            arrayOf(),
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -317,6 +334,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                remoteAnimationTargets,
                wallpaperTargets,
                arrayOf(),
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -324,6 +342,53 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        assertTrue(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation())
    }

    /**
     * The canned animation should launch a cross fade when there are different wallpapers on lock
     * and home screen.
     */
    @Test
    @EnableFlags(Flags.FLAG_FASTER_UNLOCK_TRANSITION)
    fun manualUnlock_multipleWallpapers() {
        var lastFadeInAlpha = -1f
        var lastFadeOutAlpha = -1f

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                arrayOf(remoteTarget1, remoteTarget2),
                wallpaperTargets,
                lockWallpaperTargets,
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )

        for (i in 0..10) {
            clearInvocations(surfaceTransactionApplier)
            val amount = i / 10f

            keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(amount)

            val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>()
            verify(surfaceTransactionApplier, times(2)).scheduleApply(
                    captorSb.capture { sp ->
                        sp.surface == surfaceControlWp || sp.surface == surfaceControlLockWp })

            val fadeInAlpha = captorSb.getLastValue { it.surface == surfaceControlWp }.alpha
            val fadeOutAlpha = captorSb.getLastValue { it.surface == surfaceControlLockWp }.alpha

            if (amount == 0f) {
                assertTrue (fadeInAlpha == 0f)
                assertTrue (fadeOutAlpha == 1f)
            } else if (amount == 1f) {
                assertTrue (fadeInAlpha == 1f)
                assertTrue (fadeOutAlpha == 0f)
            } else {
                assertTrue(fadeInAlpha >= lastFadeInAlpha)
                assertTrue(fadeOutAlpha <= lastFadeOutAlpha)
            }
            lastFadeInAlpha = fadeInAlpha
            lastFadeOutAlpha = fadeOutAlpha
        }
    }

    /**
     * If we are not wake and unlocking, we expect the unlock animation to play normally.
     */
@@ -333,6 +398,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                arrayOf(remoteTarget1, remoteTarget2),
                wallpaperTargets,
                arrayOf(),
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -378,6 +444,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                remoteAnimationTargets,
                wallpaperTargets,
                arrayOf(),
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -387,7 +454,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        clearInvocations(surfaceTransactionApplier)

        keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)
        keyguardUnlockAnimationController.setWallpaperAppearAmount(1f)
        keyguardUnlockAnimationController.setWallpaperAppearAmount(1f, wallpaperTargets)

        val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>()
        verify(surfaceTransactionApplier, times(1)).scheduleApply(
@@ -414,6 +481,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                remoteAnimationTargets,
                wallpaperTargets,
                arrayOf(),
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -423,7 +491,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        clearInvocations(surfaceTransactionApplier)

        keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)
        keyguardUnlockAnimationController.setWallpaperAppearAmount(1f)
        keyguardUnlockAnimationController.setWallpaperAppearAmount(1f, wallpaperTargets)

        val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>()
        verify(surfaceTransactionApplier, times(1)).scheduleApply(
@@ -532,8 +600,8 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
            }
        }

        fun getLastValue(): T {
            return allArgs.last()
        fun getLastValue(predicate: Predicate<T>? = null): T {
            return if (predicate != null) allArgs.last(predicate::test) else allArgs.last()
        }

        fun getAllValues(): List<T> {