From 5c85bb936a336fc39b0c4f895647754795ba2660 Mon Sep 17 00:00:00 2001 From: Chandru Date: Fri, 21 Oct 2022 12:03:23 +0000 Subject: [PATCH 1/2] Refactor deeply nested rim animator into three cases for scanning, success, not successful Bug: 254814998 Test: verified manually, face scanning rim pulses 6 times, face scanning rim success animation identical, face scanning failure/not success animation identical to build without change. Change-Id: Iefd7e8e82c2eebb5f50ace7ab66931a43258e8ac --- .../android/systemui/FaceScanningOverlay.kt | 129 +++++++++++------- 1 file changed, 80 insertions(+), 49 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index e69adbd8b6346..7e839dc39485c 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -19,6 +19,7 @@ package com.android.systemui import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.AnimatorSet +import android.animation.TimeInterpolator import android.animation.ValueAnimator import android.content.Context import android.graphics.Canvas @@ -163,54 +164,14 @@ class FaceScanningOverlay( } rimAnimator?.cancel() - rimAnimator = AnimatorSet().apply { - if (showScanningAnim) { - // animate in camera protection, rim, and then pulse in/out - playSequentially( - cameraProtectionAnimator, - createRimAppearAnimator(), - createPulseAnimator() - ) - } else { - val rimDisappearAnimator = ValueAnimator.ofFloat( - rimProgress, - if (faceAuthSucceeded) PULSE_RADIUS_SUCCESS - else SHOW_CAMERA_PROTECTION_SCALE - ).apply { - duration = - if (faceAuthSucceeded) PULSE_SUCCESS_DISAPPEAR_DURATION - else PULSE_ERROR_DISAPPEAR_DURATION - interpolator = - if (faceAuthSucceeded) Interpolators.STANDARD_DECELERATE - else Interpolators.STANDARD - addUpdateListener(this@FaceScanningOverlay::updateRimProgress) - addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - rimProgress = HIDDEN_RIM_SCALE - invalidate() - } - }) - } - if (faceAuthSucceeded) { - val successOpacityAnimator = ValueAnimator.ofInt(255, 0).apply { - duration = PULSE_SUCCESS_DISAPPEAR_DURATION - interpolator = Interpolators.LINEAR - addUpdateListener(this@FaceScanningOverlay::updateRimAlpha) - addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - rimPaint.alpha = 255 - invalidate() - } - }) - } - val rimSuccessAnimator = AnimatorSet() - rimSuccessAnimator.playTogether(rimDisappearAnimator, successOpacityAnimator) - playTogether(rimSuccessAnimator, cameraProtectionAnimator) - } else { - playTogether(rimDisappearAnimator, cameraProtectionAnimator) - } - } - + rimAnimator = if (showScanningAnim) { + createFaceScanningRimAnimator() + } else if (faceAuthSucceeded) { + createFaceSuccessRimAnimator() + } else { + createFaceNotSuccessRimAnimator() + } + rimAnimator?.apply { addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { rimAnimator = null @@ -219,7 +180,77 @@ class FaceScanningOverlay( } } }) - start() + } + rimAnimator?.start() + } + + private fun createFaceSuccessRimAnimator(): AnimatorSet { + val rimSuccessAnimator = AnimatorSet() + rimSuccessAnimator.playTogether( + createRimDisappearAnimator( + PULSE_RADIUS_SUCCESS, + PULSE_SUCCESS_DISAPPEAR_DURATION, + Interpolators.STANDARD_DECELERATE + ), + createSuccessOpacityAnimator(), + ) + return AnimatorSet().apply { + playTogether(rimSuccessAnimator, cameraProtectionAnimator) + } + } + + private fun createFaceNotSuccessRimAnimator(): AnimatorSet { + return AnimatorSet().apply { + playTogether( + createRimDisappearAnimator( + SHOW_CAMERA_PROTECTION_SCALE, + PULSE_ERROR_DISAPPEAR_DURATION, + Interpolators.STANDARD + ), + cameraProtectionAnimator, + ) + } + } + + private fun createRimDisappearAnimator( + endValue: Float, + animDuration: Long, + timeInterpolator: TimeInterpolator + ): ValueAnimator { + return ValueAnimator.ofFloat(rimProgress, endValue).apply { + duration = animDuration + interpolator = timeInterpolator + addUpdateListener(this@FaceScanningOverlay::updateRimProgress) + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + rimProgress = HIDDEN_RIM_SCALE + invalidate() + } + }) + } + } + + private fun createSuccessOpacityAnimator(): ValueAnimator { + return ValueAnimator.ofInt(255, 0).apply { + duration = PULSE_SUCCESS_DISAPPEAR_DURATION + interpolator = Interpolators.LINEAR + addUpdateListener(this@FaceScanningOverlay::updateRimAlpha) + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + rimPaint.alpha = 255 + invalidate() + } + }) + } + } + + private fun createFaceScanningRimAnimator(): AnimatorSet { + return AnimatorSet().apply { + playSequentially( + cameraProtectionAnimator, + createRimAppearAnimator(), + createPulseAnimator() + ) } } From 2b784144a457c5fc16e6f6ec0846450b03c388e4 Mon Sep 17 00:00:00 2001 From: Chandru Date: Fri, 21 Oct 2022 12:17:39 +0000 Subject: [PATCH 2/2] Move private methods together below overriden public methods. Bug: 254814998 Test: NA Change-Id: If4e2ba62d16a74d4e4aba86dd2de67535685111c --- .../android/systemui/FaceScanningOverlay.kt | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index 7e839dc39485c..3e0fa455d39e9 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -96,32 +96,6 @@ class FaceScanningOverlay( } } - private fun drawFaceScanningRim(canvas: Canvas) { - val rimPath = Path(protectionPath) - scalePath(rimPath, rimProgress) - rimPaint.style = Paint.Style.FILL - val rimPaintAlpha = rimPaint.alpha - rimPaint.color = ColorUtils.blendARGB( - faceScanningAnimColor, - Color.WHITE, - statusBarStateController.dozeAmount - ) - rimPaint.alpha = rimPaintAlpha - canvas.drawPath(rimPath, rimPaint) - } - - private fun drawCameraProtection(canvas: Canvas) { - val scaledProtectionPath = Path(protectionPath) - scalePath(scaledProtectionPath, cameraProtectionProgress) - paint.style = Paint.Style.FILL - paint.color = cameraProtectionColor - canvas.drawPath(scaledProtectionPath, paint) - } - - override fun updateVisOnUpdateCutout(): Boolean { - return false // instead, we always update the visibility whenever face scanning starts/ends - } - override fun enableShowProtection(show: Boolean) { val showScanningAnimNow = keyguardUpdateMonitor.isFaceDetectionRunning && show if (showScanningAnimNow == showScanningAnim) { @@ -184,6 +158,61 @@ class FaceScanningOverlay( rimAnimator?.start() } + override fun updateVisOnUpdateCutout(): Boolean { + return false // instead, we always update the visibility whenever face scanning starts/ends + } + + override fun updateProtectionBoundingPath() { + super.updateProtectionBoundingPath() + rimRect.set(protectionRect) + rimRect.scale(rimProgress) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + if (mBounds.isEmpty()) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + return + } + if (showScanningAnim) { + // Make sure that our measured height encompasses the extra space for the animation + mTotalBounds.union(mBoundingRect) + mTotalBounds.union( + rimRect.left.toInt(), + rimRect.top.toInt(), + rimRect.right.toInt(), + rimRect.bottom.toInt()) + setMeasuredDimension( + resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), + resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)) + } else { + setMeasuredDimension( + resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), + resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)) + } + } + + private fun drawFaceScanningRim(canvas: Canvas) { + val rimPath = Path(protectionPath) + scalePath(rimPath, rimProgress) + rimPaint.style = Paint.Style.FILL + val rimPaintAlpha = rimPaint.alpha + rimPaint.color = ColorUtils.blendARGB( + faceScanningAnimColor, + Color.WHITE, + statusBarStateController.dozeAmount + ) + rimPaint.alpha = rimPaintAlpha + canvas.drawPath(rimPath, rimPaint) + } + + private fun drawCameraProtection(canvas: Canvas) { + val scaledProtectionPath = Path(protectionPath) + scalePath(scaledProtectionPath, cameraProtectionProgress) + paint.style = Paint.Style.FILL + paint.color = cameraProtectionColor + canvas.drawPath(scaledProtectionPath, paint) + } + private fun createFaceSuccessRimAnimator(): AnimatorSet { val rimSuccessAnimator = AnimatorSet() rimSuccessAnimator.playTogether( @@ -298,35 +327,6 @@ class FaceScanningOverlay( } } - override fun updateProtectionBoundingPath() { - super.updateProtectionBoundingPath() - rimRect.set(protectionRect) - rimRect.scale(rimProgress) - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - if (mBounds.isEmpty()) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - return - } - if (showScanningAnim) { - // Make sure that our measured height encompasses the extra space for the animation - mTotalBounds.union(mBoundingRect) - mTotalBounds.union( - rimRect.left.toInt(), - rimRect.top.toInt(), - rimRect.right.toInt(), - rimRect.bottom.toInt()) - setMeasuredDimension( - resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), - resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)) - } else { - setMeasuredDimension( - resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), - resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)) - } - } - private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { override fun onBiometricAuthenticated( userId: Int,