Attach FingerprintEnrollEnrollingRfps fragment
Support enrolling RFPS on biomerics v2. Bug: 260957939 Test: atest FingerprintEnrollFindSensorViewModelTest FingerprintEnrollProgressViewModelTest FingerprintEnrollmentViewModelTest FingerprintEnrollmentActivityTest Change-Id: Ic04b934592415d03f1b119383bffd40bd5eef2bd
This commit is contained in:
@@ -123,7 +123,10 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
|
|||||||
dialog.show(fragmentManager, FingerprintErrorDialog.class.getName());
|
dialog.show(fragmentManager, FingerprintErrorDialog.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getErrorMessage(int errMsgId) {
|
/**
|
||||||
|
* Gets dialog message as error id inside {@link FingerprintManager}
|
||||||
|
*/
|
||||||
|
public static int getErrorMessage(int errMsgId) {
|
||||||
switch (errMsgId) {
|
switch (errMsgId) {
|
||||||
case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
|
case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
|
||||||
// This message happens when the underlying crypto layer decides to revoke
|
// This message happens when the underlying crypto layer decides to revoke
|
||||||
@@ -137,7 +140,10 @@ public class FingerprintErrorDialog extends InstrumentedDialogFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getErrorTitle(int errMsgId) {
|
/**
|
||||||
|
* Gets dialog title as error id inside {@link FingerprintManager}
|
||||||
|
*/
|
||||||
|
public static int getErrorTitle(int errMsgId) {
|
||||||
switch (errMsgId) {
|
switch (errMsgId) {
|
||||||
case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
|
case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
|
||||||
return R.string
|
return R.string
|
||||||
|
@@ -98,8 +98,11 @@ public class FingerprintRepository {
|
|||||||
return resources.getInteger(R.integer.suw_max_fingerprints_enrollable);
|
return resources.getInteger(R.integer.suw_max_fingerprints_enrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the first FingerprintSensorPropertiesInternal from FingerprintManager
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
|
public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
|
||||||
final List<FingerprintSensorPropertiesInternal> props = mSensorPropertiesCache;
|
final List<FingerprintSensorPropertiesInternal> props = mSensorPropertiesCache;
|
||||||
if (props == null) {
|
if (props == null) {
|
||||||
// Handle this case if it really happens
|
// Handle this case if it really happens
|
||||||
|
@@ -113,13 +113,14 @@ public class BiometricsViewModelFactory implements ViewModelProvider.Factory {
|
|||||||
new FingerprintUpdater(application), userId);
|
new FingerprintUpdater(application), userId);
|
||||||
}
|
}
|
||||||
} else if (modelClass.isAssignableFrom(FingerprintEnrollEnrollingViewModel.class)) {
|
} else if (modelClass.isAssignableFrom(FingerprintEnrollEnrollingViewModel.class)) {
|
||||||
|
final Integer userId = extras.get(USER_ID_KEY);
|
||||||
final FingerprintRepository fingerprint = provider.getFingerprintRepository(
|
final FingerprintRepository fingerprint = provider.getFingerprintRepository(
|
||||||
application);
|
application);
|
||||||
final AccessibilityRepository accessibility = provider.getAccessibilityRepository(
|
final AccessibilityRepository accessibility = provider.getAccessibilityRepository(
|
||||||
application);
|
application);
|
||||||
final VibratorRepository vibrator = provider.getVibratorRepository(application);
|
final VibratorRepository vibrator = provider.getVibratorRepository(application);
|
||||||
if (fingerprint != null && accessibility != null && vibrator != null) {
|
if (fingerprint != null && accessibility != null && vibrator != null) {
|
||||||
return (T) new FingerprintEnrollEnrollingViewModel(application, fingerprint,
|
return (T) new FingerprintEnrollEnrollingViewModel(application, userId, fingerprint,
|
||||||
accessibility, vibrator);
|
accessibility, vibrator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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 static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.ErrorDialogData;
|
||||||
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_RESTART;
|
||||||
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH;
|
||||||
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
||||||
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fingerprint error dialog, will be shown when an error occurs during fingerprint enrollment.
|
||||||
|
*/
|
||||||
|
public class FingerprintEnrollEnrollingErrorDialog extends InstrumentedDialogFragment {
|
||||||
|
|
||||||
|
private FingerprintEnrollEnrollingViewModel mViewModel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
final ErrorDialogData data = mViewModel.getErrorDialogLiveData().getValue();
|
||||||
|
final int errMsgId = data.getErrMsgId();
|
||||||
|
final boolean canAssumeUdfps = mViewModel.canAssumeUdfps();
|
||||||
|
final boolean wasTimeout = errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
|
||||||
|
|
||||||
|
builder.setTitle(data.getErrTitle())
|
||||||
|
.setMessage(data.getErrMsg())
|
||||||
|
.setCancelable(false);
|
||||||
|
if (wasTimeout && canAssumeUdfps) {
|
||||||
|
builder.setPositiveButton(
|
||||||
|
R.string.security_settings_fingerprint_enroll_dialog_try_again,
|
||||||
|
(dialog, which) -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
mViewModel.onErrorDialogAction(FINGERPRINT_ERROR_DIALOG_ACTION_RESTART);
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(
|
||||||
|
R.string.security_settings_fingerprint_enroll_dialog_ok,
|
||||||
|
(dialog, which) -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
mViewModel.onErrorDialogAction(
|
||||||
|
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
builder.setPositiveButton(
|
||||||
|
R.string.security_settings_fingerprint_enroll_dialog_ok,
|
||||||
|
(dialog, which) -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
mViewModel.onErrorDialogAction(wasTimeout
|
||||||
|
? FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
|
||||||
|
: FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
final AlertDialog dialog = builder.create();
|
||||||
|
dialog.setCanceledOnTouchOutside(false);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return SettingsEnums.DIALOG_FINGERPINT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
mViewModel = new ViewModelProvider(getActivity()).get(
|
||||||
|
FingerprintEnrollEnrollingViewModel.class);
|
||||||
|
super.onAttach(context);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,15 +16,19 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.view;
|
package com.android.settings.biometrics2.ui.view;
|
||||||
|
|
||||||
|
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Animatable2;
|
import android.graphics.drawable.Animatable2;
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@@ -35,18 +39,22 @@ import android.view.animation.Interpolator;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.transition.Transition;
|
||||||
|
import androidx.transition.TransitionSet;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.biometrics.BiometricUtils;
|
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog;
|
||||||
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
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.DeviceRotationViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
||||||
import com.android.settingslib.display.DisplayDensityUtils;
|
|
||||||
|
|
||||||
import com.airbnb.lottie.LottieAnimationView;
|
import com.airbnb.lottie.LottieAnimationView;
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin;
|
import com.google.android.setupcompat.template.FooterBarMixin;
|
||||||
@@ -59,9 +67,16 @@ import com.google.android.setupdesign.GlifLayout;
|
|||||||
public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
||||||
|
|
||||||
private static final String TAG = FingerprintEnrollEnrollingRfpsFragment.class.getSimpleName();
|
private static final String TAG = FingerprintEnrollEnrollingRfpsFragment.class.getSimpleName();
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private static final int PROGRESS_BAR_MAX = 10000;
|
||||||
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
||||||
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
|
private static final int 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 static final int HINT_TIMEOUT_DURATION = 2500;
|
private static final int HINT_TIMEOUT_DURATION = 2500;
|
||||||
|
|
||||||
private FingerprintEnrollEnrollingViewModel mEnrollingViewModel;
|
private FingerprintEnrollEnrollingViewModel mEnrollingViewModel;
|
||||||
@@ -73,8 +88,9 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
private Interpolator mFastOutLinearInInterpolator;
|
private Interpolator mFastOutLinearInInterpolator;
|
||||||
private boolean mAnimationCancelled;
|
private boolean mAnimationCancelled;
|
||||||
|
|
||||||
private View mView;
|
private GlifLayout mView;
|
||||||
private ProgressBar mProgressBar;
|
private ProgressBar mProgressBar;
|
||||||
|
private ObjectAnimator mProgressAnim;
|
||||||
private TextView mErrorText;
|
private TextView mErrorText;
|
||||||
private FooterBarMixin mFooterBarMixin;
|
private FooterBarMixin mFooterBarMixin;
|
||||||
private AnimatedVectorDrawable mIconAnimationDrawable;
|
private AnimatedVectorDrawable mIconAnimationDrawable;
|
||||||
@@ -90,8 +106,45 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
private boolean mHaveShownSfpsLeftEdgeLottie;
|
private boolean mHaveShownSfpsLeftEdgeLottie;
|
||||||
private boolean mHaveShownSfpsRightEdgeLottie;
|
private boolean mHaveShownSfpsRightEdgeLottie;
|
||||||
|
|
||||||
private final View.OnClickListener mOnSkipClickListener =
|
private final View.OnClickListener mOnSkipClickListener = v -> {
|
||||||
(v) -> mEnrollingViewModel.onSkipButtonClick();
|
mProgressViewModel.cancelEnrollment();
|
||||||
|
mEnrollingViewModel.onSkipButtonClick();
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mProgressObserver(" + progress + ")");
|
||||||
|
}
|
||||||
|
if (progress != null) {
|
||||||
|
onEnrollmentProgressChange(progress);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mHelpMessageObserver(" + helpMessage + ")");
|
||||||
|
}
|
||||||
|
if (helpMessage != null) {
|
||||||
|
onEnrollmentHelp(helpMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mErrorMessageObserver(" + errorMessage + ")");
|
||||||
|
}
|
||||||
|
if (errorMessage != null) {
|
||||||
|
onEnrollmentError(errorMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerDownObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerUpObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
private int mIconTouchCount;
|
private int mIconTouchCount;
|
||||||
|
|
||||||
@@ -103,14 +156,48 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
||||||
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
|
final TransitionSet transitionSet = (TransitionSet) getSharedElementEnterTransition();
|
||||||
|
if (transitionSet != null) {
|
||||||
|
transitionSet.addListener(new Transition.TransitionListener() {
|
||||||
|
@Override
|
||||||
|
public void onTransitionStart(@NonNull Transition transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionEnd(@NonNull Transition transition) {
|
||||||
|
transition.removeListener(this);
|
||||||
|
mAnimationCancelled = false;
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionCancel(@NonNull Transition transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionPause(@NonNull Transition transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionResume(@NonNull Transition transition) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
mEnrollingViewModel.restoreSavedState(savedInstanceState);
|
||||||
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
mEnrollingViewModel.onSaveInstanceState(outState);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
@@ -118,24 +205,25 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
return mView;
|
return mView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private View initRfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
private GlifLayout initRfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
||||||
final View containView = inflater.inflate(R.layout.sfps_enroll_enrolling, container, false);
|
final GlifLayout containView = (GlifLayout) inflater.inflate(
|
||||||
|
R.layout.fingerprint_enroll_enrolling, container, false);
|
||||||
|
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, containView);
|
||||||
(GlifLayout) containView);
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
glifLayoutHelper.setDescriptionText(
|
R.string.security_settings_fingerprint_enroll_start_message));
|
||||||
R.string.security_settings_fingerprint_enroll_start_message);
|
|
||||||
glifLayoutHelper.setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
|
glifLayoutHelper.setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
|
||||||
|
|
||||||
mShouldShowLottie = shouldShowLottie();
|
// mShouldShowLottie = shouldShowLottie(); // TODO move this call into updateOrientation()?
|
||||||
boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
// boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
||||||
|| BiometricUtils.isLandscape(activity);
|
// || BiometricUtils.isLandscape(activity);
|
||||||
updateOrientation((isLandscape
|
// updateOrientation(containView, (isLandscape
|
||||||
? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
// ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
||||||
|
|
||||||
mErrorText = containView.findViewById(R.id.error_text);
|
mErrorText = containView.findViewById(R.id.error_text);
|
||||||
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
|
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
|
||||||
mFooterBarMixin = ((GlifLayout) containView).getMixin(FooterBarMixin.class);
|
mFooterBarMixin = containView.getMixin(FooterBarMixin.class);
|
||||||
mFooterBarMixin.setSecondaryButton(
|
mFooterBarMixin.setSecondaryButton(
|
||||||
new FooterButton.Builder(activity)
|
new FooterButton.Builder(activity)
|
||||||
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
||||||
@@ -145,15 +233,12 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
final LayerDrawable fingerprintDrawable = mProgressBar != null
|
final LayerDrawable fingerprintDrawable = (LayerDrawable) mProgressBar.getBackground();
|
||||||
? (LayerDrawable) mProgressBar.getBackground() : null;
|
mIconAnimationDrawable = (AnimatedVectorDrawable)
|
||||||
if (fingerprintDrawable != null) {
|
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_animation);
|
||||||
mIconAnimationDrawable = (AnimatedVectorDrawable)
|
mIconBackgroundBlinksDrawable = (AnimatedVectorDrawable)
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_animation);
|
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_background);
|
||||||
mIconBackgroundBlinksDrawable = (AnimatedVectorDrawable)
|
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_background);
|
|
||||||
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_slow_in);
|
activity, android.R.interpolator.fast_out_slow_in);
|
||||||
@@ -162,58 +247,34 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_linear_in);
|
activity, android.R.interpolator.fast_out_linear_in);
|
||||||
|
|
||||||
if (mProgressBar != null) {
|
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
|
||||||
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
|
mProgressBar.setOnTouchListener((v, event) -> {
|
||||||
mProgressBar.setOnTouchListener((v, event) -> {
|
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
mIconTouchCount++;
|
||||||
mIconTouchCount++;
|
if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
|
||||||
if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
|
showIconTouchDialog();
|
||||||
showIconTouchDialog();
|
} else {
|
||||||
} else {
|
mProgressBar.postDelayed(mShowDialogRunnable,
|
||||||
mProgressBar.postDelayed(mShowDialogRunnable,
|
ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
|
||||||
ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
|
|
||||||
}
|
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
|
|
||||||
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
|
||||||
mProgressBar.removeCallbacks(mShowDialogRunnable);
|
|
||||||
}
|
}
|
||||||
return true;
|
} else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
|
||||||
});
|
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
||||||
}
|
mProgressBar.removeCallbacks(mShowDialogRunnable);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return containView;
|
return containView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOrientation(int orientation) {
|
@Override
|
||||||
switch (orientation) {
|
public void onStart() {
|
||||||
case Configuration.ORIENTATION_LANDSCAPE: {
|
super.onStart();
|
||||||
mIllustrationLottie = null;
|
startEnrollment();
|
||||||
break;
|
updateProgress(false /* animate */, mProgressViewModel.getProgressLiveData().getValue());
|
||||||
}
|
updateTitleAndDescription();
|
||||||
case Configuration.ORIENTATION_PORTRAIT: {
|
if (true /* TODO check mRestoring */) {
|
||||||
if (mShouldShowLottie) {
|
startIconAnimation();
|
||||||
mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Error unhandled configuration change");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTitleAndDescription() {
|
|
||||||
final Activity activity = getActivity();
|
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
|
||||||
(GlifLayout) mView);
|
|
||||||
|
|
||||||
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
|
||||||
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
|
||||||
glifLayoutHelper.setDescriptionText(
|
|
||||||
R.string.security_settings_fingerprint_enroll_start_message);
|
|
||||||
} else {
|
|
||||||
glifLayoutHelper.setDescriptionText(
|
|
||||||
R.string.security_settings_fingerprint_enroll_repeat_message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,25 +291,243 @@ public class FingerprintEnrollEnrollingRfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onCancelEnrollment(@IdRes int errorMsgId) {
|
||||||
|
// showErrorDialog() will cause onWindowFocusChanged(false), set mIsCanceled to false
|
||||||
|
// before showErrorDialog() to prevent that another error dialog is triggered again.
|
||||||
|
// TODO mIsCanceled = true;
|
||||||
|
// TODO mIsOrientationChanged = false;
|
||||||
|
mEnrollingViewModel.showErrorDialog(new FingerprintEnrollEnrollingViewModel.ErrorDialogData(
|
||||||
|
mView.getContext().getString(FingerprintErrorDialog.getErrorMessage(errorMsgId)),
|
||||||
|
mView.getContext().getString(FingerprintErrorDialog.getErrorTitle(errorMsgId)),
|
||||||
|
errorMsgId
|
||||||
|
));
|
||||||
|
cancelEnrollment();
|
||||||
|
stopIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
stopIconAnimation();
|
||||||
|
removeEnrollmentObserver();
|
||||||
|
if (!getActivity().isChangingConfigurations()) {
|
||||||
|
mProgressViewModel.cancelEnrollment();
|
||||||
|
}
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeEnrollmentObserver() {
|
||||||
|
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().removeObserver(mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().removeObserver(mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().removeObserver(mPointerUpObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelEnrollment() {
|
||||||
|
removeEnrollmentObserver();
|
||||||
|
mProgressViewModel.cancelEnrollment();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startEnrollment() {
|
||||||
|
mProgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().observe(this, mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().observe(this, mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().observe(this, mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().observe(this, mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().observe(this, mPointerUpObserver);
|
||||||
|
mProgressViewModel.startEnrollment(ENROLL_ENROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEnrollmentHelp(@NonNull EnrollmentStatusMessage helpMessage) {
|
||||||
|
final CharSequence helpStr = helpMessage.getStr();
|
||||||
|
if (!TextUtils.isEmpty(helpStr)) {
|
||||||
|
mErrorText.removeCallbacks(mTouchAgainRunnable);
|
||||||
|
showError(helpStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEnrollmentError(@NonNull EnrollmentStatusMessage errorMessage) {
|
||||||
|
onCancelEnrollment(errorMessage.getMsgId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
|
||||||
|
updateProgress(true /* animate */, progress);
|
||||||
|
updateTitleAndDescription();
|
||||||
|
animateFlash();
|
||||||
|
mErrorText.removeCallbacks(mTouchAgainRunnable);
|
||||||
|
mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(boolean animate, @NonNull EnrollmentProgress enrollmentProgress) {
|
||||||
|
if (!mProgressViewModel.isEnrolling()) {
|
||||||
|
Log.d(TAG, "Enrollment not started yet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int progress = getProgress(enrollmentProgress);
|
||||||
|
// Only clear the error when progress has been made.
|
||||||
|
// TODO (b/234772728) Add tests.
|
||||||
|
if (mProgressBar != null && mProgressBar.getProgress() < progress) {
|
||||||
|
clearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
animateProgress(progress);
|
||||||
|
} else {
|
||||||
|
if (mProgressBar != null) {
|
||||||
|
mProgressBar.setProgress(progress);
|
||||||
|
}
|
||||||
|
if (progress >= PROGRESS_BAR_MAX) {
|
||||||
|
mDelayedFinishRunnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getProgress(@NonNull EnrollmentProgress progress) {
|
||||||
|
if (progress.getSteps() == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int displayProgress = Math.max(0, progress.getSteps() + 1 - progress.getRemaining());
|
||||||
|
return PROGRESS_BAR_MAX * displayProgress / (progress.getSteps() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showError(CharSequence error) {
|
||||||
|
mErrorText.setText(error);
|
||||||
|
if (mErrorText.getVisibility() == View.INVISIBLE) {
|
||||||
|
mErrorText.setVisibility(View.VISIBLE);
|
||||||
|
mErrorText.setTranslationY(mView.getContext().getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.fingerprint_error_text_appear_distance));
|
||||||
|
mErrorText.setAlpha(0f);
|
||||||
|
mErrorText.animate()
|
||||||
|
.alpha(1f)
|
||||||
|
.translationY(0f)
|
||||||
|
.setDuration(200)
|
||||||
|
.setInterpolator(mLinearOutSlowInInterpolator)
|
||||||
|
.start();
|
||||||
|
} else {
|
||||||
|
mErrorText.animate().cancel();
|
||||||
|
mErrorText.setAlpha(1f);
|
||||||
|
mErrorText.setTranslationY(0f);
|
||||||
|
}
|
||||||
|
if (isResumed() && mEnrollingViewModel.isAccessibilityEnabled()) {
|
||||||
|
mEnrollingViewModel.vibrateError(getClass().getSimpleName() + "::showError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearError() {
|
||||||
|
if (mErrorText.getVisibility() == View.VISIBLE) {
|
||||||
|
mErrorText.animate()
|
||||||
|
.alpha(0f)
|
||||||
|
.translationY(getResources().getDimensionPixelSize(
|
||||||
|
R.dimen.fingerprint_error_text_disappear_distance))
|
||||||
|
.setDuration(100)
|
||||||
|
.setInterpolator(mFastOutLinearInInterpolator)
|
||||||
|
.withEndAction(() -> mErrorText.setVisibility(View.INVISIBLE))
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
// TODO stopListenOrientationEvent();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateProgress(int progress) {
|
||||||
|
if (mProgressAnim != null) {
|
||||||
|
mProgressAnim.cancel();
|
||||||
|
}
|
||||||
|
ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress",
|
||||||
|
mProgressBar.getProgress(), progress);
|
||||||
|
anim.addListener(mProgressAnimationListener);
|
||||||
|
anim.setInterpolator(mFastOutSlowInInterpolator);
|
||||||
|
anim.setDuration(250);
|
||||||
|
anim.start();
|
||||||
|
mProgressAnim = anim;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Runnable mTouchAgainRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Use mView to getString to prevent activity is missing during rotation
|
||||||
|
showError(mView.getContext().getString(
|
||||||
|
R.string.security_settings_fingerprint_enroll_lift_touch_again));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// private void updateOrientation(@NonNull GlifLayout glifLayout, int orientation) {
|
||||||
|
// switch (orientation) {
|
||||||
|
// case Configuration.ORIENTATION_LANDSCAPE: {
|
||||||
|
// mIllustrationLottie = null;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case Configuration.ORIENTATION_PORTRAIT: {
|
||||||
|
// if (shouldShowLottie()) {
|
||||||
|
// mIllustrationLottie = glifLayout.findViewById(R.id.illustration_lottie);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// default:
|
||||||
|
// Log.e(TAG, "Error unhandled configuration change");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private void animateFlash() {
|
||||||
|
if (mIconBackgroundBlinksDrawable != null) {
|
||||||
|
mIconBackgroundBlinksDrawable.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTitleAndDescription() {
|
||||||
|
final EnrollmentProgress progressLiveData =
|
||||||
|
mProgressViewModel.getProgressLiveData().getValue();
|
||||||
|
new GlifLayoutHelper(getActivity(), mView).setDescriptionText(mView.getContext().getString(
|
||||||
|
progressLiveData == null || progressLiveData.getSteps() == -1
|
||||||
|
? R.string.security_settings_fingerprint_enroll_start_message
|
||||||
|
: R.string.security_settings_fingerprint_enroll_repeat_message));
|
||||||
|
}
|
||||||
|
|
||||||
private void showIconTouchDialog() {
|
private void showIconTouchDialog() {
|
||||||
mIconTouchCount = 0;
|
mIconTouchCount = 0;
|
||||||
//TODO EnrollingActivity should observe live data and add dialog fragment
|
//TODO EnrollingActivity should observe live data and add dialog fragment
|
||||||
mEnrollingViewModel.onIconTouchDialogShow();
|
mEnrollingViewModel.onIconTouchDialogShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldShowLottie() {
|
private final Runnable mShowDialogRunnable = () -> showIconTouchDialog();
|
||||||
DisplayDensityUtils displayDensity = new DisplayDensityUtils(getContext());
|
|
||||||
int currentDensityIndex = displayDensity.getCurrentIndexForDefaultDisplay();
|
|
||||||
final int currentDensity = displayDensity.getDefaultDisplayDensityValues()
|
|
||||||
[currentDensityIndex];
|
|
||||||
final int defaultDensity = displayDensity.getDefaultDensityForDefaultDisplay();
|
|
||||||
return defaultDensity == currentDensity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable mShowDialogRunnable = new Runnable() {
|
private final Animator.AnimatorListener mProgressAnimationListener =
|
||||||
|
new Animator.AnimatorListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
stopIconAnimation();
|
||||||
|
|
||||||
|
if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
|
||||||
|
mProgressBar.postDelayed(mDelayedFinishRunnable, 250L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Give the user a chance to see progress completed before jumping to the next stage.
|
||||||
|
private final Runnable mDelayedFinishRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
showIconTouchDialog();
|
mEnrollingViewModel.onSkipButtonClick();
|
||||||
|
/* TODO launchFinish(); */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -16,15 +16,20 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.view;
|
package com.android.settings.biometrics2.ui.view;
|
||||||
|
|
||||||
|
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.RawRes;
|
import android.annotation.RawRes;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
import android.graphics.drawable.Animatable2;
|
import android.graphics.drawable.Animatable2;
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -39,11 +44,14 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.transition.Transition;
|
||||||
|
import androidx.transition.TransitionSet;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.biometrics.BiometricUtils;
|
|
||||||
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
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.DeviceRotationViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
||||||
@@ -51,6 +59,8 @@ import com.android.settingslib.display.DisplayDensityUtils;
|
|||||||
|
|
||||||
import com.airbnb.lottie.LottieAnimationView;
|
import com.airbnb.lottie.LottieAnimationView;
|
||||||
import com.airbnb.lottie.LottieCompositionFactory;
|
import com.airbnb.lottie.LottieCompositionFactory;
|
||||||
|
import com.airbnb.lottie.LottieProperty;
|
||||||
|
import com.airbnb.lottie.model.KeyPath;
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin;
|
import com.google.android.setupcompat.template.FooterBarMixin;
|
||||||
import com.google.android.setupcompat.template.FooterButton;
|
import com.google.android.setupcompat.template.FooterButton;
|
||||||
import com.google.android.setupdesign.GlifLayout;
|
import com.google.android.setupdesign.GlifLayout;
|
||||||
@@ -64,9 +74,9 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
|
|
||||||
private static final String TAG = FingerprintEnrollEnrollingSfpsFragment.class.getSimpleName();
|
private static final String TAG = FingerprintEnrollEnrollingSfpsFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final int PROGRESS_BAR_MAX = 10000;
|
||||||
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
||||||
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
|
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
|
||||||
private static final int HINT_TIMEOUT_DURATION = 2500;
|
|
||||||
|
|
||||||
private static final int STAGE_UNKNOWN = -1;
|
private static final int STAGE_UNKNOWN = -1;
|
||||||
private static final int SFPS_STAGE_NO_ANIMATION = 0;
|
private static final int SFPS_STAGE_NO_ANIMATION = 0;
|
||||||
@@ -84,8 +94,9 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
private Interpolator mFastOutLinearInInterpolator;
|
private Interpolator mFastOutLinearInInterpolator;
|
||||||
private boolean mAnimationCancelled;
|
private boolean mAnimationCancelled;
|
||||||
|
|
||||||
private View mView;
|
private GlifLayout mView;
|
||||||
private ProgressBar mProgressBar;
|
private ProgressBar mProgressBar;
|
||||||
|
private ObjectAnimator mProgressAnim;
|
||||||
private TextView mErrorText;
|
private TextView mErrorText;
|
||||||
private FooterBarMixin mFooterBarMixin;
|
private FooterBarMixin mFooterBarMixin;
|
||||||
private AnimatedVectorDrawable mIconAnimationDrawable;
|
private AnimatedVectorDrawable mIconAnimationDrawable;
|
||||||
@@ -103,6 +114,24 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
|
|
||||||
private final View.OnClickListener mOnSkipClickListener =
|
private final View.OnClickListener mOnSkipClickListener =
|
||||||
(v) -> mEnrollingViewModel.onSkipButtonClick();
|
(v) -> mEnrollingViewModel.onSkipButtonClick();
|
||||||
|
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerDownObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerUpObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
private int mIconTouchCount;
|
private int mIconTouchCount;
|
||||||
|
|
||||||
@@ -114,41 +143,73 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
||||||
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
|
final TransitionSet transitionSet = (TransitionSet) getSharedElementEnterTransition();
|
||||||
|
if (transitionSet != null) {
|
||||||
|
transitionSet.addListener(new Transition.TransitionListener() {
|
||||||
|
@Override
|
||||||
|
public void onTransitionStart(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionEnd(@NonNull Transition transition) {
|
||||||
|
transition.removeListener(this);
|
||||||
|
mAnimationCancelled = false;
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionCancel(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionPause(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionResume(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
mEnrollingViewModel.restoreSavedState(savedInstanceState);
|
||||||
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
mEnrollingViewModel.onSaveInstanceState(outState);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
mView = initSfpsLayout(inflater, container);
|
mView = initSfpsLayout(inflater, container);
|
||||||
final Configuration config = getActivity().getResources().getConfiguration();
|
|
||||||
maybeHideSfpsText(config);
|
|
||||||
return mView;
|
return mView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private View initSfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
private GlifLayout initSfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
||||||
final View containView = inflater.inflate(R.layout.sfps_enroll_enrolling, container, false);
|
final GlifLayout containView = (GlifLayout) inflater.inflate(R.layout.sfps_enroll_enrolling,
|
||||||
|
container, false);
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
|
||||||
(GlifLayout) containView);
|
|
||||||
glifLayoutHelper.setDescriptionText(
|
|
||||||
R.string.security_settings_fingerprint_enroll_start_message);
|
|
||||||
updateTitleAndDescription();
|
|
||||||
|
|
||||||
mShouldShowLottie = shouldShowLottie();
|
new GlifLayoutHelper(activity, containView).setDescriptionText(
|
||||||
boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
getString(R.string.security_settings_fingerprint_enroll_start_message));
|
||||||
|| BiometricUtils.isLandscape(activity);
|
|
||||||
updateOrientation((isLandscape
|
mShouldShowLottie = shouldShowLottie(); // Move shouldShowLottie into updateOrientation()?
|
||||||
? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
mIllustrationLottie = containView.findViewById(R.id.illustration_lottie);
|
||||||
|
|
||||||
mErrorText = containView.findViewById(R.id.error_text);
|
mErrorText = containView.findViewById(R.id.error_text);
|
||||||
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
|
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
|
||||||
mFooterBarMixin = ((GlifLayout) containView).getMixin(FooterBarMixin.class);
|
mFooterBarMixin = containView.getMixin(FooterBarMixin.class);
|
||||||
mFooterBarMixin.setSecondaryButton(
|
mFooterBarMixin.setSecondaryButton(
|
||||||
new FooterButton.Builder(activity)
|
new FooterButton.Builder(activity)
|
||||||
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
||||||
@@ -158,16 +219,6 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
final LayerDrawable fingerprintDrawable = mProgressBar != null
|
|
||||||
? (LayerDrawable) mProgressBar.getBackground() : null;
|
|
||||||
if (fingerprintDrawable != null) {
|
|
||||||
mIconAnimationDrawable = (AnimatedVectorDrawable)
|
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_animation);
|
|
||||||
mIconBackgroundBlinksDrawable = (AnimatedVectorDrawable)
|
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_background);
|
|
||||||
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_slow_in);
|
activity, android.R.interpolator.fast_out_slow_in);
|
||||||
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
@@ -175,37 +226,161 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_linear_in);
|
activity, android.R.interpolator.fast_out_linear_in);
|
||||||
|
|
||||||
if (mProgressBar != null) {
|
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
|
||||||
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
|
mProgressBar.setOnTouchListener((v, event) -> {
|
||||||
mProgressBar.setOnTouchListener((v, event) -> {
|
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
mIconTouchCount++;
|
||||||
mIconTouchCount++;
|
if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
|
||||||
if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
|
showIconTouchDialog();
|
||||||
showIconTouchDialog();
|
} else {
|
||||||
} else {
|
mProgressBar.postDelayed(mShowDialogRunnable,
|
||||||
mProgressBar.postDelayed(mShowDialogRunnable,
|
ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
|
||||||
ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
|
|
||||||
}
|
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
|
|
||||||
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
|
||||||
mProgressBar.removeCallbacks(mShowDialogRunnable);
|
|
||||||
}
|
}
|
||||||
return true;
|
} else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
|
||||||
});
|
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
||||||
}
|
mProgressBar.removeCallbacks(mShowDialogRunnable);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
maybeHideSfpsText(activity.getResources().getConfiguration());
|
||||||
return containView;
|
return containView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitleAndDescription() {
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
startEnrollment();
|
||||||
|
updateProgress(false /* animate */);
|
||||||
|
updateTitleAndDescription(new GlifLayoutHelper(getActivity(), mView));
|
||||||
|
if (true /* TODO mRestoring */) {
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Activity activity = getActivity();
|
@Override
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
public void onStop() {
|
||||||
(GlifLayout) mView);
|
stopIconAnimation();
|
||||||
|
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().removeObserver(mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().removeObserver(mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().removeObserver(mPointerUpObserver);
|
||||||
|
if (!getActivity().isChangingConfigurations()) {
|
||||||
|
mProgressViewModel.cancelEnrollment();
|
||||||
|
}
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startEnrollment() {
|
||||||
|
mProgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().observe(this, mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().observe(this, mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().observe(this, mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().observe(this, mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().observe(this, mPointerUpObserver);
|
||||||
|
mProgressViewModel.startEnrollment(ENROLL_ENROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(boolean animate) {
|
||||||
|
if (!mProgressViewModel.isEnrolling()) {
|
||||||
|
Log.d(TAG, "Enrollment not started yet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EnrollmentProgress enrollmentProgress =
|
||||||
|
mProgressViewModel.getProgressLiveData().getValue();
|
||||||
|
final int progress = getProgress(enrollmentProgress);
|
||||||
|
// Only clear the error when progress has been made.
|
||||||
|
// TODO (b/234772728) Add tests.
|
||||||
|
if (mProgressBar != null && mProgressBar.getProgress() < progress) {
|
||||||
|
clearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
animateProgress(progress);
|
||||||
|
} else {
|
||||||
|
if (mProgressBar != null) {
|
||||||
|
mProgressBar.setProgress(progress);
|
||||||
|
}
|
||||||
|
if (progress >= PROGRESS_BAR_MAX) {
|
||||||
|
mDelayedFinishRunnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getProgress(@NonNull EnrollmentProgress progress) {
|
||||||
|
if (progress.getSteps() == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int displayProgress = Math.max(0, progress.getSteps() + 1 - progress.getRemaining());
|
||||||
|
return PROGRESS_BAR_MAX * displayProgress / (progress.getSteps() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearError() {
|
||||||
|
applySfpsErrorDynamicColors(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies dynamic colors corresponding to showing or clearing errors on the progress bar
|
||||||
|
* and finger lottie for SFPS
|
||||||
|
*/
|
||||||
|
private void applySfpsErrorDynamicColors(boolean isError) {
|
||||||
|
applyProgressBarDynamicColor(isError);
|
||||||
|
if (mIllustrationLottie != null) {
|
||||||
|
applyLottieDynamicColor(isError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyProgressBarDynamicColor(boolean isError) {
|
||||||
|
final Context context = getActivity().getApplicationContext();
|
||||||
|
int error_color = context.getColor(R.color.sfps_enrollment_progress_bar_error_color);
|
||||||
|
int progress_bar_fill_color = context.getColor(
|
||||||
|
R.color.sfps_enrollment_progress_bar_fill_color);
|
||||||
|
ColorStateList fillColor = ColorStateList.valueOf(
|
||||||
|
isError ? error_color : progress_bar_fill_color);
|
||||||
|
mProgressBar.setProgressTintList(fillColor);
|
||||||
|
mProgressBar.setProgressTintMode(PorterDuff.Mode.SRC);
|
||||||
|
mProgressBar.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyLottieDynamicColor(boolean isError) {
|
||||||
|
final Context context = getActivity().getApplicationContext();
|
||||||
|
int error_color = context.getColor(R.color.sfps_enrollment_fp_error_color);
|
||||||
|
int fp_captured_color = context.getColor(R.color.sfps_enrollment_fp_captured_color);
|
||||||
|
int color = isError ? error_color : fp_captured_color;
|
||||||
|
mIllustrationLottie.addValueCallback(
|
||||||
|
new KeyPath(".blue100", "**"),
|
||||||
|
LottieProperty.COLOR_FILTER,
|
||||||
|
frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
||||||
|
);
|
||||||
|
mIllustrationLottie.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
// TODO stopListenOrientationEvent();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateProgress(int progress) {
|
||||||
|
if (mProgressAnim != null) {
|
||||||
|
mProgressAnim.cancel();
|
||||||
|
}
|
||||||
|
ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress",
|
||||||
|
mProgressBar.getProgress(), progress);
|
||||||
|
anim.addListener(mProgressAnimationListener);
|
||||||
|
anim.setInterpolator(mFastOutSlowInInterpolator);
|
||||||
|
anim.setDuration(250);
|
||||||
|
anim.start();
|
||||||
|
mProgressAnim = anim;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTitleAndDescription(@NonNull GlifLayoutHelper glifLayoutHelper) {
|
||||||
if (mIsAccessibilityEnabled) {
|
if (mIsAccessibilityEnabled) {
|
||||||
mEnrollingViewModel.clearTalkback();
|
mEnrollingViewModel.clearTalkback();
|
||||||
((GlifLayout) mView).getDescriptionTextView().setAccessibilityLiveRegion(
|
glifLayoutHelper.getGlifLayout().getDescriptionTextView().setAccessibilityLiveRegion(
|
||||||
View.ACCESSIBILITY_LIVE_REGION_POLITE);
|
View.ACCESSIBILITY_LIVE_REGION_POLITE);
|
||||||
}
|
}
|
||||||
switch (getCurrentSfpsStage()) {
|
switch (getCurrentSfpsStage()) {
|
||||||
@@ -273,12 +448,13 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
// announce a different string for a11y upon entering the page.
|
// announce a different string for a11y upon entering the page.
|
||||||
glifLayoutHelper.setHeaderText(
|
glifLayoutHelper.setHeaderText(
|
||||||
R.string.security_settings_sfps_enroll_find_sensor_title);
|
R.string.security_settings_sfps_enroll_find_sensor_title);
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_sfps_enroll_start_message);
|
R.string.security_settings_sfps_enroll_start_message));
|
||||||
final CharSequence description = getString(
|
final CharSequence description = getString(
|
||||||
R.string.security_settings_sfps_enroll_find_sensor_message);
|
R.string.security_settings_sfps_enroll_find_sensor_message);
|
||||||
((GlifLayout) mView).getHeaderTextView().setContentDescription(description);
|
glifLayoutHelper.getGlifLayout().getHeaderTextView().setContentDescription(
|
||||||
activity.setTitle(description);
|
description);
|
||||||
|
glifLayoutHelper.getActivity().setTitle(description);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -327,8 +503,8 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getStageThresholdSteps(int index) {
|
private int getStageThresholdSteps(int index) {
|
||||||
|
final EnrollmentProgress progressLiveData =
|
||||||
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
mProgressViewModel.getProgressLiveData().getValue();
|
||||||
|
|
||||||
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
||||||
Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
|
Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
|
||||||
@@ -338,7 +514,7 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
* mEnrollingViewModel.getEnrollStageThreshold(index));
|
* mEnrollingViewModel.getEnrollStageThreshold(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOrientation(int orientation) {
|
private void updateOrientation() {
|
||||||
mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
|
mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,9 +548,7 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
|
private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(),
|
new GlifLayoutHelper(getActivity(), mView).setDescriptionText(description);
|
||||||
(GlifLayout) mView);
|
|
||||||
glifLayoutHelper.setDescriptionText(description);
|
|
||||||
LottieCompositionFactory.fromRawRes(getActivity(), lottie)
|
LottieCompositionFactory.fromRawRes(getActivity(), lottie)
|
||||||
.addListener((c) -> {
|
.addListener((c) -> {
|
||||||
mIllustrationLottie.setComposition(c);
|
mIllustrationLottie.setComposition(c);
|
||||||
@@ -390,6 +564,38 @@ public class FingerprintEnrollEnrollingSfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final Animator.AnimatorListener mProgressAnimationListener =
|
||||||
|
new Animator.AnimatorListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
stopIconAnimation();
|
||||||
|
|
||||||
|
if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
|
||||||
|
mProgressBar.postDelayed(mDelayedFinishRunnable, 250L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Give the user a chance to see progress completed before jumping to the next stage.
|
||||||
|
private final Runnable mDelayedFinishRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
/* TODO launchFinish(); */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final Animatable2.AnimationCallback mIconAnimationCallback =
|
private final Animatable2.AnimationCallback mIconAnimationCallback =
|
||||||
new Animatable2.AnimationCallback() {
|
new Animatable2.AnimationCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
@@ -16,37 +16,39 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.view;
|
package com.android.settings.biometrics2.ui.view;
|
||||||
|
|
||||||
|
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
|
||||||
|
|
||||||
import android.annotation.RawRes;
|
import android.annotation.RawRes;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.drawable.Animatable2;
|
import android.graphics.drawable.Animatable2;
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable;
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.transition.Transition;
|
||||||
|
import androidx.transition.TransitionSet;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.biometrics.BiometricUtils;
|
import com.android.settings.biometrics.BiometricUtils;
|
||||||
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
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.DeviceRotationViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
||||||
@@ -67,6 +69,7 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
|
|
||||||
private static final String TAG = FingerprintEnrollEnrollingUdfpsFragment.class.getSimpleName();
|
private static final String TAG = FingerprintEnrollEnrollingUdfpsFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final int PROGRESS_BAR_MAX = 10000;
|
||||||
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
|
||||||
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
|
private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
|
||||||
private static final int HINT_TIMEOUT_DURATION = 2500;
|
private static final int HINT_TIMEOUT_DURATION = 2500;
|
||||||
@@ -94,8 +97,7 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
private boolean mHaveShownUdfpsCenterLottie;
|
private boolean mHaveShownUdfpsCenterLottie;
|
||||||
private boolean mHaveShownUdfpsGuideLottie;
|
private boolean mHaveShownUdfpsGuideLottie;
|
||||||
|
|
||||||
private View mView;
|
private GlifLayout mView;
|
||||||
private ProgressBar mProgressBar;
|
|
||||||
private TextView mErrorText;
|
private TextView mErrorText;
|
||||||
private FooterBarMixin mFooterBarMixin;
|
private FooterBarMixin mFooterBarMixin;
|
||||||
private AnimatedVectorDrawable mIconAnimationDrawable;
|
private AnimatedVectorDrawable mIconAnimationDrawable;
|
||||||
@@ -106,6 +108,24 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
|
|
||||||
private final View.OnClickListener mOnSkipClickListener =
|
private final View.OnClickListener mOnSkipClickListener =
|
||||||
(v) -> mEnrollingViewModel.onSkipButtonClick();
|
(v) -> mEnrollingViewModel.onSkipButtonClick();
|
||||||
|
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerDownObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
private final Observer<Integer> mPointerUpObserver = sensorId -> {
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
|
||||||
private int mIconTouchCount;
|
private int mIconTouchCount;
|
||||||
|
|
||||||
@@ -117,14 +137,53 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
||||||
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
|
final TransitionSet transitionSet = (TransitionSet) getSharedElementEnterTransition();
|
||||||
|
if (transitionSet != null) {
|
||||||
|
transitionSet.addListener(new Transition.TransitionListener() {
|
||||||
|
@Override
|
||||||
|
public void onTransitionStart(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionEnd(@NonNull Transition transition) {
|
||||||
|
transition.removeListener(this);
|
||||||
|
startEnrollment();
|
||||||
|
mAnimationCancelled = false;
|
||||||
|
startIconAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionCancel(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionPause(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransitionResume(@NonNull Transition transition) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
mEnrollingViewModel.restoreSavedState(savedInstanceState);
|
||||||
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
mEnrollingViewModel.onSaveInstanceState(outState);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
@@ -132,46 +191,44 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
return mView;
|
return mView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private View initUdfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
private GlifLayout initUdfpsLayout(LayoutInflater inflater, ViewGroup container) {
|
||||||
final View containView = inflater.inflate(R.layout.udfps_enroll_enrolling, container,
|
final GlifLayout containView = (GlifLayout) inflater.inflate(
|
||||||
false);
|
R.layout.udfps_enroll_enrolling, container, false);
|
||||||
|
|
||||||
final Activity activity = getActivity();
|
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
|
||||||
(GlifLayout) containView);
|
|
||||||
final int rotation = mRotationViewModel.getLiveData().getValue();
|
final int rotation = mRotationViewModel.getLiveData().getValue();
|
||||||
final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
|
|
||||||
Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL);
|
|
||||||
|
|
||||||
|
|
||||||
//TODO implement b/20653554
|
|
||||||
if (rotation == Surface.ROTATION_90) {
|
if (rotation == Surface.ROTATION_90) {
|
||||||
|
final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
|
||||||
|
Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL);
|
||||||
final LinearLayout layoutContainer = containView.findViewById(
|
final LinearLayout layoutContainer = containView.findViewById(
|
||||||
R.id.layout_container);
|
R.id.layout_container);
|
||||||
|
layoutContainer.setPaddingRelative(
|
||||||
|
(int) getResources().getDimension(R.dimen.rotation_90_enroll_padding_start),
|
||||||
|
0,
|
||||||
|
isLayoutRtl ? 0 : (int) getResources().getDimension(
|
||||||
|
R.dimen.rotation_90_enroll_padding_end),
|
||||||
|
0);
|
||||||
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
lp.setMarginEnd((int) getResources().getDimension(
|
lp.setMarginEnd((int) getResources().getDimension(
|
||||||
R.dimen.rotation_90_enroll_margin_end));
|
R.dimen.rotation_90_enroll_margin_end));
|
||||||
layoutContainer.setPaddingRelative((int) getResources().getDimension(
|
|
||||||
R.dimen.rotation_90_enroll_padding_start), 0, isLayoutRtl
|
|
||||||
? 0 : (int) getResources().getDimension(
|
|
||||||
R.dimen.rotation_90_enroll_padding_end), 0);
|
|
||||||
layoutContainer.setLayoutParams(lp);
|
layoutContainer.setLayoutParams(lp);
|
||||||
containView.setLayoutParams(lp);
|
containView.setLayoutParams(lp);
|
||||||
}
|
}
|
||||||
glifLayoutHelper.setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
|
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
new GlifLayoutHelper(activity, containView).setDescriptionText(
|
||||||
|
getString(R.string.security_settings_udfps_enroll_start_message));
|
||||||
updateTitleAndDescription();
|
updateTitleAndDescription();
|
||||||
|
|
||||||
mShouldShowLottie = shouldShowLottie();
|
mShouldShowLottie = shouldShowLottie();
|
||||||
boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
||||||
|| BiometricUtils.isLandscape(activity);
|
|| BiometricUtils.isLandscape(activity);
|
||||||
updateOrientation((isLandscape
|
updateOrientation(containView, (isLandscape
|
||||||
? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
||||||
|
|
||||||
mErrorText = containView.findViewById(R.id.error_text);
|
mErrorText = containView.findViewById(R.id.error_text);
|
||||||
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
|
mFooterBarMixin = containView.getMixin(FooterBarMixin.class);
|
||||||
mFooterBarMixin = ((GlifLayout) containView).getMixin(FooterBarMixin.class);
|
|
||||||
mFooterBarMixin.setSecondaryButton(
|
mFooterBarMixin.setSecondaryButton(
|
||||||
new FooterButton.Builder(activity)
|
new FooterButton.Builder(activity)
|
||||||
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
||||||
@@ -181,16 +238,6 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
final LayerDrawable fingerprintDrawable = mProgressBar != null
|
|
||||||
? (LayerDrawable) mProgressBar.getBackground() : null;
|
|
||||||
if (fingerprintDrawable != null) {
|
|
||||||
mIconAnimationDrawable = (AnimatedVectorDrawable)
|
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_animation);
|
|
||||||
mIconBackgroundBlinksDrawable = (AnimatedVectorDrawable)
|
|
||||||
fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_background);
|
|
||||||
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_slow_in);
|
activity, android.R.interpolator.fast_out_slow_in);
|
||||||
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
@@ -198,41 +245,100 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
|
||||||
activity, android.R.interpolator.fast_out_linear_in);
|
activity, android.R.interpolator.fast_out_linear_in);
|
||||||
|
|
||||||
if (mProgressBar != null) {
|
return containView;
|
||||||
mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.SRC);
|
}
|
||||||
mProgressBar.setOnTouchListener((v, event) -> {
|
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
@Override
|
||||||
mIconTouchCount++;
|
public void onStart() {
|
||||||
if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
|
super.onStart();
|
||||||
showIconTouchDialog();
|
if (true /* TODO mRestoring && !mIsCanceled */) {
|
||||||
} else {
|
startEnrollment();
|
||||||
mProgressBar.postDelayed(mShowDialogRunnable,
|
}
|
||||||
ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
|
updateProgress(false /* animate */, mProgressViewModel.getProgressLiveData().getValue());
|
||||||
}
|
updateTitleAndDescription();
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
|
if (true /* TODO mRestoring */) {
|
||||||
|| event.getActionMasked() == MotionEvent.ACTION_UP) {
|
startIconAnimation();
|
||||||
mProgressBar.removeCallbacks(mShowDialogRunnable);
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
stopIconAnimation();
|
||||||
|
removeEnrollmentObserver();
|
||||||
|
if (!getActivity().isChangingConfigurations()) {
|
||||||
|
mProgressViewModel.cancelEnrollment();
|
||||||
|
}
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeEnrollmentObserver() {
|
||||||
|
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().removeObserver(mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().removeObserver(mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().removeObserver(mPointerUpObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startEnrollment() {
|
||||||
|
mProgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
|
||||||
|
mProgressViewModel.getHelpMessageLiveData().observe(this, mHelpMessageObserver);
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().observe(this, mErrorMessageObserver);
|
||||||
|
mProgressViewModel.getAcquireLiveData().observe(this, mAcquireObserver);
|
||||||
|
mProgressViewModel.getPointerDownLiveData().observe(this, mPointerDownObserver);
|
||||||
|
mProgressViewModel.getPointerUpLiveData().observe(this, mPointerUpObserver);
|
||||||
|
mProgressViewModel.startEnrollment(ENROLL_ENROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(boolean animate, @NonNull EnrollmentProgress enrollmentProgress) {
|
||||||
|
if (!mProgressViewModel.isEnrolling()) {
|
||||||
|
Log.d(TAG, "Enrollment not started yet");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return containView;
|
final int progress = getProgress(enrollmentProgress);
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
animateProgress(progress);
|
||||||
|
} else if (progress >= PROGRESS_BAR_MAX) {
|
||||||
|
mDelayedFinishRunnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getProgress(@NonNull EnrollmentProgress progress) {
|
||||||
|
if (progress.getSteps() == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int displayProgress = Math.max(0, progress.getSteps() + 1 - progress.getRemaining());
|
||||||
|
return PROGRESS_BAR_MAX * displayProgress / (progress.getSteps() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
// TODO stopListenOrientationEvent();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateProgress(int progress) {
|
||||||
|
// UDFPS animations are owned by SystemUI
|
||||||
|
if (progress >= PROGRESS_BAR_MAX) {
|
||||||
|
// Wait for any animations in SysUI to finish, then proceed to next page
|
||||||
|
getActivity().getMainThreadHandler().postDelayed(mDelayedFinishRunnable, 400L);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitleAndDescription() {
|
private void updateTitleAndDescription() {
|
||||||
|
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity,
|
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(activity, mView);
|
||||||
(GlifLayout) mView);
|
|
||||||
|
|
||||||
switch (getCurrentStage()) {
|
switch (getCurrentStage()) {
|
||||||
case STAGE_CENTER:
|
case STAGE_CENTER:
|
||||||
glifLayoutHelper.setHeaderText(
|
glifLayoutHelper.setHeaderText(
|
||||||
R.string.security_settings_fingerprint_enroll_repeat_title);
|
R.string.security_settings_fingerprint_enroll_repeat_title);
|
||||||
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_udfps_enroll_start_message);
|
R.string.security_settings_udfps_enroll_start_message));
|
||||||
} else if (!mHaveShownUdfpsCenterLottie && mIllustrationLottie != null) {
|
} else if (!mHaveShownUdfpsCenterLottie && mIllustrationLottie != null) {
|
||||||
mHaveShownUdfpsCenterLottie = true;
|
mHaveShownUdfpsCenterLottie = true;
|
||||||
// Note: Update string reference when differentiate in between udfps & sfps
|
// Note: Update string reference when differentiate in between udfps & sfps
|
||||||
@@ -247,8 +353,8 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
glifLayoutHelper.setHeaderText(
|
glifLayoutHelper.setHeaderText(
|
||||||
R.string.security_settings_fingerprint_enroll_repeat_title);
|
R.string.security_settings_fingerprint_enroll_repeat_title);
|
||||||
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_udfps_enroll_repeat_a11y_message);
|
R.string.security_settings_udfps_enroll_repeat_a11y_message));
|
||||||
} else if (!mHaveShownUdfpsGuideLottie && mIllustrationLottie != null) {
|
} else if (!mHaveShownUdfpsGuideLottie && mIllustrationLottie != null) {
|
||||||
mHaveShownUdfpsGuideLottie = true;
|
mHaveShownUdfpsGuideLottie = true;
|
||||||
mIllustrationLottie.setContentDescription(
|
mIllustrationLottie.setContentDescription(
|
||||||
@@ -280,11 +386,11 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
configureEnrollmentStage("", R.raw.udfps_left_edge_hint_lottie);
|
configureEnrollmentStage("", R.raw.udfps_left_edge_hint_lottie);
|
||||||
} else if (mIllustrationLottie == null) {
|
} else if (mIllustrationLottie == null) {
|
||||||
if (isStageHalfCompleted()) {
|
if (isStageHalfCompleted()) {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_fingerprint_enroll_repeat_message);
|
R.string.security_settings_fingerprint_enroll_repeat_message));
|
||||||
} else {
|
} else {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_udfps_enroll_edge_message);
|
R.string.security_settings_udfps_enroll_edge_message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -300,11 +406,11 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
|
|
||||||
} else if (mIllustrationLottie == null) {
|
} else if (mIllustrationLottie == null) {
|
||||||
if (isStageHalfCompleted()) {
|
if (isStageHalfCompleted()) {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_fingerprint_enroll_repeat_message);
|
R.string.security_settings_fingerprint_enroll_repeat_message));
|
||||||
} else {
|
} else {
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_udfps_enroll_edge_message);
|
R.string.security_settings_udfps_enroll_edge_message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -317,11 +423,11 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
// announce a different string for a11y upon entering the page.
|
// announce a different string for a11y upon entering the page.
|
||||||
glifLayoutHelper.setHeaderText(
|
glifLayoutHelper.setHeaderText(
|
||||||
R.string.security_settings_fingerprint_enroll_udfps_title);
|
R.string.security_settings_fingerprint_enroll_udfps_title);
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_udfps_enroll_start_message);
|
R.string.security_settings_udfps_enroll_start_message));
|
||||||
final CharSequence description = getString(
|
final CharSequence description = getString(
|
||||||
R.string.security_settings_udfps_enroll_a11y);
|
R.string.security_settings_udfps_enroll_a11y);
|
||||||
((GlifLayout) mView).getHeaderTextView().setContentDescription(description);
|
mView.getHeaderTextView().setContentDescription(description);
|
||||||
activity.setTitle(description);
|
activity.setTitle(description);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -337,7 +443,7 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
return defaultDensity == currentDensity;
|
return defaultDensity == currentDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOrientation(int orientation) {
|
private void updateOrientation(@NonNull GlifLayout glifLayout, int orientation) {
|
||||||
switch (orientation) {
|
switch (orientation) {
|
||||||
case Configuration.ORIENTATION_LANDSCAPE: {
|
case Configuration.ORIENTATION_LANDSCAPE: {
|
||||||
mIllustrationLottie = null;
|
mIllustrationLottie = null;
|
||||||
@@ -345,7 +451,7 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
case Configuration.ORIENTATION_PORTRAIT: {
|
case Configuration.ORIENTATION_PORTRAIT: {
|
||||||
if (mShouldShowLottie) {
|
if (mShouldShowLottie) {
|
||||||
mIllustrationLottie = mView.findViewById(R.id.illustration_lottie);
|
mIllustrationLottie = glifLayout.findViewById(R.id.illustration_lottie);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -390,7 +496,6 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStageHalfCompleted() {
|
private boolean isStageHalfCompleted() {
|
||||||
|
|
||||||
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
||||||
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
||||||
return false;
|
return false;
|
||||||
@@ -431,9 +536,7 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
|
private void configureEnrollmentStage(CharSequence description, @RawRes int lottie) {
|
||||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(),
|
new GlifLayoutHelper(getActivity(), mView).setDescriptionText(description);
|
||||||
(GlifLayout) mView);
|
|
||||||
glifLayoutHelper.setDescriptionText(description);
|
|
||||||
LottieCompositionFactory.fromRawRes(getActivity(), lottie)
|
LottieCompositionFactory.fromRawRes(getActivity(), lottie)
|
||||||
.addListener((c) -> {
|
.addListener((c) -> {
|
||||||
mIllustrationLottie.setComposition(c);
|
mIllustrationLottie.setComposition(c);
|
||||||
@@ -449,6 +552,14 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Give the user a chance to see progress completed before jumping to the next stage.
|
||||||
|
private final Runnable mDelayedFinishRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
/* TODO launchFinish(); */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final Animatable2.AnimationCallback mIconAnimationCallback =
|
private final Animatable2.AnimationCallback mIconAnimationCallback =
|
||||||
new Animatable2.AnimationCallback() {
|
new Animatable2.AnimationCallback() {
|
||||||
@Override
|
@Override
|
||||||
@@ -458,13 +569,14 @@ public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start animation after it has ended.
|
// Start animation after it has ended.
|
||||||
|
/* TODO check mProgressBar?
|
||||||
mProgressBar.post(new Runnable() {
|
mProgressBar.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
startIconAnimation();
|
startIconAnimation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import static android.view.View.OnClickListener;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -37,6 +38,7 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation;
|
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation;
|
||||||
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
|
||||||
|
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ public class FingerprintEnrollFindRfpsFragment extends Fragment {
|
|||||||
private static final String TAG = "FingerprintEnrollFindRfpsFragment";
|
private static final String TAG = "FingerprintEnrollFindRfpsFragment";
|
||||||
|
|
||||||
private FingerprintEnrollFindSensorViewModel mViewModel;
|
private FingerprintEnrollFindSensorViewModel mViewModel;
|
||||||
private FingerprintEnrollProgressViewModel mPorgressViewModel;
|
private FingerprintEnrollProgressViewModel mProgressViewModel;
|
||||||
|
|
||||||
private View mView;
|
private View mView;
|
||||||
private GlifLayout mGlifLayout;
|
private GlifLayout mGlifLayout;
|
||||||
@@ -77,7 +79,21 @@ public class FingerprintEnrollFindRfpsFragment extends Fragment {
|
|||||||
Log.d(TAG, "mProgressObserver(" + progress + ")");
|
Log.d(TAG, "mProgressObserver(" + progress + ")");
|
||||||
}
|
}
|
||||||
if (progress != null && !progress.isInitialStep()) {
|
if (progress != null && !progress.isInitialStep()) {
|
||||||
mViewModel.onStartButtonClick();
|
stopLookingForFingerprint(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Observer<EnrollmentStatusMessage> mLastCancelMessageObserver = errorMessage -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mErrorMessageObserver(" + errorMessage + ")");
|
||||||
|
}
|
||||||
|
if (errorMessage != null) {
|
||||||
|
if (errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
|
||||||
|
mProgressViewModel.clearProgressLiveData();
|
||||||
|
mViewModel.onStartButtonClick();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "mErrorMessageObserver(" + errorMessage + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,40 +167,48 @@ public class FingerprintEnrollFindRfpsFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
final boolean isEnrolling = mProgressViewModel.isEnrolling();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onStop(), stop looking for fingerprint, animation exist:"
|
Log.d(TAG, "onStop(), current enrolling: " + isEnrolling + ", animation exist:"
|
||||||
+ (mAnimation != null));
|
+ (mAnimation != null));
|
||||||
}
|
}
|
||||||
stopLookingForFingerprint();
|
if (!isEnrolling) {
|
||||||
|
stopLookingForFingerprint(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startLookingForFingerprint() {
|
private void startLookingForFingerprint() {
|
||||||
if (mPorgressViewModel.isEnrolling()) {
|
if (mProgressViewModel.isEnrolling()) {
|
||||||
Log.d(TAG, "startLookingForFingerprint(), failed because isEnrolling is true before"
|
Log.d(TAG, "startLookingForFingerprint(), failed because isEnrolling is true before"
|
||||||
+ " starting");
|
+ " starting");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPorgressViewModel.clearProgressLiveData();
|
mProgressViewModel.clearProgressLiveData();
|
||||||
mPorgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
|
mProgressViewModel.getProgressLiveData().observe(this, mProgressObserver);
|
||||||
final boolean startResult = mPorgressViewModel.startEnrollment(ENROLL_FIND_SENSOR);
|
final boolean startResult = mProgressViewModel.startEnrollment(ENROLL_FIND_SENSOR);
|
||||||
if (!startResult) {
|
if (!startResult) {
|
||||||
Log.e(TAG, "startLookingForFingerprint(), failed to start enrollment");
|
Log.e(TAG, "startLookingForFingerprint(), failed to start enrollment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopLookingForFingerprint() {
|
private void stopLookingForFingerprint(boolean waitForLastCancelErrMsg) {
|
||||||
if (!mPorgressViewModel.isEnrolling()) {
|
if (!mProgressViewModel.isEnrolling()) {
|
||||||
Log.d(TAG, "stopLookingForFingerprint(), failed because isEnrolling is false before"
|
Log.d(TAG, "stopLookingForFingerprint(), failed because isEnrolling is false before"
|
||||||
+ " stopping");
|
+ " stopping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPorgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
||||||
final boolean cancelResult = mPorgressViewModel.cancelEnrollment();
|
final boolean cancelResult = mProgressViewModel.cancelEnrollment();
|
||||||
if (!cancelResult) {
|
if (!cancelResult) {
|
||||||
Log.e(TAG, "stopLookingForFingerprint(), failed to cancel enrollment");
|
Log.e(TAG, "stopLookingForFingerprint(), failed to cancel enrollment");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waitForLastCancelErrMsg) {
|
||||||
|
mProgressViewModel.getErrorMessageLiveData().observe(this,
|
||||||
|
mLastCancelMessageObserver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -203,7 +227,7 @@ public class FingerprintEnrollFindRfpsFragment extends Fragment {
|
|||||||
final FragmentActivity activity = getActivity();
|
final FragmentActivity activity = getActivity();
|
||||||
final ViewModelProvider provider = new ViewModelProvider(activity);
|
final ViewModelProvider provider = new ViewModelProvider(activity);
|
||||||
mViewModel = provider.get(FingerprintEnrollFindSensorViewModel.class);
|
mViewModel = provider.get(FingerprintEnrollFindSensorViewModel.class);
|
||||||
mPorgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -98,6 +98,7 @@ public class FingerprintEnrollFindSfpsFragment extends Fragment {
|
|||||||
Log.d(TAG, "mProgressObserver(" + progress + ")");
|
Log.d(TAG, "mProgressObserver(" + progress + ")");
|
||||||
}
|
}
|
||||||
if (progress != null && !progress.isInitialStep()) {
|
if (progress != null && !progress.isInitialStep()) {
|
||||||
|
mProgressViewModel.clearProgressLiveData();
|
||||||
mViewModel.onStartButtonClick();
|
mViewModel.onStartButtonClick();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -85,15 +85,15 @@ public class FingerprintEnrollFinishFragment extends Fragment {
|
|||||||
(GlifLayout) mView);
|
(GlifLayout) mView);
|
||||||
|
|
||||||
glifLayoutHelper.setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title);
|
glifLayoutHelper.setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title);
|
||||||
glifLayoutHelper.setDescriptionText(
|
glifLayoutHelper.setDescriptionText(getString(
|
||||||
R.string.security_settings_fingerprint_enroll_finish_v2_message);
|
R.string.security_settings_fingerprint_enroll_finish_v2_message));
|
||||||
|
|
||||||
final int maxEnrollments = mFingerprintEnrollFinishViewModel.getMaxFingerprints();
|
final int maxEnrollments = mFingerprintEnrollFinishViewModel.getMaxFingerprints();
|
||||||
final int enrolled = mFingerprintEnrollFinishViewModel.getNumOfEnrolledFingerprintsSize();
|
final int enrolled = mFingerprintEnrollFinishViewModel.getNumOfEnrolledFingerprintsSize();
|
||||||
if (mCanAssumeSfps) {
|
if (mCanAssumeSfps) {
|
||||||
if (enrolled < maxEnrollments) {
|
if (enrolled < maxEnrollments) {
|
||||||
glifLayoutHelper.setDescriptionText(R.string
|
glifLayoutHelper.setDescriptionText(getString(R.string
|
||||||
.security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message);
|
.security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewMo
|
|||||||
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
|
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE;
|
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE;
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID;
|
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID;
|
||||||
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.ErrorDialogData;
|
||||||
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_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_SKIP;
|
||||||
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
|
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
|
||||||
@@ -63,8 +64,8 @@ import androidx.lifecycle.viewmodel.MutableCreationExtras;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
|
import com.android.settings.biometrics.fingerprint.FingerprintEnrollFinish;
|
||||||
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollEnrolling;
|
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFinish;
|
||||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
||||||
import com.android.settings.biometrics2.factory.BiometricsViewModelFactory;
|
import com.android.settings.biometrics2.factory.BiometricsViewModelFactory;
|
||||||
import com.android.settings.biometrics2.ui.model.CredentialModel;
|
import com.android.settings.biometrics2.ui.model.CredentialModel;
|
||||||
@@ -72,6 +73,7 @@ import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
|
|||||||
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator;
|
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.DeviceFoldedViewModel;
|
||||||
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel;
|
||||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
||||||
@@ -88,11 +90,16 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
private static final String TAG = "FingerprintEnrollmentActivity";
|
private static final String TAG = "FingerprintEnrollmentActivity";
|
||||||
|
|
||||||
private static final String INTRO_TAG = "enroll-intro";
|
private static final String INTRO_TAG = "intro";
|
||||||
private static final String FIND_UDFPS_TAG = "enroll-find-udfps";
|
private static final String FIND_UDFPS_TAG = "find-udfps";
|
||||||
private static final String FIND_SFPS_TAG = "enroll-find-sfps";
|
private static final String FIND_SFPS_TAG = "find-sfps";
|
||||||
private static final String FIND_RFPS_TAG = "enroll-find-rfps";
|
private static final String FIND_RFPS_TAG = "find-rfps";
|
||||||
|
private static final String ENROLLING_UDFPS_TAG = "enrolling-udfps";
|
||||||
|
private static final String ENROLLING_SFPS_TAG = "enrolling-sfps";
|
||||||
|
private static final String ENROLLING_RFPS_TAG = "enrolling-rfps";
|
||||||
|
private static final String FINISH_TAG = "finish";
|
||||||
private static final String SKIP_SETUP_FIND_FPS_DIALOG_TAG = "skip-setup-dialog";
|
private static final String SKIP_SETUP_FIND_FPS_DIALOG_TAG = "skip-setup-dialog";
|
||||||
|
private static final String ENROLLING_ERROR_DIALOG_TAG = "enrolling-error-dialog";
|
||||||
|
|
||||||
protected static final int LAUNCH_CONFIRM_LOCK_ACTIVITY = 1;
|
protected static final int LAUNCH_CONFIRM_LOCK_ACTIVITY = 1;
|
||||||
|
|
||||||
@@ -115,6 +122,22 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
onFindSensorAction(action);
|
onFindSensorAction(action);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private final Observer<Boolean> mEnrollingDoneObserver = isDone -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mEnrollingDoneObserver(" + isDone + ")");
|
||||||
|
}
|
||||||
|
if (isDone != null) {
|
||||||
|
onEnrollingDone(isDone);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final Observer<ErrorDialogData> mEnrollingErrorDialogObserver = data -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mEnrollingErrorDialogObserver(" + data + ")");
|
||||||
|
}
|
||||||
|
if (data != null) {
|
||||||
|
startEnrollingErrorDialog();
|
||||||
|
}
|
||||||
|
};
|
||||||
private final ActivityResultCallback<ActivityResult> mNextActivityResultCallback =
|
private final ActivityResultCallback<ActivityResult> mNextActivityResultCallback =
|
||||||
result -> mViewModel.onContinueEnrollActivityResult(result,
|
result -> mViewModel.onContinueEnrollActivityResult(result,
|
||||||
mAutoCredentialViewModel.getUserId());
|
mAutoCredentialViewModel.getUserId());
|
||||||
@@ -154,6 +177,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
} else {
|
} else {
|
||||||
final FragmentManager manager = getSupportFragmentManager();
|
final FragmentManager manager = getSupportFragmentManager();
|
||||||
String[] tags = new String[] {
|
String[] tags = new String[] {
|
||||||
|
ENROLLING_UDFPS_TAG,
|
||||||
|
ENROLLING_SFPS_TAG,
|
||||||
|
ENROLLING_RFPS_TAG,
|
||||||
FIND_UDFPS_TAG,
|
FIND_UDFPS_TAG,
|
||||||
FIND_SFPS_TAG,
|
FIND_SFPS_TAG,
|
||||||
FIND_RFPS_TAG,
|
FIND_RFPS_TAG,
|
||||||
@@ -169,7 +195,12 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
}
|
}
|
||||||
if (tag.equals(INTRO_TAG)) {
|
if (tag.equals(INTRO_TAG)) {
|
||||||
attachIntroViewModel();
|
attachIntroViewModel();
|
||||||
} else { // FIND_UDFPS_TAG, FIND_SFPS_TAG, FIND_RFPS_TAG
|
} else if (tag.equals(FIND_UDFPS_TAG) || tag.equals(FIND_SFPS_TAG)
|
||||||
|
|| tag.equals(FIND_RFPS_TAG)) {
|
||||||
|
attachFindSensorViewModel();
|
||||||
|
attachIntroViewModel();
|
||||||
|
} else { // ENROLLING_UDFPS_TAG, ENROLLING_SFPS_TAG, ENROLLING_RFPS_TAG
|
||||||
|
attachEnrollingViewModel();
|
||||||
attachFindSensorViewModel();
|
attachFindSensorViewModel();
|
||||||
attachIntroViewModel();
|
attachIntroViewModel();
|
||||||
}
|
}
|
||||||
@@ -205,35 +236,29 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
|
|
||||||
// We need to make sure token is valid before entering find sensor page
|
// We need to make sure token is valid before entering find sensor page
|
||||||
private void startFindSensorFragment() {
|
private void startFindSensorFragment() {
|
||||||
attachFindSensorViewModel();
|
// Always setToken into progressViewModel even it is not necessary action for UDFPS
|
||||||
if (mViewModel.canAssumeUdfps()) {
|
mViewModelProvider.get(FingerprintEnrollProgressViewModel.class)
|
||||||
// UDFPS does not need to start real fingerprint enrolling during finding sensor
|
.setToken(mAutoCredentialViewModel.getToken());
|
||||||
startFindFpsFragmentWithProgressViewModel(FingerprintEnrollFindUdfpsFragment.class,
|
|
||||||
FIND_UDFPS_TAG, false /* initProgressViewModel */);
|
|
||||||
} else if (mViewModel.canAssumeSfps()) {
|
|
||||||
startFindFpsFragmentWithProgressViewModel(FingerprintEnrollFindSfpsFragment.class,
|
|
||||||
FIND_SFPS_TAG, true /* initProgressViewModel */);
|
|
||||||
} else {
|
|
||||||
startFindFpsFragmentWithProgressViewModel(FingerprintEnrollFindRfpsFragment.class,
|
|
||||||
FIND_RFPS_TAG, true /* initProgressViewModel */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startFindFpsFragmentWithProgressViewModel(
|
attachFindSensorViewModel();
|
||||||
@NonNull Class<? extends Fragment> findFpsClass, @NonNull String tag,
|
|
||||||
boolean initProgressViewModel) {
|
final String tag;
|
||||||
if (initProgressViewModel) {
|
final Class<? extends Fragment> fragmentClass;
|
||||||
final FingerprintEnrollProgressViewModel progressViewModel =
|
if (mViewModel.canAssumeUdfps()) {
|
||||||
mViewModelProvider.get(FingerprintEnrollProgressViewModel.class);
|
tag = FIND_UDFPS_TAG;
|
||||||
progressViewModel.setToken(mAutoCredentialViewModel.getToken());
|
fragmentClass = FingerprintEnrollFindUdfpsFragment.class;
|
||||||
|
} else if (mViewModel.canAssumeSfps()) {
|
||||||
|
tag = FIND_SFPS_TAG;
|
||||||
|
fragmentClass = FingerprintEnrollFindSfpsFragment.class;
|
||||||
|
} else {
|
||||||
|
tag = FIND_RFPS_TAG;
|
||||||
|
fragmentClass = FingerprintEnrollFindRfpsFragment.class;
|
||||||
}
|
}
|
||||||
final FingerprintEnrollFindSensorViewModel findSensorViewModel =
|
|
||||||
mViewModelProvider.get(FingerprintEnrollFindSensorViewModel.class);
|
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setReorderingAllowed(true)
|
.setReorderingAllowed(true)
|
||||||
.setCustomAnimations(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out,
|
.setCustomAnimations(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out,
|
||||||
R.anim.sud_slide_back_in, R.anim.sud_slide_back_out)
|
R.anim.sud_slide_back_in, R.anim.sud_slide_back_out)
|
||||||
.replace(R.id.fragment_container_view, findFpsClass, null, tag)
|
.replace(R.id.fragment_container_view, fragmentClass, null, tag)
|
||||||
.addToBackStack(tag)
|
.addToBackStack(tag)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
@@ -248,11 +273,68 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
findSensorViewModel.getActionLiveData().observe(this, mFindSensorActionObserver);
|
findSensorViewModel.getActionLiveData().observe(this, mFindSensorActionObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startEnrollingFragment() {
|
||||||
|
// Always setToken into progressViewModel even it is not necessary action for SFPS or RFPS
|
||||||
|
mViewModelProvider.get(FingerprintEnrollProgressViewModel.class)
|
||||||
|
.setToken(mAutoCredentialViewModel.getToken());
|
||||||
|
|
||||||
|
attachEnrollingViewModel();
|
||||||
|
|
||||||
|
final String tag;
|
||||||
|
final Class<? extends Fragment> fragmentClass;
|
||||||
|
if (mViewModel.canAssumeUdfps()) {
|
||||||
|
tag = ENROLLING_UDFPS_TAG;
|
||||||
|
fragmentClass = FingerprintEnrollEnrollingUdfpsFragment.class;
|
||||||
|
} else if (mViewModel.canAssumeSfps()) {
|
||||||
|
tag = ENROLLING_SFPS_TAG;
|
||||||
|
fragmentClass = FingerprintEnrollEnrollingSfpsFragment.class;
|
||||||
|
} else {
|
||||||
|
tag = ENROLLING_RFPS_TAG;
|
||||||
|
fragmentClass = FingerprintEnrollEnrollingRfpsFragment.class;
|
||||||
|
}
|
||||||
|
getSupportFragmentManager().beginTransaction()
|
||||||
|
.setReorderingAllowed(true)
|
||||||
|
.setCustomAnimations(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out,
|
||||||
|
R.anim.sud_slide_back_in, R.anim.sud_slide_back_out)
|
||||||
|
.replace(R.id.fragment_container_view, fragmentClass, null, tag)
|
||||||
|
.addToBackStack(tag)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachEnrollingViewModel() {
|
||||||
|
final FingerprintEnrollEnrollingViewModel enrollingViewModel =
|
||||||
|
mViewModelProvider.get(FingerprintEnrollEnrollingViewModel.class);
|
||||||
|
enrollingViewModel.clearBackPressedData();
|
||||||
|
enrollingViewModel.getErrorDialogLiveData().observe(this, mEnrollingErrorDialogObserver);
|
||||||
|
|
||||||
|
final FingerprintEnrollProgressViewModel progressViewModel =
|
||||||
|
mViewModelProvider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
|
progressViewModel.getDoneLiveData().observe(this, mEnrollingDoneObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startFinishActivity() {
|
||||||
|
final boolean isSuw = mViewModel.getRequest().isSuw();
|
||||||
|
if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) {
|
||||||
|
Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag");
|
||||||
|
}
|
||||||
|
Intent intent = new Intent(this, isSuw
|
||||||
|
? SetupFingerprintEnrollFinish.class
|
||||||
|
: FingerprintEnrollFinish.class);
|
||||||
|
intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra());
|
||||||
|
intent.putExtras(mViewModel.getNextActivityBaseIntentExtras());
|
||||||
|
mNextActivityLauncher.launch(intent);
|
||||||
|
}
|
||||||
|
|
||||||
private void startSkipSetupFindFpsDialog() {
|
private void startSkipSetupFindFpsDialog() {
|
||||||
new SkipSetupFindFpsDialog().show(getSupportFragmentManager(),
|
new SkipSetupFindFpsDialog().show(getSupportFragmentManager(),
|
||||||
SKIP_SETUP_FIND_FPS_DIALOG_TAG);
|
SKIP_SETUP_FIND_FPS_DIALOG_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startEnrollingErrorDialog() {
|
||||||
|
new FingerprintEnrollEnrollingErrorDialog().show(getSupportFragmentManager(),
|
||||||
|
ENROLLING_ERROR_DIALOG_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) {
|
private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) {
|
||||||
onSetActivityResult(new ActivityResult(RESULT_CANCELED, null));
|
onSetActivityResult(new ActivityResult(RESULT_CANCELED, null));
|
||||||
}
|
}
|
||||||
@@ -365,26 +447,43 @@ public class FingerprintEnrollmentActivity extends FragmentActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START: {
|
case FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START: {
|
||||||
final boolean isSuw = mViewModel.getRequest().isSuw();
|
startEnrollingFragment();
|
||||||
if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) {
|
|
||||||
Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag");
|
|
||||||
}
|
|
||||||
Intent intent = new Intent(this, isSuw
|
|
||||||
? SetupFingerprintEnrollEnrolling.class
|
|
||||||
: FingerprintEnrollEnrolling.class);
|
|
||||||
intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra());
|
|
||||||
intent.putExtras(mViewModel.getNextActivityBaseIntentExtras());
|
|
||||||
mNextActivityLauncher.launch(intent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onEnrollingDone(boolean isDone) {
|
||||||
|
if (!isDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final FingerprintEnrollProgressViewModel progressViewModel =
|
||||||
|
mViewModelProvider.get(FingerprintEnrollProgressViewModel.class);
|
||||||
|
progressViewModel.clearProgressLiveData();
|
||||||
|
|
||||||
|
startFinishActivity();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mViewModel.checkFinishActivityDuringOnPause(isFinishing(), isChangingConfigurations());
|
mViewModel.checkFinishActivityDuringOnPause(isFinishing(), isChangingConfigurations());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
final FragmentManager manager = getSupportFragmentManager();
|
||||||
|
final String[] tags = new String[] {ENROLLING_UDFPS_TAG, ENROLLING_SFPS_TAG,
|
||||||
|
ENROLLING_RFPS_TAG };
|
||||||
|
for (String tag: tags) {
|
||||||
|
final Fragment fragment = manager.findFragmentByTag(tag);
|
||||||
|
if (fragment != null) {
|
||||||
|
mViewModelProvider.get(FingerprintEnrollEnrollingViewModel.class).onBackPressed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid, boolean first) {
|
protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid, boolean first) {
|
||||||
theme.applyStyle(R.style.SetupWizardPartnerResource, true);
|
theme.applyStyle(R.style.SetupWizardPartnerResource, true);
|
||||||
|
@@ -68,15 +68,13 @@ public class GlifLayoutHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@NonNull
|
||||||
* Sets description resId to GlifLayout
|
public Activity getActivity() {
|
||||||
*/
|
return mActivity;
|
||||||
public void setDescriptionText(int resId) {
|
}
|
||||||
CharSequence previousDescription = mGlifLayout.getDescriptionText();
|
|
||||||
CharSequence description = mActivity.getString(resId);
|
@NonNull
|
||||||
// Prevent a11y for re-reading the same string
|
public GlifLayout getGlifLayout() {
|
||||||
if (!TextUtils.equals(previousDescription, description)) {
|
return mGlifLayout;
|
||||||
mGlifLayout.setDescriptionText(resId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,26 +16,32 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics2.ui.viewmodel;
|
package com.android.settings.biometrics2.ui.viewmodel;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.VibrationAttributes;
|
import android.os.VibrationAttributes;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import com.android.settings.biometrics2.data.repository.AccessibilityRepository;
|
import com.android.settings.biometrics2.data.repository.AccessibilityRepository;
|
||||||
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
|
||||||
import com.android.settings.biometrics2.data.repository.VibratorRepository;
|
import com.android.settings.biometrics2.data.repository.VibratorRepository;
|
||||||
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewModel explaining the fingerprint enrolling page
|
* ViewModel explaining the fingerprint enrolling page
|
||||||
*/
|
*/
|
||||||
public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel
|
public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel {
|
||||||
implements DefaultLifecycleObserver {
|
|
||||||
|
|
||||||
private static final String TAG = FingerprintEnrollEnrollingViewModel.class.getSimpleName();
|
private static final String TAG = FingerprintEnrollEnrollingViewModel.class.getSimpleName();
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
@@ -45,34 +51,117 @@ public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel
|
|||||||
private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
|
private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
|
||||||
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY);
|
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY);
|
||||||
|
|
||||||
//Enrolling skip
|
/**
|
||||||
|
* Enrolling skipped
|
||||||
|
*/
|
||||||
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP = 0;
|
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP = 0;
|
||||||
|
|
||||||
//Icon touch dialog show
|
/**
|
||||||
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_DIALOG = 0;
|
* Enrolling finished
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE = 1;
|
||||||
|
|
||||||
//Icon touch dialog dismiss
|
/**
|
||||||
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_DIALOG = 1;
|
* Icon touch dialog show
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_DIALOG = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon touch dialog dismiss
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_DIALOG = 3;
|
||||||
|
|
||||||
|
@IntDef(prefix = { "FINGERPRINT_ENROLL_ENROLLING_ACTION_" }, value = {
|
||||||
|
FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP,
|
||||||
|
FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE,
|
||||||
|
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_DIALOG,
|
||||||
|
FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_DIALOG
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface FingerprintEnrollEnrollingAction {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enrolling skipped
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enrolling finished
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon touch dialog show
|
||||||
|
*/
|
||||||
|
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_RESTART = 2;
|
||||||
|
|
||||||
|
@IntDef(prefix = { "FINGERPRINT_ERROR_DIALOG_ACTION_" }, value = {
|
||||||
|
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH,
|
||||||
|
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT,
|
||||||
|
FINGERPRINT_ERROR_DIALOG_ACTION_RESTART
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface FingerprintErrorDialogAction {}
|
||||||
|
|
||||||
|
|
||||||
|
private final int mUserId;
|
||||||
private final FingerprintRepository mFingerprintRepository;
|
private final FingerprintRepository mFingerprintRepository;
|
||||||
private final AccessibilityRepository mAccessibilityRepository;
|
private final AccessibilityRepository mAccessibilityRepository;
|
||||||
private final VibratorRepository mVibratorRepository;
|
private final VibratorRepository mVibratorRepository;
|
||||||
|
|
||||||
private EnrollmentRequest mEnrollmentRequest = null;
|
private final MutableLiveData<Boolean> mBackPressedLiveData = new MutableLiveData<>(false);
|
||||||
private final MutableLiveData<Integer> mEnrollingLiveData = new MutableLiveData<>();
|
private final MutableLiveData<Integer> mEnrollingLiveData = new MutableLiveData<>();
|
||||||
private final MutableLiveData<Integer> mIconTouchDialogLiveData = new MutableLiveData<>();
|
private final MutableLiveData<Integer> mIconTouchDialogLiveData = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<ErrorDialogData> mErrorDialogLiveData = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Integer> mErrorDialogActionLiveData = new MutableLiveData<>();
|
||||||
|
|
||||||
public FingerprintEnrollEnrollingViewModel(Application application,
|
public FingerprintEnrollEnrollingViewModel(Application application,
|
||||||
|
int userId,
|
||||||
FingerprintRepository fingerprintRepository,
|
FingerprintRepository fingerprintRepository,
|
||||||
AccessibilityRepository accessibilityRepository,
|
AccessibilityRepository accessibilityRepository,
|
||||||
VibratorRepository vibratorRepository) {
|
VibratorRepository vibratorRepository) {
|
||||||
super(application);
|
super(application);
|
||||||
|
mUserId = userId;
|
||||||
mFingerprintRepository = fingerprintRepository;
|
mFingerprintRepository = fingerprintRepository;
|
||||||
mAccessibilityRepository = accessibilityRepository;
|
mAccessibilityRepository = accessibilityRepository;
|
||||||
mVibratorRepository = vibratorRepository;
|
mVibratorRepository = vibratorRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies activity to show error dialog
|
||||||
|
*/
|
||||||
|
public void showErrorDialog(@NonNull ErrorDialogData errorDialogData) {
|
||||||
|
mErrorDialogLiveData.postValue(errorDialogData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<ErrorDialogData> getErrorDialogLiveData() {
|
||||||
|
return mErrorDialogLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves new user dialog action to mErrorDialogActionLiveData
|
||||||
|
*/
|
||||||
|
public void onErrorDialogAction(@FingerprintErrorDialogAction int action) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onErrorDialogAction(" + action + ")");
|
||||||
|
}
|
||||||
|
mErrorDialogActionLiveData.postValue(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears back press data
|
||||||
|
*/
|
||||||
|
public void clearBackPressedData() {
|
||||||
|
mBackPressedLiveData.setValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User trigger back pressed
|
||||||
|
*/
|
||||||
|
public void onBackPressed() {
|
||||||
|
mBackPressedLiveData.postValue(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User clicks skip button
|
* User clicks skip button
|
||||||
*/
|
*/
|
||||||
@@ -84,6 +173,17 @@ public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel
|
|||||||
mEnrollingLiveData.postValue(action);
|
mEnrollingLiveData.postValue(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is enrolling finished
|
||||||
|
*/
|
||||||
|
public void onEnrollingDone() {
|
||||||
|
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP;
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onEnrollingDone, post action " + action);
|
||||||
|
}
|
||||||
|
mEnrollingLiveData.postValue(action);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon touch dialog show
|
* Icon touch dialog show
|
||||||
*/
|
*/
|
||||||
@@ -120,20 +220,6 @@ public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel
|
|||||||
return mFingerprintRepository.getEnrollStageCount();
|
return mFingerprintRepository.getEnrollStageCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The first sensor type is UDFPS sensor or not
|
|
||||||
*/
|
|
||||||
public boolean canAssumeUdfps() {
|
|
||||||
return mFingerprintRepository.canAssumeUdfps();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The first sensor type is SFPS sensor or not
|
|
||||||
*/
|
|
||||||
public boolean canAssumeSfps() {
|
|
||||||
return mFingerprintRepository.canAssumeSfps();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests interruption of the accessibility feedback from all accessibility services.
|
* Requests interruption of the accessibility feedback from all accessibility services.
|
||||||
*/
|
*/
|
||||||
@@ -154,8 +240,80 @@ public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel
|
|||||||
* Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
|
* Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
|
||||||
* caller to specify the vibration is owned by someone else and set a reason for vibration.
|
* caller to specify the vibration is owned by someone else and set a reason for vibration.
|
||||||
*/
|
*/
|
||||||
public void vibrateError(int uid, String opPkg, String reason) {
|
public void vibrateError(String reason) {
|
||||||
mVibratorRepository.vibrate(uid, opPkg, VIBRATE_EFFECT_ERROR, reason,
|
mVibratorRepository.vibrate(mUserId, getApplication().getOpPackageName(),
|
||||||
FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
|
VIBRATE_EFFECT_ERROR, reason, FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the first FingerprintSensorPropertiesInternal from FingerprintManager
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
|
||||||
|
return mFingerprintRepository.getFirstFingerprintSensorPropertiesInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first sensor type is UDFPS sensor or not
|
||||||
|
*/
|
||||||
|
public boolean canAssumeUdfps() {
|
||||||
|
return mFingerprintRepository.canAssumeUdfps();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves current state to outState
|
||||||
|
*/
|
||||||
|
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
|
// TODO
|
||||||
|
// mRestoring = true;
|
||||||
|
// mIsCanceled = savedInstanceState.getBoolean(KEY_STATE_CANCELED, false);
|
||||||
|
// mPreviousRotation = savedInstanceState.getInt(KEY_STATE_PREVIOUS_ROTATION,
|
||||||
|
// getDisplay().getRotation());
|
||||||
|
// mIsOrientationChanged = mPreviousRotation != getDisplay().getRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores saved state from previous savedInstanceState
|
||||||
|
*/
|
||||||
|
public void restoreSavedState(@Nullable Bundle savedInstanceState) {
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
// outState.putBoolean(KEY_STATE_CANCELED, mIsCanceled);
|
||||||
|
// outState.putInt(KEY_STATE_PREVIOUS_ROTATION, mPreviousRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for passing to FingerprintEnrollEnrollingErrorDialog
|
||||||
|
*/
|
||||||
|
public static class ErrorDialogData {
|
||||||
|
@NonNull private final CharSequence mErrMsg;
|
||||||
|
@NonNull private final CharSequence mErrTitle;
|
||||||
|
@NonNull private final int mErrMsgId;
|
||||||
|
|
||||||
|
public ErrorDialogData(@NonNull CharSequence errMsg, @NonNull CharSequence errTitle,
|
||||||
|
int errMsgId) {
|
||||||
|
mErrMsg = errMsg;
|
||||||
|
mErrTitle = errTitle;
|
||||||
|
mErrMsgId = errMsgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence getErrMsg() {
|
||||||
|
return mErrMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence getErrTitle() {
|
||||||
|
return mErrTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getErrMsgId() {
|
||||||
|
return mErrMsgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ErrorDialogData.class.getSimpleName() + "{id:" + mErrMsgId + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,17 +55,17 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
private final MutableLiveData<EnrollmentStatusMessage> mErrorMessageLiveData =
|
private final MutableLiveData<EnrollmentStatusMessage> mErrorMessageLiveData =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
private final MutableLiveData<Boolean> mAcquireLiveData = new MutableLiveData<>();
|
private final MutableLiveData<Boolean> mAcquireLiveData = new MutableLiveData<>();
|
||||||
private final MutableLiveData<Integer> mPointerDownLiveData = new MutableLiveData<>();
|
private final MutableLiveData<Integer> mPointerDownLiveData = new MutableLiveData<>();
|
||||||
private final MutableLiveData<Integer> mPointerUpLiveData = new MutableLiveData<>();
|
private final MutableLiveData<Integer> mPointerUpLiveData = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> mDoneLiveData = new MutableLiveData<>(false);
|
||||||
|
|
||||||
private byte[] mToken = null;
|
private byte[] mToken = null;
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
|
|
||||||
private final FingerprintUpdater mFingerprintUpdater;
|
private final FingerprintUpdater mFingerprintUpdater;
|
||||||
private final MessageDisplayController mMessageDisplayController;
|
private final MessageDisplayController mMessageDisplayController;
|
||||||
private EnrollmentHelper mEnrollmentHelper;
|
@Nullable private CancellationSignal mCancellationSignal = null;
|
||||||
private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() {
|
private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -78,7 +78,11 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
+ ", post progress as " + progress);
|
+ ", post progress as " + progress);
|
||||||
}
|
}
|
||||||
mProgressLiveData.postValue(progress);
|
mProgressLiveData.postValue(progress);
|
||||||
// TODO set enrolling to false when remaining is 0 during implementing b/260957933
|
|
||||||
|
final Boolean done = remaining == 0;
|
||||||
|
if (!done.equals(mDoneLiveData.getValue())) {
|
||||||
|
mDoneLiveData.postValue(done);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -136,7 +140,10 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
* clear progress
|
* clear progress
|
||||||
*/
|
*/
|
||||||
public void clearProgressLiveData() {
|
public void clearProgressLiveData() {
|
||||||
|
mDoneLiveData.setValue(false);
|
||||||
mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
|
mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
|
||||||
|
mHelpMessageLiveData.setValue(null);
|
||||||
|
mErrorMessageLiveData.setValue(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<EnrollmentProgress> getProgressLiveData() {
|
public LiveData<EnrollmentProgress> getProgressLiveData() {
|
||||||
@@ -151,18 +158,21 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
return mErrorMessageLiveData;
|
return mErrorMessageLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<Boolean> getAcquireLiveData() {
|
public LiveData<Boolean> getAcquireLiveData() {
|
||||||
return mAcquireLiveData;
|
return mAcquireLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<Integer> getPointerDownLiveData() {
|
public LiveData<Integer> getPointerDownLiveData() {
|
||||||
return mPointerDownLiveData;
|
return mPointerDownLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<Integer> getPointerUpLiveData() {
|
public LiveData<Integer> getPointerUpLiveData() {
|
||||||
return mPointerUpLiveData;
|
return mPointerUpLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getDoneLiveData() {
|
||||||
|
return mDoneLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts enrollment and return latest isEnrolling() result
|
* Starts enrollment and return latest isEnrolling() result
|
||||||
@@ -172,16 +182,18 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
Log.e(TAG, "Null hardware auth token for enroll");
|
Log.e(TAG, "Null hardware auth token for enroll");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isEnrolling()) {
|
if (mCancellationSignal != null) {
|
||||||
Log.w(TAG, "Enrolling has started, shall not start again");
|
Log.w(TAG, "Enrolling has started, shall not start again");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.e(TAG, "startEnrollment(" + reason + ")");
|
||||||
|
}
|
||||||
|
|
||||||
mEnrollmentHelper = new EnrollmentHelper(
|
mCancellationSignal = new CancellationSignal();
|
||||||
mMessageDisplayController != null
|
mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId,
|
||||||
? mMessageDisplayController
|
mMessageDisplayController != null ? mMessageDisplayController : mEnrollmentCallback,
|
||||||
: mEnrollmentCallback);
|
reason);
|
||||||
mEnrollmentHelper.startEnrollment(mFingerprintUpdater, mToken, mUserId, reason);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,86 +201,22 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
|
|||||||
* Cancels enrollment and return latest isEnrolling result
|
* Cancels enrollment and return latest isEnrolling result
|
||||||
*/
|
*/
|
||||||
public boolean cancelEnrollment() {
|
public boolean cancelEnrollment() {
|
||||||
if (!isEnrolling() || mEnrollmentHelper == null) {
|
final CancellationSignal cancellationSignal = mCancellationSignal;
|
||||||
Log.e(TAG, "Fail to cancel enrollment, enrollmentController exist:"
|
if (cancellationSignal == null) {
|
||||||
+ (mEnrollmentHelper != null));
|
Log.e(TAG, "Fail to cancel enrollment, has cancelled or not start");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mEnrollmentHelper.cancelEnrollment();
|
mCancellationSignal = null;
|
||||||
mEnrollmentHelper = null;
|
cancellationSignal.cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnrolling() {
|
public boolean isEnrolling() {
|
||||||
return (mEnrollmentHelper != null);
|
return (mCancellationSignal != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSteps() {
|
private int getSteps() {
|
||||||
return mProgressLiveData.getValue().getSteps();
|
return mProgressLiveData.getValue().getSteps();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to stop latest message from onEnrollmentError() after user cancelled
|
|
||||||
* enrollment. This class will not forward message anymore after mCancellationSignal is sent.
|
|
||||||
*/
|
|
||||||
private static class EnrollmentHelper extends EnrollmentCallback {
|
|
||||||
|
|
||||||
@NonNull private final EnrollmentCallback mEnrollmentCallback;
|
|
||||||
@Nullable private CancellationSignal mCancellationSignal = new CancellationSignal();
|
|
||||||
|
|
||||||
EnrollmentHelper(@NonNull EnrollmentCallback enrollmentCallback) {
|
|
||||||
mEnrollmentCallback = enrollmentCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnrollmentError(int errMsgId, CharSequence errString) {
|
|
||||||
if (mCancellationSignal == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mEnrollmentCallback.onEnrollmentError(errMsgId, errString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
|
||||||
if (mCancellationSignal == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mEnrollmentCallback.onEnrollmentHelp(helpMsgId, helpString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnrollmentProgress(int remaining) {
|
|
||||||
if (mCancellationSignal == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mEnrollmentCallback.onEnrollmentProgress(remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts enrollment
|
|
||||||
*/
|
|
||||||
public boolean startEnrollment(@NonNull FingerprintUpdater fingerprintUpdater,
|
|
||||||
@NonNull byte[] token, int userId, @EnrollReason int reason) {
|
|
||||||
if (mCancellationSignal == null) {
|
|
||||||
// Not allow enrolling twice as same instance. Allocate a new instance for second
|
|
||||||
// enrollment.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fingerprintUpdater.enroll(token, mCancellationSignal, userId, this, reason);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels current enrollment
|
|
||||||
*/
|
|
||||||
public void cancelEnrollment() {
|
|
||||||
final CancellationSignal cancellationSignal = mCancellationSignal;
|
|
||||||
mCancellationSignal = null;
|
|
||||||
|
|
||||||
if (cancellationSignal != null) {
|
|
||||||
cancellationSignal.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user