From 2ffe187d1bbb75708ed19e54bb8d39d4cdf7f985 Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Mon, 11 Sep 2023 04:54:42 +0000 Subject: [PATCH] Implement sfps enroll improvement feature with feature provider Bug: 288155127 Test: Manually Test: atest FingerprintEnrollEnrollingTest.java Change-Id: Idb6e5afab4b9cbf8f2ed26819a55dcb34acb1ab9 --- aconfig/Android.bp | 1 + ...iometrics_integration_declarations.aconfig | 9 ++ .../FingerprintEnrollEnrolling.java | 100 +++++++++++------- .../FingerprintFeatureProvider.java | 27 +++++ .../FingerprintFeatureProviderImpl.java | 33 ++++++ .../feature/SfpsEnrollmentFeature.java | 91 ++++++++++++++++ .../feature/SfpsEnrollmentFeatureImpl.java | 89 ++++++++++++++++ .../settings/overlay/FeatureFactory.kt | 9 ++ .../settings/overlay/FeatureFactoryImpl.kt | 6 ++ .../FingerprintEnrollEnrollingTest.java | 26 +++++ .../testutils/FakeFeatureFactory.java | 8 ++ .../settings/testutils/FakeFeatureFactory.kt | 3 + .../testutils/FakeFeatureFactory.java | 8 ++ 13 files changed, 369 insertions(+), 41 deletions(-) create mode 100644 aconfig/settings_biometrics_integration_declarations.aconfig create mode 100644 src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProvider.java create mode 100644 src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProviderImpl.java create mode 100644 src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java create mode 100644 src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java diff --git a/aconfig/Android.bp b/aconfig/Android.bp index 6daa90cb1a7..7b571e0b89d 100644 --- a/aconfig/Android.bp +++ b/aconfig/Android.bp @@ -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", ], } diff --git a/aconfig/settings_biometrics_integration_declarations.aconfig b/aconfig/settings_biometrics_integration_declarations.aconfig new file mode 100644 index 00000000000..529e126e41c --- /dev/null +++ b/aconfig/settings_biometrics_integration_declarations.aconfig @@ -0,0 +1,9 @@ +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" +} + diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index be2a948a87b..1d84f7dcf01 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -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 diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProvider.java b/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProvider.java new file mode 100644 index 00000000000..906f95a57a9 --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProvider.java @@ -0,0 +1,27 @@ +/* + * 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(); +} diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProviderImpl.java b/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProviderImpl.java new file mode 100644 index 00000000000..27c216d53e7 --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintFeatureProviderImpl.java @@ -0,0 +1,33 @@ +/* + * 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; + } +} diff --git a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java new file mode 100644 index 00000000000..10177dbff3a --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeature.java @@ -0,0 +1,91 @@ +/* + * 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.feature; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling; + +import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieComposition; + +import java.util.function.Function; +import java.util.function.Supplier; + +public interface SfpsEnrollmentFeature { + + /** + * Gets current SFPS enrollment stage. + * @param progressSteps current step of enrollment + * @param mapper a mapper to map each stage to its threshold + * @return current enrollment stage + */ + int getCurrentSfpsEnrollStage(int progressSteps, Function mapper); + + /** + * Gets the vendor string by feature. + * @param context Context + * @param id An integer identifying the error message + * @param msg A human-readable string that can be shown in UI + * @return A human-readable string of specific feature + */ + default CharSequence getFeaturedVendorString(Context context, int id, CharSequence msg) { + return msg; + } + + /** + * Gets the stage header string by feature. + * @param stage the specific stage + * @return the resource id of the header text of the specific stage + */ + int getFeaturedStageHeaderResource(int stage); + + /** + * Gets the enrollment lottie resource id per stage + * @param stage current enrollment stage + * @return enrollment lottie resource id + */ + int getSfpsEnrollLottiePerStage(int stage); + + /** + * Handles extra stuffs on lottie composition. + * @param animView the view related to the lottie + * @param composition lottie composition + * @param stage current enrollment stage + */ + default void handleOnEnrollmentLottieComposition( + LottieAnimationView animView, LottieComposition composition, int stage) {} + + /** + * Handles extra stuffs on receiving enrollment help. + * @param helpMsgId help message id + * @param helpString help message + * @param enrollingSupplier supplier of enrolling context + */ + default void handleOnEnrollmentHelp(int helpMsgId, CharSequence helpString, + Supplier enrollingSupplier) {} + + /** + * Gets the fingerprint enrollment threshold. + * @param context context + * @param index the enrollment stage index + * @return threshold + */ + float getEnrollStageThreshold(@NonNull Context context, int index); +} diff --git a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java new file mode 100644 index 00000000000..2e24482881a --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java @@ -0,0 +1,89 @@ +/* + * 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.feature; + +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_CENTER; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_FINGERTIP; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_LEFT_EDGE; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_RIGHT_EDGE; +import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.STAGE_UNKNOWN; + +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; + +import androidx.annotation.NonNull; + +import com.android.settings.R; + +import java.util.function.Function; + +public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature { + + private FingerprintManager mFingerprintManager; + + @Override + public int getCurrentSfpsEnrollStage(int progressSteps, Function mapper) { + if (mapper == null) { + return STAGE_UNKNOWN; + } + if (progressSteps < mapper.apply(0)) { + return SFPS_STAGE_NO_ANIMATION; + } else if (progressSteps < mapper.apply(1)) { + return SFPS_STAGE_CENTER; + } else if (progressSteps < mapper.apply(2)) { + return SFPS_STAGE_FINGERTIP; + } else if (progressSteps < mapper.apply(3)) { + return SFPS_STAGE_LEFT_EDGE; + } else { + return SFPS_STAGE_RIGHT_EDGE; + } + } + + @Override + public int getFeaturedStageHeaderResource(int stage) { + return switch (stage) { + case SFPS_STAGE_NO_ANIMATION + -> R.string.security_settings_fingerprint_enroll_repeat_title; + case SFPS_STAGE_CENTER -> R.string.security_settings_sfps_enroll_finger_center_title; + case SFPS_STAGE_FINGERTIP -> R.string.security_settings_sfps_enroll_fingertip_title; + case SFPS_STAGE_LEFT_EDGE -> R.string.security_settings_sfps_enroll_left_edge_title; + case SFPS_STAGE_RIGHT_EDGE -> R.string.security_settings_sfps_enroll_right_edge_title; + default -> throw new IllegalArgumentException("Invalid stage: " + stage); + }; + } + + @Override + public int getSfpsEnrollLottiePerStage(int stage) { + return switch (stage) { + case SFPS_STAGE_NO_ANIMATION -> R.raw.sfps_lottie_no_animation; + case SFPS_STAGE_CENTER -> R.raw.sfps_lottie_pad_center; + case SFPS_STAGE_FINGERTIP -> R.raw.sfps_lottie_tip; + case SFPS_STAGE_LEFT_EDGE -> R.raw.sfps_lottie_left_edge; + case SFPS_STAGE_RIGHT_EDGE -> R.raw.sfps_lottie_right_edge; + default -> throw new IllegalArgumentException("Invalid stage: " + stage); + }; + } + + @Override + public float getEnrollStageThreshold(@NonNull Context context, int index) { + if (mFingerprintManager == null) { + mFingerprintManager = context.getSystemService(FingerprintManager.class); + } + return mFingerprintManager.getEnrollStageThreshold(index); + } +} diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt index 7645076f288..ac689d91687 100644 --- a/src/com/android/settings/overlay/FeatureFactory.kt +++ b/src/com/android/settings/overlay/FeatureFactory.kt @@ -21,6 +21,7 @@ import com.android.settings.accessibility.AccessibilitySearchFeatureProvider import com.android.settings.accounts.AccountFeatureProvider import com.android.settings.applications.ApplicationFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider import com.android.settings.bluetooth.BluetoothFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider @@ -104,8 +105,16 @@ abstract class FeatureFactory { */ abstract val bluetoothFeatureProvider: BluetoothFeatureProvider + /** + * Retrieves implementation for Face feature. + */ abstract val faceFeatureProvider: FaceFeatureProvider + /** + * Retrieves implementation for Fingerprint feature. + */ + abstract val fingerprintFeatureProvider: FingerprintFeatureProvider + /** * Gets implementation for Biometrics repository provider. */ diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt index 0afe9f473be..7f991b7b7d8 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt @@ -29,6 +29,8 @@ import com.android.settings.accounts.AccountFeatureProviderImpl import com.android.settings.applications.ApplicationFeatureProviderImpl import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProviderImpl +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProviderImpl import com.android.settings.biometrics2.factory.BiometricsRepositoryProviderImpl import com.android.settings.bluetooth.BluetoothFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProviderImpl @@ -145,6 +147,10 @@ open class FeatureFactoryImpl : FeatureFactory() { override val faceFeatureProvider: FaceFeatureProvider by lazy { FaceFeatureProviderImpl() } + override val fingerprintFeatureProvider: FingerprintFeatureProvider by lazy { + FingerprintFeatureProviderImpl() + } + override val biometricsRepositoryProvider by lazy { BiometricsRepositoryProviderImpl() } override val wifiTrackerLibProvider: WifiTrackerLibProvider by lazy { 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 4de369e5f41..61500d1856d 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java @@ -53,6 +53,9 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Vibrator; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.view.Display; import android.view.Surface; import android.view.View; @@ -62,6 +65,9 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.settings.R; +import com.android.settings.biometrics.fingerprint.feature.SfpsEnrollmentFeatureImpl; +import com.android.settings.flags.Flags; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.widget.RingProgressBar; @@ -71,6 +77,7 @@ import com.google.android.setupdesign.GlifLayout; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -93,6 +100,8 @@ public class FingerprintEnrollEnrollingTest { private static final String ENROLL_PROGRESS_COLOR_LIGHT = "#699FF3"; private static final String ENROLL_PROGRESS_COLOR_DARK = "#7DA7F1"; + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private FingerprintManager mFingerprintManager; @@ -594,6 +603,23 @@ public class FingerprintEnrollEnrollingTest { assertThat(getLayout().getDescriptionTextView().getVisibility()).isEqualTo(View.GONE); } + @Test + @RequiresFlagsDisabled(Flags.FLAG_SFPS_ENROLL_REFINEMENT) + public void testFingerprintFeatureProvider_impl() { + // We should always get default implementation when the flag is disabled. + assertThat(FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()) + .isInstanceOf(FingerprintFeatureProviderImpl.class); + } + + @Test + @RequiresFlagsDisabled(Flags.FLAG_SFPS_ENROLL_REFINEMENT) + public void testFingerprintFeatureProvider_sfpsEnrollmentFeatureImpl() { + // We should always get default implementation when the flag is disabled. + assertThat(FeatureFactory.getFeatureFactory() + .getFingerprintFeatureProvider().getSfpsEnrollmentFeature()) + .isInstanceOf(SfpsEnrollmentFeatureImpl.class); + } + private GlifLayout getLayout() { return (GlifLayout) mActivity.findViewById(R.id.setup_wizard_layout); } diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java index 52a5f24cf44..9156cae5d8f 100644 --- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java @@ -24,6 +24,7 @@ import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; @@ -80,6 +81,7 @@ public class FakeFeatureFactory extends FeatureFactory { public final AccountFeatureProvider mAccountFeatureProvider; public final BluetoothFeatureProvider mBluetoothFeatureProvider; public final FaceFeatureProvider mFaceFeatureProvider; + public final FingerprintFeatureProvider mFingerprintFeatureProvider; public final BiometricsRepositoryProvider mBiometricsRepositoryProvider; public PanelFeatureProvider panelFeatureProvider; @@ -132,6 +134,7 @@ public class FakeFeatureFactory extends FeatureFactory { panelFeatureProvider = mock(PanelFeatureProvider.class); mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class); mFaceFeatureProvider = mock(FaceFeatureProvider.class); + mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class); mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class); wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class); securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class); @@ -256,6 +259,11 @@ public class FakeFeatureFactory extends FeatureFactory { return mFaceFeatureProvider; } + @Override + public FingerprintFeatureProvider getFingerprintFeatureProvider() { + return mFingerprintFeatureProvider; + } + @Override public BiometricsRepositoryProvider getBiometricsRepositoryProvider() { return mBiometricsRepositoryProvider; diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt index 95f25adc999..54299eb3802 100644 --- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt +++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt @@ -22,6 +22,7 @@ import com.android.settings.accessibility.AccessibilitySearchFeatureProvider import com.android.settings.accounts.AccountFeatureProvider import com.android.settings.applications.ApplicationFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider import com.android.settings.bluetooth.BluetoothFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider @@ -120,6 +121,8 @@ class FakeFeatureFactory : FeatureFactory() { get() = TODO("Not yet implemented") override val faceFeatureProvider: FaceFeatureProvider get() = TODO("Not yet implemented") + override val fingerprintFeatureProvider: FingerprintFeatureProvider + get() = TODO("Not yet implemented") override val biometricsRepositoryProvider: BiometricsRepositoryProvider get() = TODO("Not yet implemented") override val wifiTrackerLibProvider: WifiTrackerLibProvider diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java index a3a92a30b70..b5062a06c56 100644 --- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -24,6 +24,7 @@ import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; +import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; @@ -79,6 +80,7 @@ public class FakeFeatureFactory extends FeatureFactory { public final AccountFeatureProvider mAccountFeatureProvider; public final BluetoothFeatureProvider mBluetoothFeatureProvider; public final FaceFeatureProvider mFaceFeatureProvider; + public final FingerprintFeatureProvider mFingerprintFeatureProvider; public final BiometricsRepositoryProvider mBiometricsRepositoryProvider; public PanelFeatureProvider panelFeatureProvider; @@ -131,6 +133,7 @@ public class FakeFeatureFactory extends FeatureFactory { panelFeatureProvider = mock(PanelFeatureProvider.class); mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class); mFaceFeatureProvider = mock(FaceFeatureProvider.class); + mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class); mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class); wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class); securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class); @@ -255,6 +258,11 @@ public class FakeFeatureFactory extends FeatureFactory { return mFaceFeatureProvider; } + @Override + public FingerprintFeatureProvider getFingerprintFeatureProvider() { + return mFingerprintFeatureProvider; + } + @Override public BiometricsRepositoryProvider getBiometricsRepositoryProvider() { return mBiometricsRepositoryProvider;