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

Commit 76746773 authored by Josh Tsuji's avatar Josh Tsuji
Browse files

Override alpha to 0f if we're no longer interactive.

This is a safe way to ensure the surface is immediately
no longer visible, until the screen off lifecycle event
arrives and ends up canceling the unlock sequence and
sleeping the device. WM resets the surface alpha after
the animation ends, so this should be safe.

Since the surface alpha is usually close to 0f when this
condition is met, it's not usually perceptible that we
jump-cut to 0f.

Test: press the power button while also triggering an unlock
Test: atest KeyguardUnlockAnimationControllerTest
Bug: 260094933
Change-Id: I15a9decf1dcfac0b60b3f4e97a2e470098961743
parent f1f50ee2
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Context
import android.graphics.Matrix
import android.graphics.Rect
import android.os.Handler
import android.os.PowerManager
import android.os.RemoteException
import android.util.Log
import android.view.RemoteAnimationTarget
@@ -145,7 +146,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
    private val featureFlags: FeatureFlags,
    private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
    private val statusBarStateController: SysuiStatusBarStateController,
    private val notificationShadeWindowController: NotificationShadeWindowController
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val powerManager: PowerManager
) : KeyguardStateController.Callback, ISysuiUnlockAnimationController.Stub() {

    interface KeyguardUnlockAnimationListener {
@@ -783,10 +785,15 @@ class KeyguardUnlockAnimationController @Inject constructor(
                    surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y
            )


            val animationAlpha = when {
                // If we're snapping the keyguard back, immediately begin fading it out.
            val animationAlpha =
                    if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount
                    else surfaceBehindAlpha
                keyguardStateController.isSnappingKeyguardBackAfterSwipe -> amount
                // If the screen has turned back off, the unlock animation is going to be cancelled,
                // so set the surface alpha to 0f so it's no longer visible.
                !powerManager.isInteractive -> 0f
                else -> surfaceBehindAlpha
            }

            // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
            // unable to draw
+65 −8
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import android.app.ActivityManager
import android.app.WindowConfiguration
import android.graphics.Point
import android.graphics.Rect
import android.os.PowerManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.RemoteAnimationTarget
@@ -19,15 +20,16 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor.forClass
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -56,6 +58,8 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
    private lateinit var statusBarStateController: SysuiStatusBarStateController
    @Mock
    private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock
    private lateinit var powerManager: PowerManager

    @Mock
    private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController.Stub
@@ -79,12 +83,13 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController = KeyguardUnlockAnimationController(
            context, keyguardStateController, { keyguardViewMediator }, keyguardViewController,
            featureFlags, { biometricUnlockController }, statusBarStateController,
            notificationShadeWindowController
            notificationShadeWindowController, powerManager
        )
        keyguardUnlockAnimationController.setLauncherUnlockController(
            launcherUnlockAnimationController)

        `when`(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
        whenever(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
        whenever(powerManager.isInteractive).thenReturn(true)

        // All of these fields are final, so we can't mock them, but are needed so that the surface
        // appear amount setter doesn't short circuit.
@@ -96,6 +101,12 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.surfaceTransactionApplier = surfaceTransactionApplier
    }

    @After
    fun tearDown() {
        keyguardUnlockAnimationController.surfaceBehindEntryAnimator.cancel()
        keyguardUnlockAnimationController.surfaceBehindAlphaAnimator.cancel()
    }

    /**
     * If we're wake and unlocking, we are animating from the black/AOD screen to the app/launcher
     * underneath. The LightRevealScrim will animate circularly from the fingerprint reader,
@@ -104,7 +115,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
     */
    @Test
    fun noSurfaceAnimation_ifWakeAndUnlocking() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
        whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
@@ -135,7 +146,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
     */
    @Test
    fun surfaceAnimation_ifNotWakeAndUnlocking() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false)
        whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
@@ -159,7 +170,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
     */
    @Test
    fun fadeInSurfaceBehind_ifRequestedShowSurface_butNotFlinging() {
        `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false)
        whenever(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
@@ -181,7 +192,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
     */
    @Test
    fun playCannedUnlockAnimation_ifRequestedShowSurface_andFlinging() {
        `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true)
        whenever(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
@@ -215,7 +226,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {

    @Test
    fun doNotPlayCannedUnlockAnimation_ifLaunchingApp() {
        `when`(notificationShadeWindowController.isLaunchingActivity).thenReturn(true)
        whenever(notificationShadeWindowController.isLaunchingActivity).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTargets,
@@ -275,4 +286,50 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
                false /* cancelled */)
    }

    @Test
    fun surfaceBehindAlphaOverriddenTo0_ifNotInteractive() {
        whenever(powerManager.isInteractive).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                remoteAnimationTargets,
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )

        keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)

        val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java)
        verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture())

        val params = captor.value

        // We expect that we've set the surface behind to alpha = 0f since we're not interactive.
        assertEquals(params.alpha, 0f)
        assertTrue(params.matrix.isIdentity)

        verifyNoMoreInteractions(surfaceTransactionApplier)
    }

    @Test
    fun surfaceBehindAlphaNotOverriddenTo0_ifInteractive() {
        whenever(powerManager.isInteractive).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                remoteAnimationTargets,
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )

        keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)

        val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java)
        verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture())

        val params = captor.value
        assertEquals(params.alpha, 1f)
        assertTrue(params.matrix.isIdentity)

        verifyNoMoreInteractions(surfaceTransactionApplier)
    }
}