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

Commit 7761aa3c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix issue where surface was animated while wake and unlocking." into...

Merge "Fix issue where surface was animated while wake and unlocking." into sc-v2-dev am: b024f668

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16466631

Change-Id: I324e663b42e6412c2a450105eff2638850602d5a
parents 2cc9570c b024f668
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Matrix
import android.view.RemoteAnimationTarget
import android.view.SyncRtSurfaceTransactionApplier
import android.view.View
import androidx.annotation.VisibleForTesting
import androidx.core.math.MathUtils
import com.android.internal.R
import com.android.keyguard.KeyguardClockSwitchController
@@ -32,6 +33,7 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Lazy
import javax.inject.Inject
@@ -91,7 +93,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
    private val keyguardViewMediator: Lazy<KeyguardViewMediator>,
    private val keyguardViewController: KeyguardViewController,
    private val smartspaceTransitionController: SmartspaceTransitionController,
    private val featureFlags: FeatureFlags
    private val featureFlags: FeatureFlags,
    private val biometricUnlockController: BiometricUnlockController
) : KeyguardStateController.Callback {

    /**
@@ -105,7 +108,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * If we're unlocking via biometrics, PIN entry, or from clicking a notification, a canned
     * animation is started in [notifyStartKeyguardExitAnimation].
     */
    private var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null
    @VisibleForTesting
    var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null
    private var surfaceBehindRemoteAnimationTarget: RemoteAnimationTarget? = null
    private var surfaceBehindRemoteAnimationStartTime: Long = 0

@@ -132,7 +136,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * Animator that animates in the surface behind the keyguard. This is used to play a canned
     * animation on the surface, if we're not doing a swipe gesture.
     */
    private val surfaceBehindEntryAnimator = ValueAnimator.ofFloat(0f, 1f)
    @VisibleForTesting
    val surfaceBehindEntryAnimator = ValueAnimator.ofFloat(0f, 1f)

    /** Rounded corner radius to apply to the surface behind the keyguard. */
    private var roundedCornerRadius = 0f
@@ -220,8 +225,19 @@ class KeyguardUnlockAnimationController @Inject constructor(
        // to animate it in. Otherwise, the swipe touch events will continue animating it.
        if (!requestedShowSurfaceBehindKeyguard) {
            keyguardViewController.hide(startTime, 350)

            // If we're wake and unlocking, we don't want to animate the surface since we're going
            // to do the light reveal scrim from the black AOD screen. Make it visible and end the
            // remote aimation.
            if (biometricUnlockController.isWakeAndUnlock) {
                setSurfaceBehindAppearAmount(1f)
                keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
                    false /* cancelled */)
            } else {
                // Otherwise, animate it in normally.
                surfaceBehindEntryAnimator.start()
            }
        }

        // Finish the keyguard remote animation if the dismiss amount has crossed the threshold.
        // Check it here in case there is no more change to the dismiss amount after the last change
@@ -264,7 +280,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * animations and swipe gestures to animate the surface's entry (and exit, if the swipe is
     * cancelled).
     */
    private fun setSurfaceBehindAppearAmount(amount: Float) {
    fun setSurfaceBehindAppearAmount(amount: Float) {
        if (surfaceBehindRemoteAnimationTarget == null) {
            return
        }
+134 −0
Original line number Diff line number Diff line
package com.android.systemui.keyguard

import android.app.ActivityManager
import android.app.WindowConfiguration
import android.graphics.Point
import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.RemoteAnimationTarget
import android.view.SurfaceControl
import android.view.SyncRtSurfaceTransactionApplier
import android.view.ViewRootImpl
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardViewController
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
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
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations

@RunWith(AndroidTestingRunner::class)
@RunWithLooper
@SmallTest
class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
    private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController

    @Mock
    private lateinit var keyguardViewMediator: KeyguardViewMediator
    @Mock
    private lateinit var keyguardStateController: KeyguardStateController
    @Mock
    private lateinit var keyguardViewController: KeyguardViewController
    @Mock
    private lateinit var smartspaceTransitionController: SmartspaceTransitionController
    @Mock
    private lateinit var featureFlags: FeatureFlags
    @Mock
    private lateinit var biometricUnlockController: BiometricUnlockController
    @Mock
    private lateinit var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier

    private lateinit var remoteAnimationTarget: RemoteAnimationTarget

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        keyguardUnlockAnimationController = KeyguardUnlockAnimationController(
            context, keyguardStateController, { keyguardViewMediator }, keyguardViewController,
            smartspaceTransitionController, featureFlags, biometricUnlockController
        )

        `when`(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))

        // 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.
        remoteAnimationTarget = RemoteAnimationTarget(
            0, 0, null, false, Rect(), Rect(), 0, Point(), Rect(), Rect(),
            mock(WindowConfiguration::class.java), false, mock(SurfaceControl::class.java), Rect(),
            mock(ActivityManager.RunningTaskInfo::class.java), false)

        // 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
        // this is a reasonable way to test.
        keyguardUnlockAnimationController.surfaceTransactionApplier = surfaceTransactionApplier
    }

    /**
     * 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,
     * revealing the app/launcher below. In this case, we want to make sure we are not animating the
     * surface, or the user will see the wallpaper briefly as the app animates in.
     */
    @Test
    fun noSurfaceAnimation_ifWakeAndUnlocking() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartKeyguardExitAnimation(
            remoteAnimationTarget,
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )

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

        val params = captor.value

        // We expect that we've instantly set the surface behind to alpha = 1f, and have no
        // transforms (translate, scale) on its matrix.
        assertEquals(params.alpha, 1f)
        assertTrue(params.matrix.isIdentity)

        // Also expect we've immediately asked the keyguard view mediator to finish the remote
        // animation.
        verify(keyguardViewMediator, times(1)).onKeyguardExitRemoteAnimationFinished(
            false /* cancelled */)

        verifyNoMoreInteractions(surfaceTransactionApplier)
    }

    /**
     * If we are not wake and unlocking, we expect the unlock animation to play normally.
     */
    @Test
    fun surfaceAnimation_ifNotWakeAndUnlocking() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartKeyguardExitAnimation(
            remoteAnimationTarget,
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )

        // Make sure the animator was started.
        assertTrue(keyguardUnlockAnimationController.surfaceBehindEntryAnimator.isRunning)

        // Since the animation is running, we should not have finished the remote animation.
        verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
            false /* cancelled */)
    }
}
 No newline at end of file