diff options
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())      }  } |