diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index 714e210f9f1..c2bcee33428 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -18,6 +18,7 @@ package com.android.settings.biometrics.fingerprint; import android.animation.Animator; import android.animation.ObjectAnimator; +import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Dialog; import android.app.settings.SettingsEnums; @@ -58,6 +59,8 @@ import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupcompat.util.WizardManagerHelper; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -69,11 +72,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { static final String TAG_SIDECAR = "sidecar"; private static final int PROGRESS_BAR_MAX = 10000; - private static final int FINISH_DELAY = 250; - /** - * Enroll with two center touches before going to guided enrollment. - */ - private static final int NUM_CENTER_TOUCHES = 2; + + private static final int STAGE_UNKNOWN = -1; + private static final int STAGE_CENTER = 0; + private static final int STAGE_GUIDED = 1; + private static final int STAGE_FINGERTIP = 2; + private static final int STAGE_EDGES = 3; + + @IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_EDGES}) + @Retention(RetentionPolicy.SOURCE) + private @interface EnrollStage {} /** * If we don't see progress during this time, we show an error message to remind the users that @@ -100,6 +108,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); + private FingerprintManager mFingerprintManager; private boolean mCanAssumeUdfps; @Nullable private ProgressBar mProgressBar; private ObjectAnimator mProgressAnim; @@ -125,9 +134,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); + mFingerprintManager = getSystemService(FingerprintManager.class); final List props = - fingerprintManager.getSensorPropertiesInternal(); + mFingerprintManager.getSensorPropertiesInternal(); mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType(); mAccessibilityManager = getSystemService(AccessibilityManager.class); @@ -273,7 +282,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { // UDFPS animations are owned by SystemUI if (progress >= PROGRESS_BAR_MAX) { // Wait for any animations in SysUI to finish, then proceed to next page - getMainThreadHandler().postDelayed(mDelayedFinishRunnable, FINISH_DELAY); + getMainThreadHandler().postDelayed(mDelayedFinishRunnable, getFinishDelay()); } return; } @@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } private void updateTitleAndDescription() { + if (mCanAssumeUdfps) { + updateTitleAndDescriptionForUdfps(); + return; + } + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { - if (mCanAssumeUdfps) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); + } else { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); + } + } + + private void updateTitleAndDescriptionForUdfps() { + switch (getCurrentStage()) { + case STAGE_CENTER: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + setDescriptionText(R.string.security_settings_udfps_enroll_start_message); + break; + + case STAGE_GUIDED: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + if (mIsAccessibilityEnabled) { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); + } + break; + + case STAGE_FINGERTIP: + setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title); + if (isStageHalfCompleted()) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_title); + } else { + setDescriptionText(""); + } + break; + + case STAGE_EDGES: + setHeaderText(R.string.security_settings_udfps_enroll_edge_title); + if (isStageHalfCompleted()) { + setDescriptionText( + R.string.security_settings_fingerprint_enroll_repeat_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_edge_message); + } + break; + + case STAGE_UNKNOWN: + default: // setHeaderText(R.string.security_settings_fingerprint_enroll_udfps_title); // Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle, // which gets announced for a11y upon entering the page. For UDFPS, we want to @@ -309,41 +365,61 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { getLayout().setHeaderText( R.string.security_settings_fingerprint_enroll_udfps_title); setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - final CharSequence description = getString( R.string.security_settings_udfps_enroll_a11y); getLayout().getHeaderTextView().setContentDescription(description); setTitle(description); - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); - } - } else if (mCanAssumeUdfps && !isCenterEnrollmentComplete()) { - if (mIsSetupWizard) { - setHeaderText(R.string.security_settings_udfps_enroll_title_one_more_time); - } else { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - } - setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - } else { - if (mCanAssumeUdfps) { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - if (mIsAccessibilityEnabled) { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); - } else { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); - } - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); - } + break; } } - private boolean isCenterEnrollmentComplete() { + @EnrollStage + private int getCurrentStage() { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + return STAGE_UNKNOWN; + } + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + if (progressSteps < getStageThresholdSteps(0)) { + return STAGE_CENTER; + } else if (progressSteps < getStageThresholdSteps(1)) { + return STAGE_GUIDED; + } else if (progressSteps < getStageThresholdSteps(2)) { + return STAGE_FINGERTIP; + } else { + return STAGE_EDGES; + } + } + + private boolean isStageHalfCompleted() { + // Prior to first enrollment step. if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { return false; } - final int stepsEnrolled = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); - return stepsEnrolled >= NUM_CENTER_TOUCHES; + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + int prevThresholdSteps = 0; + for (int i = 0; i < mFingerprintManager.getEnrollStageCount(); i++) { + final int thresholdSteps = getStageThresholdSteps(i); + if (progressSteps >= prevThresholdSteps && progressSteps < thresholdSteps) { + final int adjustedProgress = progressSteps - prevThresholdSteps; + final int adjustedThreshold = thresholdSteps - prevThresholdSteps; + return adjustedProgress >= adjustedThreshold / 2; + } + prevThresholdSteps = thresholdSteps; + } + + // After last enrollment step. + return true; + } + + private int getStageThresholdSteps(int index) { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet"); + return 1; + } + return Math.round(mSidecar.getEnrollmentSteps() + * mFingerprintManager.getEnrollStageThreshold(index)); } @Override @@ -489,25 +565,29 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mOrientationEventListener = null; } - private final Animator.AnimatorListener mProgressAnimationListener - = new Animator.AnimatorListener() { + private final Animator.AnimatorListener mProgressAnimationListener = + new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { } + @Override + public void onAnimationStart(Animator animation) { } - @Override - public void onAnimationRepeat(Animator animation) { } + @Override + public void onAnimationRepeat(Animator animation) { } - @Override - public void onAnimationEnd(Animator animation) { - if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { - mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); - } - } + @Override + public void onAnimationEnd(Animator animation) { + if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { + mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); + } + } - @Override - public void onAnimationCancel(Animator animation) { } - }; + @Override + public void onAnimationCancel(Animator animation) { } + }; + + private long getFinishDelay() { + return mCanAssumeUdfps ? 400L : 250L; + } // Give the user a chance to see progress completed before jumping to the next stage. private final Runnable mDelayedFinishRunnable = new Runnable() {