Loading src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +128 −48 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; /** Loading @@ -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 Loading @@ -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; Loading @@ -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<FingerprintSensorPropertiesInternal> props = fingerprintManager.getSensorPropertiesInternal(); mFingerprintManager.getSensorPropertiesInternal(); mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType(); mAccessibilityManager = getSystemService(AccessibilityManager.class); Loading Loading @@ -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; } Loading @@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } private void updateTitleAndDescription() { if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { if (mCanAssumeUdfps) { updateTitleAndDescriptionForUdfps(); return; } if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { 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 Loading @@ -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); break; } } 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); @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 { setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); } return STAGE_EDGES; } } private boolean isCenterEnrollmentComplete() { 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 Loading Loading @@ -489,8 +565,8 @@ 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) { } Loading @@ -501,7 +577,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { @Override public void onAnimationEnd(Animator animation) { if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); } } Loading @@ -509,6 +585,10 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { 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() { @Override Loading Loading
src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +128 −48 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; /** Loading @@ -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 Loading @@ -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; Loading @@ -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<FingerprintSensorPropertiesInternal> props = fingerprintManager.getSensorPropertiesInternal(); mFingerprintManager.getSensorPropertiesInternal(); mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType(); mAccessibilityManager = getSystemService(AccessibilityManager.class); Loading Loading @@ -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; } Loading @@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } private void updateTitleAndDescription() { if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { if (mCanAssumeUdfps) { updateTitleAndDescriptionForUdfps(); return; } if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { 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 Loading @@ -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); break; } } 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); @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 { setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); } return STAGE_EDGES; } } private boolean isCenterEnrollmentComplete() { 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 Loading Loading @@ -489,8 +565,8 @@ 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) { } Loading @@ -501,7 +577,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { @Override public void onAnimationEnd(Animator animation) { if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); } } Loading @@ -509,6 +585,10 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { 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() { @Override Loading