Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ffe187d authored by Wu Ahan's avatar Wu Ahan Committed by MiltonWu
Browse files

Implement sfps enroll improvement feature with feature provider

Bug: 288155127
Test: Manually
Test: atest FingerprintEnrollEnrollingTest.java
Change-Id: Idb6e5afab4b9cbf8f2ed26819a55dcb34acb1ab9
parent 6a9297df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ aconfig_declarations {
        "settings_experience_flag_declarations.aconfig",
        "settings_onboarding_experience_flag_declarations.aconfig",
        "settings_telephony_flag_declarations.aconfig",
        "settings_biometrics_integration_declarations.aconfig",
    ],
}

+9 −0
Original line number Diff line number Diff line
package: "com.android.settings.flags"

flag {
  name: "sfps_enroll_refinement"
  namespace: "biometrics_integration"
  description: "This flag controls whether the sfps pause enrollment feature should be enabled"
  bug: "288155127"
}
+59 −41
Original line number Diff line number Diff line
@@ -68,10 +68,13 @@ import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.biometrics.fingerprint.feature.SfpsEnrollmentFeature;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.display.DisplayDensityUtils;

import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.LottieCompositionFactory;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.model.KeyPath;
@@ -99,27 +102,22 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {

    private static final int PROGRESS_BAR_MAX = 10000;

    private static final int STAGE_UNKNOWN = -1;
    public 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_LEFT_EDGE = 3;
    private static final int STAGE_RIGHT_EDGE = 4;

    @VisibleForTesting
    protected static final int SFPS_STAGE_NO_ANIMATION = 0;
    public static final int SFPS_STAGE_NO_ANIMATION = 0;

    @VisibleForTesting
    protected static final int SFPS_STAGE_CENTER = 1;
    public static final int SFPS_STAGE_CENTER = 1;

    @VisibleForTesting
    protected static final int SFPS_STAGE_FINGERTIP = 2;
    public static final int SFPS_STAGE_FINGERTIP = 2;

    @VisibleForTesting
    protected static final int SFPS_STAGE_LEFT_EDGE = 3;
    public static final int SFPS_STAGE_LEFT_EDGE = 3;

    @VisibleForTesting
    protected static final int SFPS_STAGE_RIGHT_EDGE = 4;
    public static final int SFPS_STAGE_RIGHT_EDGE = 4;

    @IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_LEFT_EDGE,
            STAGE_RIGHT_EDGE})
@@ -196,6 +194,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
    private OrientationEventListener mOrientationEventListener;
    private int mPreviousRotation = 0;

    private SfpsEnrollmentFeature mSfpsEnrollmentFeature;

    @VisibleForTesting
    protected boolean shouldShowLottie() {
        DisplayDensityUtils displayDensity = new DisplayDensityUtils(getApplicationContext());
@@ -232,6 +232,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
        mAccessibilityManager = getSystemService(AccessibilityManager.class);
        mIsAccessibilityEnabled = mAccessibilityManager.isEnabled();

        mSfpsEnrollmentFeature = mCanAssumeSfps
                ? FeatureFactory.getFeatureFactory()
                        .getFingerprintFeatureProvider().getSfpsEnrollmentFeature()
                : null;

        listenOrientationEvent();

        if (mCanAssumeUdfps) {
@@ -599,7 +604,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
        }
        switch (getCurrentSfpsStage()) {
            case SFPS_STAGE_NO_ANIMATION:
                setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
                setHeaderText(mSfpsEnrollmentFeature
                        .getFeaturedStageHeaderResource(SFPS_STAGE_NO_ANIMATION));
                if (!mHaveShownSfpsNoAnimationLottie && mIllustrationLottie != null) {
                    mHaveShownSfpsNoAnimationLottie = true;
                    mIllustrationLottie.setContentDescription(
@@ -608,39 +614,48 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
                                    0
                            )
                    );
                    configureEnrollmentStage(R.raw.sfps_lottie_no_animation);
                    configureEnrollmentStage(mSfpsEnrollmentFeature
                            .getSfpsEnrollLottiePerStage(SFPS_STAGE_NO_ANIMATION));
                }
                break;

            case SFPS_STAGE_CENTER:
                setHeaderText(R.string.security_settings_sfps_enroll_finger_center_title);
                setHeaderText(mSfpsEnrollmentFeature
                        .getFeaturedStageHeaderResource(SFPS_STAGE_CENTER));
                if (!mHaveShownSfpsCenterLottie && mIllustrationLottie != null) {
                    mHaveShownSfpsCenterLottie = true;
                    configureEnrollmentStage(R.raw.sfps_lottie_pad_center);
                    configureEnrollmentStage(mSfpsEnrollmentFeature
                            .getSfpsEnrollLottiePerStage(SFPS_STAGE_CENTER));
                }
                break;

            case SFPS_STAGE_FINGERTIP:
                setHeaderText(R.string.security_settings_sfps_enroll_fingertip_title);
                setHeaderText(mSfpsEnrollmentFeature
                        .getFeaturedStageHeaderResource(SFPS_STAGE_FINGERTIP));
                if (!mHaveShownSfpsTipLottie && mIllustrationLottie != null) {
                    mHaveShownSfpsTipLottie = true;
                    configureEnrollmentStage(R.raw.sfps_lottie_tip);
                    configureEnrollmentStage(mSfpsEnrollmentFeature
                            .getSfpsEnrollLottiePerStage(SFPS_STAGE_FINGERTIP));
                }
                break;

            case SFPS_STAGE_LEFT_EDGE:
                setHeaderText(R.string.security_settings_sfps_enroll_left_edge_title);
                setHeaderText(mSfpsEnrollmentFeature
                        .getFeaturedStageHeaderResource(SFPS_STAGE_LEFT_EDGE));
                if (!mHaveShownSfpsLeftEdgeLottie && mIllustrationLottie != null) {
                    mHaveShownSfpsLeftEdgeLottie = true;
                    configureEnrollmentStage(R.raw.sfps_lottie_left_edge);
                    configureEnrollmentStage(mSfpsEnrollmentFeature
                            .getSfpsEnrollLottiePerStage(SFPS_STAGE_LEFT_EDGE));
                }
                break;

            case SFPS_STAGE_RIGHT_EDGE:
                setHeaderText(R.string.security_settings_sfps_enroll_right_edge_title);
                setHeaderText(mSfpsEnrollmentFeature
                        .getFeaturedStageHeaderResource(SFPS_STAGE_RIGHT_EDGE));
                if (!mHaveShownSfpsRightEdgeLottie && mIllustrationLottie != null) {
                    mHaveShownSfpsRightEdgeLottie = true;
                    configureEnrollmentStage(R.raw.sfps_lottie_right_edge);
                    configureEnrollmentStage(mSfpsEnrollmentFeature
                            .getSfpsEnrollLottiePerStage(SFPS_STAGE_RIGHT_EDGE));
                }
                break;

@@ -661,15 +676,23 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
    }

    @VisibleForTesting void configureEnrollmentStage(@RawRes int lottie) {
        if (lottie == STAGE_UNKNOWN) return;
        if (!mCanAssumeSfps) {
            setDescriptionText("");
        }
        LottieCompositionFactory.fromRawRes(this, lottie)
                .addListener((c) -> {
                    mIllustrationLottie.setComposition(c);
                    mIllustrationLottie.setVisibility(View.VISIBLE);
                    mIllustrationLottie.playAnimation();
                });
                .addListener((c) -> onLottieComposition(mIllustrationLottie, c));
    }

    private void onLottieComposition(LottieAnimationView view, LottieComposition composition) {
        if (view == null || composition == null) {
            return;
        }
        view.setComposition(composition);
        view.setVisibility(View.VISIBLE);
        view.playAnimation();
        mSfpsEnrollmentFeature.handleOnEnrollmentLottieComposition(
                view, composition, getCurrentSfpsStage());
    }

    @EnrollStage
