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

Commit 8bbe39d6 authored by Josh Tsuji's avatar Josh Tsuji
Browse files

Animate all targets to accomodate swiping during split screen.

These now scale out from the middle of the screen together,
instead of only one being visible and the rest jump-cutting in.

This should also obviate the need for the root task fix, since
we now animate all tasks WM gives us anyway. I updated b/232852578
to reference this CL in case that inadverently regresses something,
but it should not!

Fixes: 206741900
Test: added new keyguard test (atest SystemUITests)
Test: manual on tablet + regular device w/ no split screen
Change-Id: I7db8cda87b056970d9c3a6a383fb996489fd793e
parent 50d3d730
Loading
Loading
Loading
Loading
+56 −65
Original line number Diff line number Diff line
@@ -241,9 +241,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
     */
    @VisibleForTesting
    var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null
    private var surfaceBehindRemoteAnimationTarget: RemoteAnimationTarget? = null
    private var surfaceBehindRemoteAnimationTargets: Array<RemoteAnimationTarget>? = null
    private var surfaceBehindRemoteAnimationStartTime: Long = 0
    private var surfaceBehindParams: SyncRtSurfaceTransactionApplier.SurfaceParams? = null

    /**
     * Alpha value applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the
@@ -458,7 +457,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * (fingerprint, tap, etc.) and the keyguard is going away.
     */
    fun notifyStartSurfaceBehindRemoteAnimation(
        target: RemoteAnimationTarget,
        targets: Array<RemoteAnimationTarget>,
        startTime: Long,
        requestedShowSurfaceBehindKeyguard: Boolean
    ) {
@@ -467,10 +466,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
                    keyguardViewController.viewRootImpl.view)
        }

        // New animation, new params.
        surfaceBehindParams = null

        surfaceBehindRemoteAnimationTarget = target
        surfaceBehindRemoteAnimationTargets = targets
        surfaceBehindRemoteAnimationStartTime = startTime

        // If we specifically requested that the surface behind be made visible (vs. it being made
@@ -597,7 +593,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * keyguard dismiss amount and the method of dismissal.
     */
    private fun updateSurfaceBehindAppearAmount() {
        if (surfaceBehindRemoteAnimationTarget == null) {
        if (surfaceBehindRemoteAnimationTargets == null) {
            return
        }

@@ -715,46 +711,42 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * cancelled).
     */
    fun setSurfaceBehindAppearAmount(amount: Float) {
        if (surfaceBehindRemoteAnimationTarget == null) {
            return
        }

        // Otherwise, animate in the surface's scale/transltion.
        val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.height()
        surfaceBehindRemoteAnimationTargets?.forEach { surfaceBehindRemoteAnimationTarget ->
            val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget.screenSpaceBounds.height()

            var scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR +
                    (1f - SURFACE_BEHIND_START_SCALE_FACTOR) *
                    MathUtils.clamp(amount, 0f, 1f))

        // If we're dismissing via swipe to the Launcher, we'll play in-window scale animations, so
        // don't also scale the window.
            // If we're dismissing via swipe to the Launcher, we'll play in-window scale animations,
            // so don't also scale the window.
            if (keyguardStateController.isDismissingFromSwipe &&
                    willUnlockWithInWindowLauncherAnimations) {
                scaleFactor = 1f
            }

            // Translate up from the bottom.
            surfaceBehindMatrix.setTranslate(
                    surfaceBehindRemoteAnimationTarget.screenSpaceBounds.left.toFloat(),
                    surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
            )

            // Scale up from a point at the center-bottom of the surface.
        surfaceBehindMatrix.setScale(
            surfaceBehindMatrix.postScale(
                    scaleFactor,
                    scaleFactor,
            surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.width() / 2f,
                    keyguardViewController.viewRootImpl.width / 2f,
                    surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y
            )

        // Translate up from the bottom.
        surfaceBehindMatrix.postTranslate(
            0f,
            surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
        )

            // If we're snapping the keyguard back, immediately begin fading it out.
            val animationAlpha =
                    if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount
                    else surfaceBehindAlpha

        // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is unable
        // to draw
        val sc: SurfaceControl? = surfaceBehindRemoteAnimationTarget?.leash
            // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
            // unable to draw
            val sc: SurfaceControl? = surfaceBehindRemoteAnimationTarget.leash
            if (keyguardViewController.viewRootImpl.view?.visibility != View.VISIBLE &&
                    sc?.isValid == true) {
                with(SurfaceControl.Transaction()) {
@@ -766,7 +758,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
            } else {
                applyParamsToSurface(
                        SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
                    surfaceBehindRemoteAnimationTarget!!.leash)
                                surfaceBehindRemoteAnimationTarget.leash)
                                .withMatrix(surfaceBehindMatrix)
                                .withCornerRadius(roundedCornerRadius)
                                .withAlpha(animationAlpha)
@@ -774,6 +766,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
                )
            }
        }
    }

    /**
     * Called by [KeyguardViewMediator] to let us know that the remote animation has finished, and
@@ -796,8 +789,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
        launcherUnlockController?.setUnlockAmount(1f, false /* forceIfAnimating */)

        // That target is no longer valid since the animation finished, null it out.
        surfaceBehindRemoteAnimationTarget = null
        surfaceBehindParams = null
        surfaceBehindRemoteAnimationTargets = null

        playingCannedUnlockAnimation = false
        willUnlockWithInWindowLauncherAnimations = false
