Merge "Fix issue where surface was animated while wake and unlocking." into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b024f66885
@@ -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,7 +225,18 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
||||
// to animate it in. Otherwise, the swipe touch events will continue animating it.
|
||||
if (!requestedShowSurfaceBehindKeyguard) {
|
||||
keyguardViewController.hide(startTime, 350)
|
||||
surfaceBehindEntryAnimator.start()
|
||||
|
||||
// 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.
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
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 */)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user