summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt100
3 files changed, 174 insertions, 19 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 2925d8dbd03a..872a32cfc24d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -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
/**
@@ -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.
@@ -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
@@ -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.
*/
@@ -492,6 +523,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
*/
fun notifyStartSurfaceBehindRemoteAnimation(
targets: Array<RemoteAnimationTarget>,
+ wallpapers: Array<RemoteAnimationTarget>,
startTime: Long,
requestedShowSurfaceBehindKeyguard: Boolean
) {
@@ -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
@@ -839,6 +874,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.
*
@@ -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()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 1a126d72f9e9..0cee65f77201 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -156,6 +156,7 @@ import dagger.Lazy;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.concurrent.Executor;
/**
@@ -2686,9 +2687,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(
@@ -2937,6 +2942,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 {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
index 2c81e82f34df..47df64fc33e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -150,6 +162,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
)
@@ -174,6 +187,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
true /* requestedShowSurfaceBehindKeyguard */
)
@@ -196,6 +210,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
true /* requestedShowSurfaceBehindKeyguard */
)
@@ -216,6 +231,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
fun playCannedUnlockAnimation_ifDidNotRequestShowSurface() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
)
@@ -230,6 +246,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
true /* requestedShowSurfaceBehindKeyguard */
)
@@ -245,6 +262,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
+ wallpaperTargets,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
)
@@ -259,6 +277,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
fun surfaceAnimation_multipleTargets() {
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
arrayOf(remoteTarget1, remoteTarget2),
+ wallpaperTargets,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
)
@@ -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 ->
@@ -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)
}
@@ -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
+ }
+ }
}