Merge "Show less secure warning in Network details settings" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f1c91ee..223b473f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2815,20 +2815,6 @@
</intent-filter>
</activity>
- <activity android:name=".biometrics2.ui.view.FingerprintEnrollmentActivity"
- android:exported="true"
- android:theme="@style/GlifTheme.Light" />
-
- <activity android:name=".biometrics2.ui.view.FingerprintEnrollmentActivity$InternalActivity"
- android:exported="false"
- android:theme="@style/GlifTheme.Light"
- android:taskAffinity="com.android.settings.root" />
-
- <activity android:name=".biometrics2.ui.view.FingerprintEnrollmentActivity$SetupActivity"
- android:exported="true"
- android:permission="android.permission.MANAGE_FINGERPRINT"
- android:theme="@style/GlifTheme.Light" />
-
<activity android:name=".biometrics.fingerprint.FingerprintEnrollIntroductionInternal"
android:exported="false"
android:theme="@style/GlifTheme.Light"
diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig
index b90ff9f..2c8eade 100644
--- a/aconfig/settings_flag_declarations.aconfig
+++ b/aconfig/settings_flag_declarations.aconfig
@@ -42,3 +42,10 @@
description: "Feature flag to remove relevant slices dependencies."
bug: "297367302"
}
+
+flag {
+ name: "support_raw_dynamic_icons"
+ namespace: "android_settings"
+ description: "Flag to gate support of injected preference icons containing raw data"
+ bug: "351884562"
+}
diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
index f4c928c..1ee980e 100644
--- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
+++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
@@ -43,7 +43,6 @@
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal;
-import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
import com.android.settings.core.FeatureFlags;
import com.android.settings.homepage.DeepLinkHomepageActivity;
import com.android.settings.homepage.DeepLinkHomepageActivityInternal;
@@ -255,8 +254,6 @@
.buildSearchIntent(mContext, SettingsEnums.SETTINGS_HOMEPAGE);
addActivityFilter(activityFilters, searchIntent);
}
- addActivityFilter(activityFilters, FingerprintEnrollmentActivity.class);
- addActivityFilter(activityFilters, FingerprintEnrollmentActivity.InternalActivity.class);
addActivityFilter(activityFilters, FingerprintEnrollIntroduction.class);
addActivityFilter(activityFilters, FingerprintEnrollIntroductionInternal.class);
addActivityFilter(activityFilters, FingerprintEnrollEnrolling.class);
diff --git a/src/com/android/settings/biometrics/BiometricUtils.java b/src/com/android/settings/biometrics/BiometricUtils.java
index 3376d86..09b2dba 100644
--- a/src/com/android/settings/biometrics/BiometricUtils.java
+++ b/src/com/android/settings/biometrics/BiometricUtils.java
@@ -16,7 +16,6 @@
package com.android.settings.biometrics;
-import static android.util.FeatureFlagUtils.SETTINGS_BIOMETRICS2_ENROLLMENT;
import android.annotation.IntDef;
import android.app.Activity;
@@ -33,7 +32,6 @@
import android.os.storage.StorageManager;
import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
-import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Surface;
@@ -50,7 +48,6 @@
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor;
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction;
-import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
@@ -254,17 +251,8 @@
public static Intent getFingerprintFindSensorIntent(@NonNull Context context,
@NonNull Intent activityIntent) {
final boolean isSuw = WizardManagerHelper.isAnySetupWizard(activityIntent);
- final Intent intent;
- if (FeatureFlagUtils.isEnabled(context, SETTINGS_BIOMETRICS2_ENROLLMENT)) {
- intent = new Intent(context, isSuw
- ? FingerprintEnrollmentActivity.SetupActivity.class
- : FingerprintEnrollmentActivity.class);
- intent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, true);
- } else {
- intent = new Intent(context, isSuw
- ? SetupFingerprintEnrollFindSensor.class
- : FingerprintEnrollFindSensor.class);
- }
+ final Intent intent = new Intent(context, isSuw
+ ? SetupFingerprintEnrollFindSensor.class : FingerprintEnrollFindSensor.class);
if (isSuw) {
SetupWizardUtils.copySetupExtras(activityIntent, intent);
}
@@ -279,16 +267,8 @@
public static Intent getFingerprintIntroIntent(@NonNull Context context,
@NonNull Intent activityIntent) {
final boolean isSuw = WizardManagerHelper.isAnySetupWizard(activityIntent);
- final Intent intent;
- if (FeatureFlagUtils.isEnabled(context, SETTINGS_BIOMETRICS2_ENROLLMENT)) {
- intent = new Intent(context, isSuw
- ? FingerprintEnrollmentActivity.SetupActivity.class
- : FingerprintEnrollmentActivity.class);
- } else {
- intent = new Intent(context, isSuw
- ? SetupFingerprintEnrollIntroduction.class
- : FingerprintEnrollIntroduction.class);
- }
+ final Intent intent = new Intent(context, isSuw
+ ? SetupFingerprintEnrollIntroduction.class : FingerprintEnrollIntroduction.class);
if (isSuw) {
WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index d35cda4..cb7d617 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -45,7 +45,6 @@
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImeAwareEditText;
@@ -70,8 +69,6 @@
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.GatekeeperPasswordProvider;
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
-import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment;
@@ -833,15 +830,8 @@
if (KEY_FINGERPRINT_ADD.equals(key)) {
mIsEnrolling = true;
Intent intent = new Intent();
- if (FeatureFlagUtils.isEnabled(getContext(),
- FeatureFlagUtils.SETTINGS_BIOMETRICS2_ENROLLMENT)) {
- intent.setClassName(SETTINGS_PACKAGE_NAME,
- FingerprintEnrollmentActivity.InternalActivity.class.getName());
- intent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, true);
- } else {
- intent.setClassName(SETTINGS_PACKAGE_NAME,
- FingerprintEnrollEnrolling.class.getName());
- }
+ intent.setClassName(SETTINGS_PACKAGE_NAME,
+ FingerprintEnrollEnrolling.class.getName());
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
if (mCalibrator != null) {
@@ -1126,12 +1116,7 @@
private void addFirstFingerprint(@Nullable Long gkPwHandle) {
Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME,
- FeatureFlagUtils.isEnabled(getActivity(),
- FeatureFlagUtils.SETTINGS_BIOMETRICS2_ENROLLMENT)
- ? FingerprintEnrollmentActivity.InternalActivity.class.getName()
- : FingerprintEnrollIntroductionInternal.class.getName()
- );
-
+ FingerprintEnrollIntroductionInternal.class.getName());
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true);
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE);
diff --git a/src/com/android/settings/biometrics2/OWNERS b/src/com/android/settings/biometrics2/OWNERS
deleted file mode 100644
index ac806eb..0000000
--- a/src/com/android/settings/biometrics2/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# The Android Biometric team should approve all changes to biometrics2 subdirectories.
-set noparent
-
-include /src/com/android/settings/biometrics/OWNERS
diff --git a/src/com/android/settings/biometrics2/data/repository/FingerprintRepository.java b/src/com/android/settings/biometrics2/data/repository/FingerprintRepository.java
deleted file mode 100644
index 6a9892a..0000000
--- a/src/com/android/settings/biometrics2/data/repository/FingerprintRepository.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.data.repository;
-
-import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.settings.R;
-import com.android.settings.biometrics.ParentalControlsUtils;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-
-import java.util.List;
-
-/**
- * This repository is used to call all APIs in {@link FingerprintManager}
- */
-public class FingerprintRepository {
-
- private static final String TAG = "FingerprintRepository";
- @NonNull
- private final FingerprintManager mFingerprintManager;
-
- private List<FingerprintSensorPropertiesInternal> mSensorPropertiesCache;
-
- public FingerprintRepository(@NonNull FingerprintManager fingerprintManager) {
- mFingerprintManager = fingerprintManager;
- mFingerprintManager.addAuthenticatorsRegisteredCallback(
- new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
- @Override
- public void onAllAuthenticatorsRegistered(
- List<FingerprintSensorPropertiesInternal> sensors) {
- mSensorPropertiesCache = sensors;
- }
- });
- }
-
- /**
- * The first sensor type is UDFPS sensor or not
- */
- public boolean canAssumeUdfps() {
- FingerprintSensorPropertiesInternal prop = getFirstFingerprintSensorPropertiesInternal();
- return prop != null && prop.isAnyUdfpsType();
- }
-
- /**
- * The first sensor type is Side fps sensor or not
- */
- public boolean canAssumeSfps() {
- FingerprintSensorPropertiesInternal prop = getFirstFingerprintSensorPropertiesInternal();
- return prop != null && prop.isAnySidefpsType();
- }
-
- /**
- * Get max possible number of fingerprints for a user
- */
- public int getMaxFingerprints() {
- FingerprintSensorPropertiesInternal prop = getFirstFingerprintSensorPropertiesInternal();
- return prop != null ? prop.maxEnrollmentsPerUser : 0;
- }
-
- /**
- * Get number of fingerprints that this user enrolled.
- */
- public int getNumOfEnrolledFingerprintsSize(int userId) {
- final List<Fingerprint> list = mFingerprintManager.getEnrolledFingerprints(userId);
- return list != null ? list.size() : 0;
- }
-
- /**
- * Get maximum possible fingerprints in setup wizard flow
- */
- public int getMaxFingerprintsInSuw(@NonNull Resources resources) {
- return resources.getInteger(R.integer.suw_max_fingerprints_enrollable);
- }
-
- /**
- * Gets the first FingerprintSensorPropertiesInternal from FingerprintManager
- */
- @Nullable
- public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
- final List<FingerprintSensorPropertiesInternal> props = mSensorPropertiesCache;
- if (props == null) {
- // Handle this case if it really happens
- Log.e(TAG, "Sensor properties cache is null");
- return null;
- }
- return props.size() > 0 ? props.get(0) : null;
- }
-
- /**
- * Call FingerprintManager to generate challenge for first sensor
- */
- public void generateChallenge(int userId,
- @NonNull FingerprintManager.GenerateChallengeCallback callback) {
- mFingerprintManager.generateChallenge(userId, callback);
- }
-
- /**
- * Get parental consent required or not during enrollment process
- */
- public boolean isParentalConsentRequired(@NonNull Context context) {
- return ParentalControlsUtils.parentConsentRequired(context, TYPE_FINGERPRINT) != null;
- }
-
- /**
- * Get fingerprint is disable by admin or not
- */
- public boolean isDisabledByAdmin(@NonNull Context context, int userId) {
- return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
- context, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, userId) != null;
- }
-
- /**
- * Get fingerprint enroll stage threshold
- */
- public float getEnrollStageThreshold(int index) {
- return mFingerprintManager.getEnrollStageThreshold(index);
- }
-
- /**
- * Get fingerprint enroll stage count
- */
- public int getEnrollStageCount() {
- return mFingerprintManager.getEnrollStageCount();
- }
-}
diff --git a/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProvider.java b/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProvider.java
deleted file mode 100644
index fdc5745..0000000
--- a/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProvider.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.factory;
-
-import android.app.Application;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-
-/**
- * Interface for BiometricsRepositoryProvider
- */
-public interface BiometricsRepositoryProvider {
-
- /**
- * Get FingerprintRepository
- */
- @Nullable
- FingerprintRepository getFingerprintRepository(@NonNull Application application);
-}
diff --git a/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProviderImpl.java b/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProviderImpl.java
deleted file mode 100644
index 22409c8..0000000
--- a/src/com/android/settings/biometrics2/factory/BiometricsRepositoryProviderImpl.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.factory;
-
-import android.app.Application;
-import android.hardware.fingerprint.FingerprintManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.settings.Utils;
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-
-/**
- * Implementation for BiometricsRepositoryProvider
- */
-public class BiometricsRepositoryProviderImpl implements BiometricsRepositoryProvider {
-
- private static volatile FingerprintRepository sFingerprintRepository;
-
- /**
- * Get FingerprintRepository
- */
- @Nullable
- @Override
- public FingerprintRepository getFingerprintRepository(@NonNull Application application) {
- final FingerprintManager fingerprintManager =
- Utils.getFingerprintManagerOrNull(application);
- if (fingerprintManager == null) {
- return null;
- }
- if (sFingerprintRepository == null) {
- synchronized (FingerprintRepository.class) {
- if (sFingerprintRepository == null) {
- sFingerprintRepository = new FingerprintRepository(fingerprintManager);
- }
- }
- }
- return sFingerprintRepository;
- }
-}
diff --git a/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java b/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java
deleted file mode 100644
index 516f471..0000000
--- a/src/com/android/settings/biometrics2/factory/BiometricsViewModelFactory.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.factory;
-
-import android.app.Application;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.ViewModel;
-import androidx.lifecycle.ViewModelProvider;
-import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory;
-import androidx.lifecycle.viewmodel.CreationExtras;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-import com.android.settings.biometrics2.ui.model.CredentialModel;
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
-import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator;
-import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
-
-/**
- * View model factory for biometric enrollment fragment
- */
-public class BiometricsViewModelFactory implements ViewModelProvider.Factory {
-
- private static final String TAG = "BiometricsViewModelFactory";
-
- public static final CreationExtras.Key<ChallengeGenerator> CHALLENGE_GENERATOR_KEY =
- new CreationExtras.Key<ChallengeGenerator>() {};
- public static final CreationExtras.Key<EnrollmentRequest> ENROLLMENT_REQUEST_KEY =
- new CreationExtras.Key<EnrollmentRequest>() {};
- public static final CreationExtras.Key<CredentialModel> CREDENTIAL_MODEL_KEY =
- new CreationExtras.Key<CredentialModel>() {};
-
- @NonNull
- @Override
- @SuppressWarnings("unchecked")
- public <T extends ViewModel> T create(@NonNull Class<T> modelClass,
- @NonNull CreationExtras extras) {
- final Application application = extras.get(AndroidViewModelFactory.APPLICATION_KEY);
-
- if (application == null) {
- Log.w(TAG, "create, null application");
- return create(modelClass);
- }
- final FeatureFactory featureFactory = FeatureFactory.getFeatureFactory();
- final BiometricsRepositoryProvider provider =
- featureFactory.getBiometricsRepositoryProvider();
-
- if (modelClass.isAssignableFrom(AutoCredentialViewModel.class)) {
- final LockPatternUtils lockPatternUtils =
- featureFactory.getSecurityFeatureProvider().getLockPatternUtils(application);
- final ChallengeGenerator challengeGenerator = extras.get(CHALLENGE_GENERATOR_KEY);
- final CredentialModel credentialModel = extras.get(CREDENTIAL_MODEL_KEY);
- if (challengeGenerator != null && credentialModel != null) {
- return (T) new AutoCredentialViewModel(application, lockPatternUtils,
- challengeGenerator, credentialModel);
- }
- } else if (modelClass.isAssignableFrom(DeviceFoldedViewModel.class)) {
- return (T) new DeviceFoldedViewModel(new ScreenSizeFoldProvider(application),
- application.getMainExecutor());
- } else if (modelClass.isAssignableFrom(DeviceRotationViewModel.class)) {
- return (T) new DeviceRotationViewModel(application);
- } else if (modelClass.isAssignableFrom(FingerprintEnrollFindSensorViewModel.class)) {
- final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY);
- if (request != null) {
- return (T) new FingerprintEnrollFindSensorViewModel(application, request.isSuw());
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollIntroViewModel.class)) {
- final FingerprintRepository repository = provider.getFingerprintRepository(application);
- final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY);
- final CredentialModel credentialModel = extras.get(CREDENTIAL_MODEL_KEY);
- if (repository != null && request != null && credentialModel != null) {
- return (T) new FingerprintEnrollIntroViewModel(application, repository, request,
- credentialModel.getUserId());
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollmentViewModel.class)) {
- final FingerprintRepository repository = provider.getFingerprintRepository(application);
- final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY);
- if (repository != null && request != null) {
- return (T) new FingerprintEnrollmentViewModel(application, repository, request);
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollProgressViewModel.class)) {
- final CredentialModel credentialModel = extras.get(CREDENTIAL_MODEL_KEY);
- if (credentialModel != null) {
- return (T) new FingerprintEnrollProgressViewModel(application,
- new FingerprintUpdater(application), credentialModel.getUserId());
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollEnrollingViewModel.class)) {
- final CredentialModel credentialModel = extras.get(CREDENTIAL_MODEL_KEY);
- final FingerprintRepository fingerprint = provider.getFingerprintRepository(
- application);
- if (fingerprint != null && credentialModel != null) {
- return (T) new FingerprintEnrollEnrollingViewModel(application,
- credentialModel.getUserId(), fingerprint);
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollFinishViewModel.class)) {
- final CredentialModel credentialModel = extras.get(CREDENTIAL_MODEL_KEY);
- final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY);
- final FingerprintRepository fingerprint = provider.getFingerprintRepository(
- application);
- if (fingerprint != null && credentialModel != null && request != null) {
- return (T) new FingerprintEnrollFinishViewModel(application,
- credentialModel.getUserId(), request, fingerprint);
- }
- } else if (modelClass.isAssignableFrom(FingerprintEnrollErrorDialogViewModel.class)) {
- final EnrollmentRequest request = extras.get(ENROLLMENT_REQUEST_KEY);
- if (request != null) {
- return (T) new FingerprintEnrollErrorDialogViewModel(application, request.isSuw());
- }
- }
- return create(modelClass);
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/CredentialModel.kt b/src/com/android/settings/biometrics2/ui/model/CredentialModel.kt
deleted file mode 100644
index 5350733..0000000
--- a/src/com/android/settings/biometrics2/ui/model/CredentialModel.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-import android.content.Intent.EXTRA_USER_ID
-import android.os.Bundle
-import android.os.UserHandle
-import androidx.annotation.VisibleForTesting
-import com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE
-import com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN
-import com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE
-import java.time.Clock
-
-/**
- * Secret credential data including
- * 1. userId
- * 2. challenge
- * 3. token
- * 4. gkPwHandle
- */
-class CredentialModel(bundle: Bundle?, private val clock: Clock) {
-
- private val mInitMillis = clock.millis()
-
- /** userId for this credential */
- val userId: Int = (bundle ?: Bundle()).getInt(EXTRA_USER_ID, UserHandle.myUserId())
-
- private var clearGkPwHandleMillis: Long? = null
-
- /** Gatekeeper password handle */
- var gkPwHandle: Long = (bundle ?: Bundle()).getLong(EXTRA_KEY_GK_PW_HANDLE, INVALID_GK_PW_HANDLE)
- private set
-
- val isValidGkPwHandle: Boolean
- get() = gkPwHandle != INVALID_GK_PW_HANDLE
-
- /** Clear gatekeeper password handle data */
- fun clearGkPwHandle() {
- clearGkPwHandleMillis = clock.millis()
- gkPwHandle = INVALID_GK_PW_HANDLE
- }
-
- /** Check user id is valid or not */
- val isValidUserId: Boolean
- get() = userId != UserHandle.USER_NULL
-
- private var updateChallengeMillis: Long? = null
-
- var challenge: Long = (bundle ?: Bundle()).getLong(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE)
- set(value) {
- updateChallengeMillis = clock.millis()
- field = value
- }
-
- val isValidChallenge: Boolean
- get() = challenge != INVALID_CHALLENGE
-
- private var updateTokenMillis: Long? = null
-
- /** Challenge token */
- var token: ByteArray? = (bundle ?: Bundle()).getByteArray(EXTRA_KEY_CHALLENGE_TOKEN)
- set(value) {
- updateTokenMillis = clock.millis()
- field = value
- }
-
- val isValidToken: Boolean
- get() = token != null
-
- /** Returns a string representation of the object */
- override fun toString(): String {
- val gkPwHandleLen = "$gkPwHandle".length
- val tokenLen = token?.size ?: 0
- val challengeLen = "$challenge".length
- return (javaClass.simpleName + ":{initMillis:$mInitMillis"
- + ", userId:$userId"
- + ", challenge:{len:$challengeLen"
- + ", updateMillis:$updateChallengeMillis}"
- + ", token:{len:$tokenLen, isValid:$isValidToken"
- + ", updateMillis:$updateTokenMillis}"
- + ", gkPwHandle:{len:$gkPwHandleLen, isValid:$isValidGkPwHandle"
- + ", clearMillis:$clearGkPwHandleMillis}"
- + " }")
- }
-
- companion object {
- /** Default value for an invalid challenge */
- @VisibleForTesting
- const val INVALID_CHALLENGE = -1L
-
- /** Default value if GkPwHandle is invalid */
- @VisibleForTesting
- const val INVALID_GK_PW_HANDLE = 0L
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/EnrollmentProgress.kt b/src/com/android/settings/biometrics2/ui/model/EnrollmentProgress.kt
deleted file mode 100644
index 7b35a68..0000000
--- a/src/com/android/settings/biometrics2/ui/model/EnrollmentProgress.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-/** Biometric Enrollment progress */
-class EnrollmentProgress(val steps: Int, val remaining: Int) {
-
- val isInitialStep: Boolean
- get() = steps == INITIAL_STEPS
-
- override fun toString(): String {
- return ("${javaClass.simpleName}@${Integer.toHexString(hashCode())}"
- + "{steps:$steps, remaining:$remaining}")
- }
-
- companion object {
- const val INITIAL_STEPS = -1
- const val INITIAL_REMAINING = 0
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/EnrollmentRequest.kt b/src/com/android/settings/biometrics2/ui/model/EnrollmentRequest.kt
deleted file mode 100644
index 4696c62..0000000
--- a/src/com/android/settings/biometrics2/ui/model/EnrollmentRequest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import com.android.settings.SetupWizardUtils
-import com.android.settings.biometrics.BiometricEnrollActivity.EXTRA_SKIP_INTRO
-import com.google.android.setupcompat.util.WizardManagerHelper
-import com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW
-
-/**
- * Biometric enrollment generic intent data, which includes
- * 1. isSuw
- * 2. isAfterSuwOrSuwSuggestedAction
- * 3. theme
- * 4. isFromSettingsSummery
- * 5. isSkipIntro
- * 6. isSkipFindSensor
- * 7. a helper method, getSetupWizardExtras
- */
-class EnrollmentRequest(
- intent: Intent,
- context: Context,
- isSetupActivity: Boolean
-) {
- val isSuw: Boolean = isSetupActivity && WizardManagerHelper.isAnySetupWizard(intent)
-
- val isAfterSuwOrSuwSuggestedAction = (isSetupActivity
- && (WizardManagerHelper.isDeferredSetupWizard(intent)
- || WizardManagerHelper.isPortalSetupWizard(intent)
- || intent.getBooleanExtra(EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, false)))
-
- private val _suwExtras = getSuwExtras(isSuw, intent)
-
- val isSkipIntro = intent.getBooleanExtra(EXTRA_SKIP_INTRO, false)
-
- val isSkipFindSensor = intent.getBooleanExtra(EXTRA_SKIP_FIND_SENSOR, false)
-
- val theme = SetupWizardUtils.getTheme(context, intent)
-
- val suwExtras: Bundle
- get() = Bundle(_suwExtras)
-
- /**
- * Returns a string representation of the object
- */
- override fun toString(): String {
- return (javaClass.simpleName + ":{isSuw:" + isSuw
- + ", isAfterSuwOrSuwSuggestedAction:" + isAfterSuwOrSuwSuggestedAction
- + "}")
- }
-
- companion object {
- const val EXTRA_SKIP_FIND_SENSOR = "skip_find_sensor"
- private fun getSuwExtras(isSuw: Boolean, intent: Intent): Bundle {
- val toIntent = Intent()
- if (isSuw) {
- SetupWizardUtils.copySetupExtras(intent, toIntent)
- }
- return toIntent.extras ?: Bundle()
- }
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/EnrollmentStatusMessage.kt b/src/com/android/settings/biometrics2/ui/model/EnrollmentStatusMessage.kt
deleted file mode 100644
index 6dd0c5c..0000000
--- a/src/com/android/settings/biometrics2/ui/model/EnrollmentStatusMessage.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-/** Enrolling status message (help or error) */
-class EnrollmentStatusMessage(val msgId: Int, string: CharSequence?) {
-
- /** Status string */
- val str: CharSequence = string ?: ""
-
- override fun toString(): String {
- return "${javaClass.simpleName}@${Integer.toHexString(hashCode())}{id:$msgId, str:$str}"
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/FingerprintEnrollIntroStatus.kt b/src/com/android/settings/biometrics2/ui/model/FingerprintEnrollIntroStatus.kt
deleted file mode 100644
index 4cbaffa..0000000
--- a/src/com/android/settings/biometrics2/ui/model/FingerprintEnrollIntroStatus.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-
-enum class FingerprintEnrollable {
- // Unconfirmed case, this value is invalid, and view shall bypass this value
- FINGERPRINT_ENROLLABLE_UNKNOWN,
- // User is allowed to enrolled a new fingerprint
- FINGERPRINT_ENROLLABLE_OK,
- // User is not allowed to enroll because the number has reached maximum
- FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
-}
-
-/**
- * Fingerprint onboarding introduction page data, it contains following information which needs
- * to be passed from view model to view.
- * 1. mEnrollableStatus: User is allowed to enroll a new fingerprint or not.
- * 2. mHasScrollToBottom: User has scrolled to the bottom of this page or not.
- */
-class FingerprintEnrollIntroStatus(
- private val mHasScrollToBottom: Boolean,
- /** Enrollable status. It means that user is allowed to enroll a new fingerprint or not. */
- val enrollableStatus: FingerprintEnrollable
-) {
- /** Get info for this onboarding introduction page has scrolled to bottom or not */
- fun hasScrollToBottom(): Boolean {
- return mHasScrollToBottom
- }
-
- override fun toString(): String {
- return ("${javaClass.simpleName}@${Integer.toHexString(hashCode())}"
- + "{scrollToBottom:$mHasScrollToBottom"
- + ", enrollableStatus:$enrollableStatus}")
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingIconTouchDialog.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingIconTouchDialog.kt
deleted file mode 100644
index 9f99d17..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingIconTouchDialog.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.app.Dialog
-import android.content.Context
-import android.content.DialogInterface
-import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.DialogFragment
-import com.android.settings.R
-
-/**
- * Icon Touch dialog
- */
-class FingerprintEnrollEnrollingIconTouchDialog : DialogFragment() {
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
- requireActivity().bindFingerprintEnrollEnrollingIconTouchDialog()
-}
-
-fun Context.bindFingerprintEnrollEnrollingIconTouchDialog(): AlertDialog =
- AlertDialog.Builder(this, R.style.Theme_AlertDialog)
- .setTitle(R.string.security_settings_fingerprint_enroll_touch_dialog_title)
- .setMessage(R.string.security_settings_fingerprint_enroll_touch_dialog_message)
- .setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok) {
- dialog: DialogInterface?, _: Int -> dialog?.dismiss()
- }
- .create()
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.kt
deleted file mode 100644
index 2530628..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.kt
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.animation.Animator
-import android.animation.ObjectAnimator
-import android.content.Context
-import android.graphics.PorterDuff
-import android.graphics.drawable.Animatable2
-import android.graphics.drawable.AnimatedVectorDrawable
-import android.graphics.drawable.Drawable
-import android.graphics.drawable.LayerDrawable
-import android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL
-import android.os.Bundle
-import android.text.TextUtils
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.MotionEvent
-import android.view.View
-import android.view.ViewGroup
-import android.view.animation.AnimationUtils.loadInterpolator
-import android.view.animation.Interpolator
-import android.widget.ProgressBar
-import android.widget.TextView
-import androidx.activity.OnBackPressedCallback
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-import kotlinx.coroutines.launch
-
-/**
- * Fragment is used to handle enrolling process for rfps
- */
-class FingerprintEnrollEnrollingRfpsFragment : Fragment() {
-
- private var _enrollingViewModel: FingerprintEnrollEnrollingViewModel? = null
- private val enrollingViewModel: FingerprintEnrollEnrollingViewModel
- get() = _enrollingViewModel!!
-
- private var _progressViewModel: FingerprintEnrollProgressViewModel? = null
- private val progressViewModel: FingerprintEnrollProgressViewModel
- get() = _progressViewModel!!
-
- private var _errorDialogViewModel: FingerprintEnrollErrorDialogViewModel? = null
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel
- get() = _errorDialogViewModel!!
-
- private var fastOutSlowInInterpolator: Interpolator? = null
- private var linearOutSlowInInterpolator: Interpolator? = null
- private var fastOutLinearInInterpolator: Interpolator? = null
-
- private var isAnimationCancelled = false
-
- private var enrollingView: GlifLayout? = null
- private val progressBar: ProgressBar
- get() = enrollingView!!.findViewById(R.id.fingerprint_progress_bar)!!
-
- private var progressAnim: ObjectAnimator? = null
-
- private val errorText: TextView
- get() = enrollingView!!.findViewById(R.id.error_text)!!
-
- private val iconAnimationDrawable: AnimatedVectorDrawable?
- get() = (progressBar.background as LayerDrawable)
- .findDrawableByLayerId(R.id.fingerprint_animation) as AnimatedVectorDrawable?
-
- private val iconBackgroundBlinksDrawable: AnimatedVectorDrawable?
- get() = (progressBar.background as LayerDrawable)
- .findDrawableByLayerId(R.id.fingerprint_background) as AnimatedVectorDrawable?
-
- private var iconTouchCount = 0
-
- private val touchAgainRunnable = Runnable {
- showError(
- // Use enrollingView to getString to prevent activity is missing during rotation
- enrollingView!!.context.getString(
- R.string.security_settings_fingerprint_enroll_lift_touch_again
- )
- )
- }
-
- private val onSkipClickListener = View.OnClickListener { _: View? ->
- enrollingViewModel.setOnSkipPressed()
- cancelEnrollment(true)
- }
-
- private var enrollingCancelSignal: Any? = null
-
- private val progressObserver = Observer { progress: EnrollmentProgress? ->
- if (progress != null && progress.steps >= 0) {
- onEnrollmentProgressChange(progress)
- }
- }
-
- private val helpMessageObserver = Observer { helpMessage: EnrollmentStatusMessage? ->
- helpMessage?.let { onEnrollmentHelp(it) }
- }
-
- private val errorMessageObserver = Observer { errorMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "errorMessageObserver($errorMessage)")
- errorMessage?.let { onEnrollmentError(it) }
- }
-
- private val canceledSignalObserver = Observer { canceledSignal: Any? ->
- canceledSignal?.let { onEnrollmentCanceled(it) }
- }
-
- private val onBackPressedCallback: OnBackPressedCallback =
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- isEnabled = false
- enrollingViewModel.setOnBackPressed()
- cancelEnrollment(true)
- }
- }
-
- override fun onAttach(context: Context) {
- ViewModelProvider(requireActivity()).let { provider ->
- _enrollingViewModel = provider[FingerprintEnrollEnrollingViewModel::class.java]
- _progressViewModel = provider[FingerprintEnrollProgressViewModel::class.java]
- _errorDialogViewModel = provider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
- super.onAttach(context)
- requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
- }
-
- override fun onDetach() {
- onBackPressedCallback.isEnabled = false
- super.onDetach()
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- enrollingView = inflater.inflate(
- R.layout.fingerprint_enroll_enrolling, container, false
- ) as GlifLayout
- return enrollingView!!
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- iconAnimationDrawable!!.registerAnimationCallback(iconAnimationCallback)
-
- progressBar.setOnTouchListener { _: View?, event: MotionEvent ->
- if (event.actionMasked == MotionEvent.ACTION_DOWN) {
- iconTouchCount++
- if (iconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
- showIconTouchDialog()
- } else {
- progressBar.postDelayed(
- showDialogRunnable,
- ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN
- )
- }
- } else if (event.actionMasked == MotionEvent.ACTION_CANCEL
- || event.actionMasked == MotionEvent.ACTION_UP
- ) {
- progressBar.removeCallbacks(showDialogRunnable)
- }
- true
- }
-
- requireActivity().bindFingerprintEnrollEnrollingRfpsView(
- view = enrollingView!!,
- onSkipClickListener = onSkipClickListener
- )
-
- fastOutSlowInInterpolator =
- loadInterpolator(requireContext(), android.R.interpolator.fast_out_slow_in)
- linearOutSlowInInterpolator =
- loadInterpolator(requireContext(), android.R.interpolator.linear_out_slow_in)
- fastOutLinearInInterpolator =
- loadInterpolator(requireContext(), android.R.interpolator.fast_out_linear_in)
-
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.triggerRetryFlow.collect { retryEnrollment() }
- }
- }
- }
-
- private fun retryEnrollment() {
- isAnimationCancelled = false
- startIconAnimation()
- startEnrollment()
-
- clearError()
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- updateTitleAndDescription()
- }
-
- override fun onStart() {
- super.onStart()
-
- val isEnrolling = progressViewModel.isEnrolling
- val isErrorDialogShown = errorDialogViewModel.isDialogShown
- Log.d(TAG, "onStart(), isEnrolling:$isEnrolling, isErrorDialog:$isErrorDialogShown")
- if (!isErrorDialogShown) {
- isAnimationCancelled = false
- startIconAnimation()
- startEnrollment()
- }
-
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- updateTitleAndDescription()
- }
-
- private fun startIconAnimation() {
- iconAnimationDrawable?.start()
- }
-
- private fun stopIconAnimation() {
- isAnimationCancelled = true
- iconAnimationDrawable?.stop()
- }
-
- override fun onStop() {
- stopIconAnimation()
- removeEnrollmentObservers()
- val isEnrolling = progressViewModel.isEnrolling
- val isConfigChange = requireActivity().isChangingConfigurations
- Log.d(TAG, "onStop(), enrolling:$isEnrolling isConfigChange:$isConfigChange")
- if (isEnrolling && !isConfigChange) {
- cancelEnrollment(false)
- }
- super.onStop()
- }
-
- private fun removeEnrollmentObservers() {
- progressViewModel.errorMessageLiveData.removeObserver(errorMessageObserver)
- progressViewModel.progressLiveData.removeObserver(progressObserver)
- progressViewModel.helpMessageLiveData.removeObserver(helpMessageObserver)
- }
-
- private fun cancelEnrollment(waitForLastCancelErrMsg: Boolean) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "cancelEnrollment(), failed because isEnrolling is false")
- return
- }
- removeEnrollmentObservers()
- if (waitForLastCancelErrMsg) {
- progressViewModel.canceledSignalLiveData.observe(this, canceledSignalObserver)
- } else {
- enrollingCancelSignal = null
- }
- val cancelResult: Boolean = progressViewModel.cancelEnrollment()
- if (!cancelResult) {
- Log.e(TAG, "cancelEnrollment(), failed to cancel enrollment")
- }
- }
-
- private fun startEnrollment() {
- enrollingCancelSignal = progressViewModel.startEnrollment(ENROLL_ENROLL)
- if (enrollingCancelSignal == null) {
- Log.e(TAG, "startEnrollment(), failed")
- } else {
- Log.d(TAG, "startEnrollment(), success")
- }
- progressViewModel.progressLiveData.observe(this, progressObserver)
- progressViewModel.helpMessageLiveData.observe(this, helpMessageObserver)
- progressViewModel.errorMessageLiveData.observe(this, errorMessageObserver)
- }
-
- private fun onEnrollmentHelp(helpMessage: EnrollmentStatusMessage) {
- Log.d(TAG, "onEnrollmentHelp($helpMessage)")
- val helpStr: CharSequence = helpMessage.str
- if (!TextUtils.isEmpty(helpStr)) {
- errorText.removeCallbacks(touchAgainRunnable)
- showError(helpStr)
- }
- }
-
- private fun onEnrollmentError(errorMessage: EnrollmentStatusMessage) {
- stopIconAnimation()
-
- cancelEnrollment(true)
- lifecycleScope.launch {
- Log.d(TAG, "newDialog $errorMessage")
- errorDialogViewModel.newDialog(errorMessage.msgId)
- }
- }
-
- private fun onEnrollmentCanceled(canceledSignal: Any) {
- Log.d(
- TAG,
- "onEnrollmentCanceled enrolling:$enrollingCancelSignal, canceled:$canceledSignal"
- )
- if (enrollingCancelSignal === canceledSignal) {
- progressViewModel.canceledSignalLiveData.removeObserver(canceledSignalObserver)
- progressViewModel.clearProgressLiveData()
- if (enrollingViewModel.onBackPressed) {
- enrollingViewModel.onCancelledDueToOnBackPressed()
- } else if (enrollingViewModel.onSkipPressed) {
- enrollingViewModel.onCancelledDueToOnSkipPressed()
- }
- }
- }
-
- private fun onEnrollmentProgressChange(progress: EnrollmentProgress) {
- updateProgress(true /* animate */, progress)
- updateTitleAndDescription()
- animateFlash()
- errorText.removeCallbacks(touchAgainRunnable)
- errorText.postDelayed(touchAgainRunnable, HINT_TIMEOUT_DURATION.toLong())
- }
-
- private fun updateProgress(animate: Boolean, enrollmentProgress: EnrollmentProgress) {
- val progress = getProgress(enrollmentProgress)
- Log.d(TAG, "updateProgress($animate, $enrollmentProgress), old:${progressBar.progress}"
- + ", new:$progress")
-
- // Only clear the error when progress has been made.
- // TODO (b/234772728) Add tests.
- if (progressBar.progress < progress) {
- clearError()
- }
- if (animate) {
- animateProgress(progress)
- } else {
- progressBar.progress = progress
- if (progress >= PROGRESS_BAR_MAX) {
- delayedFinishRunnable.run()
- }
- }
- }
-
- private fun getProgress(progress: EnrollmentProgress): Int {
- if (progress.steps == -1) {
- return 0
- }
- val displayProgress = 0.coerceAtLeast(progress.steps + 1 - progress.remaining)
- return PROGRESS_BAR_MAX * displayProgress / (progress.steps + 1)
- }
-
- private fun showError(error: CharSequence) {
- errorText.text = error
- if (errorText.visibility == View.INVISIBLE) {
- errorText.visibility = View.VISIBLE
- errorText.translationY = enrollingView!!.context.resources.getDimensionPixelSize(
- R.dimen.fingerprint_error_text_appear_distance
- ).toFloat()
- errorText.alpha = 0f
- errorText.animate()
- .alpha(1f)
- .translationY(0f)
- .setDuration(200)
- .setInterpolator(linearOutSlowInInterpolator)
- .start()
- } else {
- errorText.animate().cancel()
- errorText.alpha = 1f
- errorText.translationY = 0f
- }
- if (isResumed && enrollingViewModel.isAccessibilityEnabled) {
- enrollingViewModel.vibrateError(javaClass.simpleName + "::showError")
- }
- }
-
- private fun clearError() {
- if (errorText.visibility == View.VISIBLE) {
- errorText.animate()
- .alpha(0f)
- .translationY(
- resources.getDimensionPixelSize(
- R.dimen.fingerprint_error_text_disappear_distance
- ).toFloat()
- )
- .setDuration(100)
- .setInterpolator(fastOutLinearInInterpolator)
- .withEndAction { errorText.visibility = View.INVISIBLE }
- .start()
- }
- }
-
- private fun animateProgress(progress: Int) {
- progressAnim?.cancel()
- val anim = ObjectAnimator.ofInt(
- progressBar /* target */,
- "progress" /* propertyName */,
- progressBar.progress /* values[0] */,
- progress /* values[1] */
- )
- anim.addListener(progressAnimationListener)
- anim.interpolator = fastOutSlowInInterpolator
- anim.setDuration(ANIMATION_DURATION)
- anim.start()
- progressAnim = anim
- }
-
- private fun animateFlash() {
- iconBackgroundBlinksDrawable?.start()
- }
-
- private fun updateTitleAndDescription() {
- val progressLiveData: EnrollmentProgress = progressViewModel.progressLiveData.value!!
- GlifLayoutHelper(activity!!, enrollingView!!).setDescriptionText(
- enrollingView!!.context.getString(
- if (progressLiveData.steps == -1)
- R.string.security_settings_fingerprint_enroll_start_message
- else
- R.string.security_settings_fingerprint_enroll_repeat_message
- )
- )
- }
-
- private fun showIconTouchDialog() {
- iconTouchCount = 0
- enrollingViewModel.showIconTouchDialog()
- }
-
- private val showDialogRunnable = Runnable { showIconTouchDialog() }
-
- private val progressAnimationListener: Animator.AnimatorListener =
- object : Animator.AnimatorListener {
- override fun onAnimationStart(animation: Animator) {
- startIconAnimation()
- }
-
- override fun onAnimationRepeat(animation: Animator) {}
- override fun onAnimationEnd(animation: Animator) {
- stopIconAnimation()
- if (progressBar.progress >= PROGRESS_BAR_MAX) {
- progressBar.postDelayed(delayedFinishRunnable, ANIMATION_DURATION)
- }
- }
-
- override fun onAnimationCancel(animation: Animator) {}
- }
-
- // Give the user a chance to see progress completed before jumping to the next stage.
- private val delayedFinishRunnable = Runnable { enrollingViewModel.onEnrollingDone() }
-
- private val iconAnimationCallback: Animatable2.AnimationCallback =
- object : Animatable2.AnimationCallback() {
- override fun onAnimationEnd(d: Drawable) {
- if (isAnimationCancelled) {
- return
- }
-
- // Start animation after it has ended.
- progressBar.post { startIconAnimation() }
- }
- }
-
- companion object {
- private const val DEBUG = false
- private const val TAG = "FingerprintEnrollEnrollingRfpsFragment"
- private const val PROGRESS_BAR_MAX = 10000
- private const val ANIMATION_DURATION = 250L
- private const val ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN: Long = 500
- private const val ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3
-
- /**
- * If we don't see progress during this time, we show an error message to remind the users that
- * they need to lift the finger and touch again.
- */
- private const val HINT_TIMEOUT_DURATION = 2500
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollEnrollingRfpsView(
- view: GlifLayout,
- onSkipClickListener: View.OnClickListener
-) {
- GlifLayoutHelper(this, view).let {
- it.setDescriptionText(
- getString(
- R.string.security_settings_fingerprint_enroll_start_message
- )
- )
- it.setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title)
- }
-
- view.findViewById<ProgressBar>(R.id.fingerprint_progress_bar)!!
- .progressBackgroundTintMode = PorterDuff.Mode.SRC
-
- view.getMixin(FooterBarMixin::class.java).secondaryButton =
- FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
- .setListener(onSkipClickListener)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.kt
deleted file mode 100644
index 7faeeac..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.kt
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.animation.Animator
-import android.animation.ObjectAnimator
-import android.annotation.RawRes
-import android.content.Context
-import android.content.res.ColorStateList
-import android.content.res.Configuration
-import android.graphics.PorterDuff
-import android.graphics.PorterDuffColorFilter
-import android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.MotionEvent
-import android.view.View
-import android.view.ViewGroup
-import android.view.animation.AccelerateDecelerateInterpolator
-import android.view.animation.AnimationUtils
-import android.view.animation.Interpolator
-import android.widget.ProgressBar
-import android.widget.RelativeLayout
-import androidx.activity.OnBackPressedCallback
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-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
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-import com.google.android.setupdesign.template.DescriptionMixin
-import com.google.android.setupdesign.template.HeaderMixin
-import kotlin.math.roundToInt
-import kotlinx.coroutines.launch
-
-/**
- * Fragment is used to handle enrolling process for sfps
- */
-class FingerprintEnrollEnrollingSfpsFragment : Fragment() {
-
- private var _enrollingViewModel: FingerprintEnrollEnrollingViewModel? = null
- private val enrollingViewModel: FingerprintEnrollEnrollingViewModel
- get() = _enrollingViewModel!!
-
- private var _progressViewModel: FingerprintEnrollProgressViewModel? = null
- private val progressViewModel: FingerprintEnrollProgressViewModel
- get() = _progressViewModel!!
-
- private var _errorDialogViewModel: FingerprintEnrollErrorDialogViewModel? = null
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel
- get() = _errorDialogViewModel!!
-
- private val fastOutSlowInInterpolator: Interpolator
- get() = AnimationUtils.loadInterpolator(
- activity,
- androidx.appcompat.R.interpolator.fast_out_slow_in,
- )
-
- private var enrollingView: GlifLayout? = null
-
- private val progressBar: ProgressBar
- get() = enrollingView!!.findViewById(R.id.fingerprint_progress_bar)!!
-
- private var progressAnim: ObjectAnimator? = null
-
- private val progressAnimationListener: Animator.AnimatorListener =
- object : Animator.AnimatorListener {
- override fun onAnimationStart(animation: Animator) {}
- override fun onAnimationRepeat(animation: Animator) {}
- override fun onAnimationEnd(animation: Animator) {
- if (progressBar.progress >= PROGRESS_BAR_MAX) {
- progressBar.postDelayed(delayedFinishRunnable, PROGRESS_ANIMATION_DURATION)
- }
- }
-
- override fun onAnimationCancel(animation: Animator) {}
- }
-
- private val illustrationLottie: LottieAnimationView
- get() = enrollingView!!.findViewById(R.id.illustration_lottie)!!
-
- private var haveShownSfpsNoAnimationLottie = false
- private var haveShownSfpsCenterLottie = false
- private var haveShownSfpsTipLottie = false
- private var haveShownSfpsLeftEdgeLottie = false
- private var haveShownSfpsRightEdgeLottie = false
-
- private var helpAnimation: ObjectAnimator? = null
-
- private var iconTouchCount = 0
-
- private val showIconTouchDialogRunnable = Runnable { showIconTouchDialog() }
-
- private var enrollingCancelSignal: Any? = null
-
- // Give the user a chance to see progress completed before jumping to the next stage.
- private val delayedFinishRunnable = Runnable { enrollingViewModel.onEnrollingDone() }
-
- private val onSkipClickListener = View.OnClickListener { _: View? ->
- enrollingViewModel.setOnSkipPressed()
- cancelEnrollment(true)
- }
-
- private val progressObserver = Observer { progress: EnrollmentProgress? ->
- if (progress != null && progress.steps >= 0) {
- onEnrollmentProgressChange(progress)
- }
- }
-
- private val helpMessageObserver = Observer { helpMessage: EnrollmentStatusMessage? ->
- helpMessage?.let { onEnrollmentHelp(it) }
- }
-
- private val errorMessageObserver = Observer { errorMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "errorMessageObserver($errorMessage)")
- errorMessage?.let { onEnrollmentError(it) }
- }
-
- private val canceledSignalObserver = Observer { canceledSignal: Any? ->
- Log.d(TAG, "canceledSignalObserver($canceledSignal)")
- canceledSignal?.let { onEnrollmentCanceled(it) }
- }
-
- private val onBackPressedCallback: OnBackPressedCallback =
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- isEnabled = false
- enrollingViewModel.setOnBackPressed()
- cancelEnrollment(true)
- }
- }
-
- override fun onAttach(context: Context) {
- ViewModelProvider(requireActivity()).let { provider ->
- _enrollingViewModel = provider[FingerprintEnrollEnrollingViewModel::class.java]
- _progressViewModel = provider[FingerprintEnrollProgressViewModel::class.java]
- _errorDialogViewModel = provider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
- super.onAttach(context)
- requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
- }
-
- override fun onDetach() {
- onBackPressedCallback.isEnabled = false
- super.onDetach()
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- enrollingView = inflater.inflate(
- R.layout.sfps_enroll_enrolling,
- container, false
- ) as GlifLayout
- return enrollingView
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- requireActivity().bindFingerprintEnrollEnrollingSfpsView(
- view = enrollingView!!,
- onSkipClickListener = onSkipClickListener
- )
-
- // setHelpAnimation()
- helpAnimation = ObjectAnimator.ofFloat(
- enrollingView!!.findViewById<RelativeLayout>(R.id.progress_lottie)!!,
- "translationX" /* propertyName */,
- 0f,
- HELP_ANIMATION_TRANSLATION_X,
- -1 * HELP_ANIMATION_TRANSLATION_X,
- HELP_ANIMATION_TRANSLATION_X,
- 0f
- ).also {
- it.interpolator = AccelerateDecelerateInterpolator()
- it.setDuration(HELP_ANIMATION_DURATION)
- it.setAutoCancel(false)
- }
-
- progressBar.setOnTouchListener { _: View?, event: MotionEvent ->
- if (event.actionMasked == MotionEvent.ACTION_DOWN) {
- iconTouchCount++
- if (iconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
- showIconTouchDialog()
- } else {
- progressBar.postDelayed(
- showIconTouchDialogRunnable,
- ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN
- )
- }
- } else if (event.actionMasked == MotionEvent.ACTION_CANCEL
- || event.actionMasked == MotionEvent.ACTION_UP
- ) {
- progressBar.removeCallbacks(showIconTouchDialogRunnable)
- }
- true
- }
-
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.triggerRetryFlow.collect { retryEnrollment() }
- }
- }
- }
-
- private fun retryEnrollment() {
- startEnrollment()
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- }
-
- override fun onStart() {
- super.onStart()
- val isEnrolling = progressViewModel.isEnrolling
- val isErrorDialogShown = errorDialogViewModel.isDialogShown
- Log.d(TAG, "onStart(), isEnrolling:$isEnrolling, isErrorDialog:$isErrorDialogShown")
- if (!isErrorDialogShown) {
- startEnrollment()
- }
-
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- progressViewModel.helpMessageLiveData.value.let {
- if (it != null) {
- onEnrollmentHelp(it)
- } else {
- clearError()
- updateTitleAndDescription()
- }
- }
- }
-
- override fun onStop() {
- removeEnrollmentObservers()
- val isEnrolling = progressViewModel.isEnrolling
- val isConfigChange = requireActivity().isChangingConfigurations
- Log.d(TAG, "onStop(), enrolling:$isEnrolling isConfigChange:$isConfigChange")
- if (isEnrolling && !isConfigChange) {
- cancelEnrollment(false)
- }
- super.onStop()
- }
-
- private fun removeEnrollmentObservers() {
- progressViewModel.errorMessageLiveData.removeObserver(errorMessageObserver)
- progressViewModel.progressLiveData.removeObserver(progressObserver)
- progressViewModel.helpMessageLiveData.removeObserver(helpMessageObserver)
- }
-
- private fun cancelEnrollment(waitForLastCancelErrMsg: Boolean) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "cancelEnrollment(), failed because isEnrolling is false")
- return
- }
- removeEnrollmentObservers()
- if (waitForLastCancelErrMsg) {
- progressViewModel.canceledSignalLiveData.observe(this, canceledSignalObserver)
- } else {
- enrollingCancelSignal = null
- }
- val cancelResult: Boolean = progressViewModel.cancelEnrollment()
- if (!cancelResult) {
- Log.e(TAG, "cancelEnrollment(), failed to cancel enrollment")
- }
- }
-
- private fun startEnrollment() {
- enrollingCancelSignal = progressViewModel.startEnrollment(ENROLL_ENROLL)
- if (enrollingCancelSignal == null) {
- Log.e(TAG, "startEnrollment(), failed")
- } else {
- Log.d(TAG, "startEnrollment(), success")
- }
- progressViewModel.progressLiveData.observe(this, progressObserver)
- progressViewModel.helpMessageLiveData.observe(this, helpMessageObserver)
- progressViewModel.errorMessageLiveData.observe(this, errorMessageObserver)
- }
-
- private fun configureEnrollmentStage(description: CharSequence, @RawRes lottie: Int) {
- GlifLayoutHelper(requireActivity(), enrollingView!!).setDescriptionText(description)
- LottieCompositionFactory.fromRawRes(activity, lottie)
- .addListener { c: LottieComposition ->
- illustrationLottie.setComposition(c)
- illustrationLottie.visibility = View.VISIBLE
- illustrationLottie.playAnimation()
- }
- }
-
- private val currentSfpsStage: Int
- get() {
- val progressLiveData: EnrollmentProgress =
- progressViewModel.progressLiveData.value
- ?: return STAGE_UNKNOWN
- val progressSteps: Int = progressLiveData.steps - progressLiveData.remaining
- return if (progressSteps < getStageThresholdSteps(0)) {
- SFPS_STAGE_NO_ANIMATION
- } else if (progressSteps < getStageThresholdSteps(1)) {
- SFPS_STAGE_CENTER
- } else if (progressSteps < getStageThresholdSteps(2)) {
- SFPS_STAGE_FINGERTIP
- } else if (progressSteps < getStageThresholdSteps(3)) {
- SFPS_STAGE_LEFT_EDGE
- } else {
- SFPS_STAGE_RIGHT_EDGE
- }
- }
-
- private fun onEnrollmentHelp(helpMessage: EnrollmentStatusMessage) {
- Log.d(TAG, "onEnrollmentHelp($helpMessage)")
- val helpStr: CharSequence = helpMessage.str
- if (helpStr.isNotEmpty()) {
- showError(helpStr)
- }
- }
-
- private fun onEnrollmentError(errorMessage: EnrollmentStatusMessage) {
- cancelEnrollment(true)
- lifecycleScope.launch {
- Log.d(TAG, "newDialog $errorMessage")
- errorDialogViewModel.newDialog(errorMessage.msgId)
- }
- }
-
- private fun onEnrollmentCanceled(canceledSignal: Any) {
- Log.d(
- TAG,
- "onEnrollmentCanceled enrolling:$enrollingCancelSignal, canceled:$canceledSignal"
- )
- if (enrollingCancelSignal === canceledSignal) {
- progressViewModel.canceledSignalLiveData.removeObserver(canceledSignalObserver)
- progressViewModel.clearProgressLiveData()
- if (enrollingViewModel.onBackPressed) {
- enrollingViewModel.onCancelledDueToOnBackPressed()
- } else if (enrollingViewModel.onSkipPressed) {
- enrollingViewModel.onCancelledDueToOnSkipPressed()
- }
- }
- }
-
- private fun announceEnrollmentProgress(announcement: CharSequence) {
- enrollingViewModel.sendAccessibilityEvent(announcement)
- }
-
- private fun onEnrollmentProgressChange(progress: EnrollmentProgress) {
- updateProgress(true /* animate */, progress)
- if (enrollingViewModel.isAccessibilityEnabled) {
- val percent: Int =
- ((progress.steps - progress.remaining).toFloat() / progress.steps.toFloat() * 100).toInt()
- val announcement: CharSequence = getString(
- R.string.security_settings_sfps_enroll_progress_a11y_message, percent
- )
- announceEnrollmentProgress(announcement)
- illustrationLottie.contentDescription =
- getString(R.string.security_settings_sfps_animation_a11y_label, percent)
- }
- updateTitleAndDescription()
- }
-
- private fun updateProgress(animate: Boolean, enrollmentProgress: EnrollmentProgress) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "Enrollment not started yet")
- return
- }
-
- val progress = getProgress(enrollmentProgress)
- Log.d(TAG, "updateProgress($animate, $enrollmentProgress), old:${progressBar.progress}"
- + ", new:$progress")
-
- // Only clear the error when progress has been made.
- // TODO (b/234772728) Add tests.
- if (progressBar.progress < progress) {
- clearError()
- }
- if (animate) {
- animateProgress(progress)
- } else {
- progressBar.progress = progress
- if (progress >= PROGRESS_BAR_MAX) {
- delayedFinishRunnable.run()
- }
- }
- }
-
- private fun getProgress(progress: EnrollmentProgress): Int {
- if (progress.steps == -1) {
- return 0
- }
- val displayProgress = 0.coerceAtLeast(progress.steps + 1 - progress.remaining)
- return PROGRESS_BAR_MAX * displayProgress / (progress.steps + 1)
- }
-
- private fun showError(error: CharSequence) {
- enrollingView!!.let {
- it.headerText = error
- it.headerTextView.contentDescription = error
- GlifLayoutHelper(requireActivity(), it).setDescriptionText("")
- }
-
- if (isResumed && !helpAnimation!!.isRunning) {
- helpAnimation!!.start()
- }
- applySfpsErrorDynamicColors(true)
- if (isResumed && enrollingViewModel.isAccessibilityEnabled) {
- enrollingViewModel.vibrateError(javaClass.simpleName + "::showError")
- }
- }
-
- private fun clearError() {
- applySfpsErrorDynamicColors(false)
- }
-
- private fun animateProgress(progress: Int) {
- progressAnim?.cancel()
- progressAnim = ObjectAnimator.ofInt(
- progressBar,
- "progress",
- progressBar.progress,
- progress
- ).also {
- it.addListener(progressAnimationListener)
- it.interpolator = fastOutSlowInInterpolator
- it.setDuration(PROGRESS_ANIMATION_DURATION)
- it.start()
- }
- }
-
- /**
- * Applies dynamic colors corresponding to showing or clearing errors on the progress bar
- * and finger lottie for SFPS
- */
- private fun applySfpsErrorDynamicColors(isError: Boolean) {
- progressBar.applyProgressBarDynamicColor(requireContext(), isError)
- illustrationLottie.applyLottieDynamicColor(requireContext(), isError)
- }
-
- private fun getStageThresholdSteps(index: Int): Int {
- val progressLiveData: EnrollmentProgress? =
- progressViewModel.progressLiveData.value
- if (progressLiveData == null || progressLiveData.steps == -1) {
- Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet")
- return 1
- }
- return (progressLiveData.steps
- * enrollingViewModel.getEnrollStageThreshold(index)).roundToInt()
- }
-
- private fun updateTitleAndDescription() {
- val helper = GlifLayoutHelper(requireActivity(), enrollingView!!)
- if (enrollingViewModel.isAccessibilityEnabled) {
- enrollingViewModel.clearTalkback()
- helper.glifLayout.descriptionTextView.accessibilityLiveRegion =
- View.ACCESSIBILITY_LIVE_REGION_POLITE
- }
- val stage = currentSfpsStage
- if (DEBUG) {
- Log.d(
- TAG, "updateTitleAndDescription, stage:" + stage
- + ", noAnimation:" + haveShownSfpsNoAnimationLottie
- + ", center:" + haveShownSfpsCenterLottie
- + ", tip:" + haveShownSfpsTipLottie
- + ", leftEdge:" + haveShownSfpsLeftEdgeLottie
- + ", rightEdge:" + haveShownSfpsRightEdgeLottie
- )
- }
- when (stage) {
- SFPS_STAGE_NO_ANIMATION -> {
- helper.setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title)
- if (!haveShownSfpsNoAnimationLottie) {
- haveShownSfpsNoAnimationLottie = true
- illustrationLottie.contentDescription =
- getString(R.string.security_settings_sfps_animation_a11y_label, 0)
- configureEnrollmentStage(
- getString(R.string.security_settings_sfps_enroll_start_message),
- R.raw.sfps_lottie_no_animation
- )
- }
- }
-
- SFPS_STAGE_CENTER -> {
- helper.setHeaderText(R.string.security_settings_sfps_enroll_finger_center_title)
- if (!haveShownSfpsCenterLottie) {
- haveShownSfpsCenterLottie = true
- configureEnrollmentStage(
- getString(R.string.security_settings_sfps_enroll_start_message),
- R.raw.sfps_lottie_pad_center
- )
- }
- }
-
- SFPS_STAGE_FINGERTIP -> {
- helper.setHeaderText(R.string.security_settings_sfps_enroll_fingertip_title)
- if (!haveShownSfpsTipLottie) {
- haveShownSfpsTipLottie = true
- configureEnrollmentStage("", R.raw.sfps_lottie_tip)
- }
- }
-
- SFPS_STAGE_LEFT_EDGE -> {
- helper.setHeaderText(R.string.security_settings_sfps_enroll_left_edge_title)
- if (!haveShownSfpsLeftEdgeLottie) {
- haveShownSfpsLeftEdgeLottie = true
- configureEnrollmentStage("", R.raw.sfps_lottie_left_edge)
- }
- }
-
- SFPS_STAGE_RIGHT_EDGE -> {
- helper.setHeaderText(R.string.security_settings_sfps_enroll_right_edge_title)
- if (!haveShownSfpsRightEdgeLottie) {
- haveShownSfpsRightEdgeLottie = true
- configureEnrollmentStage("", R.raw.sfps_lottie_right_edge)
- }
- }
-
- STAGE_UNKNOWN -> {
- // Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle,
- // which gets announced for a11y upon entering the page. For SFPS, we want to
- // announce a different string for a11y upon entering the page.
- helper.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title)
- helper.setDescriptionText(
- getString(R.string.security_settings_sfps_enroll_start_message)
- )
- val description: CharSequence = getString(
- R.string.security_settings_sfps_enroll_find_sensor_message
- )
- helper.glifLayout.headerTextView.contentDescription = description
- helper.activity.title = description
- }
-
- else -> {
- helper.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title)
- helper.setDescriptionText(
- getString(R.string.security_settings_sfps_enroll_start_message)
- )
- val description: CharSequence = getString(
- R.string.security_settings_sfps_enroll_find_sensor_message
- )
- helper.glifLayout.headerTextView.contentDescription = description
- helper.activity.title = description
- }
- }
- }
-
- private fun showIconTouchDialog() {
- iconTouchCount = 0
- enrollingViewModel.showIconTouchDialog()
- }
-
- companion object {
- private val TAG = FingerprintEnrollEnrollingSfpsFragment::class.java.simpleName
- private const val DEBUG = false
- private const val PROGRESS_BAR_MAX = 10000
- private const val HELP_ANIMATION_DURATION = 550L
- private const val HELP_ANIMATION_TRANSLATION_X = 40f
- private const val PROGRESS_ANIMATION_DURATION = 250L
- private const val ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN: Long = 500
- private const val ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3
- private const val STAGE_UNKNOWN = -1
- private const val SFPS_STAGE_NO_ANIMATION = 0
- private const val SFPS_STAGE_CENTER = 1
- private const val SFPS_STAGE_FINGERTIP = 2
- private const val SFPS_STAGE_LEFT_EDGE = 3
- private const val SFPS_STAGE_RIGHT_EDGE = 4
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollEnrollingSfpsView(
- view: GlifLayout,
- onSkipClickListener: View.OnClickListener
-) {
- GlifLayoutHelper(this, view).setDescriptionText(
- getString(R.string.security_settings_fingerprint_enroll_start_message)
- )
-
- view.getMixin(FooterBarMixin::class.java).secondaryButton = FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
- .setListener(onSkipClickListener)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
-
- view.findViewById<ProgressBar>(R.id.fingerprint_progress_bar)!!.progressBackgroundTintMode =
- PorterDuff.Mode.SRC
-
- view.findViewById<ProgressBar>(R.id.fingerprint_progress_bar)!!
- .applyProgressBarDynamicColor(this, false)
-
- view.findViewById<LottieAnimationView>(R.id.illustration_lottie)!!
- .applyLottieDynamicColor(this, false)
-
- view.maybeHideSfpsText(resources.configuration.orientation)
-}
-
-private fun ProgressBar.applyProgressBarDynamicColor(context: Context, isError: Boolean) {
- progressTintList = ColorStateList.valueOf(
- context.getColor(
- if (isError)
- R.color.sfps_enrollment_progress_bar_error_color
- else
- R.color.sfps_enrollment_progress_bar_fill_color
- )
- )
- progressTintMode = PorterDuff.Mode.SRC
- invalidate()
-}
-
-fun LottieAnimationView.applyLottieDynamicColor(context: Context, isError: Boolean) {
- addValueCallback(
- KeyPath(".blue100", "**"),
- LottieProperty.COLOR_FILTER
- ) {
- PorterDuffColorFilter(
- context.getColor(
- if (isError)
- R.color.sfps_enrollment_fp_error_color
- else
- R.color.sfps_enrollment_fp_captured_color
- ),
- PorterDuff.Mode.SRC_ATOP
- )
- }
- invalidate()
-}
-
-fun GlifLayout.maybeHideSfpsText(@Configuration.Orientation orientation: Int) {
- val headerMixin: HeaderMixin = getMixin(HeaderMixin::class.java)
- val descriptionMixin: DescriptionMixin = getMixin(DescriptionMixin::class.java)
-
- val isLandscape = (orientation == Configuration.ORIENTATION_LANDSCAPE)
- headerMixin.setAutoTextSizeEnabled(isLandscape)
- if (isLandscape) {
- headerMixin.textView.minLines = 0
- headerMixin.textView.maxLines = 10
- descriptionMixin.textView.minLines = 0
- descriptionMixin.textView.maxLines = 10
- } else {
- headerMixin.textView.setLines(4)
- // hide the description
- descriptionMixin.textView.setLines(0)
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.kt
deleted file mode 100644
index 7e754ac..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.kt
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.annotation.RawRes
-import android.content.Context
-import android.hardware.biometrics.BiometricFingerprintConstants
-import android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.Surface.ROTATION_270
-import android.view.Surface.ROTATION_90
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.RelativeLayout
-import android.widget.TextView
-import androidx.activity.OnBackPressedCallback
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import com.airbnb.lottie.LottieAnimationView
-import com.airbnb.lottie.LottieComposition
-import com.airbnb.lottie.LottieCompositionFactory
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.android.settings.biometrics2.ui.widget.UdfpsEnrollView
-import com.android.settingslib.display.DisplayDensityUtils
-import kotlinx.coroutines.launch
-import kotlin.math.roundToInt
-
-/**
- * Fragment is used to handle enrolling process for udfps
- */
-class FingerprintEnrollEnrollingUdfpsFragment : Fragment() {
-
- private var _enrollingViewModel: FingerprintEnrollEnrollingViewModel? = null
- private val enrollingViewModel: FingerprintEnrollEnrollingViewModel
- get() = _enrollingViewModel!!
-
- private var _rotationViewModel: DeviceRotationViewModel? = null
- private val rotationViewModel: DeviceRotationViewModel
- get() = _rotationViewModel!!
-
- private var _progressViewModel: FingerprintEnrollProgressViewModel? = null
- private val progressViewModel: FingerprintEnrollProgressViewModel
- get() = _progressViewModel!!
-
- private var _errorDialogViewModel: FingerprintEnrollErrorDialogViewModel? = null
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel
- get() = _errorDialogViewModel!!
-
- private var illustrationLottie: LottieAnimationView? = null
-
- private var haveShownTipLottie = false
- private var haveShownLeftEdgeLottie = false
- private var haveShownRightEdgeLottie = false
- private var haveShownCenterLottie = false
- private var haveShownGuideLottie = false
-
- private var enrollingView: RelativeLayout? = null
-
- private val titleText: TextView
- get() = enrollingView!!.findViewById(R.id.suc_layout_title)!!
-
- private val subTitleText: TextView
- get() = enrollingView!!.findViewById(R.id.sud_layout_subtitle)!!
-
- private val udfpsEnrollView: UdfpsEnrollView
- get() = enrollingView!!.findViewById(R.id.udfps_animation_view)!!
-
- private val skipBtn: Button
- get() = enrollingView!!.findViewById(R.id.skip_btn)!!
-
- private val icon: ImageView
- get() = enrollingView!!.findViewById(R.id.sud_layout_icon)!!
-
- private val shouldShowLottie: Boolean
- get() {
- val displayDensity = DisplayDensityUtils(requireContext())
- val currentDensityIndex: Int = displayDensity.currentIndexForDefaultDisplay
- val currentDensity: Int =
- displayDensity.defaultDisplayDensityValues[currentDensityIndex]
- val defaultDensity: Int = displayDensity.defaultDensityForDefaultDisplay
- return defaultDensity == currentDensity
- }
-
- private val isAccessibilityEnabled
- get() = enrollingViewModel.isAccessibilityEnabled
-
- private var rotation = -1
-
- private var enrollingCancelSignal: Any? = null
-
- private val onSkipClickListener = View.OnClickListener { _: View? ->
- enrollingViewModel.setOnSkipPressed()
- cancelEnrollment(true) // TODO Add test after b/273640000 fixed
- }
-
- private val progressObserver = Observer { progress: EnrollmentProgress? ->
- if (progress != null && progress.steps >= 0) {
- onEnrollmentProgressChange(progress)
- }
- }
-
- private val helpMessageObserver = Observer { helpMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "helpMessageObserver($helpMessage)")
- helpMessage?.let { onEnrollmentHelp(it) }
- }
-
- private val errorMessageObserver = Observer { errorMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "errorMessageObserver($errorMessage)")
- errorMessage?.let { onEnrollmentError(it) }
- }
-
- private val canceledSignalObserver = Observer { canceledSignal: Any? ->
- Log.d(TAG, "canceledSignalObserver($canceledSignal)")
- canceledSignal?.let { onEnrollmentCanceled(it) }
- }
-
- private val acquireObserver =
- Observer { isAcquiredGood: Boolean? -> isAcquiredGood?.let { onAcquired(it) } }
-
- private val pointerDownObserver =
- Observer { sensorId: Int? -> sensorId?.let { onPointerDown(it) } }
-
- private val pointerUpObserver =
- Observer { sensorId: Int? -> sensorId?.let { onPointerUp(it) } }
-
- private val rotationObserver =
- Observer { rotation: Int? -> rotation?.let { onRotationChanged(it) } }
-
- private val onBackPressedCallback: OnBackPressedCallback =
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- isEnabled = false
- enrollingViewModel.setOnBackPressed()
- cancelEnrollment(true)
- }
- }
-
- // Give the user a chance to see progress completed before jumping to the next stage.
- private val delayedFinishRunnable = Runnable { enrollingViewModel.onEnrollingDone() }
-
- override fun onAttach(context: Context) {
- ViewModelProvider(requireActivity()).let { provider ->
- _enrollingViewModel = provider[FingerprintEnrollEnrollingViewModel::class.java]
- _rotationViewModel = provider[DeviceRotationViewModel::class.java]
- _progressViewModel = provider[FingerprintEnrollProgressViewModel::class.java]
- _errorDialogViewModel = provider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
- super.onAttach(context)
- requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
- }
-
- override fun onDetach() {
- onBackPressedCallback.isEnabled = false
- super.onDetach()
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View = (inflater.inflate(
- R.layout.udfps_enroll_enrolling_v2, container, false
- ) as RelativeLayout).also {
- enrollingView = it
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- rotation = rotationViewModel.liveData.value!!
- updateIllustrationLottie(rotation)
-
- requireActivity().bindFingerprintEnrollEnrollingUdfpsView(
- view = enrollingView!!,
- sensorProperties = enrollingViewModel.firstFingerprintSensorPropertiesInternal!!,
- rotation = rotation,
- onSkipClickListener = onSkipClickListener,
- )
-
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.triggerRetryFlow.collect { retryEnrollment() }
- }
- }
- }
-
- private fun retryEnrollment() {
- reattachUdfpsEnrollView()
-
- startEnrollment()
-
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- progressViewModel.helpMessageLiveData.value.let {
- if (it != null) {
- onEnrollmentHelp(it)
- } else {
- updateTitleAndDescription()
- }
- }
- }
-
- override fun onStart() {
- super.onStart()
- val isEnrolling = progressViewModel.isEnrolling
- val isErrorDialogShown = errorDialogViewModel.isDialogShown
- Log.d(TAG, "onStart(), isEnrolling:$isEnrolling, isErrorDialog:$isErrorDialogShown")
- if (!isErrorDialogShown) {
- startEnrollment()
- }
-
- updateProgress(false /* animate */, progressViewModel.progressLiveData.value!!)
- progressViewModel.helpMessageLiveData.value.let {
- if (it != null) {
- onEnrollmentHelp(it)
- } else {
- updateTitleAndDescription()
- }
- }
- }
-
- private fun reattachUdfpsEnrollView() {
- enrollingView!!.let {
- val newUdfpsView = LayoutInflater.from(requireActivity()).inflate(
- R.layout.udfps_enroll_enrolling_v2_udfps_view,
- null
- )
- val index = it.indexOfChild(udfpsEnrollView)
- val lp = udfpsEnrollView.layoutParams
-
- it.removeView(udfpsEnrollView)
- it.addView(newUdfpsView, index, lp)
- udfpsEnrollView.setSensorProperties(
- enrollingViewModel.firstFingerprintSensorPropertiesInternal
- )
- }
-
- // Clear lottie status
- haveShownTipLottie = false
- haveShownLeftEdgeLottie = false
- haveShownRightEdgeLottie = false
- haveShownCenterLottie = false
- haveShownGuideLottie = false
- illustrationLottie?.let {
- it.contentDescription = ""
- it.visibility = View.GONE
- }
- }
-
- override fun onResume() {
- super.onResume()
- rotationViewModel.liveData.observe(this, rotationObserver)
- }
-
- override fun onPause() {
- rotationViewModel.liveData.removeObserver(rotationObserver)
- super.onPause()
- }
-
- override fun onStop() {
- removeEnrollmentObservers()
- val isEnrolling = progressViewModel.isEnrolling
- val isConfigChange = requireActivity().isChangingConfigurations
- Log.d(TAG, "onStop(), enrolling:$isEnrolling isConfigChange:$isConfigChange")
- if (isEnrolling && !isConfigChange) {
- cancelEnrollment(false)
- }
- super.onStop()
- }
-
- private fun removeEnrollmentObservers() {
- progressViewModel.errorMessageLiveData.removeObserver(errorMessageObserver)
- progressViewModel.progressLiveData.removeObserver(progressObserver)
- progressViewModel.helpMessageLiveData.removeObserver(helpMessageObserver)
- progressViewModel.acquireLiveData.removeObserver(acquireObserver)
- progressViewModel.pointerDownLiveData.removeObserver(pointerDownObserver)
- progressViewModel.pointerUpLiveData.removeObserver(pointerUpObserver)
- }
-
- private fun cancelEnrollment(waitForLastCancelErrMsg: Boolean) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "cancelEnrollment(), failed because isEnrolling is false")
- return
- }
- removeEnrollmentObservers()
- if (waitForLastCancelErrMsg) {
- progressViewModel.canceledSignalLiveData.observe(this, canceledSignalObserver)
- } else {
- enrollingCancelSignal = null
- }
- val cancelResult: Boolean = progressViewModel.cancelEnrollment()
- if (!cancelResult) {
- Log.e(TAG, "cancelEnrollment(), failed to cancel enrollment")
- }
- }
-
- private fun startEnrollment() {
- enrollingCancelSignal = progressViewModel.startEnrollment(ENROLL_ENROLL)
- if (enrollingCancelSignal == null) {
- Log.e(TAG, "startEnrollment(), failed")
- } else {
- Log.d(TAG, "startEnrollment(), success")
- }
- progressViewModel.progressLiveData.observe(this, progressObserver)
- progressViewModel.helpMessageLiveData.observe(this, helpMessageObserver)
- progressViewModel.errorMessageLiveData.observe(this, errorMessageObserver)
- progressViewModel.acquireLiveData.observe(this, acquireObserver)
- progressViewModel.pointerDownLiveData.observe(this, pointerDownObserver)
- progressViewModel.pointerUpLiveData.observe(this, pointerUpObserver)
- }
-
- private fun updateProgress(animate: Boolean, enrollmentProgress: EnrollmentProgress) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "Enrollment not started yet")
- return
- }
-
- val progress = getProgress(enrollmentProgress)
- Log.d(TAG, "updateProgress($animate, $enrollmentProgress), progress:$progress")
-
- if (enrollmentProgress.steps != -1) {
- udfpsEnrollView.onEnrollmentProgress(
- enrollmentProgress.remaining,
- enrollmentProgress.steps
- )
- }
-
- if (progress >= PROGRESS_BAR_MAX) {
- if (animate) {
- // Wait animations to finish, then proceed to next page
- activity!!.mainThreadHandler.postDelayed(delayedFinishRunnable, 400L)
- } else {
- delayedFinishRunnable.run()
- }
- }
- }
-
- private fun getProgress(progress: EnrollmentProgress): Int {
- if (progress.steps == -1) {
- return 0
- }
- val displayProgress = 0.coerceAtLeast(progress.steps + 1 - progress.remaining)
- return PROGRESS_BAR_MAX * displayProgress / (progress.steps + 1)
- }
-
- private fun updateTitleAndDescription() {
- Log.d(TAG, "updateTitleAndDescription($currentStage)")
- when (currentStage) {
- STAGE_CENTER -> {
- titleText.setText(R.string.security_settings_fingerprint_enroll_repeat_title)
- if (isAccessibilityEnabled || illustrationLottie == null) {
- subTitleText.setText(R.string.security_settings_udfps_enroll_start_message)
- } else if (!haveShownCenterLottie) {
- haveShownCenterLottie = true
- // Note: Update string reference when differentiate in between udfps & sfps
- illustrationLottie!!.contentDescription = getString(R.string.security_settings_sfps_enroll_finger_center_title)
- configureEnrollmentStage(R.raw.udfps_center_hint_lottie)
- }
- }
-
- STAGE_GUIDED -> {
- titleText.setText(R.string.security_settings_fingerprint_enroll_repeat_title)
- if (isAccessibilityEnabled || illustrationLottie == null) {
- subTitleText.setText(
- R.string.security_settings_udfps_enroll_repeat_a11y_message
- )
- } else if (!haveShownGuideLottie) {
- haveShownGuideLottie = true
- illustrationLottie!!.contentDescription =
- getString(R.string.security_settings_fingerprint_enroll_repeat_message)
- // TODO(b/228100413) Could customize guided lottie animation
- configureEnrollmentStage(R.raw.udfps_center_hint_lottie)
- }
- }
-
- STAGE_FINGERTIP -> {
- titleText.setText(R.string.security_settings_udfps_enroll_fingertip_title)
- if (!haveShownTipLottie && illustrationLottie != null) {
- haveShownTipLottie = true
- illustrationLottie!!.contentDescription =
- getString(R.string.security_settings_udfps_tip_fingerprint_help)
- configureEnrollmentStage(R.raw.udfps_tip_hint_lottie)
- }
- }
-
- STAGE_LEFT_EDGE -> {
- titleText.setText(R.string.security_settings_udfps_enroll_left_edge_title)
- if (!haveShownLeftEdgeLottie && illustrationLottie != null) {
- haveShownLeftEdgeLottie = true
- illustrationLottie!!.contentDescription =
- getString(R.string.security_settings_udfps_side_fingerprint_help)
- configureEnrollmentStage(R.raw.udfps_left_edge_hint_lottie)
- } else if (illustrationLottie == null) {
- if (isStageHalfCompleted) {
- subTitleText.setText(
- R.string.security_settings_fingerprint_enroll_repeat_message
- )
- } else {
- subTitleText.setText(R.string.security_settings_udfps_enroll_edge_message)
- }
- }
- }
-
- STAGE_RIGHT_EDGE -> {
- titleText.setText(R.string.security_settings_udfps_enroll_right_edge_title)
- if (!haveShownRightEdgeLottie && illustrationLottie != null) {
- haveShownRightEdgeLottie = true
- illustrationLottie!!.contentDescription =
- getString(R.string.security_settings_udfps_side_fingerprint_help)
- configureEnrollmentStage(R.raw.udfps_right_edge_hint_lottie)
- } else if (illustrationLottie == null) {
- if (isStageHalfCompleted) {
- subTitleText.setText(
- R.string.security_settings_fingerprint_enroll_repeat_message
- )
- } else {
- subTitleText.setText(R.string.security_settings_udfps_enroll_edge_message)
- }
- }
- }
-
- STAGE_UNKNOWN -> {
- titleText.setText(R.string.security_settings_fingerprint_enroll_udfps_title)
- subTitleText.setText(R.string.security_settings_udfps_enroll_start_message)
- val description: CharSequence = getString(
- R.string.security_settings_udfps_enroll_a11y
- )
- requireActivity().title = description
- }
-
- else -> {
- titleText.setText(R.string.security_settings_fingerprint_enroll_udfps_title)
- subTitleText.setText(R.string.security_settings_udfps_enroll_start_message)
- val description: CharSequence = getString(
- R.string.security_settings_udfps_enroll_a11y
- )
- requireActivity().title = description
- }
- }
- }
-
- private fun updateIllustrationLottie(@Surface.Rotation rotation: Int) {
- if (rotation == ROTATION_90 || rotation == ROTATION_270) {
- illustrationLottie = null
- } else if (shouldShowLottie) {
- illustrationLottie =
- enrollingView!!.findViewById(R.id.illustration_lottie)
- }
- }
-
- private val currentStage: Int
- get() {
- val progress = progressViewModel.progressLiveData.value!!
- if (progress.steps == -1) {
- return STAGE_UNKNOWN
- }
- val progressSteps: Int = progress.steps - progress.remaining
- return if (progressSteps < getStageThresholdSteps(0)) {
- STAGE_CENTER
- } else if (progressSteps < getStageThresholdSteps(1)) {
- STAGE_GUIDED
- } else if (progressSteps < getStageThresholdSteps(2)) {
- STAGE_FINGERTIP
- } else if (progressSteps < getStageThresholdSteps(3)) {
- STAGE_LEFT_EDGE
- } else {
- STAGE_RIGHT_EDGE
- }
- }
-
- private val isStageHalfCompleted: Boolean
- get() {
- val progress: EnrollmentProgress = progressViewModel.progressLiveData.value!!
- if (progress.steps == -1) {
- return false
- }
- val progressSteps: Int = progress.steps - progress.remaining
- var prevThresholdSteps = 0
- for (i in 0 until enrollingViewModel.getEnrollStageCount()) {
- val thresholdSteps = getStageThresholdSteps(i)
- if (progressSteps in prevThresholdSteps until thresholdSteps) {
- val adjustedProgress = progressSteps - prevThresholdSteps
- val adjustedThreshold = thresholdSteps - prevThresholdSteps
- return adjustedProgress >= adjustedThreshold / 2
- }
- prevThresholdSteps = thresholdSteps
- }
-
- // After last enrollment step.
- return true
- }
-
- private fun getStageThresholdSteps(index: Int): Int {
- val progress: EnrollmentProgress = progressViewModel.progressLiveData.value!!
- if (progress.steps == -1) {
- Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet")
- return 1
- }
- return (progress.steps * enrollingViewModel.getEnrollStageThreshold(index)).roundToInt()
- }
-
- private fun configureEnrollmentStage(@RawRes lottie: Int) {
- subTitleText.text = ""
- LottieCompositionFactory.fromRawRes(activity, lottie)
- .addListener { c: LottieComposition ->
- illustrationLottie?.let {
- it.setComposition(c)
- it.visibility = View.VISIBLE
- it.playAnimation()
- }
- }
- }
-
- private fun onEnrollmentProgressChange(progress: EnrollmentProgress) {
- updateProgress(true /* animate */, progress)
- updateTitleAndDescription()
- if (isAccessibilityEnabled) {
- val steps: Int = progress.steps
- val remaining: Int = progress.remaining
- val percent = ((steps - remaining).toFloat() / steps.toFloat() * 100).toInt()
- val announcement: CharSequence = activity!!.getString(
- R.string.security_settings_udfps_enroll_progress_a11y_message, percent
- )
- enrollingViewModel.sendAccessibilityEvent(announcement)
- }
- }
-
- private fun onEnrollmentHelp(helpMessage: EnrollmentStatusMessage) {
- Log.d(TAG, "onEnrollmentHelp($helpMessage)")
- val helpStr: CharSequence = helpMessage.str
- if (helpStr.isNotEmpty()) {
- showError(helpStr)
- udfpsEnrollView.onEnrollmentHelp()
- }
- }
-
- private fun onEnrollmentError(errorMessage: EnrollmentStatusMessage) {
- cancelEnrollment(true)
- lifecycleScope.launch {
- Log.d(TAG, "newDialog $errorMessage")
- errorDialogViewModel.newDialog(errorMessage.msgId)
- }
- }
-
- private fun onEnrollmentCanceled(canceledSignal: Any) {
- Log.d(
- TAG,
- "onEnrollmentCanceled enrolling:$enrollingCancelSignal, canceled:$canceledSignal"
- )
- if (enrollingCancelSignal === canceledSignal) {
- progressViewModel.canceledSignalLiveData.removeObserver(canceledSignalObserver)
- progressViewModel.clearProgressLiveData()
- if (enrollingViewModel.onBackPressed) {
- enrollingViewModel.onCancelledDueToOnBackPressed()
- } else if (enrollingViewModel.onSkipPressed) {
- enrollingViewModel.onCancelledDueToOnSkipPressed()
- }
- }
- }
-
- private fun onAcquired(isAcquiredGood: Boolean) {
- udfpsEnrollView.onAcquired(isAcquiredGood)
- }
-
- private fun onPointerDown(sensorId: Int) {
- udfpsEnrollView.onPointerDown(sensorId)
- }
-
- private fun onPointerUp(sensorId: Int) {
- udfpsEnrollView.onPointerUp(sensorId)
- }
-
- private fun showError(error: CharSequence) {
- titleText.text = error
- titleText.contentDescription = error
- subTitleText.contentDescription = ""
- }
-
- private fun onRotationChanged(newRotation: Int) {
- if ((newRotation + 2) % 4 == rotation) {
- rotation = newRotation
- requireContext().configLayout(newRotation, titleText, subTitleText, icon, skipBtn)
- }
- }
-
- companion object {
- private val TAG = "FingerprintEnrollEnrollingUdfpsFragment"
- private const val PROGRESS_BAR_MAX = 10000
- private const val STAGE_UNKNOWN = -1
- private const val STAGE_CENTER = 0
- private const val STAGE_GUIDED = 1
- private const val STAGE_FINGERTIP = 2
- private const val STAGE_LEFT_EDGE = 3
- private const val STAGE_RIGHT_EDGE = 4
- }
-}
-
-
-fun FragmentActivity.bindFingerprintEnrollEnrollingUdfpsView(
- view: RelativeLayout,
- sensorProperties: FingerprintSensorPropertiesInternal,
- @Surface.Rotation rotation: Int,
- onSkipClickListener: View.OnClickListener
-) {
- view.findViewById<UdfpsEnrollView>(R.id.udfps_animation_view)!!.setSensorProperties(
- sensorProperties
- )
-
- val titleText = view.findViewById<TextView>(R.id.suc_layout_title)!!
- val subTitleText = view.findViewById<TextView>(R.id.sud_layout_subtitle)!!
- val icon = view.findViewById<ImageView>(R.id.sud_layout_icon)!!
- val skipBtn = view.findViewById<Button>(R.id.skip_btn)!!.also {
- it.setOnClickListener(onSkipClickListener)
- }
- configLayout(rotation, titleText, subTitleText, icon, skipBtn)
-}
-
-private fun Context.configLayout(
- @Surface.Rotation newRotation: Int,
- titleText: TextView,
- subTitleText: TextView,
- icon: ImageView,
- skipBtn: Button
-) {
- if (newRotation == ROTATION_270) {
- val iconLP = RelativeLayout.LayoutParams(-2, -2)
- iconLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- iconLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view)
- iconLP.topMargin = convertDpToPixel(76.64f)
- iconLP.leftMargin = convertDpToPixel(151.54f)
- icon.layoutParams = iconLP
- val titleLP = RelativeLayout.LayoutParams(-1, -2)
- titleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- titleLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view)
- titleLP.topMargin = convertDpToPixel(138f)
- titleLP.leftMargin = convertDpToPixel(144f)
- titleText.layoutParams = titleLP
- val subtitleLP = RelativeLayout.LayoutParams(-1, -2)
- subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- subtitleLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view)
- subtitleLP.topMargin = convertDpToPixel(198f)
- subtitleLP.leftMargin = convertDpToPixel(144f)
- subTitleText.layoutParams = subtitleLP
- } else if (newRotation == ROTATION_90) {
- val metrics = resources.displayMetrics
- val iconLP = RelativeLayout.LayoutParams(-2, -2)
- iconLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- iconLP.addRule(RelativeLayout.ALIGN_PARENT_START)
- iconLP.topMargin = convertDpToPixel(76.64f)
- iconLP.leftMargin = convertDpToPixel(71.99f)
- icon.layoutParams = iconLP
- val titleLP = RelativeLayout.LayoutParams(
- metrics.widthPixels / 2, -2
- )
- titleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- titleLP.addRule(RelativeLayout.ALIGN_PARENT_START, R.id.udfps_animation_view)
- titleLP.topMargin = convertDpToPixel(138f)
- titleLP.leftMargin = convertDpToPixel(66f)
- titleText.layoutParams = titleLP
- val subtitleLP = RelativeLayout.LayoutParams(
- metrics.widthPixels / 2, -2
- )
- subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP)
- subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_START)
- subtitleLP.topMargin = convertDpToPixel(198f)
- subtitleLP.leftMargin = convertDpToPixel(66f)
- subTitleText.layoutParams = subtitleLP
- }
- if (newRotation == ROTATION_90 || newRotation == ROTATION_270) {
- val skipBtnLP = skipBtn.layoutParams as RelativeLayout.LayoutParams
- skipBtnLP.topMargin = convertDpToPixel(26f)
- skipBtnLP.leftMargin = convertDpToPixel(54f)
- skipBtn.requestLayout()
- }
-}
-
-fun Context.convertDpToPixel(dp: Float): Int {
- return (dp * resources.displayMetrics.density).toInt()
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollErrorDialog.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollErrorDialog.kt
deleted file mode 100644
index 882cbcf..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollErrorDialog.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 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.biometrics2.ui.view
-
-import android.app.Dialog
-import android.content.Context
-import android.content.DialogInterface
-import android.hardware.biometrics.BiometricConstants
-import android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS
-import android.hardware.fingerprint.FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE
-import android.os.Bundle
-import android.util.Log
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.DialogFragment
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import com.android.settings.R
-import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog.getErrorMessage
-import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog.getErrorTitle
-import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog.getSetupErrorMessage
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
-import kotlinx.coroutines.launch
-
-/**
- * Fingerprint error dialog, will be shown when an error occurs during fingerprint enrollment.
- */
-class FingerprintEnrollErrorDialog : DialogFragment() {
-
- private val viewModel: FingerprintEnrollErrorDialogViewModel?
- get() = activity?.let {
- ViewModelProvider(it)[FingerprintEnrollErrorDialogViewModel::class.java]
- }
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- val errorMsgId: Int = requireArguments().getInt(KEY_ERROR_MSG_ID)
- val okButtonSetResultAction =
- if (errorMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT)
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
- else
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
- return requireActivity().bindFingerprintEnrollEnrollingErrorDialog(
- errorMsgId = errorMsgId,
- isSuw = viewModel!!.isSuw,
- tryAgainButtonClickListener = { dialog: DialogInterface?, _: Int ->
- activity?.lifecycleScope?.launch {
- Log.d(TAG, "tryAgain flow")
- viewModel?.triggerRetry()
- dialog?.dismiss()
- }
- },
- okButtonClickListener = { dialog: DialogInterface?, _: Int ->
- activity?.lifecycleScope?.launch {
- Log.d(TAG, "ok flow as $okButtonSetResultAction")
- viewModel?.setResultAndFinish(okButtonSetResultAction)
- dialog?.dismiss()
- }
- }
- )
- }
-
- companion object {
- private const val TAG = "FingerprintEnrollErrorDialog"
- private const val KEY_ERROR_MSG_ID = "error_msg_id"
-
- fun newInstance(errorMsgId: Int): FingerprintEnrollErrorDialog {
- val dialog = FingerprintEnrollErrorDialog()
- val args = Bundle()
- args.putInt(KEY_ERROR_MSG_ID, errorMsgId)
- dialog.arguments = args
- return dialog
- }
- }
-}
-
-fun Context.bindFingerprintEnrollEnrollingErrorDialog(
- errorMsgId: Int,
- isSuw: Boolean,
- tryAgainButtonClickListener: DialogInterface.OnClickListener,
- okButtonClickListener: DialogInterface.OnClickListener
-): AlertDialog = AlertDialog.Builder(this)
- .setTitle(getString(getErrorTitle(errorMsgId)))
- .setMessage(
- getString(
- if (isSuw)
- getSetupErrorMessage(errorMsgId)
- else
- getErrorMessage(errorMsgId)
- )
- )
- .setCancelable(false).apply {
- if (errorMsgId == FINGERPRINT_ERROR_UNABLE_TO_PROCESS) {
- setPositiveButton(
- R.string.security_settings_fingerprint_enroll_dialog_try_again,
- tryAgainButtonClickListener
- )
- setNegativeButton(
- R.string.security_settings_fingerprint_enroll_dialog_ok,
- okButtonClickListener
- )
- } else {
- setPositiveButton(
- R.string.security_settings_fingerprint_enroll_dialog_ok,
- okButtonClickListener
- )
- }
- }
- .create()
- .apply { setCanceledOnTouchOutside(false) }
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.kt
deleted file mode 100644
index be24fc6..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindRfpsFragment.kt
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.view
-
-import android.content.Context
-import android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.settings.R
-import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-import kotlinx.coroutines.launch
-
-/**
- * Fragment explaining the side fingerprint sensor location for fingerprint enrollment.
- * It interacts with ProgressViewModel, and FingerprintFindSensorAnimation.
- * <pre>
- * | Has | UDFPS | SFPS | Other (Rear FPS) |
- * |---------------------|-------|------|------------------|
- * | Primary button | Yes | No | No |
- * | Illustration Lottie | Yes | Yes | No |
- * | Animation | No | No | Depend on layout |
- * | Progress ViewModel | No | Yes | Yes |
- * | Orientation detect | No | Yes | No |
- * | Foldable detect | No | Yes | No |
- * </pre>
- */
-class FingerprintEnrollFindRfpsFragment : Fragment() {
-
- private var _viewModel: FingerprintEnrollFindSensorViewModel? = null
- private val viewModel: FingerprintEnrollFindSensorViewModel
- get() = _viewModel!!
-
- private var _progressViewModel: FingerprintEnrollProgressViewModel? = null
- private val progressViewModel: FingerprintEnrollProgressViewModel
- get() = _progressViewModel!!
-
- private var _rotationViewModel: DeviceRotationViewModel? = null
- private val rotationViewModel: DeviceRotationViewModel
- get() = _rotationViewModel!!
-
- private var _errorDialogViewModel: FingerprintEnrollErrorDialogViewModel? = null
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel
- get() = _errorDialogViewModel!!
-
- private var findRfpsView: GlifLayout? = null
-
- private val onSkipClickListener =
- View.OnClickListener { _: View? -> viewModel.onSkipButtonClick() }
-
- private var animation: FingerprintFindSensorAnimation? = null
-
- private var enrollingCancelSignal: Any? = null
-
- @Surface.Rotation
- private var lastRotation = -1
-
- private val progressObserver = Observer { progress: EnrollmentProgress? ->
- if (progress != null && !progress.isInitialStep) {
- cancelEnrollment(true)
- }
- }
-
- private val errorMessageObserver = Observer { errorMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "errorMessageObserver($errorMessage)")
- errorMessage?.let { onEnrollmentError(it) }
- }
-
- private val canceledSignalObserver = Observer { canceledSignal: Any? ->
- canceledSignal?.let { onEnrollmentCanceled(it) }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- findRfpsView = inflater.inflate(
- R.layout.fingerprint_enroll_find_sensor,
- container,
- false
- ) as GlifLayout
-
- val animationView = findRfpsView!!.findViewById<View>(
- R.id.fingerprint_sensor_location_animation
- )
- if (animationView is FingerprintFindSensorAnimation) {
- animation = animationView
- }
-
- return findRfpsView!!
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- requireActivity().bindFingerprintEnrollFindRfpsView(
- view = findRfpsView!!,
- onSkipClickListener = onSkipClickListener
- )
-
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.triggerRetryFlow.collect { retryLookingForFingerprint() }
- }
- }
- }
-
- private fun retryLookingForFingerprint() {
- startEnrollment()
- animation?.let {
- Log.d(TAG, "retry, start animation")
- it.startAnimation()
- }
- }
-
- override fun onStart() {
- super.onStart()
- val isErrorDialogShown = errorDialogViewModel.isDialogShown
- Log.d(TAG, "onStart(), isEnrolling:${progressViewModel.isEnrolling}"
- + ", isErrorDialog:$isErrorDialogShown")
- if (!isErrorDialogShown) {
- startEnrollment()
- }
- }
-
- override fun onResume() {
- val rotationLiveData: LiveData<Int> = rotationViewModel.liveData
- lastRotation = rotationLiveData.value!!
- if (!errorDialogViewModel.isDialogShown) {
- animation?.let {
- Log.d(TAG, "onResume(), start animation")
- it.startAnimation()
- }
- }
- super.onResume()
- }
-
- override fun onPause() {
- animation?.let {
- if (DEBUG) {
- Log.d(TAG, "onPause(), pause animation")
- }
- it.pauseAnimation()
- }
- super.onPause()
- }
-
- override fun onStop() {
- super.onStop()
- removeEnrollmentObservers()
- val isEnrolling = progressViewModel.isEnrolling
- val isConfigChange = requireActivity().isChangingConfigurations
- Log.d(TAG, "onStop(), enrolling:$isEnrolling isConfigChange:$isConfigChange")
- if (isEnrolling && !isConfigChange) {
- cancelEnrollment(false)
- }
- }
-
- private fun removeEnrollmentObservers() {
- progressViewModel.progressLiveData.removeObserver(progressObserver)
- progressViewModel.helpMessageLiveData.removeObserver(errorMessageObserver)
- }
-
- private fun startEnrollment() {
- enrollingCancelSignal = progressViewModel.startEnrollment(ENROLL_FIND_SENSOR)
- if (enrollingCancelSignal == null) {
- Log.e(TAG, "startEnrollment(), failed to start enrollment")
- } else {
- Log.d(TAG, "startEnrollment(), success")
- }
- progressViewModel.progressLiveData.observe(this, progressObserver)
- progressViewModel.errorMessageLiveData.observe(this, errorMessageObserver)
- }
-
- private fun cancelEnrollment(waitForLastCancelErrMsg: Boolean) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "cancelEnrollment(), failed because isEnrolling is false")
- return
- }
- removeEnrollmentObservers()
- if (waitForLastCancelErrMsg) {
- progressViewModel.canceledSignalLiveData.observe(this, canceledSignalObserver)
- } else {
- enrollingCancelSignal = null
- }
- val cancelResult: Boolean = progressViewModel.cancelEnrollment()
- if (!cancelResult) {
- Log.e(TAG, "cancelEnrollment(), failed to cancel enrollment")
- }
- }
-
- private fun onEnrollmentError(errorMessage: EnrollmentStatusMessage) {
- cancelEnrollment(false)
- lifecycleScope.launch {
- Log.d(TAG, "newDialogFlow as $errorMessage")
- errorDialogViewModel.newDialog(errorMessage.msgId)
- }
- }
-
- private fun onEnrollmentCanceled(canceledSignal: Any) {
- Log.d(
- TAG,
- "onEnrollmentCanceled enrolling:$enrollingCancelSignal, canceled:$canceledSignal"
- )
- if (enrollingCancelSignal === canceledSignal) {
- val progress: EnrollmentProgress? = progressViewModel.progressLiveData.value
- progressViewModel.canceledSignalLiveData.removeObserver(canceledSignalObserver)
- progressViewModel.clearProgressLiveData()
- if (progress != null && !progress.isInitialStep) {
- viewModel.onStartButtonClick()
- }
- }
- }
-
- override fun onDestroy() {
- animation?.let {
- if (DEBUG) {
- Log.d(TAG, "onDestroy(), stop animation")
- }
- it.stopAnimation()
- }
- super.onDestroy()
- }
-
- override fun onAttach(context: Context) {
- ViewModelProvider(requireActivity()).let { provider ->
- _viewModel = provider[FingerprintEnrollFindSensorViewModel::class.java]
- _progressViewModel = provider[FingerprintEnrollProgressViewModel::class.java]
- _rotationViewModel = provider[DeviceRotationViewModel::class.java]
- _errorDialogViewModel = provider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
- super.onAttach(context)
- }
-
- companion object {
- private const val DEBUG = false
- private const val TAG = "FingerprintEnrollFindRfpsFragment"
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollFindRfpsView(
- view: GlifLayout,
- onSkipClickListener: View.OnClickListener,
-) {
- GlifLayoutHelper(this, view).let {
- it.setHeaderText(
- R.string.security_settings_fingerprint_enroll_find_sensor_title
- )
- it.setDescriptionText(
- getText(R.string.security_settings_fingerprint_enroll_find_sensor_message)
- )
- }
-
- view.getMixin(FooterBarMixin::class.java).secondaryButton =
- FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
- .also {
- it.setOnClickListener(onSkipClickListener)
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.kt
deleted file mode 100644
index 7455be1..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindSfpsFragment.kt
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.view
-
-import android.content.Context
-import android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.ViewGroup
-import androidx.annotation.RawRes
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import com.airbnb.lottie.LottieAnimationView
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage
-import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.android.settingslib.widget.LottieColorUtils
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-import kotlinx.coroutines.launch
-
-/**
- * Fragment explaining the side fingerprint sensor location for fingerprint enrollment.
- * It interacts with ProgressViewModel, FoldCallback (for different lottie), and
- * LottieAnimationView.
- * <pre>
- * | Has | UDFPS | SFPS | Other (Rear FPS) |
- * |---------------------|-------|------|------------------|
- * | Primary button | Yes | No | No |
- * | Illustration Lottie | Yes | Yes | No |
- * | Animation | No | No | Depend on layout |
- * | Progress ViewModel | No | Yes | Yes |
- * | Orientation detect | No | Yes | No |
- * | Foldable detect | No | Yes | No |
- * </pre>
- */
-class FingerprintEnrollFindSfpsFragment : Fragment() {
-
- private var _viewModel: FingerprintEnrollFindSensorViewModel? = null
- private val viewModel: FingerprintEnrollFindSensorViewModel
- get() = _viewModel!!
-
- private var _progressViewModel: FingerprintEnrollProgressViewModel? = null
- private val progressViewModel: FingerprintEnrollProgressViewModel
- get() = _progressViewModel!!
-
- private var _rotationViewModel: DeviceRotationViewModel? = null
- private val rotationViewModel: DeviceRotationViewModel
- get() = _rotationViewModel!!
-
- private var _foldedViewModel: DeviceFoldedViewModel? = null
- private val foldedViewModel: DeviceFoldedViewModel
- get() = _foldedViewModel!!
-
- private var _errorDialogViewModel: FingerprintEnrollErrorDialogViewModel? = null
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel
- get() = _errorDialogViewModel!!
-
- private var findSfpsView: GlifLayout? = null
-
- private val onSkipClickListener =
- View.OnClickListener { _: View? -> viewModel.onSkipButtonClick() }
-
- private val illustrationLottie: LottieAnimationView
- get() = findSfpsView!!.findViewById(R.id.illustration_lottie)!!
-
- private var enrollingCancelSignal: Any? = null
-
- @Surface.Rotation
- private var animationRotation = -1
-
- private val rotationObserver = Observer { rotation: Int? ->
- rotation?.let { onRotationChanged(it) }
- }
-
- private val progressObserver = Observer { progress: EnrollmentProgress? ->
- if (progress != null && !progress.isInitialStep) {
- cancelEnrollment(true)
- }
- }
-
- private val errorMessageObserver = Observer{ errorMessage: EnrollmentStatusMessage? ->
- Log.d(TAG, "errorMessageObserver($errorMessage)")
- errorMessage?.let { onEnrollmentError(it) }
- }
-
- private val canceledSignalObserver = Observer { canceledSignal: Any? ->
- canceledSignal?.let { onEnrollmentCanceled(it) }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View = (inflater.inflate(
- R.layout.sfps_enroll_find_sensor_layout,
- container,
- false
- ) as GlifLayout).also {
- findSfpsView = it
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- requireActivity().bindFingerprintEnrollFindSfpsView(
- view = findSfpsView!!,
- onSkipClickListener = onSkipClickListener
- )
-
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.triggerRetryFlow.collect { startEnrollment() }
- }
- }
- }
-
- override fun onStart() {
- super.onStart()
- val isErrorDialogShown = errorDialogViewModel.isDialogShown
- Log.d(TAG, "onStart(), isEnrolling:${progressViewModel.isEnrolling}"
- + ", isErrorDialog:$isErrorDialogShown")
- if (!isErrorDialogShown) {
- startEnrollment()
- }
- }
-
- override fun onResume() {
- super.onResume()
- val rotationLiveData: LiveData<Int> = rotationViewModel.liveData
- playLottieAnimation(rotationLiveData.value!!)
- rotationLiveData.observe(this, rotationObserver)
- }
-
- override fun onPause() {
- rotationViewModel.liveData.removeObserver(rotationObserver)
- super.onPause()
- }
-
- override fun onStop() {
- super.onStop()
- val isEnrolling = progressViewModel.isEnrolling
- val isConfigChange = requireActivity().isChangingConfigurations
- Log.d(TAG, "onStop(), enrolling:$isEnrolling isConfigChange:$isConfigChange")
- if (isEnrolling && !isConfigChange) {
- cancelEnrollment(false)
- }
- }
-
- private fun removeEnrollmentObservers() {
- progressViewModel.errorMessageLiveData.removeObserver(errorMessageObserver)
- progressViewModel.progressLiveData.removeObserver(progressObserver)
- }
-
- private fun startEnrollment() {
- enrollingCancelSignal = progressViewModel.startEnrollment(ENROLL_FIND_SENSOR)
- if (enrollingCancelSignal == null) {
- Log.e(TAG, "startEnrollment(), failed to start enrollment")
- } else {
- Log.d(TAG, "startEnrollment(), success")
- }
- progressViewModel.progressLiveData.observe(this, progressObserver)
- progressViewModel.errorMessageLiveData.observe(this, errorMessageObserver)
- }
-
- private fun cancelEnrollment(waitForLastCancelErrMsg: Boolean) {
- if (!progressViewModel.isEnrolling) {
- Log.d(TAG, "cancelEnrollment(), failed because isEnrolling is false")
- return
- }
- removeEnrollmentObservers()
- if (waitForLastCancelErrMsg) {
- progressViewModel.canceledSignalLiveData.observe(this, canceledSignalObserver)
- } else {
- enrollingCancelSignal = null
- }
- val cancelResult: Boolean = progressViewModel.cancelEnrollment()
- if (!cancelResult) {
- Log.e(TAG, "cancelEnrollment(), failed to cancel enrollment")
- }
- }
-
- private fun onRotationChanged(@Surface.Rotation newRotation: Int) {
- if (DEBUG) {
- Log.d(TAG, "onRotationChanged() from $animationRotation to $newRotation")
- }
- if ((newRotation + 2) % 4 == animationRotation) {
- // Fragment not changed, we just need to play correct rotation animation
- playLottieAnimation(newRotation)
- }
- }
-
- private fun onEnrollmentError(errorMessage: EnrollmentStatusMessage) {
- progressViewModel.cancelEnrollment()
- lifecycleScope.launch {
- Log.d(TAG, "newDialogFlow as $errorMessage")
- errorDialogViewModel.newDialog(errorMessage.msgId)
- }
- }
-
- private fun onEnrollmentCanceled(canceledSignal: Any) {
- Log.d(
- TAG,
- "onEnrollmentCanceled enrolling:$enrollingCancelSignal, canceled:$canceledSignal"
- )
- if (enrollingCancelSignal === canceledSignal) {
- val progress: EnrollmentProgress? = progressViewModel.progressLiveData.value
- progressViewModel.canceledSignalLiveData.removeObserver(canceledSignalObserver)
- progressViewModel.clearProgressLiveData()
- if (progress != null && !progress.isInitialStep) {
- viewModel.onStartButtonClick()
- }
- }
- }
-
- private fun playLottieAnimation(@Surface.Rotation rotation: Int) {
- @RawRes val animationRawRes = getSfpsLottieAnimationRawRes(rotation)
- Log.d(
- TAG,
- "play lottie animation $animationRawRes, previous rotation:$animationRotation"
- + ", new rotation:" + rotation
- )
- animationRotation = rotation
- illustrationLottie.setAnimation(animationRawRes)
- LottieColorUtils.applyDynamicColors(activity, illustrationLottie)
- illustrationLottie.visibility = View.VISIBLE
- illustrationLottie.playAnimation()
- }
-
- @RawRes
- private fun getSfpsLottieAnimationRawRes(@Surface.Rotation rotation: Int): Int {
- val isFolded = java.lang.Boolean.FALSE != foldedViewModel.liveData.value
- return when (rotation) {
- Surface.ROTATION_90 ->
- if (isFolded)
- R.raw.fingerprint_edu_lottie_folded_top_left
- else
- R.raw.fingerprint_edu_lottie_portrait_top_left
- Surface.ROTATION_180 ->
- if (isFolded)
- R.raw.fingerprint_edu_lottie_folded_bottom_left
- else
- R.raw.fingerprint_edu_lottie_landscape_bottom_left
- Surface.ROTATION_270 ->
- if (isFolded)
- R.raw.fingerprint_edu_lottie_folded_bottom_right
- else
- R.raw.fingerprint_edu_lottie_portrait_bottom_right
- else ->
- if (isFolded)
- R.raw.fingerprint_edu_lottie_folded_top_right
- else
- R.raw.fingerprint_edu_lottie_landscape_top_right
- }
- }
-
- override fun onAttach(context: Context) {
- ViewModelProvider(requireActivity()).let { provider ->
- _viewModel = provider[FingerprintEnrollFindSensorViewModel::class.java]
- _progressViewModel = provider[FingerprintEnrollProgressViewModel::class.java]
- _rotationViewModel = provider[DeviceRotationViewModel::class.java]
- _foldedViewModel = provider[DeviceFoldedViewModel::class.java]
- _errorDialogViewModel = provider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
- super.onAttach(context)
- }
-
- companion object {
- private const val DEBUG = false
- private const val TAG = "FingerprintEnrollFindSfpsFragment"
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollFindSfpsView(
- view: GlifLayout,
- onSkipClickListener: View.OnClickListener
-) {
- view.getMixin(FooterBarMixin::class.java).let {
- it.secondaryButton = FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
- it.secondaryButton.setOnClickListener(onSkipClickListener)
- }
-
- GlifLayoutHelper(this, view).let {
- it.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title)
- it.setDescriptionText(
- getText(R.string.security_settings_sfps_enroll_find_sensor_message)
- )
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindUdfpsFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindUdfpsFragment.kt
deleted file mode 100644
index 3dce99c..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFindUdfpsFragment.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.content.Context
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.ViewModelProvider
-import com.airbnb.lottie.LottieAnimationView
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-
-/**
- * Fragment explaining the under-display fingerprint sensor location for fingerprint enrollment.
- * It interacts with Primary button, and LottieAnimationView.
- * <pre>
- * | Has | UDFPS | SFPS | Other (Rear FPS) |
- * |---------------------|-------|------|------------------|
- * | Primary button | Yes | No | No |
- * | Illustration Lottie | Yes | Yes | No |
- * | Animation | No | No | Depend on layout |
- * | Progress ViewModel | No | Yes | Yes |
- * | Orientation detect | No | Yes | No |
- * | Foldable detect | No | Yes | No |
- * </pre>
- */
-class FingerprintEnrollFindUdfpsFragment : Fragment() {
-
- private var _viewModel: FingerprintEnrollFindSensorViewModel? = null
- private val mViewModel: FingerprintEnrollFindSensorViewModel
- get() = _viewModel!!
-
- private var findUdfpsView: GlifLayout? = null
-
- private val mOnSkipClickListener =
- View.OnClickListener { _: View? -> mViewModel.onSkipButtonClick() }
-
- private val mOnStartClickListener =
- View.OnClickListener { _: View? -> mViewModel.onStartButtonClick() }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View = (inflater.inflate(
- R.layout.udfps_enroll_find_sensor_layout,
- container,
- false
- ) as GlifLayout).also {
- findUdfpsView = it
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- requireActivity().bindFingerprintEnrollFindUdfpsView(
- view = findUdfpsView!!,
- isAccessibilityEnabled = mViewModel.isAccessibilityEnabled,
- onSkipClickListener = mOnSkipClickListener,
- onStartClickListener = mOnStartClickListener
- )
- }
-
- override fun onAttach(context: Context) {
- _viewModel = ViewModelProvider(requireActivity())[
- FingerprintEnrollFindSensorViewModel::class.java
- ]
- super.onAttach(context)
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollFindUdfpsView(
- view: GlifLayout,
- isAccessibilityEnabled: Boolean,
- onSkipClickListener: View.OnClickListener,
- onStartClickListener: View.OnClickListener,
-) {
- GlifLayoutHelper(this, view).let { helper ->
- helper.setHeaderText(R.string.security_settings_udfps_enroll_find_sensor_title)
- helper.setDescriptionText(
- getText(R.string.security_settings_udfps_enroll_find_sensor_message)
- )
- }
-
- view.getMixin(FooterBarMixin::class.java)!!.let {
- it.secondaryButton = FooterButton.Builder(this)
- .setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
- it.secondaryButton.setOnClickListener(onSkipClickListener)
-
- it.primaryButton = FooterButton.Builder(this)
- .setText(R.string.security_settings_udfps_enroll_find_sensor_start_button)
- .setButtonType(FooterButton.ButtonType.NEXT)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
- .build()
- it.primaryButton.setOnClickListener(onStartClickListener)
- }
-
- view.findViewById<LottieAnimationView>(R.id.illustration_lottie)!!.let {
- it.setOnClickListener(onStartClickListener)
- if (isAccessibilityEnabled) {
- it.setAnimation(R.raw.udfps_edu_a11y_lottie)
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.kt
deleted file mode 100644
index 2af2dee..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollFinishFragment.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.content.Context
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.ViewModelProvider
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-
-/**
- * Fragment which concludes fingerprint enrollment.
- */
-class FingerprintEnrollFinishFragment : Fragment() {
-
- private var _viewModel: FingerprintEnrollFinishViewModel? = null
- private val viewModel: FingerprintEnrollFinishViewModel
- get() = _viewModel!!
-
- private val addButtonClickListener =
- View.OnClickListener { _: View? -> viewModel.onAddButtonClick() }
-
- private val nextButtonClickListener =
- View.OnClickListener { _: View? -> viewModel.onNextButtonClick() }
- override fun onAttach(context: Context) {
- super.onAttach(context)
- _viewModel = ViewModelProvider(requireActivity())[
- FingerprintEnrollFinishViewModel::class.java
- ]
- }
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ) : View = (inflater.inflate(
- if (viewModel.canAssumeSfps())
- R.layout.sfps_enroll_finish
- else
- R.layout.fingerprint_enroll_finish,
- container,
- false
- ) as GlifLayout).also {
- requireActivity().bindFingerprintEnrollFinishFragment(
- view = it,
- isSuw = viewModel.request.isSuw,
- canAssumeSfps = viewModel.canAssumeSfps(),
- isAnotherFingerprintEnrollable = viewModel.isAnotherFingerprintEnrollable,
- nextButtonClickListener = nextButtonClickListener,
- addButtonClickListener = addButtonClickListener
- )
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollFinishFragment(
- view: GlifLayout,
- isSuw: Boolean,
- canAssumeSfps: Boolean,
- isAnotherFingerprintEnrollable: Boolean,
- nextButtonClickListener: View.OnClickListener,
- addButtonClickListener: View.OnClickListener
-) {
- GlifLayoutHelper(this, view).apply {
- setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title)
- setDescriptionText(
- getString(
- if (canAssumeSfps && isAnotherFingerprintEnrollable)
- R.string.security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message
- else
- R.string.security_settings_fingerprint_enroll_finish_v2_message
- )
- )
- }
-
- view.getMixin(FooterBarMixin::class.java).also { footer ->
- footer.primaryButton = FooterButton.Builder(this)
- .setText(
- if (isSuw)
- R.string.next_label
- else
- R.string.security_settings_fingerprint_enroll_done
- )
- .setListener(nextButtonClickListener)
- .setButtonType(FooterButton.ButtonType.NEXT)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
- .build()
- if (isAnotherFingerprintEnrollable) {
- footer.secondaryButton = FooterButton.Builder(this)
- .setText(R.string.fingerprint_enroll_button_add)
- .setListener(addButtonClickListener)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
- .build()
- }
- }
-
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.kt
deleted file mode 100644
index d1b3799..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.kt
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.app.admin.DevicePolicyManager
-import android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED
-import android.content.Context
-import android.graphics.PorterDuff
-import android.graphics.PorterDuffColorFilter
-import android.os.Bundle
-import android.text.Html
-import android.text.method.LinkMovementMethod
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.ScrollView
-import android.widget.TextView
-import androidx.annotation.StringRes
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_UNKNOWN
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel
-import com.google.android.setupcompat.template.FooterBarMixin
-import com.google.android.setupcompat.template.FooterButton
-import com.google.android.setupdesign.GlifLayout
-import com.google.android.setupdesign.template.RequireScrollMixin
-import com.google.android.setupdesign.util.DeviceHelper
-import com.google.android.setupdesign.util.DynamicColorPalette
-import com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT
-import java.util.function.Supplier
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.launch
-
-/**
- * Fingerprint intro onboarding page fragment implementation
- */
-class FingerprintEnrollIntroFragment : Fragment() {
-
- private val viewModelProvider: ViewModelProvider
- get() = ViewModelProvider(requireActivity())
-
- private var _viewModel: FingerprintEnrollIntroViewModel? = null
- private val viewModel: FingerprintEnrollIntroViewModel
- get() = _viewModel!!
-
- private var introView: GlifLayout? = null
-
- private var primaryFooterButton: FooterButton? = null
-
- private var secondaryFooterButton: FooterButton? = null
-
- private val onNextClickListener =
- View.OnClickListener { _: View? ->
- activity?.lifecycleScope?.let {
- viewModel.onNextButtonClick(it)
- }
- }
-
- private val onSkipOrCancelClickListener =
- View.OnClickListener { _: View? ->
- activity?.lifecycleScope?.let {
- viewModel.onSkipOrCancelButtonClick(it)
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View {
- introView = inflater.inflate(
- R.layout.fingerprint_enroll_introduction,
- container,
- false
- ) as GlifLayout
- return introView!!
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- requireActivity().bindFingerprintEnrollIntroView(
- view = introView!!,
- canAssumeUdfps = viewModel.canAssumeUdfps,
- isBiometricUnlockDisabledByAdmin = viewModel.isBiometricUnlockDisabledByAdmin,
- isParentalConsentRequired = viewModel.isParentalConsentRequired,
- descriptionDisabledByAdminSupplier = { getDescriptionDisabledByAdmin(view.context) }
- )
- }
-
- override fun onStart() {
- val context: Context = requireContext()
- val footerBarMixin: FooterBarMixin = footerBarMixin
- viewModel.updateEnrollableStatus(lifecycleScope)
- initPrimaryFooterButton(context, footerBarMixin)
- initSecondaryFooterButton(context, footerBarMixin)
- collectPageStatusFlowIfNeed()
- super.onStart()
- }
-
- private fun initPrimaryFooterButton(
- context: Context,
- footerBarMixin: FooterBarMixin
- ) {
- if (footerBarMixin.primaryButton != null) {
- return
- }
- primaryFooterButton = FooterButton.Builder(context)
- .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
- .setButtonType(FooterButton.ButtonType.OPT_IN)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
- .build()
- .also {
- it.setOnClickListener(onNextClickListener)
- footerBarMixin.primaryButton = it
- }
- }
-
- private fun initSecondaryFooterButton(
- context: Context,
- footerBarMixin: FooterBarMixin
- ) {
- if (footerBarMixin.secondaryButton != null) {
- return
- }
- secondaryFooterButton = FooterButton.Builder(context)
- .setText(
- if (viewModel.request.isAfterSuwOrSuwSuggestedAction)
- R.string.security_settings_fingerprint_enroll_introduction_cancel
- else
- R.string.security_settings_fingerprint_enroll_introduction_no_thanks
- )
- .setButtonType(FooterButton.ButtonType.NEXT)
- .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
- .build()
- .also {
- it.setOnClickListener(onSkipOrCancelClickListener)
- footerBarMixin.setSecondaryButton(it, true /* usePrimaryStyle */)
- }
- }
-
- private fun collectPageStatusFlowIfNeed() {
- lifecycleScope.launch {
- val status = viewModel.pageStatusFlow.first()
- Log.d(TAG, "collectPageStatusFlowIfNeed status:$status")
- if (status.hasScrollToBottom()
- || status.enrollableStatus === FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
- ) {
- // Update once and do not requireScrollWithButton() again when page has
- // scrolled to bottom or User has enrolled at least a fingerprint, because if
- // we requireScrollWithButton() again, primary button will become "More" after
- // scrolling.
- updateFooterButtons(status)
- } else {
- introView!!.getMixin(RequireScrollMixin::class.java).let {
- it.requireScrollWithButton(
- requireActivity(),
- primaryFooterButton!!,
- moreButtonTextRes,
- onNextClickListener
- )
- it.setOnRequireScrollStateChangedListener { scrollNeeded: Boolean ->
- viewModel.setHasScrolledToBottom(!scrollNeeded, lifecycleScope)
- }
- }
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- viewModel.pageStatusFlow.collect(
- this@FingerprintEnrollIntroFragment::updateFooterButtons
- )
- }
- }
- }
- }
-
- override fun onAttach(context: Context) {
- _viewModel = viewModelProvider[FingerprintEnrollIntroViewModel::class.java]
- super.onAttach(context)
- }
-
- private val footerBarMixin: FooterBarMixin
- get() = introView!!.getMixin(FooterBarMixin::class.java)
-
- private fun getDescriptionDisabledByAdmin(context: Context): String? {
- val defaultStrId: Int =
- R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled
- val devicePolicyManager: DevicePolicyManager =
- checkNotNull(requireActivity().getSystemService(DevicePolicyManager::class.java))
-
- return devicePolicyManager.resources.getString(FINGERPRINT_UNLOCK_DISABLED) {
- context.getString(defaultStrId)
- }
- }
-
- private fun updateFooterButtons(status: FingerprintEnrollIntroStatus) {
- if (DEBUG) {
- Log.d(TAG, "updateFooterButtons($status)")
- }
- primaryFooterButton!!.setText(
- context,
- if (status.enrollableStatus === FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
- R.string.done
- else if (status.hasScrollToBottom())
- R.string.security_settings_fingerprint_enroll_introduction_agree
- else
- moreButtonTextRes
- )
- secondaryFooterButton!!.visibility =
- if (status.hasScrollToBottom()
- && status.enrollableStatus !== FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
- )
- View.VISIBLE
- else
- View.INVISIBLE
-
- view!!.requireViewById<TextView>(R.id.error_text).let {
- when (status.enrollableStatus) {
- FINGERPRINT_ENROLLABLE_OK -> {
- it.text = null
- it.visibility = View.GONE
- }
-
- FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX -> {
- it.setText(R.string.fingerprint_intro_error_max)
- it.visibility = View.VISIBLE
- }
-
- FINGERPRINT_ENROLLABLE_UNKNOWN -> {}
- }
- }
- }
-
- @get:StringRes
- private val moreButtonTextRes: Int
- get() = R.string.security_settings_face_enroll_introduction_more
-
- companion object {
- private const val TAG = "FingerprintEnrollIntroFragment"
- private const val DEBUG = false
- }
-}
-
-fun FragmentActivity.bindFingerprintEnrollIntroView(
- view: GlifLayout,
- canAssumeUdfps: Boolean,
- isBiometricUnlockDisabledByAdmin: Boolean,
- isParentalConsentRequired: Boolean,
- descriptionDisabledByAdminSupplier: Supplier<String?>
-) {
- val context = view.context
-
- val iconFingerprint = view.findViewById<ImageView>(R.id.icon_fingerprint)!!
- val iconDeviceLocked = view.findViewById<ImageView>(R.id.icon_device_locked)!!
- val iconTrashCan = view.findViewById<ImageView>(R.id.icon_trash_can)!!
- val iconInfo = view.findViewById<ImageView>(R.id.icon_info)!!
- val iconShield = view.findViewById<ImageView>(R.id.icon_shield)!!
- val iconLink = view.findViewById<ImageView>(R.id.icon_link)!!
- val footerMessage6 = view.findViewById<TextView>(R.id.footer_message_6)!!
-
- PorterDuffColorFilter(
- DynamicColorPalette.getColor(context, ACCENT),
- PorterDuff.Mode.SRC_IN
- ).let { colorFilter ->
- iconFingerprint.drawable.colorFilter = colorFilter
- iconDeviceLocked.drawable.colorFilter = colorFilter
- iconTrashCan.drawable.colorFilter = colorFilter
- iconInfo.drawable.colorFilter = colorFilter
- iconShield.drawable.colorFilter = colorFilter
- iconLink.drawable.colorFilter = colorFilter
- }
-
- view.findViewById<TextView>(R.id.footer_learn_more)!!.let { learnMore ->
- learnMore.movementMethod = LinkMovementMethod.getInstance()
- val footerLinkStr: String = context.getString(
- R.string.security_settings_fingerprint_v2_enroll_introduction_message_learn_more,
- Html.FROM_HTML_MODE_LEGACY
- )
- learnMore.text = Html.fromHtml(footerLinkStr)
- }
-
- if (canAssumeUdfps) {
- footerMessage6.visibility = View.VISIBLE
- iconShield.visibility = View.VISIBLE
- } else {
- footerMessage6.visibility = View.GONE
- iconShield.visibility = View.GONE
- }
- val glifLayoutHelper = GlifLayoutHelper(this, view)
- if (isBiometricUnlockDisabledByAdmin && !isParentalConsentRequired) {
- glifLayoutHelper.setHeaderText(
- R.string.security_settings_fingerprint_enroll_introduction_title_unlock_disabled
- )
- glifLayoutHelper.setDescriptionText(descriptionDisabledByAdminSupplier.get())
- } else {
- glifLayoutHelper.setHeaderText(
- R.string.security_settings_fingerprint_enroll_introduction_title
- )
- glifLayoutHelper.setDescriptionText(
- getString(
- R.string.security_settings_fingerprint_enroll_introduction_v3_message,
- DeviceHelper.getDeviceName(context)
- )
- )
- }
-
- view.findViewById<ScrollView>(com.google.android.setupdesign.R.id.sud_scroll_view)
- ?.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.kt b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.kt
deleted file mode 100644
index ec96597..0000000
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.kt
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * 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.biometrics2.ui.view
-
-import android.annotation.StyleRes
-import android.content.Intent
-import android.content.res.ColorStateList
-import android.content.res.Configuration
-import android.content.res.Resources.Theme
-import android.graphics.Color
-import android.os.Bundle
-import android.os.SystemClock
-import android.util.Log
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.ActivityResultCallback
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
-import androidx.annotation.ColorInt
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
-import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import androidx.lifecycle.viewmodel.CreationExtras
-import androidx.lifecycle.viewmodel.MutableCreationExtras
-import com.android.settings.R
-import com.android.settings.Utils
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics2.factory.BiometricsViewModelFactory
-import com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR_KEY
-import com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CREDENTIAL_MODEL_KEY
-import com.android.settings.biometrics2.factory.BiometricsViewModelFactory.ENROLLMENT_REQUEST_KEY
-import com.android.settings.biometrics2.ui.model.CredentialModel
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest
-import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel
-import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator
-import com.android.settings.biometrics2.ui.viewmodel.CredentialAction
-import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FingerprintEnrollEnrollingAction
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollErrorDialogViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FingerprintEnrollFindSensorAction
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FingerprintEnrollFinishAction
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
-import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
-import com.google.android.setupdesign.util.ThemeHelper
-import kotlinx.coroutines.launch
-
-/**
- * Fingerprint enrollment activity implementation
- */
-open class FingerprintEnrollmentActivity : FragmentActivity() {
- /** SetupWizard activity*/
- class SetupActivity : FingerprintEnrollmentActivity()
-
- /** Internal activity for FingerprintSettings */
- class InternalActivity : FingerprintEnrollmentActivity()
-
- private val viewModelProvider: ViewModelProvider by lazy {
- ViewModelProvider(this)
- }
-
- private val viewModel: FingerprintEnrollmentViewModel by lazy {
- viewModelProvider[FingerprintEnrollmentViewModel::class.java]
- }
-
- private val autoCredentialViewModel: AutoCredentialViewModel by lazy {
- viewModelProvider[AutoCredentialViewModel::class.java]
- }
-
- private val introViewModel: FingerprintEnrollIntroViewModel by lazy {
- viewModelProvider[FingerprintEnrollIntroViewModel::class.java]
- }
-
- private val findSensorViewModel: FingerprintEnrollFindSensorViewModel by lazy {
- viewModelProvider[FingerprintEnrollFindSensorViewModel::class.java]
- }
-
- private val progressViewModel: FingerprintEnrollProgressViewModel by lazy {
- viewModelProvider[FingerprintEnrollProgressViewModel::class.java]
- }
-
- private val enrollingViewModel: FingerprintEnrollEnrollingViewModel by lazy {
- viewModelProvider[FingerprintEnrollEnrollingViewModel::class.java]
- }
-
- private val finishViewModel: FingerprintEnrollFinishViewModel by lazy {
- viewModelProvider[FingerprintEnrollFinishViewModel::class.java]
- }
-
- private val errorDialogViewModel: FingerprintEnrollErrorDialogViewModel by lazy {
- viewModelProvider[FingerprintEnrollErrorDialogViewModel::class.java]
- }
-
- private var isFirstFragmentAdded = false
-
- private val findSensorActionObserver = Observer<Int?> { action ->
- if (DEBUG) {
- Log.d(TAG, "findSensorActionObserver($action)")
- }
- action?.let { onFindSensorAction(it) }
- }
-
- private val enrollingActionObserver = Observer<Int?> { action ->
- if (DEBUG) {
- Log.d(TAG, "enrollingActionObserver($action)")
- }
- action?.let { onEnrollingAction(it) }
- }
-
- private val finishActionObserver = Observer<Int?> { action ->
- if (DEBUG) {
- Log.d(TAG, "finishActionObserver($action)")
- }
- action?.let { onFinishAction(it) }
- }
-
- private val chooseLockResultCallback: ActivityResultCallback<ActivityResult> =
- ActivityResultCallback { result ->
- onChooseOrConfirmLockResult(true /* isChooseLock */, result)
- }
-
- private val chooseLockLauncher: ActivityResultLauncher<Intent> =
- registerForActivityResult(StartActivityForResult(), chooseLockResultCallback)
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- // Theme
- setTheme(viewModel.request.theme)
- ThemeHelper.trySetDynamicColor(this)
- window.statusBarColor = Color.TRANSPARENT
-
- // fragment
- setContentView(R.layout.biometric_enrollment_container)
- val fragment: Fragment? = supportFragmentManager.findFragmentById(
- R.id.fragment_container_view
- )
- Log.d(
- TAG,
- "onCreate() has savedInstance:$(savedInstanceState != null), fragment:$fragment"
- )
-
- isFirstFragmentAdded = (savedInstanceState != null)
- if (fragment == null) {
- checkCredential()
- if (viewModel.request.isSkipFindSensor) {
- startEnrollingFragment()
- } else if (viewModel.request.isSkipIntro) {
- startFindSensorFragment()
- } else {
- startIntroFragment()
- }
- } else {
- val tag: String? = fragment.tag
- if (INTRO_TAG == tag) {
- attachIntroViewModel()
- } else if (FIND_SENSOR_TAG == tag) {
- attachFindSensorViewModel()
- attachIntroViewModel()
- } else if (ENROLLING_TAG == tag) {
- attachEnrollingViewModel()
- attachFindSensorViewModel()
- attachIntroViewModel()
- } else if (FINISH_TAG == tag) {
- attachFinishViewModel()
- attachFindSensorViewModel()
- attachIntroViewModel()
- } else {
- Log.e(TAG, "fragment tag $tag not found")
- finish()
- return
- }
- }
-
- collectFlows()
- }
-
- private fun collectFlows() {
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- viewModel.setResultFlow.collect {
- Log.d(TAG, "setResultLiveData($it)")
- onSetActivityResult(it)
- }
- }
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- autoCredentialViewModel.generateChallengeFailedFlow.collect {
- Log.d(TAG, "generateChallengeFailedFlow($it)")
- onSetActivityResult(ActivityResult(RESULT_CANCELED, null))
- }
- }
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.newDialogFlow.collect {
- Log.d(TAG, "newErrorDialogFlow($it)")
- FingerprintEnrollErrorDialog.newInstance(it).show(
- supportFragmentManager,
- ERROR_DIALOG_TAG
- )
- }
- }
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- errorDialogViewModel.setResultFlow.collect {
- Log.d(TAG, "errorDialogSetResultFlow($it)")
- when (it) {
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH -> onSetActivityResult(
- ActivityResult(BiometricEnrollBase.RESULT_FINISHED, null)
- )
-
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT -> onSetActivityResult(
- ActivityResult(BiometricEnrollBase.RESULT_TIMEOUT, null)
- )
- }
- }
- }
- }
- }
-
- private fun startFragment(fragmentClass: Class<out Fragment>, tag: String) {
- if (!isFirstFragmentAdded) {
- supportFragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .replace(R.id.fragment_container_view, fragmentClass, null, tag)
- .commit()
- isFirstFragmentAdded = true
- } else {
- supportFragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .setCustomAnimations(
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_exit,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_exit
- )
- .replace(R.id.fragment_container_view, fragmentClass, null, tag)
- .addToBackStack(tag)
- .commit()
- }
- }
-
- private fun startIntroFragment() {
- attachIntroViewModel()
- startFragment(FingerprintEnrollIntroFragment::class.java, INTRO_TAG)
- }
-
- private fun attachIntroViewModel() {
- val request: EnrollmentRequest = viewModel.request
- if (request.isSkipIntro || request.isSkipFindSensor) {
- return
- }
- lifecycleScope.launch {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- introViewModel.actionFlow.collect(this@FingerprintEnrollmentActivity::onIntroAction)
- }
- }
- }
-
- // We need to make sure token is valid before entering find sensor page
- private fun startFindSensorFragment() {
- // Always setToken into progressViewModel even it is not necessary action for UDFPS
- progressViewModel.setToken(autoCredentialViewModel.token)
- attachFindSensorViewModel()
- val fragmentClass: Class<out Fragment> = if (viewModel.canAssumeUdfps) {
- FingerprintEnrollFindUdfpsFragment::class.java
- } else if (viewModel.canAssumeSfps) {
- FingerprintEnrollFindSfpsFragment::class.java
- } else {
- FingerprintEnrollFindRfpsFragment::class.java
- }
- startFragment(fragmentClass, FIND_SENSOR_TAG)
- }
-
- private fun attachFindSensorViewModel() {
- if (viewModel.request.isSkipFindSensor) {
- return
- }
- findSensorViewModel.let {
- // Clear ActionLiveData in FragmentViewModel to prevent getting previous action during
- // recreate, like press 'Start' then press 'back' in FingerprintEnrollEnrolling
- // activity.
- it.clearActionLiveData()
- it.actionLiveData.observe(this, findSensorActionObserver)
- }
- }
-
- private fun startEnrollingFragment() {
- // Always setToken into progressViewModel even it is not necessary action for SFPS or RFPS
- progressViewModel.setToken(autoCredentialViewModel.token)
- attachEnrollingViewModel()
- val fragmentClass: Class<out Fragment> = if (viewModel.canAssumeUdfps) {
- FingerprintEnrollEnrollingUdfpsFragment::class.java
- } else if (viewModel.canAssumeSfps) {
- FingerprintEnrollEnrollingSfpsFragment::class.java
- } else {
- FingerprintEnrollEnrollingRfpsFragment::class.java
- }
- startFragment(fragmentClass, ENROLLING_TAG)
- }
-
- private fun attachEnrollingViewModel() {
- enrollingViewModel.let {
- it.clearActionLiveData()
- it.actionLiveData.observe(this, enrollingActionObserver)
- }
- }
-
- private fun startFinishFragment() {
- viewModel.isNewFingerprintAdded = true
- attachFinishViewModel()
- if (viewModel.request.isSkipFindSensor) {
- // Set page to Finish
- supportFragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .setCustomAnimations(
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_exit,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_exit
- )
- .replace(
- R.id.fragment_container_view,
- FingerprintEnrollFinishFragment::class.java,
- null,
- FINISH_TAG
- )
- .commit()
- } else {
- // Remove Enrolling page
- supportFragmentManager.popBackStack()
-
- // Remove old Finish page if any
- if (supportFragmentManager.findFragmentByTag(FINISH_TAG) != null) {
- supportFragmentManager.popBackStack(FINISH_TAG, POP_BACK_STACK_INCLUSIVE)
- }
-
- // Remove FindSensor page if maxEnrolled
- if (viewModel.isMaxEnrolledReached(autoCredentialViewModel.userId)
- && supportFragmentManager.findFragmentByTag(FIND_SENSOR_TAG) != null
- ) {
- supportFragmentManager.popBackStack(FIND_SENSOR_TAG, POP_BACK_STACK_INCLUSIVE)
- }
-
- // Add Finish page
- supportFragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .setCustomAnimations(
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_open_exit,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_enter_dynamic_color,
- com.google.android.setupdesign.R.anim.shared_x_axis_activity_close_exit
- )
- .replace(
- R.id.fragment_container_view,
- FingerprintEnrollFinishFragment::class.java,
- null,
- FINISH_TAG
- )
- .addToBackStack(FINISH_TAG)
- .commit()
- }
- }
-
- private fun attachFinishViewModel() {
- finishViewModel.let {
- it.clearActionLiveData()
- it.actionLiveData.observe(this, finishActionObserver)
- }
- }
-
- private fun onSetActivityResult(result: ActivityResult) {
- val challengeExtras: Bundle? = autoCredentialViewModel.createGeneratingChallengeExtras()
- val overrideResult: ActivityResult = viewModel.getOverrideActivityResult(
- result, challengeExtras
- )
- if (DEBUG) {
- Log.d(
- TAG, "onSetActivityResult(" + result + "), override:" + overrideResult
- + ") challengeExtras:" + challengeExtras
- )
- }
- setResult(overrideResult.resultCode, overrideResult.data)
- finish()
- }
-
- private fun checkCredential() {
- when (autoCredentialViewModel.checkCredential(lifecycleScope)) {
- CredentialAction.FAIL_NEED_TO_CHOOSE_LOCK -> {
- val intent: Intent = autoCredentialViewModel.createChooseLockIntent(
- this,
- viewModel.request.isSuw,
- viewModel.request.suwExtras
- )
- if (!viewModel.isWaitingActivityResult.compareAndSet(false, true)) {
- Log.w(TAG, "chooseLock, fail to set isWaiting flag to true")
- }
- chooseLockLauncher.launch(intent)
- return
- }
-
- CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK -> {
- val launched: Boolean = autoCredentialViewModel.createConfirmLockLauncher(
- this,
- LAUNCH_CONFIRM_LOCK_ACTIVITY,
- getString(R.string.security_settings_fingerprint_preference_title)
- ).launch()
- if (!launched) {
- // This shouldn't happen, as we should only end up at this step if a lock thingy
- // is already set.
- Log.e(TAG, "confirmLock, launched is true")
- finish()
- } else if (!viewModel.isWaitingActivityResult.compareAndSet(false, true)) {
- Log.w(TAG, "confirmLock, fail to set isWaiting flag to true")
- }
- return
- }
-
- CredentialAction.CREDENTIAL_VALID,
- CredentialAction.IS_GENERATING_CHALLENGE -> {}
- }
- }
-
- private fun onChooseOrConfirmLockResult(
- isChooseLock: Boolean,
- activityResult: ActivityResult
- ) {
- if (!viewModel.isWaitingActivityResult.compareAndSet(true, false)) {
- Log.w(TAG, "isChooseLock:$isChooseLock, fail to unset waiting flag")
- }
- if (!autoCredentialViewModel.generateChallengeAsCredentialActivityResult(
- isChooseLock,
- activityResult,
- lifecycleScope
- )
- ) {
- onSetActivityResult(activityResult)
- }
- }
-
- private fun onIntroAction(action: FingerprintEnrollIntroAction) {
- Log.d(TAG, "onIntroAction($action)")
- when (action) {
- FingerprintEnrollIntroAction.DONE_AND_FINISH -> {
- onSetActivityResult(ActivityResult(BiometricEnrollBase.RESULT_FINISHED, null))
- return
- }
-
- FingerprintEnrollIntroAction.SKIP_OR_CANCEL -> {
- onSetActivityResult(ActivityResult(BiometricEnrollBase.RESULT_SKIP, null))
- return
- }
-
- FingerprintEnrollIntroAction.CONTINUE_ENROLL -> {
- startFindSensorFragment()
- }
- }
- }
-
- private fun onFindSensorAction(@FingerprintEnrollFindSensorAction action: Int) {
- when (action) {
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP -> {
- onSetActivityResult(ActivityResult(BiometricEnrollBase.RESULT_SKIP, null))
- return
- }
-
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG -> {
- SkipSetupFindFpsDialog().show(
- supportFragmentManager,
- SKIP_SETUP_FIND_FPS_DIALOG_TAG
- )
- return
- }
-
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START -> {
- startEnrollingFragment()
- }
- }
- }
-
- private fun onEnrollingAction(@FingerprintEnrollEnrollingAction action: Int) {
- when (action) {
- FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE -> {
- startFinishFragment()
- }
-
- FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP -> {
- onSetActivityResult(ActivityResult(BiometricEnrollBase.RESULT_SKIP, null))
- }
-
- FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG -> {
- FingerprintEnrollEnrollingIconTouchDialog().show(
- supportFragmentManager,
- SKIP_SETUP_FIND_FPS_DIALOG_TAG
- )
- }
-
- FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED -> {
- if (supportFragmentManager.backStackEntryCount > 0) {
- supportFragmentManager.popBackStack()
- } else {
- onSetActivityResult(ActivityResult(RESULT_CANCELED, null))
- }
- }
- }
- }
-
- private fun onFinishAction(@FingerprintEnrollFinishAction action: Int) {
- when (action) {
- FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK -> {
- startEnrollingFragment()
- }
-
- FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK -> {
- val data: Intent? = if (viewModel.request.isSuw) {
- Intent().also {
- it.putExtras(
- viewModel.getSuwFingerprintCountExtra(
- autoCredentialViewModel.userId
- )
- )
- }
- } else {
- null
- }
- onSetActivityResult(ActivityResult(BiometricEnrollBase.RESULT_FINISHED, data))
- }
- }
- }
-
- override fun onPause() {
- super.onPause()
- viewModel.checkFinishActivityDuringOnPause(
- isFinishing,
- isChangingConfigurations,
- lifecycleScope
- )
- }
-
- override fun onDestroy() {
- viewModel.updateFingerprintSuggestionEnableState(autoCredentialViewModel.userId)
- super.onDestroy()
- }
-
- override fun onApplyThemeResource(theme: Theme, @StyleRes resid: Int, first: Boolean) {
- theme.applyStyle(R.style.SetupWizardPartnerResource, true)
- super.onApplyThemeResource(theme, resid, first)
- }
-
- @Deprecated("Deprecated in Java")
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode == LAUNCH_CONFIRM_LOCK_ACTIVITY) {
- onChooseOrConfirmLockResult(false, ActivityResult(resultCode, data))
- return
- }
- super.onActivityResult(requestCode, resultCode, data)
- }
-
- override val defaultViewModelCreationExtras: CreationExtras
- get() = MutableCreationExtras(super.defaultViewModelCreationExtras).also {
- it[CHALLENGE_GENERATOR_KEY] = FingerprintChallengeGenerator(
- featureFactory.biometricsRepositoryProvider.getFingerprintRepository(application)!!
- )
- it[ENROLLMENT_REQUEST_KEY] =
- EnrollmentRequest(intent, applicationContext, this is SetupActivity)
- it[CREDENTIAL_MODEL_KEY] =
- CredentialModel(intent.extras, SystemClock.elapsedRealtimeClock())
- }
-
- override val defaultViewModelProviderFactory: ViewModelProvider.Factory
- get() = BiometricsViewModelFactory()
-
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
- window.statusBarColor = backgroundColor
- }
-
- @get:ColorInt
- private val backgroundColor: Int
- get() {
- val stateList: ColorStateList? =
- Utils.getColorAttr(this, android.R.attr.windowBackground)
- return stateList?.defaultColor ?: Color.TRANSPARENT
- }
-
- override fun onConfigurationChanged(newConfig: Configuration) {
- viewModelProvider[DeviceFoldedViewModel::class.java].onConfigurationChanged(newConfig)
- super.onConfigurationChanged(newConfig)
- }
-
- companion object {
- private const val DEBUG = false
- private const val TAG = "FingerprintEnrollmentActivity"
- protected const val LAUNCH_CONFIRM_LOCK_ACTIVITY = 1
-
- private const val INTRO_TAG = "intro"
- private const val FIND_SENSOR_TAG = "find-sensor"
- private const val ENROLLING_TAG = "enrolling"
- private const val FINISH_TAG = "finish"
- private const val SKIP_SETUP_FIND_FPS_DIALOG_TAG = "skip-setup-dialog"
- private const val ERROR_DIALOG_TAG = "error-dialog"
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/GlifLayoutHelper.kt b/src/com/android/settings/biometrics2/ui/view/GlifLayoutHelper.kt
deleted file mode 100644
index 756f309..0000000
--- a/src/com/android/settings/biometrics2/ui/view/GlifLayoutHelper.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.view
-
-import android.app.Activity
-import android.text.TextUtils
-import android.view.View
-import androidx.annotation.StringRes
-import com.google.android.setupdesign.GlifLayout
-
-/**
- * Utils class for GlifLayout
- */
-class GlifLayoutHelper(val activity: Activity, val glifLayout: GlifLayout) {
-
- /**
- * Sets header text to GlifLayout
- */
- fun setHeaderText(@StringRes textResId: Int) {
- val layoutTitle = glifLayout.headerTextView
- val previousTitle = layoutTitle.text
- val title = activity.getText(textResId)
- if (previousTitle !== title) {
- if (!TextUtils.isEmpty(previousTitle)) {
- layoutTitle.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
- }
- glifLayout.headerText = title
- glifLayout.headerTextView.contentDescription = title
- activity.title = title
- }
- }
-
- /**
- * Sets description text to GlifLayout
- */
- fun setDescriptionText(description: CharSequence?) {
- val previousDescription = glifLayout.descriptionText
- // Prevent a11y for re-reading the same string
- if (!TextUtils.equals(previousDescription, description)) {
- glifLayout.descriptionText = description
- }
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/view/SkipSetupFindFpsDialog.kt b/src/com/android/settings/biometrics2/ui/view/SkipSetupFindFpsDialog.kt
deleted file mode 100644
index bb74e36..0000000
--- a/src/com/android/settings/biometrics2/ui/view/SkipSetupFindFpsDialog.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.view
-
-import android.app.Dialog
-import android.content.Context
-import android.content.DialogInterface
-import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.DialogFragment
-import androidx.lifecycle.ViewModelProvider
-import com.android.settings.R
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel
-
-/**
- * Skip dialog which shows when user clicks "Do it later" button in FingerprintFindSensor page.
- */
-class SkipSetupFindFpsDialog : DialogFragment() {
-
- private var mViewModel: FingerprintEnrollFindSensorViewModel? = null
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
- requireActivity().bindSkipSetupFindFpsDialog {
- _: DialogInterface?, _: Int -> mViewModel?.onSkipDialogButtonClick()
- }
-
- override fun onAttach(context: Context) {
- mViewModel = ViewModelProvider(requireActivity())[
- FingerprintEnrollFindSensorViewModel::class.java
- ]
- super.onAttach(context)
- }
-}
-
-fun Context.bindSkipSetupFindFpsDialog(
- positiveButtonClickListener: DialogInterface.OnClickListener
-): AlertDialog =
- AlertDialog.Builder(this, R.style.Theme_AlertDialog)
- .setTitle(R.string.setup_fingerprint_enroll_skip_title)
- .setPositiveButton(R.string.skip_anyway_button_label, positiveButtonClickListener)
- .setNegativeButton(R.string.go_back_button_label, null)
- .setMessage(R.string.setup_fingerprint_enroll_skip_after_adding_lock_text)
- .create()
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.kt b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.kt
deleted file mode 100644
index 95aee4b..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.kt
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Activity
-import android.app.Application
-import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.util.Log
-import androidx.activity.result.ActivityResult
-import androidx.lifecycle.AndroidViewModel
-import com.android.internal.widget.LockPatternUtils
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics.BiometricUtils
-import com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException
-import com.android.settings.biometrics2.data.repository.FingerprintRepository
-import com.android.settings.biometrics2.ui.model.CredentialModel
-import com.android.settings.password.ChooseLockGeneric
-import com.android.settings.password.ChooseLockPattern
-import com.android.settings.password.ChooseLockSettingsHelper
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.launch
-
-/**
- * AutoCredentialViewModel which uses CredentialModel to determine next actions for activity, like
- * start ChooseLockActivity, start ConfirmLockActivity, GenerateCredential, or do nothing.
- */
-class AutoCredentialViewModel(
- application: Application,
- private val lockPatternUtils: LockPatternUtils,
- private val challengeGenerator: ChallengeGenerator,
- private val credentialModel: CredentialModel
-) : AndroidViewModel(application) {
-
- /**
- * Generic callback for FingerprintManager#generateChallenge or FaceManager#generateChallenge
- */
- interface GenerateChallengeCallback {
- /** Generic generateChallenge method for FingerprintManager or FaceManager */
- fun onChallengeGenerated(sensorId: Int, userId: Int, challenge: Long)
- }
-
- /**
- * A generic interface class for calling different generateChallenge from FingerprintManager or
- * FaceManager
- */
- interface ChallengeGenerator {
-
- /** Callback that will be called later after challenge generated */
- var callback: GenerateChallengeCallback?
-
- /** Method for generating challenge from FingerprintManager or FaceManager */
- fun generateChallenge(userId: Int)
- }
-
- /** Used to generate challenge through FingerprintRepository */
- class FingerprintChallengeGenerator(
- private val fingerprintRepository: FingerprintRepository
- ) : ChallengeGenerator {
-
- override var callback: GenerateChallengeCallback? = null
-
- override fun generateChallenge(userId: Int) {
- callback?.let {
- fingerprintRepository.generateChallenge(userId) {
- sensorId: Int, uid: Int, challenge: Long ->
- it.onChallengeGenerated(sensorId, uid, challenge)
- }
- } ?:run {
- Log.e(TAG, "generateChallenge, null callback")
- }
- }
-
- companion object {
- private const val TAG = "FingerprintChallengeGenerator"
- }
- }
-
- private val _generateChallengeFailedFlow = MutableSharedFlow<Boolean>()
- val generateChallengeFailedFlow: SharedFlow<Boolean>
- get() = _generateChallengeFailedFlow.asSharedFlow()
-
-
- // flag if token is generating through checkCredential()'s generateChallenge()
- private var isGeneratingChallengeDuringCheckingCredential = false
-
- /** Get bundle which passing back to FingerprintSettings for late generateChallenge() */
- fun createGeneratingChallengeExtras(): Bundle? {
- if (!isGeneratingChallengeDuringCheckingCredential
- || !credentialModel.isValidToken
- || !credentialModel.isValidChallenge
- ) {
- return null
- }
- val bundle = Bundle()
- bundle.putByteArray(
- ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
- credentialModel.token
- )
- bundle.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, credentialModel.challenge)
- return bundle
- }
-
- /** Check credential status for biometric enrollment. */
- fun checkCredential(scope: CoroutineScope): CredentialAction {
- return if (isValidCredential) {
- CredentialAction.CREDENTIAL_VALID
- } else if (isUnspecifiedPassword) {
- CredentialAction.FAIL_NEED_TO_CHOOSE_LOCK
- } else if (credentialModel.isValidGkPwHandle) {
- val gkPwHandle = credentialModel.gkPwHandle
- credentialModel.clearGkPwHandle()
- // GkPwHandle is got through caller activity, we shall not revoke it after
- // generateChallenge(). Let caller activity to make decision.
- generateChallenge(gkPwHandle, false, scope)
- isGeneratingChallengeDuringCheckingCredential = true
- CredentialAction.IS_GENERATING_CHALLENGE
- } else {
- CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK
- }
- }
-
- private fun generateChallenge(
- gkPwHandle: Long,
- revokeGkPwHandle: Boolean,
- scope: CoroutineScope
- ) {
- challengeGenerator.callback = object : GenerateChallengeCallback {
- override fun onChallengeGenerated(sensorId: Int, userId: Int, challenge: Long) {
- var illegalStateExceptionCaught = false
- try {
- val newToken = requestGatekeeperHat(gkPwHandle, challenge, userId)
- credentialModel.challenge = challenge
- credentialModel.token = newToken
- } catch (e: IllegalStateException) {
- Log.e(TAG, "generateChallenge, IllegalStateException", e)
- illegalStateExceptionCaught = true
- } finally {
- if (revokeGkPwHandle) {
- lockPatternUtils.removeGatekeeperPasswordHandle(gkPwHandle)
- }
- Log.d(
- TAG,
- "generateChallenge(), model:$credentialModel"
- + ", revokeGkPwHandle:$revokeGkPwHandle"
- )
- // Check credential again
- if (!isValidCredential || illegalStateExceptionCaught) {
- Log.w(TAG, "generateChallenge, invalid Credential or IllegalStateException")
- scope.launch {
- _generateChallengeFailedFlow.emit(true)
- }
- }
- }
- }
- }
- challengeGenerator.generateChallenge(userId)
- }
-
- private val isValidCredential: Boolean
- get() = !isUnspecifiedPassword && credentialModel.isValidToken
-
- private val isUnspecifiedPassword: Boolean
- get() = lockPatternUtils.getActivePasswordQuality(userId) == PASSWORD_QUALITY_UNSPECIFIED
-
- /**
- * Handle activity result from ChooseLockGeneric, ConfirmLockPassword, or ConfirmLockPattern
- * @param isChooseLock true if result is coming from ChooseLockGeneric. False if result is
- * coming from ConfirmLockPassword or ConfirmLockPattern
- * @param result activity result
- * @return if it is a valid result and viewModel is generating challenge
- */
- fun generateChallengeAsCredentialActivityResult(
- isChooseLock: Boolean,
- result: ActivityResult,
- scope: CoroutineScope
- ): Boolean {
- if ((isChooseLock && result.resultCode == ChooseLockPattern.RESULT_FINISHED) ||
- (!isChooseLock && result.resultCode == Activity.RESULT_OK)) {
- result.data?.let {
- val gkPwHandle = it.getLongExtra(
- ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
- CredentialModel.INVALID_GK_PW_HANDLE
- )
- // Revoke self requested GkPwHandle because it shall only used once inside this
- // activity lifecycle.
- generateChallenge(gkPwHandle, true, scope)
- return true
- }
- }
- return false
- }
-
- val userId: Int
- get() = credentialModel.userId
-
- val token: ByteArray?
- get() = credentialModel.token
-
- @Throws(IllegalStateException::class)
- private fun requestGatekeeperHat(gkPwHandle: Long, challenge: Long, userId: Int): ByteArray? {
- val response = lockPatternUtils
- .verifyGatekeeperPasswordHandle(gkPwHandle, challenge, userId)
- if (!response.isMatched) {
- throw GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT")
- }
- return response.gatekeeperHAT
- }
-
- /** Create Intent for choosing lock */
- fun createChooseLockIntent(
- context: Context, isSuw: Boolean,
- suwExtras: Bundle
- ): Intent {
- val intent = BiometricUtils.getChooseLockIntent(
- context, isSuw,
- suwExtras
- )
- intent.putExtra(
- ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS,
- true
- )
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true)
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true)
- if (credentialModel.isValidUserId) {
- intent.putExtra(Intent.EXTRA_USER_ID, credentialModel.userId)
- }
- return intent
- }
-
- /** Create ConfirmLockLauncher */
- fun createConfirmLockLauncher(
- activity: Activity,
- requestCode: Int, title: String
- ): ChooseLockSettingsHelper {
- val builder = ChooseLockSettingsHelper.Builder(activity)
- builder.setRequestCode(requestCode)
- .setTitle(title)
- .setRequestGatekeeperPasswordHandle(true)
- .setForegroundOnly(true)
- .setReturnCredentials(true)
- if (credentialModel.isValidUserId) {
- builder.setUserId(credentialModel.userId)
- }
- return builder.build()
- }
-
- companion object {
- private const val TAG = "AutoCredentialViewModel"
- }
-}
-
-enum class CredentialAction {
-
- CREDENTIAL_VALID,
-
- /** Valid credential, activity does nothing. */
- IS_GENERATING_CHALLENGE,
-
- /** This credential looks good, but still need to run generateChallenge(). */
- FAIL_NEED_TO_CHOOSE_LOCK,
-
- /** Need activity to run confirm lock */
- FAIL_NEED_TO_CONFIRM_LOCK
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModel.java
deleted file mode 100644
index 7dc1328..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModel.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import android.content.res.Configuration;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
-
-import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
-import com.android.systemui.unfold.updates.FoldProvider;
-
-import java.util.concurrent.Executor;
-
-/**
- * ViewModel explaining the fingerprint sensor location for fingerprint enrollment.
- */
-public class DeviceFoldedViewModel extends ViewModel {
-
- private static final String TAG = "DeviceFoldedViewModel";
-
- @NonNull private final MutableLiveData<Boolean> mLiveData =
- new MutableLiveData<>(null);
-
- private final ScreenSizeFoldProvider mScreenSizeFoldProvider;
- private final FoldProvider.FoldCallback mIsFoldedCallback = isFolded -> {
- Log.d(TAG, "onFoldUpdated= " + isFolded);
- mLiveData.postValue(isFolded);
- };
-
- public DeviceFoldedViewModel(@NonNull ScreenSizeFoldProvider screenSizeFoldProvider,
- @NonNull Executor executor) {
- super();
- mScreenSizeFoldProvider = screenSizeFoldProvider;
- mScreenSizeFoldProvider.registerCallback(mIsFoldedCallback, executor);
- }
-
- /**
- * Calls this method when activity gets configuration change
- */
- public void onConfigurationChanged(@NonNull Configuration newConfig) {
- mScreenSizeFoldProvider.onConfigurationChange(newConfig);
- }
-
- /**
- * Returns FoldedLiveData
- */
- public LiveData<Boolean> getLiveData() {
- return mLiveData;
- }
-
- @Override
- protected void onCleared() {
- mScreenSizeFoldProvider.unregisterCallback(mIsFoldedCallback);
- super.onCleared();
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModel.java
deleted file mode 100644
index 07fe275..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModel.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.viewmodel;
-
-import static android.hardware.display.DisplayManager.DisplayListener;
-
-import android.app.Application;
-import android.hardware.display.DisplayManager;
-import android.util.Log;
-import android.view.DisplayInfo;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * ViewModel explaining the fingerprint sensor location for fingerprint enrollment.
- */
-public class DeviceRotationViewModel extends AndroidViewModel {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "DeviceRotationViewModel";
-
- private final DisplayManager mDisplayManager;
- private final boolean mIsReverseDefaultRotation;
- @NonNull private final DisplayInfo mDisplayInfo = new DisplayInfo();
-
- /** {@link android.hardware.display.DisplayManager} is a final class, set this member visibility
- * to 'protected' for testing
- */
- @VisibleForTesting
- protected final DisplayListener mDisplayListener = new DisplayListener() {
- @Override
- public void onDisplayAdded(int displayId) {
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- final int rotation = getRotation();
- Log.d(TAG, "onDisplayChanged(" + displayId + "), rotation:" + rotation);
- mLiveData.postValue(rotation);
- }
- };
-
- @NonNull private final MutableLiveData<Integer> mLiveData = new MutableLiveData<>();
-
- public DeviceRotationViewModel(@NonNull Application application) {
- super(application);
- mDisplayManager = application.getSystemService(DisplayManager.class);
- mDisplayManager.registerDisplayListener(mDisplayListener,
- application.getMainThreadHandler());
- mIsReverseDefaultRotation = application.getResources().getBoolean(
- com.android.internal.R.bool.config_reverseDefaultRotation);
- }
-
- /**
- * Returns current rotation.
- *
- * {@link android.view.Display} is a final class, set this method visibility to "protected" for
- * inheriting it in test
- */
- @VisibleForTesting
- @Surface.Rotation
- protected int getRotation() {
- getApplication().getDisplay().getDisplayInfo(mDisplayInfo);
- if (mIsReverseDefaultRotation) {
- return (mDisplayInfo.rotation + 1) % 4;
- } else {
- return mDisplayInfo.rotation;
- }
- }
-
- /**
- * Returns RotationLiveData
- */
- public LiveData<Integer> getLiveData() {
- final Integer lastRotation = mLiveData.getValue();
- @Surface.Rotation int newRotation = getRotation();
- if (lastRotation == null || lastRotation != newRotation) {
- Log.d(TAG, "getLiveData, update rotation from " + lastRotation + " to " + newRotation);
- mLiveData.setValue(newRotation);
- }
- return mLiveData;
- }
-
- @Override
- protected void onCleared() {
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
- super.onCleared();
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
deleted file mode 100644
index eba6a15..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import android.annotation.IntDef;
-import android.app.Application;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.os.VibrationAttributes;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * ViewModel explaining the fingerprint enrolling page
- */
-public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel {
-
- private static final String TAG = FingerprintEnrollEnrollingViewModel.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- private static final VibrationEffect VIBRATE_EFFECT_ERROR =
- VibrationEffect.createWaveform(new long[]{0, 5, 55, 60}, -1);
- private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
- VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY);
-
- /**
- * Enrolling finished
- */
- public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE = 0;
-
- /**
- * Icon touch dialog show
- */
- public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG = 1;
-
- /**
- * Has got latest cancelled event due to user skip
- */
- public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP = 2;
-
- /**
- * Has got latest cancelled event due to back key
- */
- public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED = 3;
-
- @IntDef(prefix = { "FINGERPRINT_ENROLL_ENROLLING_ACTION_" }, value = {
- FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE,
- FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG,
- FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FingerprintEnrollEnrollingAction {}
-
- private final int mUserId;
- private boolean mOnBackPressed;
- private boolean mOnSkipPressed;
- @NonNull private final FingerprintRepository mFingerprintRepository;
- private final AccessibilityManager mAccessibilityManager;
- private final Vibrator mVibrator;
-
- private final MutableLiveData<Integer> mActionLiveData = new MutableLiveData<>();
-
- public FingerprintEnrollEnrollingViewModel(
- @NonNull Application application,
- int userId,
- @NonNull FingerprintRepository fingerprintRepository
- ) {
- super(application);
- mUserId = userId;
- mFingerprintRepository = fingerprintRepository;
- mAccessibilityManager = application.getSystemService(AccessibilityManager.class);
- mVibrator = application.getSystemService(Vibrator.class);
- }
-
- public LiveData<Integer> getActionLiveData() {
- return mActionLiveData;
- }
-
- /**
- * Clears action live data
- */
- public void clearActionLiveData() {
- mActionLiveData.setValue(null);
- }
-
- public boolean getOnSkipPressed() {
- return mOnSkipPressed;
- }
-
- /**
- * User clicks skip button
- */
- public void setOnSkipPressed() {
- mOnSkipPressed = true;
- }
-
- /**
- * Enrolling is cancelled because user clicks skip
- */
- public void onCancelledDueToOnSkipPressed() {
- final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP;
- if (DEBUG) {
- Log.d(TAG, "onSkipButtonClick, post action " + action);
- }
- mOnSkipPressed = false;
- mActionLiveData.postValue(action);
- }
-
- /**
- * Is enrolling finished
- */
- public void onEnrollingDone() {
- final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE;
- if (DEBUG) {
- Log.d(TAG, "onEnrollingDone, post action " + action);
- }
- mActionLiveData.postValue(action);
- }
-
- public boolean getOnBackPressed() {
- return mOnBackPressed;
- }
-
- /**
- * Back key is pressed.
- */
- public void setOnBackPressed() {
- mOnBackPressed = true;
- }
-
- /**
- * Enrollment is cancelled because back key is pressed.
- */
- public void onCancelledDueToOnBackPressed() {
- final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
- if (DEBUG) {
- Log.d(TAG, "onCancelledEventReceivedAfterOnBackPressed, post action " + action);
- }
- mOnBackPressed = false;
- mActionLiveData.postValue(action);
- }
-
- /**
- * Icon touch dialog show
- */
- public void showIconTouchDialog() {
- final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
- if (DEBUG) {
- Log.d(TAG, "onIconTouchDialogShow, post action " + action);
- }
- mActionLiveData.postValue(action);
- }
-
- /**
- * get enroll stage threshold
- */
- public float getEnrollStageThreshold(int index) {
- return mFingerprintRepository.getEnrollStageThreshold(index);
- }
-
- /**
- * Get enroll stage count
- */
- public int getEnrollStageCount() {
- return mFingerprintRepository.getEnrollStageCount();
- }
-
- /**
- * Requests interruption of the accessibility feedback from all accessibility services.
- */
- public void clearTalkback() {
- mAccessibilityManager.interrupt();
- }
-
- /**
- * Returns if the {@link AccessibilityManager} is enabled.
- *
- * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
- */
- public boolean isAccessibilityEnabled() {
- return mAccessibilityManager.isEnabled();
- }
-
- /**
- * Sends an {@link AccessibilityEvent}.
- */
- public void sendAccessibilityEvent(CharSequence announcement) {
- AccessibilityEvent e = AccessibilityEvent.obtain();
- e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
- e.setClassName(getClass().getName());
- e.setPackageName(getApplication().getPackageName());
- e.getText().add(announcement);
- mAccessibilityManager.sendAccessibilityEvent(e);
- }
-
- /**
- * Returns if the touch exploration in the system is enabled.
- *
- * @return True if touch exploration is enabled, false otherwise.
- */
- public boolean isTouchExplorationEnabled() {
- return mAccessibilityManager.isTouchExplorationEnabled();
- }
-
- /**
- * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
- * caller to specify the vibration is owned by someone else and set a reason for vibration.
- */
- public void vibrateError(String reason) {
- mVibrator.vibrate(mUserId, getApplication().getOpPackageName(),
- VIBRATE_EFFECT_ERROR, reason, FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
- }
-
- /**
- * Gets the first FingerprintSensorPropertiesInternal from FingerprintManager
- */
- @Nullable
- public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
- return mFingerprintRepository.getFirstFingerprintSensorPropertiesInternal();
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModel.kt b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModel.kt
deleted file mode 100644
index b154fe7..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModel.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.android.settings.biometrics2.ui.viewmodel
-
-import android.app.Application
-import androidx.lifecycle.AndroidViewModel
-import kotlinx.atomicfu.AtomicBoolean
-import kotlinx.atomicfu.atomic
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
-
-class FingerprintEnrollErrorDialogViewModel(
- application: Application,
- val isSuw: Boolean
-): AndroidViewModel(application) {
-
- private val _isDialogShown: AtomicBoolean = atomic(false)
- val isDialogShown: Boolean
- get() = _isDialogShown.value
-
- private val _newDialogFlow = MutableSharedFlow<Int>()
- val newDialogFlow: SharedFlow<Int>
- get() = _newDialogFlow.asSharedFlow()
-
- private val _triggerRetryFlow = MutableSharedFlow<Any>()
- val triggerRetryFlow: SharedFlow<Any>
- get() = _triggerRetryFlow.asSharedFlow()
-
- private val _setResultFlow = MutableSharedFlow<FingerprintErrorDialogSetResultAction>()
- val setResultFlow: SharedFlow<FingerprintErrorDialogSetResultAction>
- get() = _setResultFlow.asSharedFlow()
-
- suspend fun newDialog(errorMsgId: Int) {
- _isDialogShown.compareAndSet(expect = false, update = true)
- _newDialogFlow.emit(errorMsgId)
- }
-
- suspend fun triggerRetry() {
- _isDialogShown.compareAndSet(expect = true, update = false)
- _triggerRetryFlow.emit(Any())
- }
-
- suspend fun setResultAndFinish(action: FingerprintErrorDialogSetResultAction) {
- _isDialogShown.compareAndSet(expect = true, update = false)
- _setResultFlow.emit(action)
- }
-}
-
-enum class FingerprintErrorDialogSetResultAction {
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH,
- FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModel.java
deleted file mode 100644
index 00c67c4..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModel.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.viewmodel;
-
-import android.annotation.IntDef;
-import android.app.Application;
-import android.util.Log;
-import android.view.accessibility.AccessibilityManager;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * ViewModel explaining the fingerprint sensor location for fingerprint enrollment.
- */
-public class FingerprintEnrollFindSensorViewModel extends AndroidViewModel {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "FingerprintEnrollFindSensorViewModel";
-
- /**
- * User clicks 'Skip' button on this page in Settings
- */
- public static final int FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP = 0;
-
- /**
- * User clicks 'Skip' button on this page in SetupWizard flow
- */
- public static final int FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG = 1;
-
- /**
- * User clicks 'Start' button on this page
- */
- public static final int FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START = 2;
-
- @IntDef(prefix = { "FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_" }, value = {
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP,
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG,
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FingerprintEnrollFindSensorAction {}
-
- private final AccessibilityManager mAccessibilityManager;
-
- private final boolean mIsSuw;
- @NonNull private final MutableLiveData<Integer> mActionLiveData = new MutableLiveData<>();
-
- public FingerprintEnrollFindSensorViewModel(@NonNull Application application, boolean isSuw) {
- super(application);
- mAccessibilityManager = application.getSystemService(AccessibilityManager.class);
- mIsSuw = isSuw;
- }
-
- /**
- * Returns action live data that user chooses
- */
- public LiveData<Integer> getActionLiveData() {
- return mActionLiveData;
- }
-
- /**
- * Clear ActionLiveData to prevent get obsolete data
- */
- public void clearActionLiveData() {
- mActionLiveData.setValue(null);
- }
-
- /**
- * User clicks skip button on dialog
- */
- public void onSkipDialogButtonClick() {
- final int action = FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP;
- if (DEBUG) {
- Log.d(TAG, "onSkipDialogButtonClick, post " + action);
- }
- mActionLiveData.postValue(action);
- }
-
- /**
- * User clicks skip button
- */
- public void onSkipButtonClick() {
- final int action = mIsSuw
- ? FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG
- : FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP;
- if (DEBUG) {
- Log.d(TAG, "onSkipButtonClick, post action " + action);
- }
- mActionLiveData.postValue(action);
- }
-
- /**
- * User clicks start button
- */
- public void onStartButtonClick() {
- final int action = FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
- if (DEBUG) {
- Log.d(TAG, "onStartButtonClick, post action " + action);
- }
- mActionLiveData.postValue(action);
- }
-
- /**
- * Returns the info about accessibility is enabled or not
- */
- public boolean isAccessibilityEnabled() {
- return mAccessibilityManager.isEnabled();
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java
deleted file mode 100644
index ae67f74..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModel.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import android.annotation.IntDef;
-import android.app.Application;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Finish ViewModel handles the state of the fingerprint renroll final stage
- */
-public class FingerprintEnrollFinishViewModel extends AndroidViewModel {
-
- private static final String TAG = FingerprintEnrollFinishViewModel.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- /**
- * User clicks "Add" button
- */
- public static final int FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK = 0;
-
- /**
- * User clicks "Next" button
- */
- public static final int FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK = 1;
-
- @IntDef(prefix = { "FINGERPRINT_ENROLL_FINISH_ACTION_" }, value = {
- FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK,
- FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FingerprintEnrollFinishAction {}
-
- @NonNull private final FingerprintRepository mFingerprintRepository;
- @NonNull private final EnrollmentRequest mRequest;
- private final int mUserId;
-
- private final MutableLiveData<Integer> mActionLiveData = new MutableLiveData<>();
-
- public FingerprintEnrollFinishViewModel(@NonNull Application application, int userId,
- @NonNull EnrollmentRequest request,
- @NonNull FingerprintRepository fingerprintRepository) {
- super(application);
- mUserId = userId;
- mRequest = request;
- mFingerprintRepository = fingerprintRepository;
- }
-
- @NonNull
- public EnrollmentRequest getRequest() {
- return mRequest;
- }
-
- /**
- * The first sensor type is Side fps sensor or not
- */
- public boolean canAssumeSfps() {
- return mFingerprintRepository.canAssumeSfps();
- }
-
- /**
- * Device allows user to enroll another fingerprint or not.
- */
- public boolean isAnotherFingerprintEnrollable() {
- return mFingerprintRepository.getNumOfEnrolledFingerprintsSize(mUserId)
- < mFingerprintRepository.getMaxFingerprints();
- }
-
- /**
- * Clear action LiveData
- */
- public void clearActionLiveData() {
- mActionLiveData.setValue(null);
- }
-
- /**
- * Get action LiveData
- */
- public LiveData<Integer> getActionLiveData() {
- return mActionLiveData;
- }
-
- /**
- * Handle add button Click
- */
- public void onAddButtonClick() {
- final int action = FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK;
- if (DEBUG) {
- Log.d(TAG, "onAddButtonClick post(" + action + ")");
- }
- mActionLiveData.postValue(action);
- }
-
- /**
- * Handle next button Click
- */
- public void onNextButtonClick() {
- final int action = FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK;
- if (DEBUG) {
- Log.d(TAG, "onNextButtonClick post(" + action + ")");
- }
- mActionLiveData.postValue(action);
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.kt b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.kt
deleted file mode 100644
index 98137b4..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Application
-import android.util.Log
-import androidx.lifecycle.AndroidViewModel
-import com.android.settings.biometrics2.data.repository.FingerprintRepository
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.CONTINUE_ENROLL
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.DONE_AND_FINISH
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.SKIP_OR_CANCEL
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.launch
-
-/** Fingerprint intro onboarding page view model implementation */
-class FingerprintEnrollIntroViewModel(
- application: Application,
- private val fingerprintRepository: FingerprintRepository,
- val request: EnrollmentRequest,
- private val userId: Int
-) : AndroidViewModel(application) {
-
- /** User's action flow (like clicking Agree, Skip, or Done) */
- private val _actionFlow = MutableSharedFlow<FingerprintEnrollIntroAction>()
- val actionFlow: SharedFlow<FingerprintEnrollIntroAction>
- get() = _actionFlow.asSharedFlow()
-
- private fun getEnrollableStatus(): FingerprintEnrollable {
- val num = fingerprintRepository.getNumOfEnrolledFingerprintsSize(userId)
- val max =
- if (request.isSuw && !request.isAfterSuwOrSuwSuggestedAction)
- fingerprintRepository.getMaxFingerprintsInSuw(
- getApplication<Application>().resources
- )
- else
- fingerprintRepository.maxFingerprints
- return if (num >= max)
- FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
- else
- FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
- }
-
- private val hasScrolledToBottomFlow = MutableStateFlow(HAS_SCROLLED_TO_BOTTOM_DEFAULT)
- private val enrollableStatusFlow = MutableStateFlow(getEnrollableStatus())
-
- /** Enrollable status and hasScrollToBottom live data */
- val pageStatusFlow: Flow<FingerprintEnrollIntroStatus> =
- hasScrolledToBottomFlow.combine(enrollableStatusFlow) {
- hasScrolledToBottom: Boolean, enrollableStatus: FingerprintEnrollable ->
- FingerprintEnrollIntroStatus(hasScrolledToBottom, enrollableStatus)
- }
-
- fun updateEnrollableStatus(scope: CoroutineScope) {
- scope.launch {
- enrollableStatusFlow.emit(getEnrollableStatus())
- }
- }
-
- /** The first sensor type is UDFPS sensor or not */
- val canAssumeUdfps: Boolean
- get() = fingerprintRepository.canAssumeUdfps()
-
- /** Update onboarding intro page has scrolled to bottom */
- fun setHasScrolledToBottom(value: Boolean, scope: CoroutineScope) {
- scope.launch {
- hasScrolledToBottomFlow.emit(value)
- }
- }
-
- /** Get parental consent required or not during enrollment process */
- val isParentalConsentRequired: Boolean
- get() = fingerprintRepository.isParentalConsentRequired(getApplication())
-
- /** Get fingerprint is disable by admin or not */
- val isBiometricUnlockDisabledByAdmin: Boolean
- get() = fingerprintRepository.isDisabledByAdmin(getApplication(), userId)
-
- /**
- * User clicks next button
- */
- fun onNextButtonClick(scope: CoroutineScope) {
- scope.launch {
- when (val status = enrollableStatusFlow.value) {
- FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX ->
- _actionFlow.emit(DONE_AND_FINISH)
-
- FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK ->
- _actionFlow.emit(CONTINUE_ENROLL)
-
- else -> Log.w(TAG, "fail to click next, enrolled:$status")
- }
- }
- }
-
- /** User clicks skip/cancel button */
- fun onSkipOrCancelButtonClick(scope: CoroutineScope) {
- scope.launch {
- _actionFlow.emit(SKIP_OR_CANCEL)
- }
- }
-
- companion object {
- private const val TAG = "FingerprintEnrollIntroViewModel"
- private const val HAS_SCROLLED_TO_BOTTOM_DEFAULT = false
- private val ENROLLABLE_STATUS_DEFAULT = FingerprintEnrollable.FINGERPRINT_ENROLLABLE_UNKNOWN
- }
-}
-
-enum class FingerprintEnrollIntroAction {
- /** User clicks 'Done' button on this page */
- DONE_AND_FINISH,
- /** User clicks 'Agree' button on this page */
- CONTINUE_ENROLL,
- /** User clicks 'Skip' button on this page */
- SKIP_OR_CANCEL
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
deleted file mode 100644
index 1cfec52..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.viewmodel;
-
-import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_CANCELED;
-import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
-
-import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_REMAINING;
-import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_STEPS;
-
-import android.app.Application;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.hardware.fingerprint.FingerprintManager.EnrollReason;
-import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
-import android.os.CancellationSignal;
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.settings.R;
-import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
-import com.android.settings.biometrics.fingerprint.MessageDisplayController;
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
-
-import java.util.LinkedList;
-
-/**
- * Progress ViewModel handles the state around biometric enrollment. It manages the state of
- * enrollment throughout the activity lifecycle so the app can continue after an event like
- * rotation.
- */
-public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "FingerprintEnrollProgressViewModel";
-
- private final MutableLiveData<EnrollmentProgress> mProgressLiveData = new MutableLiveData<>(
- new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
- private final MutableLiveData<EnrollmentStatusMessage> mHelpMessageLiveData =
- new MutableLiveData<>();
- private final MutableLiveData<EnrollmentStatusMessage> mErrorMessageLiveData =
- new MutableLiveData<>();
- private final MutableLiveData<Object> mCanceledSignalLiveData = new MutableLiveData<>();
- private final MutableLiveData<Boolean> mAcquireLiveData = new MutableLiveData<>();
- private final MutableLiveData<Integer> mPointerDownLiveData = new MutableLiveData<>();
- private final MutableLiveData<Integer> mPointerUpLiveData = new MutableLiveData<>();
-
- private byte[] mToken = null;
- private final int mUserId;
-
- private final FingerprintUpdater mFingerprintUpdater;
- @Nullable private CancellationSignal mCancellationSignal = null;
- @NonNull private final LinkedList<CancellationSignal> mCancelingSignalQueue =
- new LinkedList<>();
- private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() {
-
- @Override
- public void onEnrollmentProgress(int remaining) {
- final int currentSteps = getSteps();
- final EnrollmentProgress progress = new EnrollmentProgress(
- currentSteps == INITIAL_STEPS ? remaining : getSteps(), remaining);
- if (DEBUG) {
- Log.d(TAG, "onEnrollmentProgress(" + remaining + "), steps: " + currentSteps
- + ", post progress as " + progress);
- }
- mHelpMessageLiveData.setValue(null);
- mProgressLiveData.postValue(progress);
- }
-
- @Override
- public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
- if (DEBUG) {
- Log.d(TAG, "onEnrollmentHelp(" + helpMsgId + ", " + helpString + ")");
- }
- mHelpMessageLiveData.postValue(new EnrollmentStatusMessage(helpMsgId, helpString));
- }
-
- @Override
- public void onEnrollmentError(int errMsgId, CharSequence errString) {
- Log.d(TAG, "onEnrollmentError(" + errMsgId + ", " + errString
- + "), cancelingQueueSize:" + mCancelingSignalQueue.size());
- if (FINGERPRINT_ERROR_CANCELED == errMsgId && mCancelingSignalQueue.size() > 0) {
- mCanceledSignalLiveData.postValue(mCancelingSignalQueue.poll());
- } else {
- mErrorMessageLiveData.postValue(new EnrollmentStatusMessage(errMsgId, errString));
- }
- }
-
- @Override
- public void onAcquired(boolean isAcquiredGood) {
- mAcquireLiveData.postValue(isAcquiredGood);
- }
-
- @Override
- public void onUdfpsPointerDown(int sensorId) {
- mPointerDownLiveData.postValue(sensorId);
- }
-
- @Override
- public void onUdfpsPointerUp(int sensorId) {
- mPointerUpLiveData.postValue(sensorId);
- }
- };
-
- public FingerprintEnrollProgressViewModel(@NonNull Application application,
- @NonNull FingerprintUpdater fingerprintUpdater, int userId) {
- super(application);
- mFingerprintUpdater = fingerprintUpdater;
- mUserId = userId;
- }
-
- public void setToken(byte[] token) {
- mToken = token;
- }
-
- /**
- * clear progress
- */
- public void clearProgressLiveData() {
- mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
- mHelpMessageLiveData.setValue(null);
- mErrorMessageLiveData.setValue(null);
- }
-
- /**
- * clear error message
- */
- public void clearErrorMessageLiveData() {
- mErrorMessageLiveData.setValue(null);
- }
-
- public LiveData<EnrollmentProgress> getProgressLiveData() {
- return mProgressLiveData;
- }
-
- public LiveData<EnrollmentStatusMessage> getHelpMessageLiveData() {
- return mHelpMessageLiveData;
- }
-
- public LiveData<EnrollmentStatusMessage> getErrorMessageLiveData() {
- return mErrorMessageLiveData;
- }
-
- public LiveData<Object> getCanceledSignalLiveData() {
- return mCanceledSignalLiveData;
- }
-
- public LiveData<Boolean> getAcquireLiveData() {
- return mAcquireLiveData;
- }
-
- public LiveData<Integer> getPointerDownLiveData() {
- return mPointerDownLiveData;
- }
-
- public LiveData<Integer> getPointerUpLiveData() {
- return mPointerUpLiveData;
- }
-
- /**
- * Starts enrollment and return latest isEnrolling() result
- */
- public Object startEnrollment(@EnrollReason int reason) {
- if (mToken == null) {
- Log.e(TAG, "Null hardware auth token for enroll");
- return null;
- }
- if (mCancellationSignal != null) {
- Log.w(TAG, "Enrolling is running, shall not start again");
- return mCancellationSignal;
- }
- if (DEBUG) {
- Log.e(TAG, "startEnrollment(" + reason + ")");
- }
-
- // Clear data
- mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
- mHelpMessageLiveData.setValue(null);
- mErrorMessageLiveData.setValue(null);
-
- mCancellationSignal = new CancellationSignal();
-
- final Resources res = getApplication().getResources();
- if (reason == ENROLL_ENROLL
- && res.getBoolean(R.bool.enrollment_message_display_controller_flag)) {
- final EnrollmentCallback callback = new MessageDisplayController(
- getApplication().getMainThreadHandler(),
- mEnrollmentCallback,
- SystemClock.elapsedRealtimeClock(),
- res.getInteger(R.integer.enrollment_help_minimum_time_display),
- res.getInteger(R.integer.enrollment_progress_minimum_time_display),
- res.getBoolean(R.bool.enrollment_progress_priority_over_help),
- res.getBoolean(R.bool.enrollment_prioritize_acquire_messages),
- res.getInteger(R.integer.enrollment_collect_time));
- mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, callback, reason,
- new Intent());
- } else {
- mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, mEnrollmentCallback,
- reason, new Intent());
- }
- return mCancellationSignal;
- }
-
- /**
- * Cancels enrollment and return latest isEnrolling result
- */
- public boolean cancelEnrollment() {
- final CancellationSignal cancellationSignal = mCancellationSignal;
- mCancellationSignal = null;
-
- if (cancellationSignal == null) {
- Log.e(TAG, "Fail to cancel enrollment, has cancelled or not start");
- return false;
- } else {
- Log.d(TAG, "enrollment cancelled");
- }
- mCancelingSignalQueue.add(cancellationSignal);
- cancellationSignal.cancel();
-
- return true;
- }
-
- public boolean isEnrolling() {
- return (mCancellationSignal != null);
- }
-
- private int getSteps() {
- return mProgressLiveData.getValue().getSteps();
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.kt b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.kt
deleted file mode 100644
index 37b0052..0000000
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModel.kt
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Application
-import android.content.ComponentName
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Bundle
-import android.util.Log
-import androidx.activity.result.ActivityResult
-import androidx.lifecycle.AndroidViewModel
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics.fingerprint.FingerprintEnrollFinish.FINGERPRINT_SUGGESTION_ACTIVITY
-import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction
-import com.android.settings.biometrics2.data.repository.FingerprintRepository
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest
-import kotlinx.atomicfu.AtomicBoolean
-import kotlinx.atomicfu.atomic
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.launch
-
-/**
- * Fingerprint enrollment view model implementation
- */
-class FingerprintEnrollmentViewModel(
- application: Application,
- private val fingerprintRepository: FingerprintRepository,
- val request: EnrollmentRequest
-) : AndroidViewModel(application) {
-
- val isWaitingActivityResult: AtomicBoolean = atomic(false)
-
- private val _setResultFlow = MutableSharedFlow<ActivityResult>()
- val setResultFlow: SharedFlow<ActivityResult>
- get() = _setResultFlow.asSharedFlow()
-
- var isNewFingerprintAdded = false
- set(value) {
- // Only allow changing this value from false to true
- if (!field) {
- field = value
- }
- }
-
- /**
- * Get override activity result as current ViewModel status.
- *
- * FingerprintEnrollmentActivity supports user enrolls 2nd fingerprint or starts a new flow
- * through Deferred-SUW, Portal-SUW, or SUW Suggestion. Use a method to get override activity
- * result instead of putting these if-else on every setResult(), .
- */
- fun getOverrideActivityResult(
- result: ActivityResult,
- generatingChallengeExtras: Bundle?
- ): ActivityResult {
- val newResultCode = if (isNewFingerprintAdded)
- BiometricEnrollBase.RESULT_FINISHED
- else if (request.isAfterSuwOrSuwSuggestedAction)
- BiometricEnrollBase.RESULT_CANCELED
- else
- result.resultCode
-
- var newData = result.data
- if (newResultCode == BiometricEnrollBase.RESULT_FINISHED
- && generatingChallengeExtras != null
- ) {
- if (newData == null) {
- newData = Intent()
- }
- newData.putExtras(generatingChallengeExtras)
- }
- return ActivityResult(newResultCode, newData)
- }
-
- /**
- * Activity calls this method during onPause() to finish itself when back to background.
- *
- * @param isActivityFinishing Activity has called finish() or not
- * @param isChangingConfigurations Activity is finished because of configuration changed or not.
- */
- fun checkFinishActivityDuringOnPause(
- isActivityFinishing: Boolean,
- isChangingConfigurations: Boolean,
- scope: CoroutineScope
- ) {
- if (isChangingConfigurations || isActivityFinishing || request.isSuw
- || isWaitingActivityResult.value
- ) {
- return
- }
- scope.launch {
- _setResultFlow.emit(ActivityResult(BiometricEnrollBase.RESULT_TIMEOUT, null))
- }
- }
-
- /**
- * Get Suw fingerprint count extra for statistics
- */
- fun getSuwFingerprintCountExtra(userId: Int) = Bundle().also {
- it.putInt(
- SetupFingerprintEnrollIntroduction.EXTRA_FINGERPRINT_ENROLLED_COUNT,
- fingerprintRepository.getNumOfEnrolledFingerprintsSize(userId)
- )
- }
-
- /**
- * Gets the result about fingerprint enrollable
- */
- fun isMaxEnrolledReached(userId: Int): Boolean = with(fingerprintRepository) {
- maxFingerprints <= getNumOfEnrolledFingerprintsSize(userId)
- }
-
- val canAssumeUdfps: Boolean
- get() = fingerprintRepository.canAssumeUdfps()
-
- val canAssumeSfps: Boolean
- get() = fingerprintRepository.canAssumeSfps()
-
- /**
- * Update FINGERPRINT_SUGGESTION_ACTIVITY into package manager
- */
- fun updateFingerprintSuggestionEnableState(userId: Int) {
- // Only show "Add another fingerprint" if the user already enrolled one.
- // "Add fingerprint" will be shown in the main flow if the user hasn't enrolled any
- // fingerprints. If the user already added more than one fingerprint, they already know
- // to add multiple fingerprints so we don't show the suggestion.
- val state = if (fingerprintRepository.getNumOfEnrolledFingerprintsSize(userId) == 1)
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- else
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- getApplication<Application>().packageManager.setComponentEnabledSetting(
- ComponentName(
- getApplication(),
- FINGERPRINT_SUGGESTION_ACTIVITY
- ),
- state,
- PackageManager.DONT_KILL_APP
- )
- Log.d(TAG, "$FINGERPRINT_SUGGESTION_ACTIVITY enabled state: $state")
- }
-
- companion object {
- private const val TAG = "FingerprintEnrollmentViewModel"
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollDrawable.java b/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollDrawable.java
deleted file mode 100644
index 4b0b624..0000000
--- a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollDrawable.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * 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.biometrics2.ui.widget;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.PathShape;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.Build;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.PathParser;
-import android.util.TypedValue;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateDecelerateInterpolator;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.settings.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * UDFPS fingerprint drawable that is shown when enrolling
- */
-public class UdfpsEnrollDrawable extends Drawable {
- private static final String TAG = "UdfpsAnimationEnroll";
-
- private static final long TARGET_ANIM_DURATION_LONG = 800L;
- private static final long TARGET_ANIM_DURATION_SHORT = 600L;
- // 1 + SCALE_MAX is the maximum that the moving target will animate to
- private static final float SCALE_MAX = 0.25f;
- private static final float DEFAULT_STROKE_WIDTH = 3f;
- private static final float SCALE = 0.5f;
- private static final String SCALE_OVERRIDE =
- "com.android.systemui.biometrics.UdfpsEnrollHelper.scale";
- private static final String NEW_COORDS_OVERRIDE =
- "com.android.systemui.biometrics.UdfpsNewCoords";
-
- @NonNull
- private final Drawable mMovingTargetFpIcon;
- @NonNull
- private final Paint mSensorOutlinePaint;
- @NonNull
- private final Paint mBlueFill;
- @NonNull
- private final ShapeDrawable mFingerprintDrawable;
- private int mAlpha;
- private boolean mSkipDraw = false;
-
- @Nullable
- private RectF mSensorRect;
-
- // Moving target animator set
- @Nullable
- AnimatorSet mTargetAnimatorSet;
- // Moving target location
- float mCurrentX;
- float mCurrentY;
- // Moving target size
- float mCurrentScale = 1.f;
-
- @NonNull
- private final Animator.AnimatorListener mTargetAnimListener;
-
- private boolean mShouldShowTipHint = false;
- private boolean mShouldShowEdgeHint = false;
-
- private int mEnrollIcon;
- private int mMovingTargetFill;
-
- private int mTotalSteps = -1;
- private int mRemainingSteps = -1;
- private int mLocationsEnrolled = 0;
- private int mCenterTouchCount = 0;
-
- private FingerprintManager mFingerprintManager;
-
- private boolean mAccessibilityEnabled;
- private Context mContext;
- private final List<PointF> mGuidedEnrollmentPoints;
-
- UdfpsEnrollDrawable(@NonNull Context context, @Nullable AttributeSet attrs) {
- mFingerprintDrawable = defaultFactory(context);
-
- loadResources(context, attrs);
- mSensorOutlinePaint = new Paint(0 /* flags */);
- mSensorOutlinePaint.setAntiAlias(true);
- mSensorOutlinePaint.setColor(mMovingTargetFill);
- mSensorOutlinePaint.setStyle(Paint.Style.FILL);
-
- mBlueFill = new Paint(0 /* flags */);
- mBlueFill.setAntiAlias(true);
- mBlueFill.setColor(mMovingTargetFill);
- mBlueFill.setStyle(Paint.Style.FILL);
-
- mMovingTargetFpIcon = context.getResources()
- .getDrawable(R.drawable.ic_enrollment_fingerprint, null);
- mMovingTargetFpIcon.setTint(mEnrollIcon);
- mMovingTargetFpIcon.mutate();
-
- mFingerprintDrawable.setTint(mEnrollIcon);
-
- setAlpha(255);
- mTargetAnimListener = new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- updateTipHintVisibility();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- };
- mContext = context;
- mFingerprintManager = context.getSystemService(FingerprintManager.class);
- final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
- mAccessibilityEnabled = am.isEnabled();
- mGuidedEnrollmentPoints = new ArrayList<>();
- initEnrollPoint(context);
- }
-
- /** The [sensorRect] coordinates for the sensor area. */
- void onSensorRectUpdated(@NonNull RectF sensorRect) {
- int margin = ((int) sensorRect.height()) / 8;
- Rect bounds = new Rect((int) (sensorRect.left) + margin, (int) (sensorRect.top) + margin,
- (int) (sensorRect.right) - margin, (int) (sensorRect.bottom) - margin);
- updateFingerprintIconBounds(bounds);
- mSensorRect = sensorRect;
- }
-
- void setShouldSkipDraw(boolean skipDraw) {
- if (mSkipDraw == skipDraw) {
- return;
- }
- mSkipDraw = skipDraw;
- invalidateSelf();
- }
-
- void updateFingerprintIconBounds(@NonNull Rect bounds) {
- mFingerprintDrawable.setBounds(bounds);
- invalidateSelf();
- mMovingTargetFpIcon.setBounds(bounds);
- invalidateSelf();
- }
-
- void onEnrollmentProgress(final int remaining, final int totalSteps) {
- if (mTotalSteps == -1) {
- mTotalSteps = totalSteps;
- }
-
- if (remaining != mRemainingSteps) {
- mLocationsEnrolled++;
- if (isCenterEnrollmentStage()) {
- mCenterTouchCount++;
- }
- }
- mRemainingSteps = remaining;
-
- if (!isCenterEnrollmentStage()) {
- if (mTargetAnimatorSet != null && mTargetAnimatorSet.isRunning()) {
- mTargetAnimatorSet.end();
- }
-
- final PointF point = getNextGuidedEnrollmentPoint();
- if (mCurrentX != point.x || mCurrentY != point.y) {
- final ValueAnimator x = ValueAnimator.ofFloat(mCurrentX, point.x);
- x.addUpdateListener(animation -> {
- mCurrentX = (float) animation.getAnimatedValue();
- invalidateSelf();
- });
-
- final ValueAnimator y = ValueAnimator.ofFloat(mCurrentY, point.y);
- y.addUpdateListener(animation -> {
- mCurrentY = (float) animation.getAnimatedValue();
- invalidateSelf();
- });
-
- final boolean isMovingToCenter = point.x == 0f && point.y == 0f;
- final long duration = isMovingToCenter
- ? TARGET_ANIM_DURATION_SHORT
- : TARGET_ANIM_DURATION_LONG;
-
- final ValueAnimator scale = ValueAnimator.ofFloat(0, (float) Math.PI);
- scale.setDuration(duration);
- scale.addUpdateListener(animation -> {
- // Grow then shrink
- mCurrentScale = 1
- + SCALE_MAX * (float) Math.sin((float) animation.getAnimatedValue());
- invalidateSelf();
- });
-
- mTargetAnimatorSet = new AnimatorSet();
-
- mTargetAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
- mTargetAnimatorSet.setDuration(duration);
- mTargetAnimatorSet.addListener(mTargetAnimListener);
- mTargetAnimatorSet.playTogether(x, y, scale);
- mTargetAnimatorSet.start();
- } else {
- updateTipHintVisibility();
- }
- } else {
- updateTipHintVisibility();
- }
-
- updateEdgeHintVisibility();
- }
-
- @Override
- public void draw(@NonNull Canvas canvas) {
- if (mSkipDraw) {
- return;
- }
-
- // Draw moving target
- if (!isCenterEnrollmentStage()) {
- canvas.save();
- canvas.translate(mCurrentX, mCurrentY);
-
- if (mSensorRect != null) {
- canvas.scale(mCurrentScale, mCurrentScale,
- mSensorRect.centerX(), mSensorRect.centerY());
- canvas.drawOval(mSensorRect, mBlueFill);
- }
-
- mMovingTargetFpIcon.draw(canvas);
- canvas.restore();
- } else {
- if (mSensorRect != null) {
- canvas.drawOval(mSensorRect, mSensorOutlinePaint);
- }
- mFingerprintDrawable.draw(canvas);
- mFingerprintDrawable.setAlpha(getAlpha());
- mSensorOutlinePaint.setAlpha(getAlpha());
- }
-
- }
-
- @Override
- public void setAlpha(int alpha) {
- mAlpha = alpha;
- mFingerprintDrawable.setAlpha(alpha);
- mSensorOutlinePaint.setAlpha(alpha);
- mBlueFill.setAlpha(alpha);
- mMovingTargetFpIcon.setAlpha(alpha);
- invalidateSelf();
- }
-
- @Override
- public int getAlpha() {
- return mAlpha;
- }
-
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) {
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- private void updateTipHintVisibility() {
- final boolean shouldShow = isTipEnrollmentStage();
- // With the new update, we will git rid of most of this code, and instead
- // we will change the fingerprint icon.
- if (mShouldShowTipHint == shouldShow) {
- return;
- }
- mShouldShowTipHint = shouldShow;
- }
-
- private void updateEdgeHintVisibility() {
- final boolean shouldShow = isEdgeEnrollmentStage();
- if (mShouldShowEdgeHint == shouldShow) {
- return;
- }
- mShouldShowEdgeHint = shouldShow;
- }
-
- private ShapeDrawable defaultFactory(Context context) {
- String fpPath = context.getResources().getString(R.string.config_udfpsIcon);
- ShapeDrawable drawable = new ShapeDrawable(
- new PathShape(PathParser.createPathFromPathData(fpPath), 72f, 72f)
- );
- drawable.mutate();
- drawable.getPaint().setStyle(Paint.Style.STROKE);
- drawable.getPaint().setStrokeCap(Paint.Cap.ROUND);
- drawable.getPaint().setStrokeWidth(DEFAULT_STROKE_WIDTH);
- return drawable;
- }
-
- private void loadResources(Context context, @Nullable AttributeSet attrs) {
- final TypedArray ta = context.obtainStyledAttributes(attrs,
- R.styleable.BiometricsEnrollView, R.attr.biometricsEnrollStyle,
- R.style.BiometricsEnrollStyle);
- mEnrollIcon = ta.getColor(R.styleable.BiometricsEnrollView_biometricsEnrollIcon, 0);
- mMovingTargetFill = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsMovingTargetFill, 0);
- ta.recycle();
- }
-
- private boolean isCenterEnrollmentStage() {
- if (mTotalSteps == -1 || mRemainingSteps == -1) {
- return true;
- }
- return mTotalSteps - mRemainingSteps < getStageThresholdSteps(mTotalSteps, 0);
- }
-
- private int getStageThresholdSteps(int totalSteps, int stageIndex) {
- return Math.round(totalSteps * mFingerprintManager.getEnrollStageThreshold(stageIndex));
- }
-
- private PointF getNextGuidedEnrollmentPoint() {
- if (mAccessibilityEnabled || !isGuidedEnrollmentStage()) {
- return new PointF(0f, 0f);
- }
-
- float scale = SCALE;
- if (Build.IS_ENG || Build.IS_USERDEBUG) {
- scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
- SCALE_OVERRIDE, SCALE,
- UserHandle.USER_CURRENT);
- }
- final int index = mLocationsEnrolled - mCenterTouchCount;
- final PointF originalPoint = mGuidedEnrollmentPoints
- .get(index % mGuidedEnrollmentPoints.size());
- return new PointF(originalPoint.x * scale, originalPoint.y * scale);
- }
-
- private boolean isGuidedEnrollmentStage() {
- if (mAccessibilityEnabled || mTotalSteps == -1 || mRemainingSteps == -1) {
- return false;
- }
- final int progressSteps = mTotalSteps - mRemainingSteps;
- return progressSteps >= getStageThresholdSteps(mTotalSteps, 0)
- && progressSteps < getStageThresholdSteps(mTotalSteps, 1);
- }
-
- private boolean isTipEnrollmentStage() {
- if (mTotalSteps == -1 || mRemainingSteps == -1) {
- return false;
- }
- final int progressSteps = mTotalSteps - mRemainingSteps;
- return progressSteps >= getStageThresholdSteps(mTotalSteps, 1)
- && progressSteps < getStageThresholdSteps(mTotalSteps, 2);
- }
-
- private boolean isEdgeEnrollmentStage() {
- if (mTotalSteps == -1 || mRemainingSteps == -1) {
- return false;
- }
- return mTotalSteps - mRemainingSteps >= getStageThresholdSteps(mTotalSteps, 2);
- }
-
- private void initEnrollPoint(Context context) {
- // Number of pixels per mm
- float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1,
- context.getResources().getDisplayMetrics());
- boolean useNewCoords = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- NEW_COORDS_OVERRIDE, 0,
- UserHandle.USER_CURRENT) != 0;
- if (useNewCoords && (Build.IS_ENG || Build.IS_USERDEBUG)) {
- Log.v(TAG, "Using new coordinates");
- mGuidedEnrollmentPoints.add(new PointF(-0.15f * px, -1.02f * px));
- mGuidedEnrollmentPoints.add(new PointF(-0.15f * px, 1.02f * px));
- mGuidedEnrollmentPoints.add(new PointF(0.29f * px, 0.00f * px));
- mGuidedEnrollmentPoints.add(new PointF(2.17f * px, -2.35f * px));
- mGuidedEnrollmentPoints.add(new PointF(1.07f * px, -3.96f * px));
- mGuidedEnrollmentPoints.add(new PointF(-0.37f * px, -4.31f * px));
- mGuidedEnrollmentPoints.add(new PointF(-1.69f * px, -3.29f * px));
- mGuidedEnrollmentPoints.add(new PointF(-2.48f * px, -1.23f * px));
- mGuidedEnrollmentPoints.add(new PointF(-2.48f * px, 1.23f * px));
- mGuidedEnrollmentPoints.add(new PointF(-1.69f * px, 3.29f * px));
- mGuidedEnrollmentPoints.add(new PointF(-0.37f * px, 4.31f * px));
- mGuidedEnrollmentPoints.add(new PointF(1.07f * px, 3.96f * px));
- mGuidedEnrollmentPoints.add(new PointF(2.17f * px, 2.35f * px));
- mGuidedEnrollmentPoints.add(new PointF(2.58f * px, 0.00f * px));
- } else {
- Log.v(TAG, "Using old coordinates");
- mGuidedEnrollmentPoints.add(new PointF(2.00f * px, 0.00f * px));
- mGuidedEnrollmentPoints.add(new PointF(0.87f * px, -2.70f * px));
- mGuidedEnrollmentPoints.add(new PointF(-1.80f * px, -1.31f * px));
- mGuidedEnrollmentPoints.add(new PointF(-1.80f * px, 1.31f * px));
- mGuidedEnrollmentPoints.add(new PointF(0.88f * px, 2.70f * px));
- mGuidedEnrollmentPoints.add(new PointF(3.94f * px, -1.06f * px));
- mGuidedEnrollmentPoints.add(new PointF(2.90f * px, -4.14f * px));
- mGuidedEnrollmentPoints.add(new PointF(-0.52f * px, -5.95f * px));
- mGuidedEnrollmentPoints.add(new PointF(-3.33f * px, -3.33f * px));
- mGuidedEnrollmentPoints.add(new PointF(-3.99f * px, -0.35f * px));
- mGuidedEnrollmentPoints.add(new PointF(-3.62f * px, 2.54f * px));
- mGuidedEnrollmentPoints.add(new PointF(-1.49f * px, 5.57f * px));
- mGuidedEnrollmentPoints.add(new PointF(2.29f * px, 4.92f * px));
- mGuidedEnrollmentPoints.add(new PointF(3.82f * px, 1.78f * px));
- }
- }
-
-}
diff --git a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollProgressBarDrawable.java b/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollProgressBarDrawable.java
deleted file mode 100644
index 8cb4bb2..0000000
--- a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollProgressBarDrawable.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * 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.biometrics2.ui.widget;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
-import android.os.Process;
-import android.os.VibrationAttributes;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.OvershootInterpolator;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
-
-/**
- * UDFPS enrollment progress bar.
- */
-public class UdfpsEnrollProgressBarDrawable extends Drawable {
- private static final String TAG = "UdfpsProgressBar";
-
- private static final long CHECKMARK_ANIMATION_DELAY_MS = 200L;
- private static final long CHECKMARK_ANIMATION_DURATION_MS = 300L;
- private static final long FILL_COLOR_ANIMATION_DURATION_MS = 350L;
- private static final long PROGRESS_ANIMATION_DURATION_MS = 400L;
- private static final float STROKE_WIDTH_DP = 12f;
- private static final Interpolator DEACCEL = new DecelerateInterpolator();
-
- private static final VibrationEffect VIBRATE_EFFECT_ERROR =
- VibrationEffect.createWaveform(new long[]{0, 5, 55, 60}, -1);
- private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
- VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY);
-
- private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
- VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
-
- private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
- VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
-
- private final float mStrokeWidthPx;
- @ColorInt
- private final int mProgressColor;
- @ColorInt
- private final int mHelpColor;
- @ColorInt
- private final int mOnFirstBucketFailedColor;
- @NonNull
- private final Drawable mCheckmarkDrawable;
- @NonNull
- private final Interpolator mCheckmarkInterpolator;
- @NonNull
- private final Paint mBackgroundPaint;
- @VisibleForTesting
- @NonNull
- final Paint mFillPaint;
- @NonNull
- private final Vibrator mVibrator;
- @NonNull
- private final boolean mIsAccessibilityEnabled;
- @NonNull
- private final Context mContext;
-
- private boolean mAfterFirstTouch;
-
- private int mRemainingSteps = 0;
- private int mTotalSteps = 0;
- private float mProgress = 0f;
- @Nullable
- private ValueAnimator mProgressAnimator;
- @NonNull
- private final ValueAnimator.AnimatorUpdateListener mProgressUpdateListener;
-
- private boolean mShowingHelp = false;
- @Nullable
- private ValueAnimator mFillColorAnimator;
- @NonNull
- private final ValueAnimator.AnimatorUpdateListener mFillColorUpdateListener;
-
- @Nullable
- private ValueAnimator mBackgroundColorAnimator;
- @NonNull
- private final ValueAnimator.AnimatorUpdateListener mBackgroundColorUpdateListener;
-
- private boolean mComplete = false;
- private float mCheckmarkScale = 0f;
- @Nullable
- private ValueAnimator mCheckmarkAnimator;
- @NonNull
- private final ValueAnimator.AnimatorUpdateListener mCheckmarkUpdateListener;
-
- private int mMovingTargetFill;
- private int mMovingTargetFillError;
- private int mEnrollProgress;
- private int mEnrollProgressHelp;
- private int mEnrollProgressHelpWithTalkback;
-
- public UdfpsEnrollProgressBarDrawable(@NonNull Context context, @Nullable AttributeSet attrs) {
- mContext = context;
-
- loadResources(context, attrs);
- float density = context.getResources().getDisplayMetrics().densityDpi;
- mStrokeWidthPx = STROKE_WIDTH_DP * (density / DisplayMetrics.DENSITY_DEFAULT);
- mProgressColor = mEnrollProgress;
- final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
- mIsAccessibilityEnabled = am.isTouchExplorationEnabled();
- mOnFirstBucketFailedColor = mMovingTargetFillError;
- if (!mIsAccessibilityEnabled) {
- mHelpColor = mEnrollProgressHelp;
- } else {
- mHelpColor = mEnrollProgressHelpWithTalkback;
- }
- mCheckmarkDrawable = context.getDrawable(R.drawable.udfps_enroll_checkmark);
- mCheckmarkDrawable.mutate();
- mCheckmarkInterpolator = new OvershootInterpolator();
-
- mBackgroundPaint = new Paint();
- mBackgroundPaint.setStrokeWidth(mStrokeWidthPx);
- mBackgroundPaint.setColor(mMovingTargetFill);
- mBackgroundPaint.setAntiAlias(true);
- mBackgroundPaint.setStyle(Paint.Style.STROKE);
- mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);
-
- // Progress fill should *not* use the extracted system color.
- mFillPaint = new Paint();
- mFillPaint.setStrokeWidth(mStrokeWidthPx);
- mFillPaint.setColor(mProgressColor);
- mFillPaint.setAntiAlias(true);
- mFillPaint.setStyle(Paint.Style.STROKE);
- mFillPaint.setStrokeCap(Paint.Cap.ROUND);
-
- mVibrator = mContext.getSystemService(Vibrator.class);
-
- mProgressUpdateListener = animation -> {
- mProgress = (float) animation.getAnimatedValue();
- invalidateSelf();
- };
-
- mFillColorUpdateListener = animation -> {
- mFillPaint.setColor((int) animation.getAnimatedValue());
- invalidateSelf();
- };
-
- mCheckmarkUpdateListener = animation -> {
- mCheckmarkScale = (float) animation.getAnimatedValue();
- invalidateSelf();
- };
-
- mBackgroundColorUpdateListener = animation -> {
- mBackgroundPaint.setColor((int) animation.getAnimatedValue());
- invalidateSelf();
- };
- }
-
- void onEnrollmentProgress(final int remaining, final int totalSteps) {
- mAfterFirstTouch = true;
- updateState(remaining, totalSteps, false /* showingHelp */);
- }
-
- void onEnrollmentHelp(int remaining, int totalSteps) {
- updateState(remaining, totalSteps, true /* showingHelp */);
- }
-
- void onLastStepAcquired() {
- updateState(0, mTotalSteps, false /* showingHelp */);
- }
-
- private void updateState(int remainingSteps, int totalSteps, boolean showingHelp) {
- updateProgress(remainingSteps, totalSteps, showingHelp);
- updateFillColor(showingHelp);
- }
-
- private void updateProgress(int remainingSteps, int totalSteps, boolean showingHelp) {
- if (mRemainingSteps == remainingSteps && mTotalSteps == totalSteps) {
- return;
- }
-
- if (mShowingHelp) {
- if (mVibrator != null && mIsAccessibilityEnabled) {
- mVibrator.vibrate(Process.myUid(), mContext.getOpPackageName(),
- VIBRATE_EFFECT_ERROR, getClass().getSimpleName() + "::onEnrollmentHelp",
- FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
- }
- } else {
- // If the first touch is an error, remainingSteps will be -1 and the callback
- // doesn't come from onEnrollmentHelp. If we are in the accessibility flow,
- // we still would like to vibrate.
- if (mVibrator != null) {
- if (remainingSteps == -1 && mIsAccessibilityEnabled) {
- mVibrator.vibrate(Process.myUid(), mContext.getOpPackageName(),
- VIBRATE_EFFECT_ERROR,
- getClass().getSimpleName() + "::onFirstTouchError",
- FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
- } else if (remainingSteps != -1 && !mIsAccessibilityEnabled) {
- mVibrator.vibrate(Process.myUid(),
- mContext.getOpPackageName(),
- SUCCESS_VIBRATION_EFFECT,
- getClass().getSimpleName() + "::OnEnrollmentProgress",
- HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
- }
- }
- }
-
- mShowingHelp = showingHelp;
- mRemainingSteps = remainingSteps;
- mTotalSteps = totalSteps;
-
- final int progressSteps = Math.max(0, totalSteps - remainingSteps);
-
- // If needed, add 1 to progress and total steps to account for initial touch.
- final int adjustedSteps = mAfterFirstTouch ? progressSteps + 1 : progressSteps;
- final int adjustedTotal = mAfterFirstTouch ? mTotalSteps + 1 : mTotalSteps;
-
- final float targetProgress = Math.min(1f, (float) adjustedSteps / (float) adjustedTotal);
-
- if (mProgressAnimator != null && mProgressAnimator.isRunning()) {
- mProgressAnimator.cancel();
- }
-
- mProgressAnimator = ValueAnimator.ofFloat(mProgress, targetProgress);
- mProgressAnimator.setDuration(PROGRESS_ANIMATION_DURATION_MS);
- mProgressAnimator.addUpdateListener(mProgressUpdateListener);
- mProgressAnimator.start();
-
- if (remainingSteps == 0) {
- startCompletionAnimation();
- } else if (remainingSteps > 0) {
- rollBackCompletionAnimation();
- }
- }
-
- private void animateBackgroundColor() {
- if (mBackgroundColorAnimator != null && mBackgroundColorAnimator.isRunning()) {
- mBackgroundColorAnimator.end();
- }
- mBackgroundColorAnimator = ValueAnimator.ofArgb(mBackgroundPaint.getColor(),
- mOnFirstBucketFailedColor);
- mBackgroundColorAnimator.setDuration(FILL_COLOR_ANIMATION_DURATION_MS);
- mBackgroundColorAnimator.setRepeatCount(1);
- mBackgroundColorAnimator.setRepeatMode(ValueAnimator.REVERSE);
- mBackgroundColorAnimator.setInterpolator(DEACCEL);
- mBackgroundColorAnimator.addUpdateListener(mBackgroundColorUpdateListener);
- mBackgroundColorAnimator.start();
- }
-
- private void updateFillColor(boolean showingHelp) {
- if (!mAfterFirstTouch && showingHelp) {
- // If we are on the first touch, animate the background color
- // instead of the progress color.
- animateBackgroundColor();
- return;
- }
-
- if (mFillColorAnimator != null && mFillColorAnimator.isRunning()) {
- mFillColorAnimator.end();
- }
-
- @ColorInt final int targetColor = showingHelp ? mHelpColor : mProgressColor;
- mFillColorAnimator = ValueAnimator.ofArgb(mFillPaint.getColor(), targetColor);
- mFillColorAnimator.setDuration(FILL_COLOR_ANIMATION_DURATION_MS);
- mFillColorAnimator.setRepeatCount(1);
- mFillColorAnimator.setRepeatMode(ValueAnimator.REVERSE);
- mFillColorAnimator.setInterpolator(DEACCEL);
- mFillColorAnimator.addUpdateListener(mFillColorUpdateListener);
- mFillColorAnimator.start();
- }
-
- private void startCompletionAnimation() {
- if (mComplete) {
- return;
- }
- mComplete = true;
-
- if (mCheckmarkAnimator != null && mCheckmarkAnimator.isRunning()) {
- mCheckmarkAnimator.cancel();
- }
-
- mCheckmarkAnimator = ValueAnimator.ofFloat(mCheckmarkScale, 1f);
- mCheckmarkAnimator.setStartDelay(CHECKMARK_ANIMATION_DELAY_MS);
- mCheckmarkAnimator.setDuration(CHECKMARK_ANIMATION_DURATION_MS);
- mCheckmarkAnimator.setInterpolator(mCheckmarkInterpolator);
- mCheckmarkAnimator.addUpdateListener(mCheckmarkUpdateListener);
- mCheckmarkAnimator.start();
- }
-
- private void rollBackCompletionAnimation() {
- if (!mComplete) {
- return;
- }
- mComplete = false;
-
- // Adjust duration based on how much of the completion animation has played.
- final float animatedFraction = mCheckmarkAnimator != null
- ? mCheckmarkAnimator.getAnimatedFraction()
- : 0f;
- final long durationMs = Math.round(CHECKMARK_ANIMATION_DELAY_MS * animatedFraction);
-
- if (mCheckmarkAnimator != null && mCheckmarkAnimator.isRunning()) {
- mCheckmarkAnimator.cancel();
- }
-
- mCheckmarkAnimator = ValueAnimator.ofFloat(mCheckmarkScale, 0f);
- mCheckmarkAnimator.setDuration(durationMs);
- mCheckmarkAnimator.addUpdateListener(mCheckmarkUpdateListener);
- mCheckmarkAnimator.start();
- }
-
- private void loadResources(Context context, @Nullable AttributeSet attrs) {
- final TypedArray ta = context.obtainStyledAttributes(attrs,
- R.styleable.BiometricsEnrollView, R.attr.biometricsEnrollStyle,
- R.style.BiometricsEnrollStyle);
- mMovingTargetFill = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsMovingTargetFill, 0);
- mMovingTargetFillError = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsMovingTargetFillError, 0);
- mEnrollProgress = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsEnrollProgress, 0);
- mEnrollProgressHelp = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsEnrollProgressHelp, 0);
- mEnrollProgressHelpWithTalkback = ta.getColor(
- R.styleable.BiometricsEnrollView_biometricsEnrollProgressHelpWithTalkback, 0);
- ta.recycle();
- }
-
- @Override
- public void draw(@NonNull Canvas canvas) {
- canvas.save();
-
- // Progress starts from the top, instead of the right
- canvas.rotate(-90f, getBounds().centerX(), getBounds().centerY());
-
- final float halfPaddingPx = mStrokeWidthPx / 2f;
-
- if (mProgress < 1f) {
- // Draw the background color of the progress circle.
- canvas.drawArc(
- halfPaddingPx,
- halfPaddingPx,
- getBounds().right - halfPaddingPx,
- getBounds().bottom - halfPaddingPx,
- 0f /* startAngle */,
- 360f /* sweepAngle */,
- false /* useCenter */,
- mBackgroundPaint);
- }
-
- if (mProgress > 0f) {
- // Draw the filled portion of the progress circle.
- canvas.drawArc(
- halfPaddingPx,
- halfPaddingPx,
- getBounds().right - halfPaddingPx,
- getBounds().bottom - halfPaddingPx,
- 0f /* startAngle */,
- 360f * mProgress /* sweepAngle */,
- false /* useCenter */,
- mFillPaint);
- }
-
- canvas.restore();
-
- if (mCheckmarkScale > 0f) {
- final float offsetScale = (float) Math.sqrt(2) / 2f;
- final float centerXOffset = (getBounds().width() - mStrokeWidthPx) / 2f * offsetScale;
- final float centerYOffset = (getBounds().height() - mStrokeWidthPx) / 2f * offsetScale;
- final float centerX = getBounds().centerX() + centerXOffset;
- final float centerY = getBounds().centerY() + centerYOffset;
-
- final float boundsXOffset =
- mCheckmarkDrawable.getIntrinsicWidth() / 2f * mCheckmarkScale;
- final float boundsYOffset =
- mCheckmarkDrawable.getIntrinsicHeight() / 2f * mCheckmarkScale;
-
- final int left = Math.round(centerX - boundsXOffset);
- final int top = Math.round(centerY - boundsYOffset);
- final int right = Math.round(centerX + boundsXOffset);
- final int bottom = Math.round(centerY + boundsYOffset);
- mCheckmarkDrawable.setBounds(left, top, right, bottom);
- mCheckmarkDrawable.draw(canvas);
- }
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) {
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollView.java b/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollView.java
deleted file mode 100644
index c99cb2d..0000000
--- a/src/com/android/settings/biometrics2/ui/widget/UdfpsEnrollView.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.biometrics2.ui.widget;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.RotationUtils;
-import android.view.DisplayInfo;
-import android.view.Surface;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.settings.R;
-import com.android.systemui.biometrics.UdfpsUtils;
-import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
-
-/**
- * View corresponding with udfps_enroll_view.xml
- */
-public class UdfpsEnrollView extends FrameLayout {
- private static final String TAG = "UdfpsEnrollView";
- @NonNull
- private final UdfpsEnrollDrawable mFingerprintDrawable;
- @NonNull
- private final UdfpsEnrollProgressBarDrawable mFingerprintProgressDrawable;
- @NonNull
- private final Handler mHandler;
-
- @NonNull
- private ImageView mFingerprintProgressView;
- private UdfpsUtils mUdfpsUtils;
-
- private int mProgressBarRadius;
-
- private Rect mSensorRect;
- private UdfpsOverlayParams mOverlayParams;
- private FingerprintSensorPropertiesInternal mSensorProperties;
-
- private int mTotalSteps = -1;
- private int mRemainingSteps = -1;
- private int mLocationsEnrolled = 0;
- private int mCenterTouchCount = 0;
-
- public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
- mFingerprintProgressDrawable = new UdfpsEnrollProgressBarDrawable(context, attrs);
- mHandler = new Handler(Looper.getMainLooper());
- mUdfpsUtils = new UdfpsUtils();
- }
-
- @Override
- protected void onFinishInflate() {
- ImageView fingerprintView = findViewById(R.id.udfps_enroll_animation_fp_view);
- fingerprintView.setImageDrawable(mFingerprintDrawable);
- mFingerprintProgressView = findViewById(R.id.udfps_enroll_animation_fp_progress_view);
- mFingerprintProgressView.setImageDrawable(mFingerprintProgressDrawable);
- }
-
- /**
- * Receive enroll progress information from FingerprintEnrollEnrollingUdfpsFragment
- */
- public void onEnrollmentProgress(int remaining, int totalSteps) {
- if (mTotalSteps == -1) {
- mTotalSteps = totalSteps;
- }
- mRemainingSteps = remaining;
- mHandler.post(() -> {
- mFingerprintProgressDrawable.onEnrollmentProgress(remaining, totalSteps);
- mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps);
- });
- }
-
- /**
- * Receive enroll help information from FingerprintEnrollEnrollingUdfpsFragment
- */
- public void onEnrollmentHelp() {
- mHandler.post(
- () -> mFingerprintProgressDrawable.onEnrollmentHelp(mRemainingSteps, mTotalSteps));
- }
-
- /**
- * Receive onAcquired from FingerprintEnrollEnrollingUdfpsFragment
- */
- public void onAcquired(boolean isAcquiredGood) {
- final boolean animateIfLastStepGood =
- isAcquiredGood && (mRemainingSteps <= 2 && mRemainingSteps >= 0);
- mHandler.post(() -> {
- onFingerUp();
- if (animateIfLastStepGood) mFingerprintProgressDrawable.onLastStepAcquired();
- });
- }
-
- /**
- * Receive onPointerDown from FingerprintEnrollEnrollingUdfpsFragment
- */
- public void onPointerDown(int sensorId) {
- onFingerDown();
- }
-
- /**
- * Receive onPointerUp from FingerprintEnrollEnrollingUdfpsFragment
- */
- public void onPointerUp(int sensorId) {
- onFingerUp();
- }
-
- private final ViewTreeObserver.OnDrawListener mOnDrawListener = this::updateOverlayParams;
-
- /**
- * setup SensorProperties
- */
- public void setSensorProperties(FingerprintSensorPropertiesInternal properties) {
- mSensorProperties = properties;
- ((ViewGroup) getParent()).getViewTreeObserver().addOnDrawListener(mOnDrawListener);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- final ViewGroup parent = (ViewGroup) getParent();
- if (parent != null) {
- final ViewTreeObserver observer = parent.getViewTreeObserver();
- if (observer != null) {
- observer.removeOnDrawListener(mOnDrawListener);
- }
- }
- super.onDetachedFromWindow();
- }
-
- private void onSensorRectUpdated() {
- updateDimensions();
-
- // Updates sensor rect in relation to the overlay view
- mSensorRect.set(getPaddingX(), getPaddingY(),
- (mOverlayParams.getSensorBounds().width() + getPaddingX()),
- (mOverlayParams.getSensorBounds().height() + getPaddingY()));
- mFingerprintDrawable.onSensorRectUpdated(new RectF(mSensorRect));
- }
-
- private void updateDimensions() {
- // Original sensorBounds assume portrait mode.
- final Rect rotatedBounds = new Rect(mOverlayParams.getSensorBounds());
- int rotation = mOverlayParams.getRotation();
- if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
- RotationUtils.rotateBounds(
- rotatedBounds,
- mOverlayParams.getNaturalDisplayWidth(),
- mOverlayParams.getNaturalDisplayHeight(),
- rotation
- );
- }
-
- RelativeLayout parent = ((RelativeLayout) getParent());
- if (parent == null) {
- Log.e(TAG, "Fail to updateDimensions for " + this + ", parent null");
- return;
- }
- final int[] coords = parent.getLocationOnScreen();
- final int parentLeft = coords[0];
- final int parentTop = coords[1];
- final int parentRight = parentLeft + parent.getWidth();
- final int parentBottom = parentTop + parent.getHeight();
-
-
- RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(getWidth(),
- getHeight());
- if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
- params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- params.rightMargin = parentRight - rotatedBounds.right - getPaddingX();
- params.topMargin = rotatedBounds.top - parentTop - getPaddingY();
- } else {
- if (rotation == Surface.ROTATION_90) {
- params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- params.rightMargin = parentRight - rotatedBounds.right - getPaddingX();
- params.bottomMargin = parentBottom - rotatedBounds.bottom - getPaddingY();
- } else {
- params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
- params.bottomMargin = parentBottom - rotatedBounds.bottom - getPaddingY();
- params.leftMargin = rotatedBounds.left - parentLeft - getPaddingX();
- }
- }
- params.height = rotatedBounds.height() + 2 * getPaddingX();
- params.width = rotatedBounds.width() + 2 * getPaddingY();
- setLayoutParams(params);
- }
-
- private void onFingerDown() {
- mFingerprintDrawable.setShouldSkipDraw(true);
- mFingerprintDrawable.invalidateSelf();
- }
-
- private void onFingerUp() {
- mFingerprintDrawable.setShouldSkipDraw(false);
- mFingerprintDrawable.invalidateSelf();
- }
-
- private int getPaddingX() {
- return mProgressBarRadius;
- }
-
- private int getPaddingY() {
- return mProgressBarRadius;
- }
-
- private void updateOverlayParams() {
-
- if (mSensorProperties == null) {
- android.util.Log.e(TAG, "There is no sensor info!");
- return;
- }
-
- DisplayInfo displayInfo = new DisplayInfo();
- if (getDisplay() == null) {
- android.util.Log.e(TAG, "Can not get display");
- return;
- }
- getDisplay().getDisplayInfo(displayInfo);
- Rect udfpsBounds = mSensorProperties.getLocation().getRect();
- float scaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
- udfpsBounds.scale(scaleFactor);
-
- final Rect overlayBounds = new Rect(
- 0, /* left */
- displayInfo.getNaturalHeight() / 2, /* top */
- displayInfo.getNaturalWidth(), /* right */
- displayInfo.getNaturalHeight() /* botom */);
-
- mOverlayParams = new UdfpsOverlayParams(
- udfpsBounds,
- overlayBounds,
- displayInfo.getNaturalWidth(),
- displayInfo.getNaturalHeight(),
- scaleFactor,
- displayInfo.rotation,
- mSensorProperties.sensorType);
-
- post(() -> {
- mProgressBarRadius =
- (int) (mOverlayParams.getScaleFactor() * getContext().getResources().getInteger(
- R.integer.config_udfpsEnrollProgressBar));
- mSensorRect = new Rect(mOverlayParams.getSensorBounds());
-
- onSensorRectUpdated();
- });
-
- }
-}
-
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 3fa811a..2e5daeb 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -43,7 +43,6 @@
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HeadsetProfile;
-import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
@@ -95,6 +94,7 @@
new HashMap<String, List<CachedBluetoothDevice>>();
private boolean mIsLeContactSharingEnabled = false;
private boolean mIsLeAudioToggleEnabled = false;
+ private boolean mIsLeAudioOnlyDevice = false;
@VisibleForTesting
PreferenceCategory mProfilesContainer;
@@ -345,6 +345,11 @@
result.remove(mManager.getProfileManager().getA2dpProfile());
result.remove(mManager.getProfileManager().getHeadsetProfile());
}
+ boolean hearingAidSupported = result.contains(
+ mManager.getProfileManager().getHearingAidProfile());
+ if (leAudioSupported && !classicAudioSupported && !hearingAidSupported) {
+ mIsLeAudioOnlyDevice = true;
+ }
Log.d(TAG, "getProfiles:Map:" + mProfileDeviceMap);
return result;
}
@@ -513,19 +518,6 @@
refresh();
}
- private boolean isLeAudioOnlyDevice() {
- if (mCachedDevice.getProfiles().stream()
- .noneMatch(profile -> profile instanceof LeAudioProfile)) {
- return false;
- }
- return mCachedDevice.getProfiles().stream()
- .noneMatch(
- profile ->
- profile instanceof HearingAidProfile
- || profile instanceof A2dpProfile
- || profile instanceof HeadsetProfile);
- }
-
private void updateLeAudioConfig() {
mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
@@ -534,7 +526,7 @@
boolean isLeEnabledByDefault =
SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true);
mIsLeAudioToggleEnabled = isLeAudioToggleVisible || isLeEnabledByDefault;
- if (Flags.hideLeAudioToggleForLeAudioOnlyDevice() && isLeAudioOnlyDevice()) {
+ if (Flags.hideLeAudioToggleForLeAudioOnlyDevice() && mIsLeAudioOnlyDevice) {
mIsLeAudioToggleEnabled = false;
Log.d(
TAG,
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index ffc97dc..791b629 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -52,6 +52,7 @@
import android.util.Pair;
import android.widget.Toast;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
@@ -63,6 +64,7 @@
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
+import com.android.settings.flags.Flags;
import com.android.settings.homepage.TopLevelHighlightMixin;
import com.android.settings.homepage.TopLevelSettings;
import com.android.settings.overlay.FeatureFactory;
@@ -413,13 +415,23 @@
METHOD_GET_PROVIDER_ICON);
final Pair<String, Integer> iconInfo = TileUtils.getIconFromUri(
mContext, packageName, uri, providerMap);
- if (iconInfo == null) {
+ final Icon icon;
+ if (iconInfo != null) {
+ icon = Icon.createWithResource(iconInfo.first, iconInfo.second);
+ } else if (Flags.supportRawDynamicIcons()) {
+ icon = TileUtils.getRawIconFromUri(mContext, uri, providerMap);
+ } else {
+ icon = null;
+ }
+ if (icon == null) {
Log.w(TAG, "Failed to get icon from uri " + uri);
return;
}
- final Icon icon = Icon.createWithResource(iconInfo.first, iconInfo.second);
+
+ final String iconPackage = (iconInfo != null) ? iconInfo.first : null;
+
ThreadUtils.postOnMainThread(() -> {
- setPreferenceIcon(preference, tile, forceRoundedIcon, iconInfo.first, icon);
+ setPreferenceIcon(preference, tile, forceRoundedIcon, iconPackage, icon);
});
});
return;
@@ -435,14 +447,21 @@
}
private void setPreferenceIcon(Preference preference, Tile tile, boolean forceRoundedIcon,
- String iconPackage, Icon icon) {
+ @Nullable String iconPackage, Icon icon) {
Drawable iconDrawable = icon.loadDrawable(preference.getContext());
if (iconDrawable == null) {
Log.w(TAG, "Set null preference icon for: " + iconPackage);
preference.setIcon(null);
return;
}
+ // Tint homepage icons
if (TextUtils.equals(tile.getCategory(), CategoryKey.CATEGORY_HOMEPAGE)) {
+ // Skip tinting and Adaptive Icon transformation for homepage account type raw icons
+ if (TextUtils.equals(tile.getGroupKey(), "top_level_account_category")
+ && iconPackage == null) {
+ preference.setIcon(iconDrawable);
+ return;
+ }
iconDrawable.setTint(Utils.getHomepageIconColor(preference.getContext()));
}
diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt
index 675d789..84b82cb 100644
--- a/src/com/android/settings/overlay/FeatureFactory.kt
+++ b/src/com/android/settings/overlay/FeatureFactory.kt
@@ -22,7 +22,6 @@
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
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider
@@ -119,11 +118,6 @@
abstract val fingerprintFeatureProvider: FingerprintFeatureProvider
/**
- * Gets implementation for Biometrics repository provider.
- */
- abstract val biometricsRepositoryProvider: BiometricsRepositoryProvider
-
- /**
* Gets implementation for the WifiTrackerLib.
*/
abstract val wifiTrackerLibProvider: WifiTrackerLibProvider
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt
index 2142ea5..a21d7e3 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt
@@ -31,7 +31,6 @@
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
import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl
@@ -152,8 +151,6 @@
FingerprintFeatureProviderImpl()
}
- override val biometricsRepositoryProvider by lazy { BiometricsRepositoryProviderImpl() }
-
override val wifiTrackerLibProvider: WifiTrackerLibProvider by lazy {
WifiTrackerLibProviderImpl()
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 1213b0d..42a74dd 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -44,6 +44,7 @@
import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.TargetInfo;
import com.android.settings.R;
+import com.android.settings.flags.Flags;
import com.android.settingslib.qrcode.QrCodeGenerator;
import com.google.zxing.WriterException;
@@ -69,6 +70,10 @@
@Override
public int getMetricsCategory() {
+ if (Flags.enableWifiSharingRuntimeFragment()) {
+ return SettingsEnums.SETTINGS_WIFI_DPP_QR_SHARING;
+ }
+
return SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR;
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
index 9b92234..2d1f4c0 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
@@ -90,6 +90,9 @@
@Mock
private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
+ private @Mock A2dpProfile mA2dpProfile;
+ private @Mock LeAudioProfile mLeAudioProfile;
+
@Override
public void setUp() {
super.setUp();
@@ -103,11 +106,13 @@
mConnectableProfiles = new ArrayList<>();
when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedBluetoothDeviceManager);
+ setUpMockProfiles();
when(mCachedBluetoothDeviceManager.getCachedDevicesCopy())
.thenReturn(ImmutableList.of(mCachedDevice));
- when(mCachedDevice.getConnectableProfiles()).thenAnswer(invocation ->
- new ArrayList<>(mConnectableProfiles)
- );
+ when(mCachedDevice.getConnectableProfiles())
+ .thenAnswer(invocation -> new ArrayList<>(mConnectableProfiles));
+ when(mCachedDevice.getProfiles())
+ .thenAnswer(invocation -> ImmutableList.of(mConnectableProfiles));
setupDevice(mDeviceConfig);
mController = new BluetoothDetailsProfilesController(mContext, mFragment, mLocalManager,
@@ -389,21 +394,36 @@
assertThat(mDevice.getMessageAccessPermission()).isEqualTo(BluetoothDevice.ACCESS_ALLOWED);
}
- private A2dpProfile addMockA2dpProfile(boolean preferred, boolean supportsHighQualityAudio,
- boolean highQualityAudioEnabled) {
- A2dpProfile profile = mock(A2dpProfile.class);
- when(mProfileManager.getProfileByName(eq(profile.toString()))).thenReturn(profile);
- when(profile.getNameResource(mDevice))
+ private void setUpMockProfiles() {
+ when(mA2dpProfile.toString()).thenReturn("A2DP");
+ when(mProfileManager.getProfileByName(eq(mA2dpProfile.toString())))
+ .thenReturn(mA2dpProfile);
+ when(mA2dpProfile.getNameResource(any()))
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_a2dp);
- when(profile.getHighQualityAudioOptionLabel(mDevice)).thenReturn(
+ when(mA2dpProfile.getHighQualityAudioOptionLabel(any())).thenReturn(
mContext.getString(com.android.settingslib.R
.string.bluetooth_profile_a2dp_high_quality_unknown_codec));
- when(profile.supportsHighQualityAudio(mDevice)).thenReturn(supportsHighQualityAudio);
- when(profile.isHighQualityAudioEnabled(mDevice)).thenReturn(highQualityAudioEnabled);
- when(profile.isEnabled(mDevice)).thenReturn(preferred);
- when(profile.isProfileReady()).thenReturn(true);
- mConnectableProfiles.add(profile);
- return profile;
+ when(mA2dpProfile.isProfileReady()).thenReturn(true);
+ when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
+
+ when(mLeAudioProfile.toString()).thenReturn("LE_AUDIO");
+ when(mLeAudioProfile.getNameResource(any()))
+ .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
+ when(mLeAudioProfile.isProfileReady()).thenReturn(true);
+ when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
+ }
+
+ private void addA2dpProfileToDevice(boolean preferred, boolean supportsHighQualityAudio,
+ boolean highQualityAudioEnabled) {
+ when(mA2dpProfile.supportsHighQualityAudio(any())).thenReturn(supportsHighQualityAudio);
+ when(mA2dpProfile.isHighQualityAudioEnabled(any())).thenReturn(highQualityAudioEnabled);
+ when(mA2dpProfile.isEnabled(any())).thenReturn(preferred);
+ mConnectableProfiles.add(mA2dpProfile);
+ }
+
+ private void addLeAudioProfileToDevice(boolean enabled) {
+ when(mLeAudioProfile.isEnabled(any())).thenReturn(enabled);
+ mConnectableProfiles.add(mLeAudioProfile);
}
private SwitchPreferenceCompat getHighQualityAudioPref() {
@@ -414,7 +434,7 @@
@Test
public void highQualityAudio_prefIsPresentWhenSupported() {
setupDevice(makeDefaultDeviceConfig());
- addMockA2dpProfile(true, true, true);
+ addA2dpProfileToDevice(true, true, true);
showScreen(mController);
SwitchPreferenceCompat pref = getHighQualityAudioPref();
assertThat(pref.getKey()).isEqualTo(
@@ -431,7 +451,7 @@
@Test
public void highQualityAudio_prefIsAbsentWhenNotSupported() {
setupDevice(makeDefaultDeviceConfig());
- addMockA2dpProfile(true, false, false);
+ addA2dpProfileToDevice(true, false, false);
showScreen(mController);
assertThat(mProfiles.getPreferenceCount()).isEqualTo(2);
SwitchPreferenceCompat pref = (SwitchPreferenceCompat) mProfiles.getPreference(0);
@@ -444,7 +464,7 @@
@Test
public void highQualityAudio_busyDeviceDisablesSwitch() {
setupDevice(makeDefaultDeviceConfig());
- addMockA2dpProfile(true, true, true);
+ addA2dpProfileToDevice(true, true, true);
when(mCachedDevice.isBusy()).thenReturn(true);
showScreen(mController);
SwitchPreferenceCompat pref = getHighQualityAudioPref();
@@ -454,17 +474,17 @@
@Test
public void highQualityAudio_mediaAudioDisabledAndReEnabled() {
setupDevice(makeDefaultDeviceConfig());
- A2dpProfile audioProfile = addMockA2dpProfile(true, true, true);
+ addA2dpProfileToDevice(true, true, true);
showScreen(mController);
assertThat(mProfiles.getPreferenceCount()).isEqualTo(3);
// Disabling media audio should cause the high quality audio switch to disappear, but not
// the regular audio one.
SwitchPreferenceCompat audioPref =
- (SwitchPreferenceCompat) mScreen.findPreference(audioProfile.toString());
+ (SwitchPreferenceCompat) mScreen.findPreference(mA2dpProfile.toString());
audioPref.performClick();
- verify(audioProfile).setEnabled(mDevice, false);
- when(audioProfile.isEnabled(mDevice)).thenReturn(false);
+ verify(mA2dpProfile).setEnabled(mDevice, false);
+ when(mA2dpProfile.isEnabled(mDevice)).thenReturn(false);
mController.onDeviceAttributesChanged();
assertThat(audioPref.isVisible()).isTrue();
SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
@@ -472,8 +492,8 @@
// And re-enabling media audio should make high quality switch to reappear.
audioPref.performClick();
- verify(audioProfile).setEnabled(mDevice, true);
- when(audioProfile.isEnabled(mDevice)).thenReturn(true);
+ verify(mA2dpProfile).setEnabled(mDevice, true);
+ when(mA2dpProfile.isEnabled(mDevice)).thenReturn(true);
mController.onDeviceAttributesChanged();
highQualityAudioPref = getHighQualityAudioPref();
assertThat(highQualityAudioPref.isVisible()).isTrue();
@@ -482,9 +502,9 @@
@Test
public void highQualityAudio_mediaAudioStartsDisabled() {
setupDevice(makeDefaultDeviceConfig());
- A2dpProfile audioProfile = addMockA2dpProfile(false, true, true);
+ addA2dpProfileToDevice(false, true, true);
showScreen(mController);
- SwitchPreferenceCompat audioPref = mScreen.findPreference(audioProfile.toString());
+ SwitchPreferenceCompat audioPref = mScreen.findPreference(mA2dpProfile.toString());
SwitchPreferenceCompat highQualityAudioPref = getHighQualityAudioPref();
assertThat(audioPref).isNotNull();
assertThat(audioPref.isChecked()).isFalse();
@@ -522,15 +542,9 @@
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
setupDevice(makeDefaultDeviceConfig());
- LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
- when(leAudioProfile.getNameResource(mDevice))
- .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
- when(leAudioProfile.isProfileReady()).thenReturn(true);
- when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
- when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
+ addA2dpProfileToDevice(true, true, true);
when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
- .thenReturn(ImmutableSet.of("LE_AUDIO"));
- mConnectableProfiles.add(leAudioProfile);
+ .thenReturn(ImmutableSet.of("A2DP"));
showScreen(mController);
@@ -543,15 +557,9 @@
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_BLUETOOTH_PROFILE_TOGGLE_VISIBILITY_CHECKER);
setupDevice(makeDefaultDeviceConfig());
- LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
- when(leAudioProfile.getNameResource(mDevice))
- .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
- when(leAudioProfile.isProfileReady()).thenReturn(true);
- when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
- when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
+ addA2dpProfileToDevice(true, true, true);
when(mFeatureProvider.getInvisibleProfilePreferenceKeys(any(), any()))
- .thenReturn(ImmutableSet.of("A2DP"));
- mConnectableProfiles.add(leAudioProfile);
+ .thenReturn(ImmutableSet.of("LE_AUDIO"));
showScreen(mController);
@@ -563,19 +571,8 @@
public void classicAudioDeviceWithLeAudio_showLeAudioToggle() {
mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_LE_AUDIO_TOGGLE_FOR_LE_AUDIO_ONLY_DEVICE);
setupDevice(makeDefaultDeviceConfig());
-
- LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
- when(leAudioProfile.getNameResource(mDevice))
- .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
- when(leAudioProfile.isProfileReady()).thenReturn(true);
- when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
- when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
- mConnectableProfiles.add(leAudioProfile);
- when(mCachedDevice.getProfiles())
- .thenAnswer(
- invocation ->
- ImmutableList.of(
- leAudioProfile, addMockA2dpProfile(false, false, false)));
+ addLeAudioProfileToDevice(false);
+ addA2dpProfileToDevice(false, false, false);
showScreen(mController);
@@ -587,16 +584,7 @@
public void leAudioOnlyDevice_hideLeAudioToggle() {
mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_LE_AUDIO_TOGGLE_FOR_LE_AUDIO_ONLY_DEVICE);
setupDevice(makeDefaultDeviceConfig());
-
- LeAudioProfile leAudioProfile = mock(LeAudioProfile.class);
- when(leAudioProfile.getNameResource(mDevice))
- .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio);
- when(leAudioProfile.isProfileReady()).thenReturn(true);
- when(leAudioProfile.toString()).thenReturn("LE_AUDIO");
- when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile);
- mConnectableProfiles.add(leAudioProfile);
- when(mCachedDevice.getProfiles())
- .thenAnswer(invocation -> ImmutableList.of(leAudioProfile));
+ addLeAudioProfileToDevice(false);
showScreen(mController);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ConfigurationActivityHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ConfigurationActivityHelperTest.java
index 1c72e87..47291a0 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ConfigurationActivityHelperTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ConfigurationActivityHelperTest.java
@@ -34,6 +34,7 @@
import android.os.Bundle;
import android.service.notification.ConditionProviderService;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import org.junit.Before;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
index ff25322..61d3192 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
@@ -33,6 +33,7 @@
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ManualDurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ManualDurationPreferenceControllerTest.java
index 0a600c0..29fdfdd 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ManualDurationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ManualDurationPreferenceControllerTest.java
@@ -30,6 +30,7 @@
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java b/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java
deleted file mode 100644
index 0b6a732..0000000
--- a/tests/robotests/src/com/android/settings/notification/modes/TestModeBuilder.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2024 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.notification.modes;
-
-import android.app.AutomaticZenRule;
-import android.app.NotificationManager;
-import android.content.ComponentName;
-import android.net.Uri;
-import android.service.notification.Condition;
-import android.service.notification.ZenDeviceEffects;
-import android.service.notification.ZenModeConfig;
-import android.service.notification.ZenPolicy;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.Nullable;
-
-import com.android.settingslib.notification.modes.ZenMode;
-
-import java.util.Random;
-
-class TestModeBuilder {
-
- private String mId;
- private AutomaticZenRule mRule;
- private ZenModeConfig.ZenRule mConfigZenRule;
-
- public static final ZenMode EXAMPLE = new TestModeBuilder().build();
-
- TestModeBuilder() {
- // Reasonable defaults
- int id = new Random().nextInt(1000);
- mId = "rule_" + id;
- mRule = new AutomaticZenRule.Builder("Test Rule #" + id, Uri.parse("rule://" + id))
- .setPackage("some_package")
- .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
- .setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build())
- .build();
- mConfigZenRule = new ZenModeConfig.ZenRule();
- mConfigZenRule.enabled = true;
- mConfigZenRule.pkg = "some_package";
- }
-
- TestModeBuilder(ZenMode previous) {
- mId = previous.getId();
- mRule = previous.getRule();
-
- mConfigZenRule = new ZenModeConfig.ZenRule();
- mConfigZenRule.enabled = previous.getRule().isEnabled();
- mConfigZenRule.pkg = previous.getRule().getPackageName();
- setActive(previous.isActive());
- }
-
- TestModeBuilder setId(String id) {
- mId = id;
- return this;
- }
-
- TestModeBuilder setAzr(AutomaticZenRule rule) {
- mRule = rule;
- mConfigZenRule.pkg = rule.getPackageName();
- mConfigZenRule.conditionId = rule.getConditionId();
- mConfigZenRule.enabled = rule.isEnabled();
- return this;
- }
-
- TestModeBuilder setConfigZenRule(ZenModeConfig.ZenRule configZenRule) {
- mConfigZenRule = configZenRule;
- return this;
- }
-
- TestModeBuilder setName(String name) {
- mRule.setName(name);
- mConfigZenRule.name = name;
- return this;
- }
-
- TestModeBuilder setPackage(String pkg) {
- mRule.setPackageName(pkg);
- mConfigZenRule.pkg = pkg;
- return this;
- }
-
- TestModeBuilder setOwner(ComponentName owner) {
- mRule.setOwner(owner);
- mConfigZenRule.component = owner;
- return this;
- }
-
- TestModeBuilder setConfigurationActivity(ComponentName configActivity) {
- mRule.setConfigurationActivity(configActivity);
- mConfigZenRule.configurationActivity = configActivity;
- return this;
- }
-
- TestModeBuilder setConditionId(Uri conditionId) {
- mRule.setConditionId(conditionId);
- mConfigZenRule.conditionId = conditionId;
- return this;
- }
-
- TestModeBuilder setType(@AutomaticZenRule.Type int type) {
- mRule.setType(type);
- mConfigZenRule.type = type;
- return this;
- }
-
- TestModeBuilder setInterruptionFilter(
- @NotificationManager.InterruptionFilter int interruptionFilter) {
- mRule.setInterruptionFilter(interruptionFilter);
- mConfigZenRule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
- interruptionFilter, NotificationManager.INTERRUPTION_FILTER_PRIORITY);
- return this;
- }
-
- TestModeBuilder setZenPolicy(@Nullable ZenPolicy policy) {
- mRule.setZenPolicy(policy);
- mConfigZenRule.zenPolicy = policy;
- return this;
- }
-
- TestModeBuilder setDeviceEffects(@Nullable ZenDeviceEffects deviceEffects) {
- mRule.setDeviceEffects(deviceEffects);
- mConfigZenRule.zenDeviceEffects = deviceEffects;
- return this;
- }
-
- TestModeBuilder setEnabled(boolean enabled) {
- mRule.setEnabled(enabled);
- mConfigZenRule.enabled = enabled;
- return this;
- }
-
- TestModeBuilder setManualInvocationAllowed(boolean allowed) {
- mRule.setManualInvocationAllowed(allowed);
- mConfigZenRule.allowManualInvocation = allowed;
- return this;
- }
-
- TestModeBuilder setTriggerDescription(@Nullable String triggerDescription) {
- mRule.setTriggerDescription(triggerDescription);
- mConfigZenRule.triggerDescription = triggerDescription;
- return this;
- }
-
- TestModeBuilder setIconResId(@DrawableRes int iconResId) {
- mRule.setIconResId(iconResId);
- return this;
- }
-
- TestModeBuilder setActive(boolean active) {
- if (active) {
- mConfigZenRule.enabled = true;
- mConfigZenRule.condition = new Condition(mRule.getConditionId(), "...",
- Condition.STATE_TRUE);
- } else {
- mConfigZenRule.condition = null;
- }
- return this;
- }
-
- ZenMode build() {
- return new ZenMode(mId, mRule, mConfigZenRule);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
index f850b1e..1faba30 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java
@@ -42,6 +42,7 @@
import com.android.settings.SettingsActivity;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
index c96dbb6..1140238 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
@@ -37,6 +37,7 @@
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
index 5869c6b..368b923 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java
@@ -35,6 +35,7 @@
import androidx.fragment.app.Fragment;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.widget.LayoutPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
index e50d294..862cf77 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeCallsLinkPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
index a735cd9..f2c6006 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayEffectPreferenceControllerTest.java
@@ -29,6 +29,7 @@
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
index 3ccfb9f..6c3d74f 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java
@@ -27,6 +27,7 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenModesBackend;
import org.junit.Before;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
index a7163fe..b15d4d6 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
@@ -28,6 +28,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
index b476b00..2441803 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
@@ -34,6 +34,7 @@
import androidx.lifecycle.Lifecycle;
import com.android.internal.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNamePreferenceControllerTest.java
index 0c3f4e0..b54727c 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNamePreferenceControllerTest.java
@@ -28,6 +28,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
index 03c75fb..4c8db07 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
@@ -27,6 +27,7 @@
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
index 4d30ce9..1904734 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeIconPickerListPreferenceControllerTest.java
@@ -32,6 +32,7 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
index dda58ae..100ff43 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeMessagesLinkPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNewCustomFragmentTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNewCustomFragmentTest.java
index b18ce21..dd2b49b 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNewCustomFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNewCustomFragmentTest.java
@@ -39,6 +39,7 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import com.android.internal.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
index bfa99a0..554fc6e 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisLinkPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
index b23d946..0820846 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeNotifVisPreferenceControllerTest.java
@@ -40,6 +40,7 @@
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
index 39ba9e8..772bd1d 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
index c69a8a0..8272773 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
@@ -32,6 +32,7 @@
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
index 9d9dd98..dd97d6e 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
@@ -27,6 +27,8 @@
import androidx.preference.Preference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
index 04df27e..944d432 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
@@ -51,6 +51,7 @@
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
index c1b99e5..c453403 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
@@ -34,6 +34,7 @@
import androidx.preference.TwoStatePreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
index cc6a497..42aa498 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
@@ -39,6 +39,7 @@
import androidx.preference.PreferenceCategory;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
index 7dbc802..d5c7f61 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
@@ -36,6 +36,7 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
index ffd239b..fc3cef1 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetTriggerLinkPreferenceControllerTest.java
@@ -49,6 +49,7 @@
import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.PrimarySwitchPreference;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListFragmentTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListFragmentTest.java
index 4703b8e..e105641 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListFragmentTest.java
@@ -37,6 +37,7 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import com.android.settings.notification.modes.ZenModesListAddModePreferenceController.ModeType;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
index aaf7059..dafcee7 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListItemPreferenceTest.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.service.notification.ZenModeConfig;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import org.junit.Before;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
index c0f96be..4c16f26 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesListPreferenceControllerTest.java
@@ -37,6 +37,7 @@
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.android.settingslib.search.SearchIndexableRaw;
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
index 308650f..e847fb7 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
@@ -39,6 +39,7 @@
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy;
+import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import org.junit.Before;
diff --git a/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
index 13f575f..38b4b71 100644
--- a/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragmentTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -36,13 +37,19 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.fragment.app.FragmentTransaction;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.settings.flags.Flags;
+
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
@@ -55,6 +62,7 @@
private WifiDppQrCodeGeneratorFragment mFragment;
private Context mContext;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
@@ -163,4 +171,18 @@
assertThat(mFragment.createNearbyButton(new Intent(), v -> {
})).isNotNull();
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
+ public void getMetricsCatetory_shouldReturnDppQrSharing() {
+ assertThat(mFragment.getMetricsCategory())
+ .isEqualTo(SettingsEnums.SETTINGS_WIFI_DPP_QR_SHARING);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_WIFI_SHARING_RUNTIME_FRAGMENT)
+ public void getMetricsCatetory_shouldReturnDppConfigurator() {
+ assertThat(mFragment.getMetricsCategory())
+ .isEqualTo(SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR);
+ }
}
diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
index e0f4b9e..2cb41bc 100644
--- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
@@ -25,7 +25,6 @@
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;
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
@@ -83,7 +82,6 @@
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
public final FingerprintFeatureProvider mFingerprintFeatureProvider;
- public final BiometricsRepositoryProvider mBiometricsRepositoryProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -139,7 +137,6 @@
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class);
- mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
@@ -272,11 +269,6 @@
}
@Override
- public BiometricsRepositoryProvider getBiometricsRepositoryProvider() {
- return mBiometricsRepositoryProvider;
- }
-
- @Override
public WifiTrackerLibProvider getWifiTrackerLibProvider() {
return wifiTrackerLibProvider;
}
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 5ca24a3..dc15f0b 100644
--- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
+++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
@@ -23,7 +23,6 @@
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
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider
@@ -126,8 +125,6 @@
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
get() = TODO("Not yet implemented")
override val securitySettingsFeatureProvider: SecuritySettingsFeatureProvider
diff --git a/tests/unit/src/com/android/settings/biometrics2/OWNERS b/tests/unit/src/com/android/settings/biometrics2/OWNERS
deleted file mode 100644
index a257ed8..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /src/com/android/settings/biometrics/OWNERS
diff --git a/tests/unit/src/com/android/settings/biometrics2/repository/FingerprintRepositoryTest.java b/tests/unit/src/com/android/settings/biometrics2/repository/FingerprintRepositoryTest.java
deleted file mode 100644
index 8989595..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/repository/FingerprintRepositoryTest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.biometrics2.repository;
-
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_HOME_BUTTON;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UNKNOWN;
-
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.biometrics.SensorProperties;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-public class FingerprintRepositoryTest {
-
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock private Resources mResources;
- @Mock private FingerprintManager mFingerprintManager;
-
- private Context mContext;
-
- @Before
- public void setUp() {
- mContext = ApplicationProvider.getApplicationContext();
- }
-
- @Test
- public void testCanAssumeSensorType_forUnknownSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 1);
- assertThat(repository.canAssumeUdfps()).isFalse();
- assertThat(repository.canAssumeSfps()).isFalse();
- }
-
- @Test
- public void testCanAssumeSensorType_forRearSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_REAR, 1);
- assertThat(repository.canAssumeUdfps()).isFalse();
- assertThat(repository.canAssumeSfps()).isFalse();
- }
-
- @Test
- public void testCanAssumeSensorType_forUdfpsUltrasonicSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UDFPS_ULTRASONIC, 1);
- assertThat(repository.canAssumeUdfps()).isTrue();
- assertThat(repository.canAssumeSfps()).isFalse();
- }
-
- @Test
- public void testCanAssumeSensorType_forUdfpsOpticalSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UDFPS_OPTICAL, 1);
- assertThat(repository.canAssumeUdfps()).isTrue();
- assertThat(repository.canAssumeSfps()).isFalse();
- }
-
- @Test
- public void testCanAssumeSensorType_forPowerButtonSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_POWER_BUTTON, 1);
- assertThat(repository.canAssumeUdfps()).isFalse();
- assertThat(repository.canAssumeSfps()).isTrue();
- }
-
- @Test
- public void testCanAssumeSensorType_forHomeButtonSensor() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_HOME_BUTTON, 1);
- assertThat(repository.canAssumeUdfps()).isFalse();
- assertThat(repository.canAssumeSfps()).isFalse();
- }
-
- @Test
- public void testGetMaxFingerprints() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 999);
- assertThat(repository.getMaxFingerprints()).isEqualTo(999);
- }
-
- @Test
- public void testGetNumOfEnrolledFingerprintsSize() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 999);
- setupFingerprintEnrolledFingerprints(mFingerprintManager, 10, 3);
- setupFingerprintEnrolledFingerprints(mFingerprintManager, 22, 99);
-
- assertThat(repository.getNumOfEnrolledFingerprintsSize(10)).isEqualTo(3);
- assertThat(repository.getNumOfEnrolledFingerprintsSize(22)).isEqualTo(99);
- }
-
- @Test
- public void testGetMaxFingerprintsInSuw() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 999);
- setupSuwMaxFingerprintsEnrollable(mContext, mResources, 333);
- assertThat(repository.getMaxFingerprintsInSuw(mResources))
- .isEqualTo(333);
-
- setupSuwMaxFingerprintsEnrollable(mContext, mResources, 20);
- assertThat(repository.getMaxFingerprintsInSuw(mResources)).isEqualTo(20);
- }
-
- @Test
- public void testGetFirstFingerprintSensorPropertiesInternal() {
- final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- SensorProperties.STRENGTH_STRONG,
- 5,
- new ArrayList<>() /* componentInfo */,
- TYPE_UDFPS_OPTICAL,
- true /* resetLockoutRequiresHardwareAuthToken */);
- props.add(prop);
- doAnswer(invocation -> {
- final IFingerprintAuthenticatorsRegisteredCallback callback =
- invocation.getArgument(0);
- callback.onAllAuthenticatorsRegistered(props);
- return null;
- }).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
-
- final FingerprintRepository repository = new FingerprintRepository(mFingerprintManager);
- assertThat(repository.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
- }
-
- @Test
- public void testGetEnrollStageCount() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 999);
-
- final int expectedValue = 24;
- doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
-
- assertThat(repository.getEnrollStageCount()).isEqualTo(expectedValue);
- }
-
- @Test
- public void testGetEnrollStageThreshold() {
- final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
- TYPE_UNKNOWN, 999);
-
- final float expectedValue0 = 0.42f;
- final float expectedValue1 = 0.24f;
- final float expectedValue2 = 0.33f;
- final float expectedValue3 = 0.90f;
- doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
- doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
- doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
- doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
-
- assertThat(repository.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
- assertThat(repository.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
- assertThat(repository.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
- assertThat(repository.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.kt
deleted file mode 100644
index ac62232..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-import android.content.Intent
-import android.os.Bundle
-import android.os.SystemClock
-import android.os.UserHandle
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.password.ChooseLockSettingsHelper
-import com.google.common.truth.Truth
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.util.Arrays
-
-@RunWith(AndroidJUnit4::class)
-class CredentialModelTest {
-
- private val clock = SystemClock.elapsedRealtimeClock()
-
- @Test
- fun testNullBundle() {
- val credentialModel = CredentialModel(null, clock)
- Truth.assertThat(credentialModel.userId).isEqualTo(UserHandle.myUserId())
- }
-
- companion object {
- @JvmStatic
- fun newCredentialModelIntentExtras(
- userId: Int, challenge: Long,
- token: ByteArray?, gkPwHandle: Long
- ): Bundle {
- val bundle = Bundle()
- bundle.putInt(Intent.EXTRA_USER_ID, userId)
- bundle.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge)
- bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token)
- bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
- return bundle
- }
-
- @JvmStatic
- fun newValidTokenCredentialIntentExtras(userId: Int): Bundle {
- return newCredentialModelIntentExtras(
- userId, 1L, byteArrayOf(0, 1, 2),
- CredentialModel.INVALID_GK_PW_HANDLE
- )
- }
-
- @JvmStatic
- fun newOnlySensorValidCredentialIntentExtras(userId: Int): Bundle {
- return newCredentialModelIntentExtras(
- userId, CredentialModel.INVALID_CHALLENGE, null,
- CredentialModel.INVALID_GK_PW_HANDLE
- )
- }
-
- @JvmStatic
- fun newGkPwHandleCredentialIntentExtras(userId: Int, gkPwHandle: Long): Bundle {
- return newCredentialModelIntentExtras(
- userId,
- CredentialModel.INVALID_CHALLENGE,
- null,
- gkPwHandle
- )
- }
-
- private fun checkBundleLongValue(
- bundle1: Bundle, bundle2: Bundle,
- key: String
- ) {
- if (!bundle1.containsKey(key)) {
- return
- }
- val value1 = bundle1.getInt(key)
- val value2 = bundle2.getInt(key)
- Truth.assertWithMessage(
- "bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
- + value2
- ).that(value1).isEqualTo(value2)
- }
-
- private fun checkBundleIntValue(
- bundle1: Bundle, bundle2: Bundle,
- key: String
- ) {
- if (!bundle1.containsKey(key)) {
- return
- }
- val value1 = bundle1.getLong(key)
- val value2 = bundle2.getLong(key)
- Truth.assertWithMessage(
- "bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
- + value2
- ).that(value1).isEqualTo(value2)
- }
-
- private fun checkBundleByteArrayValue(
- bundle1: Bundle, bundle2: Bundle,
- key: String
- ) {
- if (!bundle1.containsKey(key)) {
- return
- }
- val value1 = bundle1.getByteArray(key)
- val value2 = bundle2.getByteArray(key)
- val errMsg = ("bundle not match, key:" + key + ", value1:" + Arrays.toString(value1)
- + ", value2:" + Arrays.toString(value2))
- if (value1 == null) {
- Truth.assertWithMessage(errMsg).that(value2).isNull()
- } else {
- Truth.assertWithMessage(errMsg).that(value1.size).isEqualTo(
- value2!!.size
- )
- for (i in value1.indices) {
- Truth.assertWithMessage(errMsg).that(value1[i]).isEqualTo(
- value2[i]
- )
- }
- }
- }
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/model/EnrollmentRequestTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/model/EnrollmentRequestTest.kt
deleted file mode 100644
index b301433..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/model/EnrollmentRequestTest.kt
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.biometrics2.ui.model
-
-import android.content.Context
-import android.content.Intent
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.biometrics.BiometricEnrollActivity
-import com.google.android.setupcompat.util.WizardManagerHelper
-import com.google.common.truth.Truth
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class EnrollmentRequestTest {
-
- private val context = ApplicationProvider.getApplicationContext<Context>()
-
- @Test
- fun testIsSuw() {
- // Default false
- Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSuw).isFalse()
- Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSuw).isFalse()
- val trueIntent = Intent()
- trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
- Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSuw).isTrue()
- Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSuw).isFalse()
- val falseIntent = Intent()
- trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false)
- Truth.assertThat(EnrollmentRequest(falseIntent, context, true).isSuw).isFalse()
- Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSuw).isFalse()
- }
-
- @Test
- fun testIsAfterSuwOrSuwSuggestedAction() {
- // Default false
- Truth.assertThat(
- EnrollmentRequest(Intent(), context, true)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- Truth.assertThat(
- EnrollmentRequest(Intent(), context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val deferredTrueIntent = Intent()
- deferredTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, true)
- Truth.assertThat(
- EnrollmentRequest(deferredTrueIntent, context, true)
- .isAfterSuwOrSuwSuggestedAction
- ).isTrue()
- Truth.assertThat(
- EnrollmentRequest(deferredTrueIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val deferredFalseIntent = Intent()
- deferredFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, false)
- Truth.assertThat(
- EnrollmentRequest(deferredFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- Truth.assertThat(
- EnrollmentRequest(deferredFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val portalTrueIntent = Intent()
- portalTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, true)
- Truth.assertThat(
- EnrollmentRequest(portalTrueIntent, context, true)
- .isAfterSuwOrSuwSuggestedAction
- ).isTrue()
- Truth.assertThat(
- EnrollmentRequest(portalTrueIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val portalFalseIntent = Intent()
- portalFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, false)
- Truth.assertThat(
- EnrollmentRequest(portalFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- Truth.assertThat(
- EnrollmentRequest(portalFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val suggestedTrueIntent = Intent()
- suggestedTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, true)
- Truth.assertThat(
- EnrollmentRequest(suggestedTrueIntent, context, true)
- .isAfterSuwOrSuwSuggestedAction
- ).isTrue()
- Truth.assertThat(
- EnrollmentRequest(suggestedTrueIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- val suggestedFalseIntent = Intent()
- suggestedFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, false)
- Truth.assertThat(
- EnrollmentRequest(suggestedFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- Truth.assertThat(
- EnrollmentRequest(suggestedFalseIntent, context, false)
- .isAfterSuwOrSuwSuggestedAction
- ).isFalse()
- }
-
- @Test
- fun testGetSuwExtras_inSuw() {
- val suwIntent = Intent()
- suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
- val setupRequest = EnrollmentRequest(suwIntent, context, true)
- val bundle = setupRequest.suwExtras
- Truth.assertThat(bundle).isNotNull()
- Truth.assertThat(bundle.size()).isAtLeast(1)
- Truth.assertThat(bundle.getBoolean(WizardManagerHelper.EXTRA_IS_SETUP_FLOW)).isTrue()
- }
-
- @Test
- fun testGetSuwExtras_notInSuw() {
- val suwIntent = Intent()
- suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
- val setupRequest = EnrollmentRequest(suwIntent, context, false)
- val bundle = setupRequest.suwExtras
- Truth.assertThat(bundle).isNotNull()
- Truth.assertThat(bundle.size()).isEqualTo(0)
- }
-
- @Test
- fun testIsSkipIntro() {
- // Default false
- Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipIntro).isFalse()
- Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipIntro).isFalse()
- val trueIntent = Intent()
- trueIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, true)
- Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipIntro).isTrue()
- Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipIntro).isTrue()
- val falseIntent = Intent()
- falseIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, false)
- Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
- Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
- }
-
- @Test
- fun testIsSkipFindSensor() {
- // Default false
- Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipFindSensor)
- .isFalse()
- Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipFindSensor)
- .isFalse()
- val trueIntent = Intent()
- trueIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, true)
- Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipFindSensor).isTrue()
- Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipFindSensor).isTrue()
- val falseIntent = Intent()
- falseIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, false)
- Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
- .isFalse()
- Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
- .isFalse()
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.kt
deleted file mode 100644
index e708f3b..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.kt
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Activity
-import android.app.admin.DevicePolicyManager
-import android.content.Intent
-import android.os.Bundle
-import android.os.SystemClock
-import android.os.UserHandle
-import androidx.activity.result.ActivityResult
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.internal.widget.LockPatternUtils
-import com.android.internal.widget.VerifyCredentialResponse
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics2.ui.model.CredentialModel
-import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newGkPwHandleCredentialIntentExtras
-import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newOnlySensorValidCredentialIntentExtras
-import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newValidTokenCredentialIntentExtras
-import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator
-import com.android.settings.password.ChooseLockPattern
-import com.android.settings.password.ChooseLockSettingsHelper
-import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.atomic.AtomicBoolean
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.mockito.Mockito.`when` as whenever
-
-@RunWith(AndroidJUnit4::class)
-class AutoCredentialViewModelTest {
-
- @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
-
- @Mock private lateinit var lockPatternUtils: LockPatternUtils
-
- private var challengeGenerator: TestChallengeGenerator = TestChallengeGenerator()
-
- private lateinit var viewModel: AutoCredentialViewModel
- private fun newAutoCredentialViewModel(bundle: Bundle?): AutoCredentialViewModel {
- return AutoCredentialViewModel(
- ApplicationProvider.getApplicationContext(),
- lockPatternUtils,
- challengeGenerator,
- CredentialModel(bundle, SystemClock.elapsedRealtimeClock())
- )
- }
-
- @Before
- fun setUp() {
- challengeGenerator = TestChallengeGenerator()
- }
-
- private fun setupGenerateChallenge(userId: Int, newSensorId: Int, newChallenge: Long) {
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
- challengeGenerator.userId = userId
- challengeGenerator.sensorId = newSensorId
- challengeGenerator.challenge = newChallenge
- }
-
- @Test
- fun testCheckCredential_validCredentialCase() = runTest {
- val userId = 99
- viewModel = newAutoCredentialViewModel(newValidTokenCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(backgroundScope)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.CREDENTIAL_VALID)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
-
- @Test
- fun testCheckCredential_needToChooseLock() = runTest {
- val userId = 100
- viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
- )
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(backgroundScope)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CHOOSE_LOCK)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
-
- @Test
- fun testCheckCredential_needToConfirmLockForSomething() = runTest {
- val userId = 101
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(backgroundScope)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
-
- @Test
- fun testCheckCredential_needToConfirmLockForNumeric() = runTest {
- val userId = 102
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
- )
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(backgroundScope)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
-
- @Test
- fun testCheckCredential_needToConfirmLockForAlphabetic() = runTest {
- val userId = 103
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
- )
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(this)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
-
- @Test
- fun testCheckCredential_generateChallenge() = runTest {
- val userId = 104
- val gkPwHandle = 1111L
- viewModel =
- newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
- val newSensorId = 10
- val newChallenge = 20L
- setupGenerateChallenge(userId, newSensorId, newChallenge)
- whenever(
- lockPatternUtils.verifyGatekeeperPasswordHandle(
- gkPwHandle,
- newChallenge,
- userId
- )
- )
- .thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
- val hasCalledRemoveGkPwHandle = AtomicBoolean()
- Mockito.doAnswer {
- hasCalledRemoveGkPwHandle.set(true)
- null
- }.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(backgroundScope)
- runCurrent()
-
- // Check viewModel behavior
- assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
- assertThat(generateFails.size).isEqualTo(0)
-
- // Check data inside CredentialModel
- assertThat(viewModel.token).isNotNull()
- assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
- assertThat(hasCalledRemoveGkPwHandle.get()).isFalse()
-
- // Check createGeneratingChallengeExtras()
- val generatingChallengeExtras = viewModel.createGeneratingChallengeExtras()
- assertThat(generatingChallengeExtras).isNotNull()
- assertThat(generatingChallengeExtras!!.getLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE))
- .isEqualTo(newChallenge)
- val tokens =
- generatingChallengeExtras.getByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
- assertThat(tokens).isNotNull()
- assertThat(tokens!!.size).isEqualTo(1)
- assertThat(tokens[0]).isEqualTo(1)
- }
-
- @Test
- fun testCheckCredential_generateChallengeFail() = runTest {
- backgroundScope.launch {
- val userId = 104
- val gkPwHandle = 1111L
- viewModel =
- newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
- val newSensorId = 10
- val newChallenge = 20L
- setupGenerateChallenge(userId, newSensorId, newChallenge)
- whenever(
- lockPatternUtils.verifyGatekeeperPasswordHandle(
- gkPwHandle,
- newChallenge,
- userId
- )
- )
- .thenReturn(newBadCredential(0))
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run credential check
- val action = viewModel.checkCredential(this)
- runCurrent()
-
- assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
- assertThat(generateFails.size).isEqualTo(1)
- assertThat(generateFails[0]).isEqualTo(true)
- assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
-
- // Check createGeneratingChallengeExtras()
- assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
- }
- }
-
- @Test
- fun testGetUserId_fromIntent() {
- val userId = 106
- viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
-
- // Get userId
- assertThat(viewModel.userId).isEqualTo(userId)
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_invalidChooseLock() = runTest {
- backgroundScope.launch {
- val userId = 107
- val gkPwHandle = 3333L
- viewModel =
- newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
- val intent = Intent()
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- true,
- ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isFalse()
- assertThat(generateFails.size).isEqualTo(0)
- }
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_invalidConfirmLock() = runTest {
- backgroundScope.launch {
- val userId = 107
- val gkPwHandle = 3333L
- viewModel =
- newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
- val intent = Intent()
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- false,
- ActivityResult(Activity.RESULT_OK + 1, intent),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isFalse()
- assertThat(generateFails.size).isEqualTo(0)
- }
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_nullDataChooseLock() = runTest {
- val userId = 108
- val gkPwHandle = 4444L
- viewModel =
- newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- true,
- ActivityResult(ChooseLockPattern.RESULT_FINISHED, null),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isFalse()
- assertThat(generateFails.size).isEqualTo(0)
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_nullDataConfirmLock() = runTest {
- val userId = 109
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- false,
- ActivityResult(Activity.RESULT_OK, null),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isFalse()
- assertThat(generateFails.size).isEqualTo(0)
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_validChooseLock() = runTest {
- val userId = 108
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
- val gkPwHandle = 6666L
- val newSensorId = 50
- val newChallenge = 60L
- setupGenerateChallenge(userId, newSensorId, newChallenge)
- whenever(
- lockPatternUtils.verifyGatekeeperPasswordHandle(
- gkPwHandle,
- newChallenge,
- userId
- )
- )
- .thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
- val hasCalledRemoveGkPwHandle = AtomicBoolean()
- Mockito.doAnswer {
- hasCalledRemoveGkPwHandle.set(true)
- null
- }.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val intent =
- Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- true,
- ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isTrue()
- assertThat(generateFails.size).isEqualTo(0)
- assertThat(viewModel.token).isNotNull()
- assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
- assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
- }
-
- @Test
- fun testGenerateChallengeAsCredentialActivityResult_validConfirmLock() = runTest {
- val userId = 109
- viewModel =
- newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
- whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
- DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- )
- val gkPwHandle = 5555L
- val newSensorId = 80
- val newChallenge = 90L
- setupGenerateChallenge(userId, newSensorId, newChallenge)
- whenever(
- lockPatternUtils.verifyGatekeeperPasswordHandle(
- gkPwHandle,
- newChallenge,
- userId
- )
- )
- .thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
- val hasCalledRemoveGkPwHandle = AtomicBoolean()
- Mockito.doAnswer {
- hasCalledRemoveGkPwHandle.set(true)
- null
- }.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
-
- val generateFails = listOfGenerateChallengeFailedFlow()
-
- // Run generateChallengeAsCredentialActivityResult()
- val intent =
- Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
- val ret = viewModel.generateChallengeAsCredentialActivityResult(
- false,
- ActivityResult(Activity.RESULT_OK, intent),
- backgroundScope
- )
- runCurrent()
-
- assertThat(ret).isTrue()
- assertThat(generateFails.size).isEqualTo(0)
- assertThat(viewModel.token).isNotNull()
- assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
- assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
- }
-
- private fun TestScope.listOfGenerateChallengeFailedFlow(): List<Boolean> =
- mutableListOf<Boolean>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.generateChallengeFailedFlow.toList(it)
- }
- }
-
- class TestChallengeGenerator : ChallengeGenerator {
- var sensorId = -1
- var userId = UserHandle.myUserId()
- var challenge = CredentialModel.INVALID_CHALLENGE
- var callbackRunCount = 0
-
- override var callback: AutoCredentialViewModel.GenerateChallengeCallback? = null
-
- override fun generateChallenge(userId: Int) {
- callback?.let {
- it.onChallengeGenerated(sensorId, this.userId, challenge)
- ++callbackRunCount
- }
- }
- }
-
- private fun newGoodCredential(gkPwHandle: Long, hat: ByteArray): VerifyCredentialResponse {
- return VerifyCredentialResponse.Builder()
- .setGatekeeperPasswordHandle(gkPwHandle)
- .setGatekeeperHAT(hat)
- .build()
- }
-
- private fun newBadCredential(timeout: Int): VerifyCredentialResponse {
- return if (timeout > 0) {
- VerifyCredentialResponse.fromTimeout(timeout)
- } else {
- VerifyCredentialResponse.fromError()
- }
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModelTest.java
deleted file mode 100644
index c4ee18e..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceFoldedViewModelTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.viewmodel;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-import android.content.res.Configuration;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.InstantTaskExecutorRule;
-import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceFoldedViewModelTest {
-
- @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- private DeviceFoldedViewModel mViewModel;
-
- @Before
- public void setUp() {
- final Application application = ApplicationProvider.getApplicationContext();
- mViewModel = new DeviceFoldedViewModel(new ScreenSizeFoldProvider(application),
- application.getMainExecutor());
- }
-
- @Test
- public void testLiveData() {
- final Configuration config1 = new Configuration();
- config1.smallestScreenWidthDp = 601;
- mViewModel.onConfigurationChanged(config1);
- assertThat(mViewModel.getLiveData().getValue()).isFalse();
-
- final Configuration config2 = new Configuration();
- config2.smallestScreenWidthDp = 599;
- mViewModel.onConfigurationChanged(config2);
- assertThat(mViewModel.getLiveData().getValue()).isTrue();
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModelTest.java
deleted file mode 100644
index 0b7c53c..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/DeviceRotationViewModelTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2022 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.biometrics2.ui.viewmodel;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.InstantTaskExecutorRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceRotationViewModelTest {
-
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
- @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- private TestDeviceRotationViewModel mViewModel;
-
- @Before
- public void setUp() {
- TestDeviceRotationViewModel.sTestRotation = 3;
- mViewModel = new TestDeviceRotationViewModel(ApplicationProvider.getApplicationContext());
- }
-
- @Test
- public void testDefaultLiveDataNotNull() {
- assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
- }
-
- @Test
- public void testOnDisplayChange() {
- mViewModel.sTestRotation = 3;
- mViewModel.triggerOnDisplayChanged();
- assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
- }
-
- public static class TestDeviceRotationViewModel extends DeviceRotationViewModel {
-
- @Surface.Rotation static int sTestRotation = 0;
-
- public TestDeviceRotationViewModel(@NonNull Application application) {
- super(application);
- }
-
- void triggerOnDisplayChanged() {
- mDisplayListener.onDisplayChanged(0);
- }
-
- @Override
- protected int getRotation() {
- return sTestRotation;
- }
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModelTest.java
deleted file mode 100644
index d4fae60..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModelTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
-
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP;
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-
-import android.app.Application;
-import android.hardware.biometrics.SensorProperties;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
-
-import androidx.lifecycle.LiveData;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-import com.android.settings.testutils.InstantTaskExecutorRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-public class FingerprintEnrollEnrollingViewModelTest {
-
- private static final int TEST_USER_ID = 33;
-
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
- @Rule
- public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- @Mock
- private FingerprintManager mFingerprintManager;
-
- private Application mApplication;
- private FingerprintEnrollEnrollingViewModel mViewModel;
-
- @Before
- public void setUp() {
- mApplication = ApplicationProvider.getApplicationContext();
- mViewModel = new FingerprintEnrollEnrollingViewModel(
- mApplication,
- TEST_USER_ID,
- newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5)
- );
- }
-
- @Test
- public void testIconTouchDialog() {
- final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
- assertThat(actionLiveData.getValue()).isEqualTo(null);
-
- mViewModel.showIconTouchDialog();
- assertThat(actionLiveData.getValue()).isEqualTo(
- FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG);
- }
-
- @Test
- public void tesBackPressedScenario() {
- final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
- assertThat(actionLiveData.getValue()).isEqualTo(null);
- assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
-
- mViewModel.setOnBackPressed();
- assertThat(mViewModel.getOnBackPressed()).isEqualTo(true);
-
- mViewModel.onCancelledDueToOnBackPressed();
- assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
- assertThat(actionLiveData.getValue()).isEqualTo(
- FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED);
- }
-
- @Test
- public void testSkipPressedScenario() {
- final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
- assertThat(actionLiveData.getValue()).isEqualTo(null);
- assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
-
- mViewModel.setOnSkipPressed();
- assertThat(mViewModel.getOnSkipPressed()).isEqualTo(true);
-
- mViewModel.onCancelledDueToOnSkipPressed();
- assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
- assertThat(actionLiveData.getValue()).isEqualTo(
- FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP);
- }
-
- @Test
- public void testGetFirstFingerprintSensorPropertiesInternal() {
- final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- SensorProperties.STRENGTH_STRONG,
- 5,
- new ArrayList<>() /* componentInfo */,
- TYPE_UDFPS_OPTICAL,
- true /* resetLockoutRequiresHardwareAuthToken */);
- props.add(prop);
- doAnswer(invocation -> {
- final IFingerprintAuthenticatorsRegisteredCallback callback =
- invocation.getArgument(0);
- callback.onAllAuthenticatorsRegistered(props);
- return null;
- }).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
-
- mViewModel = new FingerprintEnrollEnrollingViewModel(
- mApplication,
- TEST_USER_ID,
- new FingerprintRepository(mFingerprintManager)
- );
-
- assertThat(mViewModel.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
- }
-
- @Test
- public void testGetEnrollStageCount() {
- final int expectedValue = 24;
- doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
-
- assertThat(mViewModel.getEnrollStageCount()).isEqualTo(expectedValue);
- }
-
- @Test
- public void testGetEnrollStageThreshold() {
- final float expectedValue0 = 0.42f;
- final float expectedValue1 = 0.24f;
- final float expectedValue2 = 0.33f;
- final float expectedValue3 = 0.90f;
-
- doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
- doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
- doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
- doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
-
- assertThat(mViewModel.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
- assertThat(mViewModel.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
- assertThat(mViewModel.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
- assertThat(mViewModel.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModelTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModelTest.kt
deleted file mode 100644
index 379a5c1..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollErrorDialogViewModelTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Application
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class FingerprintEnrollErrorDialogViewModelTest {
-
- private val application = ApplicationProvider.getApplicationContext<Application>()
- private var viewModel: FingerprintEnrollErrorDialogViewModel =
- FingerprintEnrollErrorDialogViewModel(application, false)
-
- @Before
- fun setUp() {
- // Make sure viewModel is new for each test
- viewModel = FingerprintEnrollErrorDialogViewModel(application, false)
- }
-
- @Test
- fun testIsDialogNotShownDefaultFalse() {
- assertThat(viewModel.isDialogShown).isFalse()
- }
-
- @Test
- fun testIsSuw() {
- assertThat(FingerprintEnrollErrorDialogViewModel(application, false).isSuw).isFalse()
- assertThat(FingerprintEnrollErrorDialogViewModel(application, true).isSuw).isTrue()
- }
-
- @Test
- fun testNewDialog() = runTest {
- val newDialogs: List<Int> = mutableListOf<Int>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.newDialogFlow.toList(it)
- }
- }
-
- runCurrent()
-
- // Default values
- assertThat(viewModel.isDialogShown).isFalse()
- assertThat(newDialogs.size).isEqualTo(0)
-
- val testErrorMsgId = 3456
- viewModel.newDialog(testErrorMsgId)
- runCurrent()
-
- // verify after emit
- assertThat(viewModel.isDialogShown).isTrue()
- assertThat(newDialogs.size).isEqualTo(1)
- assertThat(newDialogs[0]).isEqualTo(testErrorMsgId)
- }
-
- @Test
- fun testTriggerRetry() = runTest {
- val triggerRetries: List<Any> = mutableListOf<Any>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.triggerRetryFlow.toList(it)
- }
- }
-
- runCurrent()
-
- // Default values
- assertThat(triggerRetries.size).isEqualTo(0)
-
- viewModel.triggerRetry()
- runCurrent()
-
- // verify after emit
- assertThat(triggerRetries.size).isEqualTo(1)
- }
-
- @Test
- fun testSetResultFinish() = runTest {
- val setResults: List<FingerprintErrorDialogSetResultAction> =
- mutableListOf<FingerprintErrorDialogSetResultAction>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.setResultFlow.toList(it)
- }
- }
-
- runCurrent()
-
- // Default values
- assertThat(setResults.size).isEqualTo(0)
-
- viewModel.setResultAndFinish(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
- runCurrent()
-
- // verify after emit
- assertThat(setResults.size).isEqualTo(1)
- assertThat(setResults[0]).isEqualTo(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModelTest.java
deleted file mode 100644
index 18bd61a..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFindSensorViewModelTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG;
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP;
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.InstantTaskExecutorRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class FingerprintEnrollFindSensorViewModelTest {
-
- @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- private Application mApplication;
- private FingerprintEnrollFindSensorViewModel mViewModel;
-
- @Before
- public void setUp() {
- mApplication = ApplicationProvider.getApplicationContext();
- mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
- }
-
- @Test
- public void testClickSkipButtonNotInSuw() {
- mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
- mViewModel.onSkipButtonClick();
- assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
- }
-
- @Test
- public void testClickSkipButtonInSuw() {
- mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, true);
- mViewModel.onSkipButtonClick();
- assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG);
- }
-
- @Test
- public void testClickSkipDialogButton() {
- mViewModel.onSkipDialogButtonClick();
- assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
- }
-
- @Test
- public void testClickStartDialogButton() {
- mViewModel.onStartButtonClick();
- assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START);
- }
-
- @Test
- public void testClearActionLiveData() {
- assertThat(mViewModel.getActionLiveData().getValue()).isNull();
-
- mViewModel.onStartButtonClick();
- assertThat(mViewModel.getActionLiveData().getValue()).isNotNull();
-
- mViewModel.clearActionLiveData();
- assertThat(mViewModel.getActionLiveData().getValue()).isNull();
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModelTest.java
deleted file mode 100644
index ac97e72..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollFinishViewModelTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
-
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK;
-import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK;
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
-import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Application;
-import android.content.Intent;
-import android.hardware.fingerprint.FingerprintManager;
-
-import androidx.lifecycle.LiveData;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
-import com.android.settings.testutils.InstantTaskExecutorRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@RunWith(AndroidJUnit4.class)
-public class FingerprintEnrollFinishViewModelTest {
-
- private static final int USER_ID = 334;
- private static final int MAX_ENROLLABLE = 5;
-
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
- @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- @Mock private FingerprintManager mFingerprintManager;
-
- private Application mApplication;
- private EnrollmentRequest mRequest;
- private FingerprintEnrollFinishViewModel mViewModel;
-
- @Before
- public void setUp() {
- mApplication = ApplicationProvider.getApplicationContext();
- mRequest = new EnrollmentRequest(new Intent(), mApplication, true);
- mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
- newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
- }
-
- @Test
- public void testCanAssumeSfps() {
- mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
- newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
- assertThat(mViewModel.canAssumeSfps()).isFalse();
-
- mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
- newFingerprintRepository(mFingerprintManager, TYPE_REAR, MAX_ENROLLABLE));
- assertThat(mViewModel.canAssumeSfps()).isFalse();
-
- mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
- newFingerprintRepository(mFingerprintManager, TYPE_POWER_BUTTON, MAX_ENROLLABLE));
- assertThat(mViewModel.canAssumeSfps()).isTrue();
- }
-
- @Test
- public void testIsAnotherFingerprintEnrollable() {
- setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE);
- assertThat(mViewModel.isAnotherFingerprintEnrollable()).isFalse();
-
- setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE - 1);
- assertThat(mViewModel.isAnotherFingerprintEnrollable()).isTrue();
- }
-
- @Test
- public void testGetRequest() {
- assertThat(mViewModel.getRequest()).isEqualTo(mRequest);
- }
-
- @Test
- public void testOnAddButtonClick() {
- final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
-
- // Test init value
- assertThat(actionLiveData.getValue()).isNull();
-
- // Test onAddButtonClick()
- mViewModel.onAddButtonClick();
- assertThat(actionLiveData.getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK);
-
- // Clear
- mViewModel.clearActionLiveData();
- assertThat(actionLiveData.getValue()).isNull();
- }
-
- @Test
- public void testOnNextButtonClick() {
- final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
-
- // Test init value
- assertThat(actionLiveData.getValue()).isNull();
-
- // Test onNextButtonClick()
- mViewModel.onNextButtonClick();
- assertThat(actionLiveData.getValue()).isEqualTo(
- FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK);
-
- // Clear
- mViewModel.clearActionLiveData();
- assertThat(actionLiveData.getValue()).isNull();
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.kt
deleted file mode 100644
index 7494aef..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.kt
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Application
-import android.content.res.Resources
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.biometrics2.data.repository.FingerprintRepository
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
-import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.CONTINUE_ENROLL
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.DONE_AND_FINISH
-import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.SKIP_OR_CANCEL
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwDeferredRequest
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwPortalRequest
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwSuggestedActionFlowRequest
-import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
-import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
-import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.junit.MockitoJUnit
-
-@RunWith(AndroidJUnit4::class)
-class FingerprintEnrollIntroViewModelTest {
-
- @get:Rule val mockito = MockitoJUnit.rule()
-
- @Mock private lateinit var resources: Resources
- @Mock private lateinit var fingerprintManager: FingerprintManager
-
- private var application: Application = ApplicationProvider.getApplicationContext()
-
- private fun newFingerprintEnrollIntroViewModel(
- fingerprintRepository: FingerprintRepository,
- enrollmentRequest: EnrollmentRequest
- ) = FingerprintEnrollIntroViewModel(
- application,
- fingerprintRepository,
- enrollmentRequest,
- TEST_USER_ID
- )
-
- @Before
- fun setUp() {
- application = ApplicationProvider.getApplicationContext()
- }
-
- @Test
- fun testPageStatusFlowDefaultAndUpdate() = runTest {
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 1),
- newAllFalseRequest(application)
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
-
- runCurrent()
-
- // assert default values
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].hasScrollToBottom()).isFalse()
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
- viewModel.updateEnrollableStatus(backgroundScope)
- runCurrent()
-
- // assert new updated value
- assertThat(statusList.size).isEqualTo(2)
- assertThat(statusList[1].hasScrollToBottom()).isFalse()
- assertThat(statusList[1].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
- }
-
- fun testOnStartToUpdateEnrollableStatusOk_isSuw() = runTest {
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
- setupSuwMaxFingerprintsEnrollable(application, resources, 1)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newIsSuwRequest(application)
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
-
- runCurrent()
-
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusReachMax_isSuw() = runTest {
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
- setupSuwMaxFingerprintsEnrollable(application, resources, 1)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newIsSuwRequest(application)
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
-
- runCurrent()
-
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusOk_isNotSuw() = runTest {
- testOnStartToUpdateEnrollableStatusOk(newAllFalseRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusReachMax_isNotSuw() = runTest {
- testOnStartToUpdateEnrollableStatusReachMax(newAllFalseRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusOk_isSuwDeferred() = runTest {
- testOnStartToUpdateEnrollableStatusOk(newIsSuwDeferredRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusReachMax_isSuwDeferred() = runTest {
- testOnStartToUpdateEnrollableStatusReachMax(newIsSuwDeferredRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusOk_isSuwPortal() = runTest {
- testOnStartToUpdateEnrollableStatusOk(newIsSuwPortalRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusReachMax_isSuwPortal() = runTest {
- testOnStartToUpdateEnrollableStatusReachMax(newIsSuwPortalRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusOk_isSuwSuggestedActionFlow() = runTest {
- testOnStartToUpdateEnrollableStatusOk(newIsSuwSuggestedActionFlowRequest(application))
- }
-
- @Test
- fun testOnStartToUpdateEnrollableStatusReachMax_isSuwSuggestedActionFlow() = runTest {
- testOnStartToUpdateEnrollableStatusReachMax(
- newIsSuwSuggestedActionFlowRequest(application)
- )
- }
-
- private fun TestScope.testOnStartToUpdateEnrollableStatusOk(request: EnrollmentRequest) {
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- request
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
-
- runCurrent()
-
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
- }
-
- private fun TestScope.testOnStartToUpdateEnrollableStatusReachMax(request: EnrollmentRequest) {
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 5)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- request
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
-
- runCurrent()
-
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
- }
-
- @Test
- fun testIsParentalConsentRequired() {
- // We shall not mock FingerprintRepository, but
- // FingerprintRepository.isParentalConsentRequired() calls static method inside, we can't
- // mock static method
- val fingerprintRepository = Mockito.mock(
- FingerprintRepository::class.java
- )
- val viewModel = FingerprintEnrollIntroViewModel(
- application,
- fingerprintRepository,
- newAllFalseRequest(application),
- TEST_USER_ID
- )
- Mockito.`when`(
- fingerprintRepository.isParentalConsentRequired(application)
- ).thenReturn(true)
- assertThat(viewModel.isParentalConsentRequired).isEqualTo(true)
- Mockito.`when`(
- fingerprintRepository.isParentalConsentRequired(application)
- ).thenReturn(false)
- assertThat(viewModel.isParentalConsentRequired).isEqualTo(false)
- }
-
- @Test
- fun testIsBiometricUnlockDisabledByAdmin() {
- // We shall not mock FingerprintRepository, but
- // FingerprintRepository.isDisabledByAdmin() calls static method inside, we can't mock
- // static method
- val fingerprintRepository = Mockito.mock(FingerprintRepository::class.java)
- val viewModel = FingerprintEnrollIntroViewModel(
- application,
- fingerprintRepository,
- newAllFalseRequest(application),
- TEST_USER_ID
- )
- Mockito.`when`(
- fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
- ).thenReturn(true)
- assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(true)
- Mockito.`when`(
- fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
- ).thenReturn(false)
- assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(false)
- }
-
- @Test
- fun testSetHasScrolledToBottom() = runTest {
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newAllFalseRequest(application)
- )
-
- val pageStatusList = listOfPageStatusFlow(viewModel)
-
- viewModel.setHasScrolledToBottom(true, backgroundScope)
- runCurrent()
-
- assertThat(pageStatusList[pageStatusList.size-1].hasScrollToBottom()).isEqualTo(true)
- }
-
- @Test
- fun testOnNextButtonClick_enrollNext() = runTest {
- // Set latest status to FINGERPRINT_ENROLLABLE_OK
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
- setupSuwMaxFingerprintsEnrollable(application, resources, 1)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newIsSuwRequest(application)
- )
-
- val actions = listOfActionFlow(viewModel)
-
- // Perform click on `next`
- viewModel.onNextButtonClick(backgroundScope)
- runCurrent()
-
- assertThat(actions.size).isEqualTo(1)
- assertThat(actions[0]).isEqualTo(CONTINUE_ENROLL)
- }
-
- @Test
- fun testOnNextButtonClick_doneAndFinish() = runTest {
- // Set latest status to FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
- setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
- setupSuwMaxFingerprintsEnrollable(application, resources, 1)
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newIsSuwRequest(application)
- )
-
- val statusList = listOfPageStatusFlow(viewModel)
- val actionList = listOfActionFlow(viewModel)
-
- runCurrent()
-
- assertThat(statusList.size).isEqualTo(1)
- assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
-
- val actions = listOfActionFlow(viewModel)
-
- // Perform click on `next`
- viewModel.onNextButtonClick(backgroundScope)
- runCurrent()
-
- assertThat(actionList.size).isEqualTo(1)
- assertThat(actionList[0]).isEqualTo(DONE_AND_FINISH)
- }
-
- @Test
- fun testOnSkipOrCancelButtonClick() = runTest {
- val viewModel = newFingerprintEnrollIntroViewModel(
- newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
- newAllFalseRequest(application)
- )
-
- val actions = listOfActionFlow(viewModel)
-
- viewModel.onSkipOrCancelButtonClick(backgroundScope)
- runCurrent()
-
- assertThat(actions.size).isEqualTo(1)
- assertThat(actions[0]).isEqualTo(SKIP_OR_CANCEL)
- }
-
- private fun TestScope.listOfActionFlow(
- viewModel: FingerprintEnrollIntroViewModel
- ): List<FingerprintEnrollIntroAction> =
- mutableListOf<FingerprintEnrollIntroAction>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.actionFlow.toList(it)
- }
- }
-
- private fun TestScope.listOfPageStatusFlow(
- viewModel: FingerprintEnrollIntroViewModel
- ): List<FingerprintEnrollIntroStatus> =
- mutableListOf<FingerprintEnrollIntroStatus>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.pageStatusFlow.toList(it)
- }
- }
-
- companion object {
- private const val TEST_USER_ID = 33
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
deleted file mode 100644
index 2c7afa6..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel;
-
-import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
-import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR;
-import static android.hardware.fingerprint.FingerprintManager.EnrollReason;
-import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
-
-import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Application;
-import android.content.res.Resources;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.LiveData;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
-import com.android.settings.biometrics.fingerprint.MessageDisplayController;
-import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
-import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
-import com.android.settings.testutils.InstantTaskExecutorRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@RunWith(AndroidJUnit4.class)
-public class FingerprintEnrollProgressViewModelTest {
-
- private static final int TEST_USER_ID = 334;
-
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
- @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-
- @Mock private Application mApplication;
- @Mock private Resources mResources;
- @Mock private FingerprintUpdater mFingerprintUpdater;
-
- private FingerprintEnrollProgressViewModel mViewModel;
- private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>();
- private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>();
- private int mEnrollmentMessageDisplayControllerFlagResId;
-
- @Before
- public void setUp() {
- mEnrollmentMessageDisplayControllerFlagResId = ApplicationProvider.getApplicationContext()
- .getResources().getIdentifier("enrollment_message_display_controller_flag", "bool",
- SETTINGS_PACKAGE_NAME);
-
- when(mApplication.getResources()).thenReturn(mResources);
-
- // Not use MessageDisplayController by default
- when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(false);
- mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater,
- TEST_USER_ID);
-
- mCancellationSignalWrapper.mValue = null;
- mCallbackWrapper.mValue = null;
- doAnswer(invocation -> {
- mCancellationSignalWrapper.mValue = invocation.getArgument(1);
- mCallbackWrapper.mValue = invocation.getArgument(3);
- return null;
- }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
- eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt(), any());
- }
-
- @Test
- public void testStartFindSensor() {
- @EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
- final byte[] token = new byte[] { 1, 2, 3 };
- mViewModel.setToken(token);
-
- // Start enrollment
- final Object ret = mViewModel.startEnrollment(enrollReason);
-
- assertThat(ret).isNotNull();
- verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
- eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
- assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
- }
-
- @Test
- public void testStartEnrolling() {
- @EnrollReason final int enrollReason = ENROLL_ENROLL;
- final byte[] token = new byte[] { 1, 2, 3 };
- mViewModel.setToken(token);
-
- // Start enrollment
- final Object ret = mViewModel.startEnrollment(enrollReason);
-
- assertThat(ret).isNotNull();
- verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
- eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
- assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
- }
-
- @Test
- public void testStartEnrollingWithMessageDisplayController() {
- // Enable MessageDisplayController and mock handler for it
- when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
- when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
-
- @EnrollReason final int enrollReason = ENROLL_ENROLL;
- final byte[] token = new byte[] { 1, 2, 3 };
- mViewModel.setToken(token);
-
- // Start enrollment
- final Object ret = mViewModel.startEnrollment(enrollReason);
-
- assertThat(ret).isNotNull();
- verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
- eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isTrue();
- final EnrollmentCallback callback1 = mCallbackWrapper.mValue;
-
- // Cancel and start again
- mViewModel.cancelEnrollment();
- mViewModel.startEnrollment(enrollReason);
-
- // Shall not use the same MessageDisplayController
- verify(mFingerprintUpdater, times(2)).enroll(eq(token), any(CancellationSignal.class),
- eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
- assertThat(mCallbackWrapper.mValue).isNotNull();
- assertThat(callback1).isNotEqualTo(mCallbackWrapper.mValue);
- }
-
- @Test
- public void testStartEnrollmentFailBecauseOfNoToken() {
- // Start enrollment
- final Object ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);
-
- assertThat(ret).isNull();
- verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
- any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt(),
- any());
- }
-
- @Test
- public void testCancelEnrollment() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCancellationSignalWrapper.mValue).isNotNull();
-
- // Cancel enrollment
- mViewModel.cancelEnrollment();
-
- assertThat(mCancellationSignalWrapper.mValue.isCanceled()).isTrue();
- }
-
- @Test
- public void testProgressUpdate() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Test default value
- final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
- EnrollmentProgress progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(-1);
- assertThat(progress.getRemaining()).isEqualTo(0);
-
- // Update first progress
- mCallbackWrapper.mValue.onEnrollmentProgress(25);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(25);
-
- // Update second progress
- mCallbackWrapper.mValue.onEnrollmentProgress(20);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(20);
-
- // Update latest progress
- mCallbackWrapper.mValue.onEnrollmentProgress(0);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(0);
- }
-
- @Test
- public void testProgressUpdateClearHelpMessage() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
- final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
- final LiveData<EnrollmentStatusMessage> helpMsgLiveData =
- mViewModel.getHelpMessageLiveData();
-
- // Update first progress
- mCallbackWrapper.mValue.onEnrollmentProgress(25);
- EnrollmentProgress progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(25);
-
- // Update help message
- final int testHelpMsgId = 3;
- final String testHelpString = "Test Help String";
- mCallbackWrapper.mValue.onEnrollmentHelp(testHelpMsgId, testHelpString);
- final EnrollmentStatusMessage helpMsg = helpMsgLiveData.getValue();
- assertThat(helpMsg).isNotNull();
- assertThat(helpMsg.getMsgId()).isEqualTo(testHelpMsgId);
- assertThat(helpMsg.getStr().toString()).isEqualTo(testHelpString);
-
- // Update second progress
- mCallbackWrapper.mValue.onEnrollmentProgress(20);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(20);
-
- // Help message shall be set to null
- assertThat(helpMsgLiveData.getValue()).isNull();
- }
-
- @Test
- public void testProgressUpdateWithMessageDisplayController() {
- // Enable MessageDisplayController and mock handler for it
- when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
- when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
-
- mViewModel.setToken(new byte[] { 1, 2, 3 });
-
- // Start enrollment
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Test default value
- final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
- EnrollmentProgress progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(-1);
- assertThat(progress.getRemaining()).isEqualTo(0);
-
- // Update first progress
- mCallbackWrapper.mValue.onEnrollmentProgress(25);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(25);
-
- // Update second progress
- mCallbackWrapper.mValue.onEnrollmentProgress(20);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(20);
-
- // Update latest progress
- mCallbackWrapper.mValue.onEnrollmentProgress(0);
- progress = progressLiveData.getValue();
- assertThat(progress).isNotNull();
- assertThat(progress.getSteps()).isEqualTo(25);
- assertThat(progress.getRemaining()).isEqualTo(0);
- }
-
- @Test
- public void testGetErrorMessageLiveData() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Check default value
- final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getErrorMessageLiveData();
- assertThat(liveData.getValue()).isNull();
-
- // Notify error message
- final int errMsgId = 3;
- final String errMsg = "test error message";
- mCallbackWrapper.mValue.onEnrollmentError(errMsgId, errMsg);
- final EnrollmentStatusMessage value = liveData.getValue();
- assertThat(value).isNotNull();
- assertThat(value.getMsgId()).isEqualTo(errMsgId);
- assertThat(value.getStr().toString()).isEqualTo(errMsg);
- }
-
- @Test
- public void testGetHelpMessageLiveData() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Check default value
- final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getHelpMessageLiveData();
- assertThat(liveData.getValue()).isNull();
-
- // Notify help message
- final int errMsgId = 3;
- final String errMsg = "test error message";
- mCallbackWrapper.mValue.onEnrollmentHelp(errMsgId, errMsg);
- final EnrollmentStatusMessage value = liveData.getValue();
- assertThat(value).isNotNull();
- assertThat(value.getMsgId()).isEqualTo(errMsgId);
- assertThat(value.getStr().toString()).isEqualTo(errMsg);
- }
-
- @Test
- public void testGetAcquireLiveData() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Check default value
- final LiveData<Boolean> liveData = mViewModel.getAcquireLiveData();
- assertThat(liveData.getValue()).isNull();
-
- // Notify acquire message
- mCallbackWrapper.mValue.onAcquired(true);
- assertThat(liveData.getValue()).isTrue();
- }
-
- @Test
- public void testGetPointerDownLiveData() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Check default value
- final LiveData<Integer> liveData = mViewModel.getPointerDownLiveData();
- assertThat(liveData.getValue()).isNull();
-
- // Notify acquire message
- final int value = 33;
- mCallbackWrapper.mValue.onUdfpsPointerDown(value);
- assertThat(liveData.getValue()).isEqualTo(value);
- }
-
- @Test
- public void testGetPointerUpLiveData() {
- // Start enrollment
- mViewModel.setToken(new byte[] { 1, 2, 3 });
- final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
- assertThat(ret).isNotNull();
- assertThat(mCallbackWrapper.mValue).isNotNull();
-
- // Check default value
- final LiveData<Integer> liveData = mViewModel.getPointerUpLiveData();
- assertThat(liveData.getValue()).isNull();
-
- // Notify acquire message
- final int value = 44;
- mCallbackWrapper.mValue.onUdfpsPointerUp(value);
- assertThat(liveData.getValue()).isEqualTo(value);
- }
-
- private static class TestWrapper<T> {
- T mValue;
- }
-
- private static class TestHandler extends Handler {
-
- TestHandler() {
- super(Looper.getMainLooper());
- }
-
- @Override
- public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
- msg.getCallback().run();
- return true;
- }
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.kt b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.kt
deleted file mode 100644
index 6d04f35..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollmentViewModelTest.kt
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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.biometrics2.ui.viewmodel
-
-import android.app.Application
-import android.content.Intent
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorProperties
-import android.os.Bundle
-import androidx.activity.result.ActivityResult
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics2.data.repository.FingerprintRepository
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
-import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
-import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
-import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@RunWith(AndroidJUnit4::class)
-class FingerprintEnrollmentViewModelTest {
-
- @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
-
- private val application: Application
- get() = ApplicationProvider.getApplicationContext()
-
- @Mock
- private lateinit var fingerprintManager: FingerprintManager
-
- private lateinit var fingerprintRepository: FingerprintRepository
- private lateinit var viewModel: FingerprintEnrollmentViewModel
-
- @Before
- fun setUp() {
- fingerprintRepository = newFingerprintRepository(
- fingerprintManager,
- FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
- 5
- )
- viewModel = FingerprintEnrollmentViewModel(
- application,
- fingerprintRepository,
- newAllFalseRequest(application)
- )
- }
-
- @Test
- fun testGetRequest() {
- assertThat(viewModel.request).isNotNull()
- }
-
- @Test
- fun testIsWaitingActivityResultDefaultFalse() {
- assertThat(viewModel.isWaitingActivityResult.value).isFalse()
- }
-
-
- @Test
- fun testOverrideActivityResult_shallKeepNullIntent_woChallengeExtra() {
- val retResult = viewModel.getOverrideActivityResult(
- ActivityResult(22, null), null
- )
- assertThat(retResult).isNotNull()
- assertThat(retResult.data).isNull()
- }
-
- @Test
- fun testOverrideActivityResult_shallKeepNullIntent_noIntent_woChallengeExtra() {
- val intent = Intent()
- val retResult = viewModel.getOverrideActivityResult(
- ActivityResult(33, intent), null
- )
- assertThat(retResult).isNotNull()
- assertThat(retResult.data).isEqualTo(intent)
- }
-
- @Test
- fun testOverrideActivityResult_shallKeepNull_woAdded_woIntent_withChallenge() {
- val extra = Bundle()
- extra.putString("test1", "test123")
-
- val retResult = viewModel.getOverrideActivityResult(
- ActivityResult(33, null), extra
- )
-
- assertThat(retResult).isNotNull()
- assertThat(retResult.data).isNull()
- }
-
- @Test
- fun testOverrideActivityResult_shallCreateNew_woIntent_withChallenge() {
- val key1 = "test1"
- val key2 = "test2"
- val extra = Bundle().apply {
- putString(key1, "test123")
- putInt(key2, 9999)
- }
-
- viewModel.isNewFingerprintAdded = true
-
- val retResult = viewModel.getOverrideActivityResult(
- ActivityResult(33, null), extra
- )
- assertThat(retResult).isNotNull()
-
- val retIntent = retResult.data
- assertThat(retIntent).isNotNull()
-
- val retExtra = retIntent!!.extras
- assertThat(retExtra).isNotNull()
- assertThat(retExtra!!.size).isEqualTo(extra.size)
- assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
- assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
- }
-
- @Test
- fun testOverrideActivityResult_shallNotMerge_nonAdded_woIntent_withChallenge() {
- val extra = Bundle().apply {
- putString("test2", "test123")
- }
-
- val key2 = "test2"
- val intent = Intent().apply {
- putExtra(key2, 3456L)
- }
-
- val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
-
- assertThat(retResult).isNotNull()
-
- val retIntent = retResult.data
- assertThat(retIntent).isNotNull()
-
- val retExtra = retIntent!!.extras
- assertThat(retExtra).isNotNull()
- assertThat(retExtra!!.size).isEqualTo(intent.extras!!.size)
- assertThat(retExtra.getString(key2)).isEqualTo(intent.extras!!.getString(key2))
- }
-
- @Test
- fun testOverrideActivityResult_shallMerge_added_woIntent_withChallenge() {
- val key1 = "test1"
- val key2 = "test2"
- val extra = Bundle().apply {
- putString(key1, "test123")
- putInt(key2, 9999)
- }
-
- val key3 = "test3"
- val intent = Intent().apply {
- putExtra(key3, 3456L)
- }
-
- viewModel.isNewFingerprintAdded = true
-
- val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
- assertThat(retResult).isNotNull()
-
- val retIntent = retResult.data
- assertThat(retIntent).isNotNull()
-
- val retExtra = retIntent!!.extras
- assertThat(retExtra).isNotNull()
- assertThat(retExtra!!.size).isEqualTo(extra.size + intent.extras!!.size)
- assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
- assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
- assertThat(retExtra.getLong(key3)).isEqualTo(intent.extras!!.getLong(key3))
- }
-
- @Test
- fun testIsMaxEnrolledReached() {
- val uid = 100
- fingerprintRepository = newFingerprintRepository(
- fingerprintManager,
- FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
- 3
- )
- viewModel = FingerprintEnrollmentViewModel(
- application,
- fingerprintRepository,
- newAllFalseRequest(application)
- )
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 0)
- assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 1)
- assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 2)
- assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 3)
- assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
-
- setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 4)
- assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
- }
-
- @Test
- fun testSetResultFlow_defaultEmpty() = runTest {
- val activityResults = listOfSetResultFlow()
-
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(0)
- }
-
- @Test
- fun testCheckFinishActivityDuringOnPause_doNothingIfIsSuw() = runTest {
- viewModel = FingerprintEnrollmentViewModel(
- application,
- fingerprintRepository,
- newIsSuwRequest(application)
- )
-
- val activityResults = listOfSetResultFlow()
-
- viewModel.checkFinishActivityDuringOnPause(
- isActivityFinishing = false,
- isChangingConfigurations = false,
- scope = this
- )
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(0)
- }
-
- @Test
- fun testCheckFinishActivityDuringOnPause_doNothingIfIsWaitingActivity() = runTest {
- val activityResults = listOfSetResultFlow()
-
- viewModel.isWaitingActivityResult.value = true
- viewModel.checkFinishActivityDuringOnPause(
- isActivityFinishing = false,
- isChangingConfigurations = false,
- scope = this
- )
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(0)
- }
-
- @Test
- fun testCheckFinishActivityDuringOnPause_doNothingIfIsActivityFinishing() = runTest {
- val activityResults = listOfSetResultFlow()
-
- viewModel.checkFinishActivityDuringOnPause(
- isActivityFinishing = true,
- isChangingConfigurations = false,
- scope = this
- )
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(0)
- }
-
- @Test
- fun testCheckFinishActivityDuringOnPause_doNothingIfIsChangingConfigurations() = runTest {
- val activityResults = listOfSetResultFlow()
-
- viewModel.checkFinishActivityDuringOnPause(
- isActivityFinishing = false,
- isChangingConfigurations = true,
- scope = this
- )
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(0)
- }
-
- @Test
- fun testCheckFinishActivityDuringOnPause_defaultFinishSelf() = runTest {
- val activityResults = listOfSetResultFlow()
-
- viewModel.checkFinishActivityDuringOnPause(
- isActivityFinishing = false,
- isChangingConfigurations = false,
- scope = backgroundScope
- )
- runCurrent()
-
- assertThat(activityResults.size).isEqualTo(1)
- assertThat(activityResults[0].resultCode).isEqualTo(BiometricEnrollBase.RESULT_TIMEOUT)
- assertThat(activityResults[0].data).isEqualTo(null)
- }
-
- private fun TestScope.listOfSetResultFlow(): List<ActivityResult> =
- mutableListOf<ActivityResult>().also {
- backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
- viewModel.setResultFlow.toList(it)
- }
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/utils/EnrollmentRequestUtils.kt b/tests/unit/src/com/android/settings/biometrics2/utils/EnrollmentRequestUtils.kt
deleted file mode 100644
index 755f6d0..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/utils/EnrollmentRequestUtils.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.biometrics2.utils
-
-import android.content.Context
-import android.content.Intent
-import android.text.TextUtils
-import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics2.ui.model.EnrollmentRequest
-import com.google.android.setupcompat.util.WizardManagerHelper
-
-object EnrollmentRequestUtils {
- @JvmStatic
- fun newAllFalseRequest(context: Context): EnrollmentRequest {
- return newRequest(
- context = context,
- isSuw = false,
- isSuwDeferred = false,
- isSuwPortal = false,
- isSuwSuggestedActionFlow = false,
- isSuwFirstRun = false,
- isFromSettingsSummery = false)
- }
-
- @JvmStatic
- fun newIsSuwRequest(context: Context): EnrollmentRequest {
- return newRequest(
- context = context,
- isSuw = true,
- isSuwDeferred = false,
- isSuwPortal = false,
- isSuwSuggestedActionFlow = false,
- isSuwFirstRun = false,
- isFromSettingsSummery = false)
- }
-
- @JvmStatic
- fun newIsSuwDeferredRequest(context: Context): EnrollmentRequest {
- return newRequest(
- context = context,
- isSuw = true,
- isSuwDeferred = true,
- isSuwPortal = false,
- isSuwSuggestedActionFlow = false,
- isSuwFirstRun = false,
- isFromSettingsSummery = false, null)
- }
-
- @JvmStatic
- fun newIsSuwPortalRequest(context: Context): EnrollmentRequest {
- return newRequest(
- context = context,
- isSuw = true,
- isSuwDeferred = false,
- isSuwPortal = true,
- isSuwSuggestedActionFlow = false,
- isSuwFirstRun = false,
- isFromSettingsSummery = false)
- }
-
- @JvmStatic
- fun newIsSuwSuggestedActionFlowRequest(
- context: Context
- ): EnrollmentRequest {
- return newRequest(
- context = context,
- isSuw = true,
- isSuwDeferred = false,
- isSuwPortal = false,
- isSuwSuggestedActionFlow = true,
- isSuwFirstRun = false,
- isFromSettingsSummery = false)
- }
-
- fun newRequest(
- context: Context,
- isSuw: Boolean,
- isSuwDeferred: Boolean,
- isSuwPortal: Boolean,
- isSuwSuggestedActionFlow: Boolean,
- isSuwFirstRun: Boolean,
- isFromSettingsSummery: Boolean,
- theme: String? = null
- ): EnrollmentRequest {
- val i = Intent()
- i.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, isSuw)
- i.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, isSuwDeferred)
- i.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, isSuwPortal)
- i.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, isSuwSuggestedActionFlow)
- i.putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, isSuwFirstRun)
- i.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, isFromSettingsSummery)
- if (!TextUtils.isEmpty(theme)) {
- i.putExtra(WizardManagerHelper.EXTRA_THEME, theme)
- }
- return EnrollmentRequest(i, context, true)
- }
-}
diff --git a/tests/unit/src/com/android/settings/biometrics2/utils/FingerprintRepositoryUtils.java b/tests/unit/src/com/android/settings/biometrics2/utils/FingerprintRepositoryUtils.java
deleted file mode 100644
index fcf926e..0000000
--- a/tests/unit/src/com/android/settings/biometrics2/utils/FingerprintRepositoryUtils.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.biometrics2.utils;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.biometrics.SensorProperties;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintSensorProperties;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
-
-import androidx.annotation.NonNull;
-
-import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-
-import java.util.ArrayList;
-
-public class FingerprintRepositoryUtils {
-
- public static void setupSuwMaxFingerprintsEnrollable(
- @NonNull Context context,
- @NonNull Resources mockedResources,
- int numOfFp) {
- final int resId = context.getResources().getIdentifier("suw_max_fingerprints_enrollable",
- "integer", context.getPackageName());
- when(mockedResources.getInteger(resId)).thenReturn(numOfFp);
- }
-
- public static FingerprintRepository newFingerprintRepository(
- @NonNull FingerprintManager mockedFingerprintManager,
- @FingerprintSensorProperties.SensorType int sensorType,
- int maxEnrollmentsPerUser) {
-
- final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- props.add(new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- SensorProperties.STRENGTH_STRONG,
- maxEnrollmentsPerUser,
- new ArrayList<>() /* componentInfo */,
- sensorType,
- true /* resetLockoutRequiresHardwareAuthToken */));
- doAnswer(invocation -> {
- final IFingerprintAuthenticatorsRegisteredCallback callback =
- invocation.getArgument(0);
- callback.onAllAuthenticatorsRegistered(props);
- return null;
- }).when(mockedFingerprintManager).addAuthenticatorsRegisteredCallback(any());
- return new FingerprintRepository(mockedFingerprintManager);
- }
-
- public static void setupFingerprintEnrolledFingerprints(
- @NonNull FingerprintManager mockedFingerprintManager,
- int userId,
- int enrolledFingerprints) {
- final ArrayList<Fingerprint> ret = new ArrayList<>();
- for (int i = 0; i < enrolledFingerprints; ++i) {
- ret.add(new Fingerprint("name", 0, 0, 0L));
- }
- when(mockedFingerprintManager.getEnrolledFingerprints(userId)).thenReturn(ret);
- }
-}
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index b8dd5ac..6a50ffc 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -25,7 +25,6 @@
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;
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
@@ -82,7 +81,6 @@
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
public final FingerprintFeatureProvider mFingerprintFeatureProvider;
- public final BiometricsRepositoryProvider mBiometricsRepositoryProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -140,7 +138,6 @@
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class);
- mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
@@ -273,11 +270,6 @@
}
@Override
- public BiometricsRepositoryProvider getBiometricsRepositoryProvider() {
- return mBiometricsRepositoryProvider;
- }
-
- @Override
public WifiTrackerLibProvider getWifiTrackerLibProvider() {
return wifiTrackerLibProvider;
}