@@ -829,7 +821,6 @@ class KeyguardUnlockAnimationController @Inject constructor(

    private fun applyParamsToSurface(params: SyncRtSurfaceTransactionApplier.SurfaceParams) {
        surfaceTransactionApplier!!.scheduleApply(params)
        surfaceBehindParams = params
    }

    private fun fadeInSurfaceBehind() {
+1 −9
Original line number Diff line number Diff line
@@ -2587,18 +2587,10 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
                mInteractionJankMonitor.begin(
                        createInteractionJankMonitorConf("DismissPanel"));

                // Apply the opening animation on root task if exists
                RemoteAnimationTarget aniTarget = apps[0];
                for (RemoteAnimationTarget tmpTarget : apps) {
                    if (tmpTarget.taskId != -1 && !tmpTarget.hasAnimatingParent) {
                        aniTarget = tmpTarget;
                        break;
                    }
                }
                // Pass the surface and metadata to the unlock animation controller.
                mKeyguardUnlockAnimationControllerLazy.get()
                        .notifyStartSurfaceBehindRemoteAnimation(
                                aniTarget, startTime, mSurfaceBehindRemoteAnimationRequested);
                                apps, startTime, mSurfaceBehindRemoteAnimationRequested);
            } else {
                mInteractionJankMonitor.begin(
                        createInteractionJankMonitorConf("RemoteAnimationDisabled"));
+56 −13
Original line number Diff line number Diff line
@@ -27,11 +27,11 @@ 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.Mockito.`when`
import org.mockito.MockitoAnnotations

@RunWith(AndroidTestingRunner::class)
@@ -60,7 +60,18 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
    @Mock
    private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController.Stub

    private lateinit var remoteAnimationTarget: RemoteAnimationTarget
    private var surfaceControl1 = mock(SurfaceControl::class.java)
    private var remoteTarget1 = RemoteAnimationTarget(
            0 /* taskId */, 0, surfaceControl1, false, Rect(), Rect(), 0, Point(), Rect(), Rect(),
            mock(WindowConfiguration::class.java), false, surfaceControl1, Rect(),
            mock(ActivityManager.RunningTaskInfo::class.java), false)

    private var surfaceControl2 = mock(SurfaceControl::class.java)
    private var remoteTarget2 = RemoteAnimationTarget(
            1 /* taskId */, 0, surfaceControl2, false, Rect(), Rect(), 0, Point(), Rect(), Rect(),
            mock(WindowConfiguration::class.java), false, surfaceControl2, Rect(),
            mock(ActivityManager.RunningTaskInfo::class.java), false)
    private lateinit var remoteAnimationTargets: Array<RemoteAnimationTarget>

    @Before
    fun setUp() {
@@ -77,10 +88,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {

        // 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)
        remoteAnimationTargets = arrayOf(remoteTarget1)

        // 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
@@ -99,7 +107,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -130,7 +138,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -154,7 +162,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -176,7 +184,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -196,7 +204,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
    @Test
    fun playCannedUnlockAnimation_ifDidNotRequestShowSurface() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            false /* requestedShowSurfaceBehindKeyguard */
        )
@@ -210,7 +218,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        `when`(notificationShadeWindowController.isLaunchingActivity).thenReturn(true)

        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
            remoteAnimationTarget,
            remoteAnimationTargets,
            0 /* startTime */,
            true /* requestedShowSurfaceBehindKeyguard */
        )
@@ -225,11 +233,46 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        keyguardUnlockAnimationController.willUnlockWithInWindowLauncherAnimations = true

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

        assertTrue(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation())
    }

    /**
     * If we are not wake and unlocking, we expect the unlock animation to play normally.
     */
    @Test
    fun surfaceAnimation_multipleTargets() {
        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
                arrayOf(remoteTarget1, remoteTarget2),
                0 /* startTime */,
                false /* requestedShowSurfaceBehindKeyguard */
        )

        // Set appear to 50%, we'll just verify that we're not applying the identity matrix which
        // means an animation is in progress.
        keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(0.5f)

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

        val allParams = captor.allValues

        val remainingTargets = mutableListOf(surfaceControl1, surfaceControl2)
        allParams.forEach { params ->
            assertTrue(!params.matrix.isIdentity)
            remainingTargets.remove(params.surface)
        }

        // Make sure we called applyParams with each of the surface controls once. The order does
        // not matter, so don't explicitly check for that.
        assertTrue(remainingTargets.isEmpty())

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