Loading packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +73 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,7 @@ class KeyguardUnlockAnimationController @Inject constructor( @VisibleForTesting var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null private var surfaceBehindRemoteAnimationTargets: Array<RemoteAnimationTarget>? = null private var wallpaperTargets: Array<RemoteAnimationTarget>? = null private var surfaceBehindRemoteAnimationStartTime: Long = 0 /** Loading @@ -257,9 +258,13 @@ class KeyguardUnlockAnimationController @Inject constructor( */ private var surfaceBehindAlpha = 1f private var wallpaperAlpha = 1f @VisibleForTesting var surfaceBehindAlphaAnimator = ValueAnimator.ofFloat(0f, 1f) var wallpaperAlphaAnimator = ValueAnimator.ofFloat(0f, 1f) /** * Matrix applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the * app/launcher behind the keyguard. Loading Loading @@ -335,6 +340,27 @@ class KeyguardUnlockAnimationController @Inject constructor( }) } with(wallpaperAlphaAnimator) { duration = LAUNCHER_ICONS_ANIMATION_DURATION_MS interpolator = Interpolators.ALPHA_OUT addUpdateListener { valueAnimator: ValueAnimator -> wallpaperAlpha = valueAnimator.animatedValue as Float setWallpaperAppearAmount(wallpaperAlpha) } addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { Log.d(TAG, "wallpaperAlphaAnimator#onAnimationEnd, animation ended ") if (wallpaperAlpha == 1f) { wallpaperTargets = null keyguardViewMediator.get().finishExitRemoteAnimation() } else { Log.d(TAG, "wallpaperAlphaAnimator#onAnimationEnd, " + "animation was cancelled: skipping finishAnimation()") } } }) } with(surfaceBehindEntryAnimator) { duration = UNLOCK_ANIMATION_DURATION_MS startDelay = UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS Loading @@ -361,6 +387,11 @@ class KeyguardUnlockAnimationController @Inject constructor( context.resources.getDimensionPixelSize(R.dimen.rounded_corner_radius).toFloat() } fun isAnyKeyguyardAnimatorPlaying(): Boolean { return surfaceBehindAlphaAnimator.isStarted || wallpaperAlphaAnimator.isStarted || surfaceBehindEntryAnimator.isStarted } /** * Add a listener to be notified of various stages of the unlock animation. */ Loading Loading @@ -492,6 +523,7 @@ class KeyguardUnlockAnimationController @Inject constructor( */ fun notifyStartSurfaceBehindRemoteAnimation( targets: Array<RemoteAnimationTarget>, wallpapers: Array<RemoteAnimationTarget>, startTime: Long, requestedShowSurfaceBehindKeyguard: Boolean ) { Loading @@ -501,8 +533,11 @@ class KeyguardUnlockAnimationController @Inject constructor( } surfaceBehindRemoteAnimationTargets = targets wallpaperTargets = wallpapers surfaceBehindRemoteAnimationStartTime = startTime fadeInWallpaper() // If we specifically requested that the surface behind be made visible (vs. it being made // visible because we're unlocking), then we're in the middle of a swipe-to-unlock touch // gesture and the surface behind the keyguard should be made visible so that we can animate Loading Loading @@ -838,6 +873,38 @@ class KeyguardUnlockAnimationController @Inject constructor( } } /** * Modify the opacity of a wallpaper window. */ fun setWallpaperAppearAmount(amount: Float) { wallpaperTargets?.forEach { wallpaper -> val animationAlpha = when { // 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 -> amount } // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is // unable to draw val sc: SurfaceControl? = wallpaper.leash if (keyguardViewController.viewRootImpl.view?.visibility != View.VISIBLE && sc?.isValid == true) { with(SurfaceControl.Transaction()) { setAlpha(sc, animationAlpha) apply() } } else { applyParamsToSurface( SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( wallpaper.leash) .withAlpha(animationAlpha) .build() ) } } } /** * Called by [KeyguardViewMediator] to let us know that the remote animation has finished, and * we should clean up all of our state. Loading Loading @@ -903,6 +970,12 @@ class KeyguardUnlockAnimationController @Inject constructor( surfaceBehindAlphaAnimator.start() } private fun fadeInWallpaper() { Log.d(TAG, "fadeInWallpaper") wallpaperAlphaAnimator.cancel() wallpaperAlphaAnimator.start() } private fun fadeOutSurfaceBehind() { Log.d(TAG, "fadeOutSurfaceBehind") surfaceBehindAlphaAnimator.cancel() Loading packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +19 −1 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ import dagger.Lazy; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.Executor; /** Loading Loading @@ -2710,9 +2711,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, CUJ_LOCKSCREEN_UNLOCK_ANIMATION, "DismissPanel")); // Pass the surface and metadata to the unlock animation controller. RemoteAnimationTarget[] openingWallpapers = Arrays.stream(wallpapers).filter( w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray( RemoteAnimationTarget[]::new); mKeyguardUnlockAnimationControllerLazy.get() .notifyStartSurfaceBehindRemoteAnimation( apps, startTime, mSurfaceBehindRemoteAnimationRequested); apps, openingWallpapers, startTime, mSurfaceBehindRemoteAnimationRequested); } else { mInteractionJankMonitor.begin( createInteractionJankMonitorConf( Loading Loading @@ -2961,6 +2966,19 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mSurfaceBehindRemoteAnimationRequested = false; mSurfaceBehindRemoteAnimationRunning = false; mKeyguardStateController.notifyKeyguardGoingAway(false); finishExitRemoteAnimation(); } void finishExitRemoteAnimation() { if (mKeyguardUnlockAnimationControllerLazy.get().isAnyKeyguyardAnimatorPlaying() || mKeyguardStateController.isDismissingFromSwipe()) { // If the animation is ongoing, or we are not done with the swipe gesture, // it's too early to terminate the animation Log.d(TAG, "finishAnimation not executing now because " + "not all animations have finished"); return; } Log.d(TAG, "finishAnimation executing"); if (mSurfaceBehindRemoteAnimationFinishedCallback != null) { try { Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt +82 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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.argThat import com.android.systemui.util.mockito.whenever import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse Loading @@ -28,13 +29,14 @@ 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.atLeastOnce import org.mockito.Mockito.mock import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations import java.util.function.Predicate @RunWith(AndroidTestingRunner::class) @RunWithLooper Loading Loading @@ -77,6 +79,13 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { mock(ActivityManager.RunningTaskInfo::class.java), false) private lateinit var remoteAnimationTargets: Array<RemoteAnimationTarget> private var surfaceControlWp = mock(SurfaceControl::class.java) private var wallpaperTarget = RemoteAnimationTarget( 2 /* taskId */, 0, surfaceControlWp, false, Rect(), Rect(), 0, Point(), Rect(), Rect(), mock(WindowConfiguration::class.java), false, surfaceControlWp, Rect(), mock(ActivityManager.RunningTaskInfo::class.java), false) private lateinit var wallpaperTargets: Array<RemoteAnimationTarget> @Before fun setUp() { MockitoAnnotations.initMocks(this) Loading @@ -94,6 +103,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. remoteAnimationTargets = arrayOf(remoteTarget1) wallpaperTargets = arrayOf(wallpaperTarget) // 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 Loading @@ -119,18 +129,20 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, arrayOf(), 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java) verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture()) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1 }) val params = captor.value val params = captorSb.getLastValue() // 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) assertEquals(1f, params.alpha) assertTrue(params.matrix.isIdentity) // Also expect we've immediately asked the keyguard view mediator to finish the remote Loading @@ -150,6 +162,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -174,6 +187,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -196,6 +210,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -216,6 +231,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { fun playCannedUnlockAnimation_ifDidNotRequestShowSurface() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -230,6 +246,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -245,6 +262,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -259,6 +277,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { fun surfaceAnimation_multipleTargets() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( arrayOf(remoteTarget1, remoteTarget2), wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -267,10 +286,15 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { // 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 captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(2)).scheduleApply(captorSb .capture { sp -> sp.surface == surfaceControl1 || sp.surface == surfaceControl2 }) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1).description( "WallpaperSurface was expected to receive scheduleApply once" )).scheduleApply(captorWp.capture { sp -> sp.surface == surfaceControlWp}) val allParams = captor.allValues val allParams = captorSb.getAllValues() val remainingTargets = mutableListOf(surfaceControl1, surfaceControl2) allParams.forEach { params -> Loading @@ -293,20 +317,29 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f) keyguardUnlockAnimationController.setWallpaperAppearAmount(1f) val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java) verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture()) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1}) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, atLeastOnce().description("Wallpaper surface has not " + "received scheduleApply")).scheduleApply( captorWp.capture { sp -> sp.surface == surfaceControlWp }) val params = captor.value val params = captorSb.getLastValue() // We expect that we've set the surface behind to alpha = 0f since we're not interactive. assertEquals(params.alpha, 0f) assertEquals(0f, params.alpha) assertTrue(params.matrix.isIdentity) assertEquals("Wallpaper surface was expected to have opacity 0", 0f, captorWp.getLastValue().alpha) verifyNoMoreInteractions(surfaceTransactionApplier) } Loading @@ -317,19 +350,50 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 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) keyguardUnlockAnimationController.setWallpaperAppearAmount(1f) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1 }) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, atLeastOnce().description("Wallpaper surface has not " + "received scheduleApply")).scheduleApply( captorWp.capture { sp -> sp.surface == surfaceControlWp }) val params = captorSb.getLastValue() assertEquals(1f, params.alpha) assertTrue(params.matrix.isIdentity) assertEquals("Wallpaper surface was expected to have opacity 1", 1f, captorWp.getLastValue().alpha) verifyNoMoreInteractions(surfaceTransactionApplier) } private class ArgThatCaptor<T> { private var allArgs: MutableList<T> = mutableListOf() fun capture(predicate: Predicate<T>): T { return argThat{x: T -> if (predicate.test(x)) { allArgs.add(x) return@argThat true } return@argThat false } } fun getLastValue(): T { return allArgs.last() } fun getAllValues(): List<T> { return allArgs } } } Loading
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +73 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,7 @@ class KeyguardUnlockAnimationController @Inject constructor( @VisibleForTesting var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null private var surfaceBehindRemoteAnimationTargets: Array<RemoteAnimationTarget>? = null private var wallpaperTargets: Array<RemoteAnimationTarget>? = null private var surfaceBehindRemoteAnimationStartTime: Long = 0 /** Loading @@ -257,9 +258,13 @@ class KeyguardUnlockAnimationController @Inject constructor( */ private var surfaceBehindAlpha = 1f private var wallpaperAlpha = 1f @VisibleForTesting var surfaceBehindAlphaAnimator = ValueAnimator.ofFloat(0f, 1f) var wallpaperAlphaAnimator = ValueAnimator.ofFloat(0f, 1f) /** * Matrix applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the * app/launcher behind the keyguard. Loading Loading @@ -335,6 +340,27 @@ class KeyguardUnlockAnimationController @Inject constructor( }) } with(wallpaperAlphaAnimator) { duration = LAUNCHER_ICONS_ANIMATION_DURATION_MS interpolator = Interpolators.ALPHA_OUT addUpdateListener { valueAnimator: ValueAnimator -> wallpaperAlpha = valueAnimator.animatedValue as Float setWallpaperAppearAmount(wallpaperAlpha) } addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { Log.d(TAG, "wallpaperAlphaAnimator#onAnimationEnd, animation ended ") if (wallpaperAlpha == 1f) { wallpaperTargets = null keyguardViewMediator.get().finishExitRemoteAnimation() } else { Log.d(TAG, "wallpaperAlphaAnimator#onAnimationEnd, " + "animation was cancelled: skipping finishAnimation()") } } }) } with(surfaceBehindEntryAnimator) { duration = UNLOCK_ANIMATION_DURATION_MS startDelay = UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS Loading @@ -361,6 +387,11 @@ class KeyguardUnlockAnimationController @Inject constructor( context.resources.getDimensionPixelSize(R.dimen.rounded_corner_radius).toFloat() } fun isAnyKeyguyardAnimatorPlaying(): Boolean { return surfaceBehindAlphaAnimator.isStarted || wallpaperAlphaAnimator.isStarted || surfaceBehindEntryAnimator.isStarted } /** * Add a listener to be notified of various stages of the unlock animation. */ Loading Loading @@ -492,6 +523,7 @@ class KeyguardUnlockAnimationController @Inject constructor( */ fun notifyStartSurfaceBehindRemoteAnimation( targets: Array<RemoteAnimationTarget>, wallpapers: Array<RemoteAnimationTarget>, startTime: Long, requestedShowSurfaceBehindKeyguard: Boolean ) { Loading @@ -501,8 +533,11 @@ class KeyguardUnlockAnimationController @Inject constructor( } surfaceBehindRemoteAnimationTargets = targets wallpaperTargets = wallpapers surfaceBehindRemoteAnimationStartTime = startTime fadeInWallpaper() // If we specifically requested that the surface behind be made visible (vs. it being made // visible because we're unlocking), then we're in the middle of a swipe-to-unlock touch // gesture and the surface behind the keyguard should be made visible so that we can animate Loading Loading @@ -838,6 +873,38 @@ class KeyguardUnlockAnimationController @Inject constructor( } } /** * Modify the opacity of a wallpaper window. */ fun setWallpaperAppearAmount(amount: Float) { wallpaperTargets?.forEach { wallpaper -> val animationAlpha = when { // 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 -> amount } // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is // unable to draw val sc: SurfaceControl? = wallpaper.leash if (keyguardViewController.viewRootImpl.view?.visibility != View.VISIBLE && sc?.isValid == true) { with(SurfaceControl.Transaction()) { setAlpha(sc, animationAlpha) apply() } } else { applyParamsToSurface( SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( wallpaper.leash) .withAlpha(animationAlpha) .build() ) } } } /** * Called by [KeyguardViewMediator] to let us know that the remote animation has finished, and * we should clean up all of our state. Loading Loading @@ -903,6 +970,12 @@ class KeyguardUnlockAnimationController @Inject constructor( surfaceBehindAlphaAnimator.start() } private fun fadeInWallpaper() { Log.d(TAG, "fadeInWallpaper") wallpaperAlphaAnimator.cancel() wallpaperAlphaAnimator.start() } private fun fadeOutSurfaceBehind() { Log.d(TAG, "fadeOutSurfaceBehind") surfaceBehindAlphaAnimator.cancel() Loading
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +19 −1 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ import dagger.Lazy; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.Executor; /** Loading Loading @@ -2710,9 +2711,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, CUJ_LOCKSCREEN_UNLOCK_ANIMATION, "DismissPanel")); // Pass the surface and metadata to the unlock animation controller. RemoteAnimationTarget[] openingWallpapers = Arrays.stream(wallpapers).filter( w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray( RemoteAnimationTarget[]::new); mKeyguardUnlockAnimationControllerLazy.get() .notifyStartSurfaceBehindRemoteAnimation( apps, startTime, mSurfaceBehindRemoteAnimationRequested); apps, openingWallpapers, startTime, mSurfaceBehindRemoteAnimationRequested); } else { mInteractionJankMonitor.begin( createInteractionJankMonitorConf( Loading Loading @@ -2961,6 +2966,19 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mSurfaceBehindRemoteAnimationRequested = false; mSurfaceBehindRemoteAnimationRunning = false; mKeyguardStateController.notifyKeyguardGoingAway(false); finishExitRemoteAnimation(); } void finishExitRemoteAnimation() { if (mKeyguardUnlockAnimationControllerLazy.get().isAnyKeyguyardAnimatorPlaying() || mKeyguardStateController.isDismissingFromSwipe()) { // If the animation is ongoing, or we are not done with the swipe gesture, // it's too early to terminate the animation Log.d(TAG, "finishAnimation not executing now because " + "not all animations have finished"); return; } Log.d(TAG, "finishAnimation executing"); if (mSurfaceBehindRemoteAnimationFinishedCallback != null) { try { Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt +82 −18 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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.argThat import com.android.systemui.util.mockito.whenever import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse Loading @@ -28,13 +29,14 @@ 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.atLeastOnce import org.mockito.Mockito.mock import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations import java.util.function.Predicate @RunWith(AndroidTestingRunner::class) @RunWithLooper Loading Loading @@ -77,6 +79,13 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { mock(ActivityManager.RunningTaskInfo::class.java), false) private lateinit var remoteAnimationTargets: Array<RemoteAnimationTarget> private var surfaceControlWp = mock(SurfaceControl::class.java) private var wallpaperTarget = RemoteAnimationTarget( 2 /* taskId */, 0, surfaceControlWp, false, Rect(), Rect(), 0, Point(), Rect(), Rect(), mock(WindowConfiguration::class.java), false, surfaceControlWp, Rect(), mock(ActivityManager.RunningTaskInfo::class.java), false) private lateinit var wallpaperTargets: Array<RemoteAnimationTarget> @Before fun setUp() { MockitoAnnotations.initMocks(this) Loading @@ -94,6 +103,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. remoteAnimationTargets = arrayOf(remoteTarget1) wallpaperTargets = arrayOf(wallpaperTarget) // 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 Loading @@ -119,18 +129,20 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, arrayOf(), 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java) verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture()) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1 }) val params = captor.value val params = captorSb.getLastValue() // 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) assertEquals(1f, params.alpha) assertTrue(params.matrix.isIdentity) // Also expect we've immediately asked the keyguard view mediator to finish the remote Loading @@ -150,6 +162,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -174,6 +187,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -196,6 +210,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -216,6 +231,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { fun playCannedUnlockAnimation_ifDidNotRequestShowSurface() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -230,6 +246,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -245,6 +262,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -259,6 +277,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { fun surfaceAnimation_multipleTargets() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( arrayOf(remoteTarget1, remoteTarget2), wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) Loading @@ -267,10 +286,15 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { // 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 captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(2)).scheduleApply(captorSb .capture { sp -> sp.surface == surfaceControl1 || sp.surface == surfaceControl2 }) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1).description( "WallpaperSurface was expected to receive scheduleApply once" )).scheduleApply(captorWp.capture { sp -> sp.surface == surfaceControlWp}) val allParams = captor.allValues val allParams = captorSb.getAllValues() val remainingTargets = mutableListOf(surfaceControl1, surfaceControl2) allParams.forEach { params -> Loading @@ -293,20 +317,29 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f) keyguardUnlockAnimationController.setWallpaperAppearAmount(1f) val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java) verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture()) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1}) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, atLeastOnce().description("Wallpaper surface has not " + "received scheduleApply")).scheduleApply( captorWp.capture { sp -> sp.surface == surfaceControlWp }) val params = captor.value val params = captorSb.getLastValue() // We expect that we've set the surface behind to alpha = 0f since we're not interactive. assertEquals(params.alpha, 0f) assertEquals(0f, params.alpha) assertTrue(params.matrix.isIdentity) assertEquals("Wallpaper surface was expected to have opacity 0", 0f, captorWp.getLastValue().alpha) verifyNoMoreInteractions(surfaceTransactionApplier) } Loading @@ -317,19 +350,50 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( remoteAnimationTargets, wallpaperTargets, 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) keyguardUnlockAnimationController.setWallpaperAppearAmount(1f) val captorSb = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, times(1)).scheduleApply( captorSb.capture { sp -> sp.surface == surfaceControl1 }) val captorWp = ArgThatCaptor<SyncRtSurfaceTransactionApplier.SurfaceParams>() verify(surfaceTransactionApplier, atLeastOnce().description("Wallpaper surface has not " + "received scheduleApply")).scheduleApply( captorWp.capture { sp -> sp.surface == surfaceControlWp }) val params = captorSb.getLastValue() assertEquals(1f, params.alpha) assertTrue(params.matrix.isIdentity) assertEquals("Wallpaper surface was expected to have opacity 1", 1f, captorWp.getLastValue().alpha) verifyNoMoreInteractions(surfaceTransactionApplier) } private class ArgThatCaptor<T> { private var allArgs: MutableList<T> = mutableListOf() fun capture(predicate: Predicate<T>): T { return argThat{x: T -> if (predicate.test(x)) { allArgs.add(x) return@argThat true } return@argThat false } } fun getLastValue(): T { return allArgs.last() } fun getAllValues(): List<T> { return allArgs } } }