summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt187
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt6
4 files changed, 108 insertions, 148 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 90a1e5e64daf..f82ea790bb64 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -80,11 +80,6 @@ class AuthRippleController @Inject constructor(
private var circleReveal: LightRevealEffect? = null
private var udfpsController: UdfpsController? = null
-
- private var dwellScale = 2f
- private var expandedDwellScale = 2.5f
- private var aodDwellScale = 1.9f
- private var aodExpandedDwellScale = 2.3f
private var udfpsRadius: Float = -1f
override fun onInit() {
@@ -128,7 +123,7 @@ class AuthRippleController @Inject constructor(
updateSensorLocation()
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
fingerprintSensorLocation != null) {
- mView.setSensorLocation(fingerprintSensorLocation!!)
+ mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius)
showUnlockedRipple()
} else if (biometricSourceType == BiometricSourceType.FACE &&
faceSensorLocation != null) {
@@ -241,24 +236,12 @@ class AuthRippleController @Inject constructor(
}
private fun updateRippleColor() {
- mView.setColor(
- Utils.getColorAttr(sysuiContext, android.R.attr.colorAccent).defaultColor)
+ mView.setLockScreenColor(Utils.getColorAttrDefaultColor(sysuiContext,
+ R.attr.wallpaperTextColorAccent))
}
private fun showDwellRipple() {
- if (statusBarStateController.isDozing) {
- mView.startDwellRipple(
- /* startRadius */ udfpsRadius,
- /* endRadius */ udfpsRadius * aodDwellScale,
- /* expandedRadius */ udfpsRadius * aodExpandedDwellScale,
- /* isDozing */ true)
- } else {
- mView.startDwellRipple(
- /* startRadius */ udfpsRadius,
- /* endRadius */ udfpsRadius * dwellScale,
- /* expandedRadius */ udfpsRadius * expandedDwellScale,
- /* isDozing */ false)
- }
+ mView.startDwellRipple(statusBarStateController.isDozing)
}
private val keyguardUpdateMonitorCallback =
@@ -295,7 +278,7 @@ class AuthRippleController @Inject constructor(
return
}
- mView.setSensorLocation(fingerprintSensorLocation!!)
+ mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius)
showDwellRipple()
}
@@ -307,8 +290,8 @@ class AuthRippleController @Inject constructor(
private val authControllerCallback =
object : AuthController.Callback {
override fun onAllAuthenticatorsRegistered() {
- updateSensorLocation()
updateUdfpsDependentParams()
+ updateSensorLocation()
}
override fun onEnrollmentsChanged() {
@@ -329,20 +312,6 @@ class AuthRippleController @Inject constructor(
}
inner class AuthRippleCommand : Command {
- fun printLockScreenDwellInfo(pw: PrintWriter) {
- pw.println("lock screen dwell ripple: " +
- "\n\tsensorLocation=$fingerprintSensorLocation" +
- "\n\tdwellScale=$dwellScale" +
- "\n\tdwellExpand=$expandedDwellScale")
- }
-
- fun printAodDwellInfo(pw: PrintWriter) {
- pw.println("aod dwell ripple: " +
- "\n\tsensorLocation=$fingerprintSensorLocation" +
- "\n\tdwellScale=$aodDwellScale" +
- "\n\tdwellExpand=$aodExpandedDwellScale")
- }
-
override fun execute(pw: PrintWriter, args: List<String>) {
if (args.isEmpty()) {
invalidCommand(pw)
@@ -350,11 +319,9 @@ class AuthRippleController @Inject constructor(
when (args[0]) {
"dwell" -> {
showDwellRipple()
- if (statusBarStateController.isDozing) {
- printAodDwellInfo(pw)
- } else {
- printLockScreenDwellInfo(pw)
- }
+ pw.println("lock screen dwell ripple: " +
+ "\n\tsensorLocation=$fingerprintSensorLocation" +
+ "\n\tudfpsRadius=$udfpsRadius")
}
"fingerprint" -> {
updateSensorLocation()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index c6d26ffb9957..d67363079e17 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
+import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.util.AttributeSet
@@ -28,6 +29,7 @@ import android.view.View
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
import com.android.systemui.animation.Interpolators
+import com.android.systemui.statusbar.charging.DwellRippleShader
import com.android.systemui.statusbar.charging.RippleShader
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
@@ -43,23 +45,32 @@ private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
private val retractInterpolator = PathInterpolator(.05f, .93f, .1f, 1f)
- private val dwellPulseDuration = 50L
- private val dwellAlphaDuration = dwellPulseDuration
- private val dwellAlpha: Float = 1f
- private val dwellExpandDuration = 1200L - dwellPulseDuration
+ private val dwellPulseDuration = 100L
+ private val dwellExpandDuration = 2000L - dwellPulseDuration
- private val aodDwellPulseDuration = 50L
- private var aodDwellAlphaDuration = aodDwellPulseDuration
- private var aodDwellAlpha: Float = .8f
- private var aodDwellExpandDuration = 1200L - aodDwellPulseDuration
+ private var drawDwell: Boolean = false
+ private var drawRipple: Boolean = false
+ private var lockScreenColorVal = Color.WHITE
private val retractDuration = 400L
private var alphaInDuration: Long = 0
private var unlockedRippleInProgress: Boolean = false
+ private val dwellShader = DwellRippleShader()
+ private val dwellPaint = Paint()
private val rippleShader = RippleShader()
private val ripplePaint = Paint()
private var retractAnimator: Animator? = null
private var dwellPulseOutAnimator: Animator? = null
+ private var dwellRadius: Float = 0f
+ set(value) {
+ dwellShader.maxRadius = value
+ field = value
+ }
+ private var dwellOrigin: PointF = PointF()
+ set(value) {
+ dwellShader.origin = value
+ field = value
+ }
private var radius: Float = 0f
set(value) {
rippleShader.radius = value
@@ -76,6 +87,11 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
rippleShader.progress = 0f
rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
ripplePaint.shader = rippleShader
+
+ dwellShader.color = 0xffffffff.toInt() // default color
+ dwellShader.progress = 0f
+ dwellShader.distortionStrength = .4f
+ dwellPaint.shader = dwellShader
visibility = GONE
}
@@ -84,6 +100,13 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
}
+ fun setFingerprintSensorLocation(location: PointF, sensorRadius: Float) {
+ origin = location
+ radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
+ dwellOrigin = location
+ dwellRadius = sensorRadius * 1.5f
+ }
+
fun setAlphaInDuration(duration: Long) {
alphaInDuration = duration
}
@@ -97,14 +120,14 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
if (dwellPulseOutAnimator?.isRunning == true) {
- val retractRippleAnimator = ValueAnimator.ofFloat(rippleShader.progress, 0f)
+ val retractRippleAnimator = ValueAnimator.ofFloat(dwellShader.progress, 0f)
.apply {
interpolator = retractInterpolator
duration = retractDuration
addUpdateListener { animator ->
val now = animator.currentPlayTime
- rippleShader.progress = animator.animatedValue as Float
- rippleShader.time = now.toFloat()
+ dwellShader.progress = animator.animatedValue as Float
+ dwellShader.time = now.toFloat()
invalidate()
}
@@ -114,8 +137,8 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
interpolator = Interpolators.LINEAR
duration = retractDuration
addUpdateListener { animator ->
- rippleShader.color = ColorUtils.setAlphaComponent(
- rippleShader.color,
+ dwellShader.color = ColorUtils.setAlphaComponent(
+ dwellShader.color,
animator.animatedValue as Int
)
invalidate()
@@ -127,13 +150,12 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
dwellPulseOutAnimator?.cancel()
- rippleShader.shouldFadeOutRipple = false
- visibility = VISIBLE
+ drawDwell = true
}
override fun onAnimationEnd(animation: Animator?) {
- visibility = GONE
- resetRippleAlpha()
+ drawDwell = false
+ resetDwellAlpha()
}
})
start()
@@ -142,101 +164,54 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
/**
- * Ripple that moves animates from an outer ripple ring of
- * startRadius => endRadius => expandedRadius
+ * Plays a ripple animation that grows to the dwellRadius with distortion.
*/
- fun startDwellRipple(
- startRadius: Float,
- endRadius: Float,
- expandedRadius: Float,
- isDozing: Boolean
- ) {
+ fun startDwellRipple(isDozing: Boolean) {
if (unlockedRippleInProgress || dwellPulseOutAnimator?.isRunning == true) {
return
}
- // we divide by 4 because the desired startRadius and endRadius is for the ripple's outer
- // ring see RippleShader
- val startDwellProgress = startRadius / radius / 4f
- val endInitialDwellProgress = endRadius / radius / 4f
- val endExpandDwellProgress = expandedRadius / radius / 4f
-
- val alpha = if (isDozing) aodDwellAlpha else dwellAlpha
- val pulseOutEndAlpha = (255 * alpha).toInt()
- val expandDwellEndAlpha = kotlin.math.min((255 * (alpha + .25f)).toInt(), 255)
- val dwellPulseOutRippleAnimator = ValueAnimator.ofFloat(startDwellProgress,
- endInitialDwellProgress).apply {
- interpolator = Interpolators.LINEAR_OUT_SLOW_IN
- duration = if (isDozing) aodDwellPulseDuration else dwellPulseDuration
- addUpdateListener { animator ->
- val now = animator.currentPlayTime
- rippleShader.progress = animator.animatedValue as Float
- rippleShader.time = now.toFloat()
-
- invalidate()
- }
- }
+ updateDwellRippleColor(isDozing)
- val dwellPulseOutAlphaAnimator = ValueAnimator.ofInt(0, pulseOutEndAlpha).apply {
+ val dwellPulseOutRippleAnimator = ValueAnimator.ofFloat(0f, .8f).apply {
interpolator = Interpolators.LINEAR
- duration = if (isDozing) aodDwellAlphaDuration else dwellAlphaDuration
+ duration = dwellPulseDuration
addUpdateListener { animator ->
- rippleShader.color = ColorUtils.setAlphaComponent(
- rippleShader.color,
- animator.animatedValue as Int
- )
+ val now = animator.currentPlayTime
+ dwellShader.progress = animator.animatedValue as Float
+ dwellShader.time = now.toFloat()
+
invalidate()
}
}
// slowly animate outwards until we receive a call to retractRipple or startUnlockedRipple
- val expandDwellRippleAnimator = ValueAnimator.ofFloat(endInitialDwellProgress,
- endExpandDwellProgress).apply {
+ val expandDwellRippleAnimator = ValueAnimator.ofFloat(.8f, 1f).apply {
interpolator = Interpolators.LINEAR_OUT_SLOW_IN
- duration = if (isDozing) aodDwellExpandDuration else dwellExpandDuration
+ duration = dwellExpandDuration
addUpdateListener { animator ->
val now = animator.currentPlayTime
- rippleShader.progress = animator.animatedValue as Float
- rippleShader.time = now.toFloat()
+ dwellShader.progress = animator.animatedValue as Float
+ dwellShader.time = now.toFloat()
invalidate()
}
}
- val expandDwellAlphaAnimator = ValueAnimator.ofInt(pulseOutEndAlpha, expandDwellEndAlpha)
- .apply {
- interpolator = Interpolators.LINEAR
- duration = if (isDozing) aodDwellExpandDuration else dwellExpandDuration
- addUpdateListener { animator ->
- rippleShader.color = ColorUtils.setAlphaComponent(
- rippleShader.color,
- animator.animatedValue as Int
- )
- invalidate()
- }
- }
-
- val initialDwellPulseOutAnimator = AnimatorSet().apply {
- playTogether(dwellPulseOutRippleAnimator, dwellPulseOutAlphaAnimator)
- }
- val expandDwellAnimator = AnimatorSet().apply {
- playTogether(expandDwellRippleAnimator, expandDwellAlphaAnimator)
- }
-
dwellPulseOutAnimator = AnimatorSet().apply {
playSequentially(
- initialDwellPulseOutAnimator,
- expandDwellAnimator
+ dwellPulseOutRippleAnimator,
+ expandDwellRippleAnimator
)
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
retractAnimator?.cancel()
- rippleShader.shouldFadeOutRipple = false
visibility = VISIBLE
+ drawDwell = true
}
override fun onAnimationEnd(animation: Animator?) {
- visibility = GONE
+ drawDwell = false
resetRippleAlpha()
}
})
@@ -252,16 +227,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
return // Ignore if ripple effect is already playing
}
- var rippleStart = 0f
- var alphaDuration = alphaInDuration
- if (dwellPulseOutAnimator?.isRunning == true || retractAnimator?.isRunning == true) {
- rippleStart = rippleShader.progress
- alphaDuration = 0
- dwellPulseOutAnimator?.cancel()
- retractAnimator?.cancel()
- }
-
- val rippleAnimator = ValueAnimator.ofFloat(rippleStart, 1f).apply {
+ val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
interpolator = Interpolators.LINEAR_OUT_SLOW_IN
duration = AuthRippleController.RIPPLE_ANIMATION_DURATION
addUpdateListener { animator ->
@@ -274,7 +240,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
- duration = alphaDuration
+ duration = alphaInDuration
addUpdateListener { animator ->
rippleShader.color = ColorUtils.setAlphaComponent(
rippleShader.color,
@@ -293,12 +259,14 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
override fun onAnimationStart(animation: Animator?) {
unlockedRippleInProgress = true
rippleShader.shouldFadeOutRipple = true
+ drawRipple = true
visibility = VISIBLE
}
override fun onAnimationEnd(animation: Animator?) {
onAnimationEnd?.run()
unlockedRippleInProgress = false
+ drawRipple = false
visibility = GONE
}
})
@@ -313,17 +281,42 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
)
}
- fun setColor(color: Int) {
- rippleShader.color = color
+ fun setLockScreenColor(color: Int) {
+ lockScreenColorVal = color
+ rippleShader.color = lockScreenColorVal
resetRippleAlpha()
}
+ fun updateDwellRippleColor(isDozing: Boolean) {
+ if (isDozing) {
+ dwellShader.color = Color.WHITE
+ } else {
+ dwellShader.color = lockScreenColorVal
+ }
+ resetDwellAlpha()
+ }
+
+ fun resetDwellAlpha() {
+ dwellShader.color = ColorUtils.setAlphaComponent(
+ dwellShader.color,
+ 255
+ )
+ }
+
override fun onDraw(canvas: Canvas?) {
// To reduce overdraw, we mask the effect to a circle whose radius is big enough to cover
// the active effect area. Values here should be kept in sync with the
// animation implementation in the ripple shader.
- val maskRadius = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
- (1 - rippleShader.progress)) * radius * 2f
- canvas?.drawCircle(origin.x, origin.y, maskRadius, ripplePaint)
+ if (drawDwell) {
+ val maskRadius = (1 - (1 - dwellShader.progress) * (1 - dwellShader.progress) *
+ (1 - dwellShader.progress)) * dwellRadius * 2f
+ canvas?.drawCircle(dwellOrigin.x, dwellOrigin.y, maskRadius, dwellPaint)
+ }
+
+ if (drawRipple) {
+ val mask = (1 - (1 - rippleShader.progress) * (1 - rippleShader.progress) *
+ (1 - rippleShader.progress)) * radius * 2f
+ canvas?.drawCircle(origin.x, origin.y, mask, ripplePaint)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
index a1d086b5d768..73d3e2afac7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
@@ -59,8 +59,8 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
}
vec2 distort(vec2 p, float time, float distort_amount_xy, float frequency) {
- return p + vec2(sin(p.x * frequency + in_phase1),
- cos(p.y * frequency * 1.23 + in_phase2)) * distort_amount_xy;
+ return p + vec2(sin(p.y * frequency + in_phase1),
+ cos(p.x * frequency * -1.23 + in_phase2)) * distort_amount_xy;
}
vec4 ripple(vec2 p, float distort_xy, float frequency) {
@@ -73,11 +73,11 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
"""
private const val SHADER_MAIN = """vec4 main(vec2 p) {
vec4 color1 = ripple(p,
- 12 * in_distortion_strength, // distort_xy
+ 34 * in_distortion_strength, // distort_xy
0.012 // frequency
);
vec4 color2 = ripple(p,
- 17.5 * in_distortion_strength, // distort_xy
+ 49 * in_distortion_strength, // distort_xy
0.018 // frequency
);
// Alpha blend between two layers.
@@ -128,8 +128,8 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
set(value) {
field = value * 0.001f
setUniform("in_time", field)
- setUniform("in_phase1", field * 2f + 0.367f)
- setUniform("in_phase2", field * 5.2f * 1.531f)
+ setUniform("in_phase1", field * 3f + 0.367f)
+ setUniform("in_phase2", field * 7.2f * 1.531f)
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 2c4808a4b84f..5128ccc15d9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -131,7 +131,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
false /* isStrongBiometric */)
// THEN update sensor location and show ripple
- verify(rippleView).setSensorLocation(fpsLocation)
+ verify(rippleView).setFingerprintSensorLocation(fpsLocation, -1f)
verify(rippleView).startUnlockedRipple(any())
}
@@ -292,10 +292,10 @@ class AuthRippleControllerTest : SysuiTestCase() {
reset(rippleView)
captor.value.onThemeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setLockScreenColor(ArgumentMatchers.anyInt())
reset(rippleView)
captor.value.onUiModeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setLockScreenColor(ArgumentMatchers.anyInt())
}
}