Add animation for progress bar and lottie in fingerprint enrollment

Test: Manual - While enrolling a fingerprint, onHelp will cause the
lottie and progress bar to shake
Bug: 266838595

Change-Id: I547d86182a87846aca7d025b35a008675f449e2e
Merged-in: I547d86182a87846aca7d025b35a008675f449e2e
diff --git a/res/layout/sfps_enroll_enrolling.xml b/res/layout/sfps_enroll_enrolling.xml
index 498d751..e0f9d1f 100644
--- a/res/layout/sfps_enroll_enrolling.xml
+++ b/res/layout/sfps_enroll_enrolling.xml
@@ -32,11 +32,13 @@
         android:clipChildren="false">
 
         <RelativeLayout
+            android:id="@+id/progress_lottie"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1"
             android:gravity="center"
-            android:orientation="vertical">
+            android:orientation="vertical"
+            android:translationX="0dp">
 
             <!-- Animation res MUST be set in code -->
             <com.airbnb.lottie.LottieAnimationView
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 0b30f87..c76a58a 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -53,10 +53,12 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import androidx.annotation.IdRes;
@@ -185,6 +187,7 @@
     private boolean mHaveShownSfpsLeftEdgeLottie;
     private boolean mHaveShownSfpsRightEdgeLottie;
     private boolean mShouldShowLottie;
+    private ObjectAnimator mHelpAnimation;
 
     private OrientationEventListener mOrientationEventListener;
     private int mPreviousRotation = 0;
@@ -276,6 +279,7 @@
         } else if (mCanAssumeSfps) {
             setContentView(R.layout.sfps_enroll_enrolling);
             setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
+            setHelpAnimation();
         } else {
             setContentView(R.layout.fingerprint_enroll_enrolling);
             setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
@@ -350,6 +354,17 @@
         maybeHideSfpsText(config);
     }
 
+    private void setHelpAnimation() {
+        final float translationX = 40;
+        final int duration = 550;
+        final RelativeLayout progressLottieLayout = findViewById(R.id.progress_lottie);
+        mHelpAnimation = ObjectAnimator.ofFloat(progressLottieLayout,
+                "translationX" /* propertyName */,
+                0, translationX, -1 * translationX, translationX, 0f);
+        mHelpAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
+        mHelpAnimation.setDuration(duration);
+        mHelpAnimation.setAutoCancel(false);
+    }
     @Override
     protected BiometricEnrollSidecar getSidecar() {
         final FingerprintEnrollSidecar sidecar = new FingerprintEnrollSidecar(this,
@@ -755,6 +770,7 @@
         if (!TextUtils.isEmpty(helpString)) {
             if (!(mCanAssumeUdfps || mCanAssumeSfps)) {
                 mErrorText.removeCallbacks(mTouchAgainRunnable);
+                mErrorText.removeCallbacks(mTouchAgainRunnable);
             }
             showError(helpString);
         }
@@ -848,6 +864,9 @@
             // Show nothing for subtitle when getting an error message.
             setDescriptionText("");
             if (mCanAssumeSfps) {
+                if (!mHelpAnimation.isRunning()) {
+                    mHelpAnimation.start();
+                }
                 applySfpsErrorDynamicColors(getApplicationContext(), true);
             }
         } else {
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index ee6ae22..9052322 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -36,6 +36,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -80,6 +81,8 @@
 
     @Mock private LottieAnimationView mIllustrationLottie;
 
+    @Mock private ObjectAnimator mHelpAnimation;
+
     @Mock private FingerprintEnrollSidecar mSidecar;
 
     @Mock private Display mMockDisplay;
@@ -178,6 +181,15 @@
         assertThat(observedLottieAssetOrder).isEqualTo(expectedLottieAssetOrder);
     }
 
+    @Test
+    public void fingerprintSfpsEnrollHelpAnimation() {
+        initializeActivityFor(TYPE_POWER_BUTTON);
+        ReflectionHelpers.setField(mActivity, "mHelpAnimation", mHelpAnimation);
+        mActivity.onEnrollmentHelp(0 /* helpMsgId */, "Test help message" /* helpString */);
+
+        verify(mHelpAnimation).start();
+    }
+
     // SFPS_STAGE_CENTER is first stage with progress bar colors, starts at steps=25, remaining=25
     private void configureSfpsStageColorTest() {
         when(mSidecar.getEnrollmentSteps()).thenReturn(25);