@@ -699,17 +722,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
        }

        final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining();
        if (progressSteps < getStageThresholdSteps(0)) {
            return SFPS_STAGE_NO_ANIMATION;
        } else if (progressSteps < getStageThresholdSteps(1)) {
            return SFPS_STAGE_CENTER;
        } else if (progressSteps < getStageThresholdSteps(2)) {
            return SFPS_STAGE_FINGERTIP;
        } else if (progressSteps < getStageThresholdSteps(3)) {
            return SFPS_STAGE_LEFT_EDGE;
        } else {
            return SFPS_STAGE_RIGHT_EDGE;
        }
        return mSfpsEnrollmentFeature
                .getCurrentSfpsEnrollStage(progressSteps, this::getStageThresholdSteps);
    }

    private boolean isStageHalfCompleted() {
@@ -740,22 +754,26 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
            Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
            return 1;
        }
        return Math.round(mSidecar.getEnrollmentSteps()
                * mFingerprintManager.getEnrollStageThreshold(index));
        final float threshold = mSfpsEnrollmentFeature.getEnrollStageThreshold(this, index);
        return Math.round(mSidecar.getEnrollmentSteps() * threshold);
    }

    @Override
    public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
        if (!TextUtils.isEmpty(helpString)) {
        final CharSequence featuredString = mSfpsEnrollmentFeature
                .getFeaturedVendorString(this, helpMsgId, helpString);

        if (!TextUtils.isEmpty(featuredString)) {
            if (!(mCanAssumeUdfps || mCanAssumeSfps)) {
                mErrorText.removeCallbacks(mTouchAgainRunnable);
            }
            showError(helpString);
            showError(featuredString);

            if (mUdfpsEnrollHelper != null) mUdfpsEnrollHelper.onEnrollmentHelp();
        }

        dismissTouchDialogIfSfps();
        mSfpsEnrollmentFeature.handleOnEnrollmentHelp(helpMsgId, featuredString, () -> this);
    }

    @Override
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.biometrics.fingerprint;

import com.android.settings.biometrics.fingerprint.feature.SfpsEnrollmentFeature;

public interface FingerprintFeatureProvider {
    /**
     * Gets the feature implementation of SFPS enrollment.
     * @return the feature implementation
     */
    SfpsEnrollmentFeature getSfpsEnrollmentFeature();
}
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.biometrics.fingerprint;

import com.android.settings.biometrics.fingerprint.feature.SfpsEnrollmentFeature;
import com.android.settings.biometrics.fingerprint.feature.SfpsEnrollmentFeatureImpl;

public class FingerprintFeatureProviderImpl implements FingerprintFeatureProvider {

    private SfpsEnrollmentFeature mSfpsEnrollmentFeatureImpl;

    @Override
    public SfpsEnrollmentFeature getSfpsEnrollmentFeature() {
        if (mSfpsEnrollmentFeatureImpl == null) {
            mSfpsEnrollmentFeatureImpl = new SfpsEnrollmentFeatureImpl();
        }
        return mSfpsEnrollmentFeatureImpl;
    }
}
Loading