Merge "On UDFPS auth success, fade out the dwell ripple" into tm-dev
This commit is contained in:
@@ -652,7 +652,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
|
|||||||
// pre-emptively set to true to hide view
|
// pre-emptively set to true to hide view
|
||||||
mIsBouncerShowing = true;
|
mIsBouncerShowing = true;
|
||||||
if (mUdfpsSupported && mShowUnlockIcon && mAuthRippleController != null) {
|
if (mUdfpsSupported && mShowUnlockIcon && mAuthRippleController != null) {
|
||||||
mAuthRippleController.showRipple(FINGERPRINT);
|
mAuthRippleController.showUnlockRipple(FINGERPRINT);
|
||||||
}
|
}
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
if (mOnGestureDetectedRunnable != null) {
|
if (mOnGestureDetectedRunnable != null) {
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ import javax.inject.Inject
|
|||||||
import javax.inject.Provider
|
import javax.inject.Provider
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Controls the ripple effect that shows when authentication is successful.
|
* Controls two ripple effects:
|
||||||
|
* 1. Unlocked ripple: shows when authentication is successful
|
||||||
|
* 2. UDFPS dwell ripple: shows when the user has their finger down on the UDFPS area and reacts
|
||||||
|
* to errors and successes
|
||||||
|
*
|
||||||
* The ripple uses the accent color of the current theme.
|
* The ripple uses the accent color of the current theme.
|
||||||
*/
|
*/
|
||||||
@CentralSurfacesScope
|
@CentralSurfacesScope
|
||||||
@@ -115,7 +119,7 @@ class AuthRippleController @Inject constructor(
|
|||||||
notificationShadeWindowController.setForcePluginOpen(false, this)
|
notificationShadeWindowController.setForcePluginOpen(false, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showRipple(biometricSourceType: BiometricSourceType?) {
|
fun showUnlockRipple(biometricSourceType: BiometricSourceType?) {
|
||||||
if (!(keyguardUpdateMonitor.isKeyguardVisible || keyguardUpdateMonitor.isDreaming) ||
|
if (!(keyguardUpdateMonitor.isKeyguardVisible || keyguardUpdateMonitor.isDreaming) ||
|
||||||
keyguardUpdateMonitor.userNeedsStrongAuth()) {
|
keyguardUpdateMonitor.userNeedsStrongAuth()) {
|
||||||
return
|
return
|
||||||
@@ -252,11 +256,16 @@ class AuthRippleController @Inject constructor(
|
|||||||
biometricSourceType: BiometricSourceType?,
|
biometricSourceType: BiometricSourceType?,
|
||||||
isStrongBiometric: Boolean
|
isStrongBiometric: Boolean
|
||||||
) {
|
) {
|
||||||
showRipple(biometricSourceType)
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
||||||
|
mView.fadeDwellRipple()
|
||||||
|
}
|
||||||
|
showUnlockRipple(biometricSourceType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
|
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
|
||||||
mView.retractRipple()
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
||||||
|
mView.retractDwellRipple()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBiometricAcquired(
|
override fun onBiometricAcquired(
|
||||||
@@ -264,8 +273,16 @@ class AuthRippleController @Inject constructor(
|
|||||||
acquireInfo: Int
|
acquireInfo: Int
|
||||||
) {
|
) {
|
||||||
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
|
||||||
acquireInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_PARTIAL) {
|
BiometricFingerprintConstants.shouldTurnOffHbm(acquireInfo) &&
|
||||||
mView.retractRipple()
|
acquireInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD) {
|
||||||
|
// received an 'acquiredBad' message, so immediately retract
|
||||||
|
mView.retractDwellRipple()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onKeyguardBouncerChanged(bouncerIsOrWillBeShowing: Boolean) {
|
||||||
|
if (bouncerIsOrWillBeShowing) {
|
||||||
|
mView.fadeDwellRipple()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +311,7 @@ class AuthRippleController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onFingerUp() {
|
override fun onFingerUp() {
|
||||||
mView.retractRipple()
|
mView.retractDwellRipple()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,12 +354,12 @@ class AuthRippleController @Inject constructor(
|
|||||||
"fingerprint" -> {
|
"fingerprint" -> {
|
||||||
updateSensorLocation()
|
updateSensorLocation()
|
||||||
pw.println("fingerprint ripple sensorLocation=$fingerprintSensorLocation")
|
pw.println("fingerprint ripple sensorLocation=$fingerprintSensorLocation")
|
||||||
showRipple(BiometricSourceType.FINGERPRINT)
|
showUnlockRipple(BiometricSourceType.FINGERPRINT)
|
||||||
}
|
}
|
||||||
"face" -> {
|
"face" -> {
|
||||||
updateSensorLocation()
|
updateSensorLocation()
|
||||||
pw.println("face ripple sensorLocation=$faceSensorLocation")
|
pw.println("face ripple sensorLocation=$faceSensorLocation")
|
||||||
showRipple(BiometricSourceType.FACE)
|
showUnlockRipple(BiometricSourceType.FACE)
|
||||||
}
|
}
|
||||||
"custom" -> {
|
"custom" -> {
|
||||||
if (args.size != 3 ||
|
if (args.size != 3 ||
|
||||||
|
|||||||
@@ -35,12 +35,13 @@ import com.android.systemui.statusbar.charging.RippleShader
|
|||||||
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
|
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expanding ripple effect
|
* Handles two ripple effects: dwell ripple and unlocked ripple
|
||||||
* - startUnlockedRipple for the transition from biometric authentication success to showing
|
* Dwell Ripple:
|
||||||
* launcher.
|
* - startDwellRipple: dwell ripple expands outwards around the biometric area
|
||||||
* - startDwellRipple for the ripple expansion out when the user has their finger down on the UDFPS
|
* - retractDwellRipple: retracts the dwell ripple to radius 0 to signal a failure
|
||||||
* sensor area
|
* - fadeDwellRipple: fades the dwell ripple away to alpha 0
|
||||||
* - retractRipple for the ripple animation inwards to signal a failure
|
* Unlocked ripple:
|
||||||
|
* - startUnlockedRipple: ripple expands from biometric auth location to the edges of the screen
|
||||||
*/
|
*/
|
||||||
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
|
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
|
||||||
private val retractInterpolator = PathInterpolator(.05f, .93f, .1f, 1f)
|
private val retractInterpolator = PathInterpolator(.05f, .93f, .1f, 1f)
|
||||||
@@ -52,6 +53,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
private var drawRipple: Boolean = false
|
private var drawRipple: Boolean = false
|
||||||
|
|
||||||
private var lockScreenColorVal = Color.WHITE
|
private var lockScreenColorVal = Color.WHITE
|
||||||
|
private val fadeDuration = 83L
|
||||||
private val retractDuration = 400L
|
private val retractDuration = 400L
|
||||||
private var alphaInDuration: Long = 0
|
private var alphaInDuration: Long = 0
|
||||||
private var unlockedRippleInProgress: Boolean = false
|
private var unlockedRippleInProgress: Boolean = false
|
||||||
@@ -59,7 +61,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
private val dwellPaint = Paint()
|
private val dwellPaint = Paint()
|
||||||
private val rippleShader = RippleShader()
|
private val rippleShader = RippleShader()
|
||||||
private val ripplePaint = Paint()
|
private val ripplePaint = Paint()
|
||||||
private var retractAnimator: Animator? = null
|
private var fadeDwellAnimator: Animator? = null
|
||||||
|
private var retractDwellAnimator: Animator? = null
|
||||||
private var dwellPulseOutAnimator: Animator? = null
|
private var dwellPulseOutAnimator: Animator? = null
|
||||||
private var dwellRadius: Float = 0f
|
private var dwellRadius: Float = 0f
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -112,15 +115,15 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animate ripple inwards back to radius 0
|
* Animate dwell ripple inwards back to radius 0
|
||||||
*/
|
*/
|
||||||
fun retractRipple() {
|
fun retractDwellRipple() {
|
||||||
if (retractAnimator?.isRunning == true) {
|
if (retractDwellAnimator?.isRunning == true || fadeDwellAnimator?.isRunning == true) {
|
||||||
return // let the animation finish
|
return // let the animation finish
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwellPulseOutAnimator?.isRunning == true) {
|
if (dwellPulseOutAnimator?.isRunning == true) {
|
||||||
val retractRippleAnimator = ValueAnimator.ofFloat(dwellShader.progress, 0f)
|
val retractDwellRippleAnimator = ValueAnimator.ofFloat(dwellShader.progress, 0f)
|
||||||
.apply {
|
.apply {
|
||||||
interpolator = retractInterpolator
|
interpolator = retractInterpolator
|
||||||
duration = retractDuration
|
duration = retractDuration
|
||||||
@@ -145,8 +148,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retractAnimator = AnimatorSet().apply {
|
retractDwellAnimator = AnimatorSet().apply {
|
||||||
playTogether(retractRippleAnimator, retractAlphaAnimator)
|
playTogether(retractDwellRippleAnimator, retractAlphaAnimator)
|
||||||
addListener(object : AnimatorListenerAdapter() {
|
addListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
dwellPulseOutAnimator?.cancel()
|
dwellPulseOutAnimator?.cancel()
|
||||||
@@ -163,6 +166,42 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animate ripple fade to alpha=0
|
||||||
|
*/
|
||||||
|
fun fadeDwellRipple() {
|
||||||
|
if (fadeDwellAnimator?.isRunning == true) {
|
||||||
|
return // let the animation finish
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwellPulseOutAnimator?.isRunning == true || retractDwellAnimator?.isRunning == true) {
|
||||||
|
fadeDwellAnimator = ValueAnimator.ofInt(Color.alpha(dwellShader.color), 0).apply {
|
||||||
|
interpolator = Interpolators.LINEAR
|
||||||
|
duration = fadeDuration
|
||||||
|
addUpdateListener { animator ->
|
||||||
|
dwellShader.color = ColorUtils.setAlphaComponent(
|
||||||
|
dwellShader.color,
|
||||||
|
animator.animatedValue as Int
|
||||||
|
)
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
addListener(object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
|
retractDwellAnimator?.cancel()
|
||||||
|
dwellPulseOutAnimator?.cancel()
|
||||||
|
drawDwell = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationEnd(animation: Animator?) {
|
||||||
|
drawDwell = false
|
||||||
|
resetDwellAlpha()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays a ripple animation that grows to the dwellRadius with distortion.
|
* Plays a ripple animation that grows to the dwellRadius with distortion.
|
||||||
*/
|
*/
|
||||||
@@ -205,7 +244,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
)
|
)
|
||||||
addListener(object : AnimatorListenerAdapter() {
|
addListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
retractAnimator?.cancel()
|
retractDwellAnimator?.cancel()
|
||||||
|
fadeDwellAnimator?.cancel()
|
||||||
visibility = VISIBLE
|
visibility = VISIBLE
|
||||||
drawDwell = true
|
drawDwell = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
|
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
|
||||||
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
||||||
|
|
||||||
controller.showRipple(BiometricSourceType.FINGERPRINT)
|
controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
|
||||||
assertTrue("reveal didn't start on keyguardFadingAway",
|
assertTrue("reveal didn't start on keyguardFadingAway",
|
||||||
controller.startLightRevealScrimOnKeyguardFadingAway)
|
controller.startLightRevealScrimOnKeyguardFadingAway)
|
||||||
`when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
|
`when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user