Merge "Add haptic feedback to auth ripple animation" into sc-dev am: 8c8765d3c3

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14666655

Change-Id: Ida4d8577d34a8f11a4252610499cfc509036365c
This commit is contained in:
TreeHugger Robot
2021-05-26 10:53:42 +00:00
committed by Automerger Merge Worker

View File

@@ -23,7 +23,11 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PointF
import android.media.AudioAttributes
import android.os.VibrationEffect
import android.os.Vibrator
import android.util.AttributeSet
import android.util.MathUtils
import android.view.View
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
@@ -31,15 +35,26 @@ import com.android.systemui.statusbar.charging.RippleShader
private const val RIPPLE_ANIMATION_DURATION: Long = 1533
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
private const val RIPPLE_VIBRATION_PRIMITIVE: Int = VibrationEffect.Composition.PRIMITIVE_LOW_TICK
private const val RIPPLE_VIBRATION_SIZE: Int = 60
private const val RIPPLE_VIBRATION_SCALE_START: Float = 0.6f
private const val RIPPLE_VIBRATION_SCALE_DECAY: Float = -0.1f
/**
* Expanding ripple effect on the transition from biometric authentication success to showing
* launcher.
*/
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
private val vibrator: Vibrator? = context?.getSystemService(Vibrator::class.java)
private var rippleInProgress: Boolean = false
private val rippleShader = RippleShader()
private val ripplePaint = Paint()
private val rippleVibrationEffect = createVibrationEffect(vibrator)
private val rippleVibrationAttrs =
AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build()
init {
rippleShader.color = 0xffffffff.toInt() // default color
@@ -95,6 +110,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
visibility = GONE
}
})
vibrate()
animatorSet.start()
visibility = VISIBLE
rippleInProgress = true
@@ -108,4 +124,23 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
// draw over the entire screen
canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
}
private fun vibrate() {
if (rippleVibrationEffect != null) {
vibrator?.vibrate(rippleVibrationEffect, rippleVibrationAttrs)
}
}
private fun createVibrationEffect(vibrator: Vibrator?): VibrationEffect? {
if (vibrator?.areAllPrimitivesSupported(RIPPLE_VIBRATION_PRIMITIVE) == false) {
return null
}
val composition = VibrationEffect.startComposition()
for (i in 0 until RIPPLE_VIBRATION_SIZE) {
val scale =
RIPPLE_VIBRATION_SCALE_START * MathUtils.exp(RIPPLE_VIBRATION_SCALE_DECAY * i)
composition.addPrimitive(RIPPLE_VIBRATION_PRIMITIVE, scale, 0 /* delay */)
}
return composition.compose()
}
}