Bug: b/271209610 Test: 1. adb root 2. adb shell setprop sys.fflag.override.settings_biometrics2_enrollment true 3. Excute fingerprint enroll process & check the state of enroll progress is correct Change-Id: I3cac369e9dcf939a09dce11a7b9e96952bceeee8
616 lines
26 KiB
Java
616 lines
26 KiB
Java
/*
|
|
* Copyright (C) 2023 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.biometrics2.ui.view;
|
|
|
|
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
|
|
|
|
import android.annotation.RawRes;
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.res.Configuration;
|
|
import android.hardware.fingerprint.FingerprintManager;
|
|
import android.os.Bundle;
|
|
import android.text.TextUtils;
|
|
import android.util.DisplayMetrics;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Surface;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.Button;
|
|
import android.widget.ImageView;
|
|
import android.widget.RelativeLayout;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.activity.OnBackPressedCallback;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.fragment.app.Fragment;
|
|
import androidx.fragment.app.FragmentActivity;
|
|
import androidx.lifecycle.Observer;
|
|
import androidx.lifecycle.ViewModelProvider;
|
|
|
|
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.EnrollmentStatusMessage;
|
|
import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
|
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
|
|
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
|
|
import com.android.settings.biometrics2.ui.widget.UdfpsEnrollView;
|
|
import com.android.settingslib.display.DisplayDensityUtils;
|
|
|
|
import com.airbnb.lottie.LottieAnimationView;
|
|
import com.airbnb.lottie.LottieCompositionFactory;
|
|
|
|
/**
|
|
* Fragment is used to handle enrolling process for udfps
|
|
*/
|
|
public class FingerprintEnrollEnrollingUdfpsFragment extends Fragment {
|
|
|
|
private static final String TAG = FingerprintEnrollEnrollingUdfpsFragment.class.getSimpleName();
|
|
|
|
private static final int PROGRESS_BAR_MAX = 10000;
|
|
|
|
private static final int STAGE_UNKNOWN = -1;
|
|
private static final int STAGE_CENTER = 0;
|
|
private static final int STAGE_GUIDED = 1;
|
|
private static final int STAGE_FINGERTIP = 2;
|
|
private static final int STAGE_LEFT_EDGE = 3;
|
|
private static final int STAGE_RIGHT_EDGE = 4;
|
|
|
|
private FingerprintEnrollEnrollingViewModel mEnrollingViewModel;
|
|
private DeviceRotationViewModel mRotationViewModel;
|
|
private FingerprintEnrollProgressViewModel mProgressViewModel;
|
|
|
|
private LottieAnimationView mIllustrationLottie;
|
|
private boolean mHaveShownUdfpsTipLottie;
|
|
private boolean mHaveShownUdfpsLeftEdgeLottie;
|
|
private boolean mHaveShownUdfpsRightEdgeLottie;
|
|
private boolean mHaveShownUdfpsCenterLottie;
|
|
private boolean mHaveShownUdfpsGuideLottie;
|
|
|
|
private TextView mTitleText;
|
|
private TextView mSubTitleText;
|
|
private UdfpsEnrollView mUdfpsEnrollView;
|
|
private Button mSkipBtn;
|
|
private ImageView mIcon;
|
|
|
|
private boolean mShouldShowLottie;
|
|
private boolean mIsAccessibilityEnabled;
|
|
|
|
private int mRotation = -1;
|
|
|
|
private final View.OnClickListener mOnSkipClickListener =
|
|
(v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
|
|
|
|
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
|
|
if (progress != null) {
|
|
onEnrollmentProgressChange(progress);
|
|
}
|
|
};
|
|
private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
|
|
if (helpMessage != null) {
|
|
onEnrollmentHelp(helpMessage.getStr());
|
|
}
|
|
};
|
|
private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
|
|
if (errorMessage != null) {
|
|
onEnrollmentError(errorMessage);
|
|
}
|
|
};
|
|
private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
|
|
if (isAcquiredGood != null) {
|
|
onAcquired(isAcquiredGood);
|
|
}
|
|
};
|
|
private final Observer<Integer> mPointerDownObserver = sensorId -> {
|
|
if (sensorId != null) {
|
|
onPointerDown(sensorId);
|
|
}
|
|
};
|
|
private final Observer<Integer> mPointerUpObserver = sensorId -> {
|
|
if (sensorId != null) {
|
|
onPointerUp(sensorId);
|
|
}
|
|
};
|
|
|
|
private final Observer<Integer> mRotationObserver = rotation -> {
|
|
if (rotation != null) {
|
|
onRotationChanged(rotation);
|
|
}
|
|
};
|
|
|
|
private final OnBackPressedCallback mOnBackPressedCallback = new OnBackPressedCallback(true) {
|
|
@Override
|
|
public void handleOnBackPressed() {
|
|
setEnabled(false);
|
|
mEnrollingViewModel.setOnBackPressed();
|
|
cancelEnrollment();
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public void onAttach(@NonNull Context context) {
|
|
final FragmentActivity activity = getActivity();
|
|
final ViewModelProvider provider = new ViewModelProvider(activity);
|
|
mEnrollingViewModel = provider.get(FingerprintEnrollEnrollingViewModel.class);
|
|
mRotationViewModel = provider.get(DeviceRotationViewModel.class);
|
|
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
|
|
super.onAttach(context);
|
|
activity.getOnBackPressedDispatcher().addCallback(mOnBackPressedCallback);
|
|
}
|
|
|
|
@Override
|
|
public void onDetach() {
|
|
mOnBackPressedCallback.setEnabled(false);
|
|
super.onDetach();
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
final RelativeLayout containView = (RelativeLayout) inflater.inflate(
|
|
R.layout.udfps_enroll_enrolling_v2, container, false);
|
|
|
|
final Activity activity = getActivity();
|
|
mIcon = containView.findViewById(R.id.sud_layout_icon);
|
|
mTitleText = containView.findViewById(R.id.suc_layout_title);
|
|
mSubTitleText = containView.findViewById(R.id.sud_layout_subtitle);
|
|
mSkipBtn = containView.findViewById(R.id.skip_btn);
|
|
mSkipBtn.setOnClickListener(mOnSkipClickListener);
|
|
mUdfpsEnrollView = containView.findViewById(R.id.udfps_animation_view);
|
|
mUdfpsEnrollView.setSensorProperties(
|
|
mEnrollingViewModel.getFirstFingerprintSensorPropertiesInternal());
|
|
mShouldShowLottie = shouldShowLottie();
|
|
final boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
|
|
|| BiometricUtils.isLandscape(activity);
|
|
updateOrientation(containView, (isLandscape
|
|
? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT));
|
|
|
|
mRotation = mRotationViewModel.getLiveData().getValue();
|
|
configLayout(mRotation);
|
|
return containView;
|
|
}
|
|
|
|
@Override
|
|
public void onStart() {
|
|
super.onStart();
|
|
startEnrollment();
|
|
updateProgress(false /* animate */, mProgressViewModel.getProgressLiveData().getValue());
|
|
updateTitleAndDescription();
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
mRotationViewModel.getLiveData().observe(this, mRotationObserver);
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
mRotationViewModel.getLiveData().removeObserver(mRotationObserver);
|
|
super.onPause();
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
removeEnrollmentObservers();
|
|
if (!getActivity().isChangingConfigurations() && mProgressViewModel.isEnrolling()) {
|
|
mProgressViewModel.cancelEnrollment();
|
|
}
|
|
super.onStop();
|
|
}
|
|
|
|
private void removeEnrollmentObservers() {
|
|
preRemoveEnrollmentObservers();
|
|
mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
|
|
}
|
|
|
|
private void preRemoveEnrollmentObservers() {
|
|
mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
|
|
mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
|
|
mProgressViewModel.getAcquireLiveData().removeObserver(mAcquireObserver);
|
|
mProgressViewModel.getPointerDownLiveData().removeObserver(mPointerDownObserver);
|
|
mProgressViewModel.getPointerUpLiveData().removeObserver(mPointerUpObserver);
|
|
}
|
|
|
|
private void cancelEnrollment() {
|
|
preRemoveEnrollmentObservers();
|
|
mProgressViewModel.cancelEnrollment();
|
|
}
|
|
|
|
private void startEnrollment() {
|
|
final boolean startResult = mProgressViewModel.startEnrollment(ENROLL_ENROLL);
|
|
if (!startResult) {
|
|
Log.e(TAG, "startEnrollment(), failed");
|
|
}
|
|
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);
|
|
}
|
|
|
|
private void updateProgress(boolean animate, @NonNull EnrollmentProgress enrollmentProgress) {
|
|
if (!mProgressViewModel.isEnrolling()) {
|
|
Log.d(TAG, "Enrollment not started yet");
|
|
return;
|
|
}
|
|
|
|
final int progress = getProgress(enrollmentProgress);
|
|
|
|
if (mProgressViewModel.getProgressLiveData().getValue().getSteps() != -1) {
|
|
mUdfpsEnrollView.onEnrollmentProgress(enrollmentProgress.getRemaining(),
|
|
enrollmentProgress.getSteps());
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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() {
|
|
switch (getCurrentStage()) {
|
|
case STAGE_CENTER:
|
|
mTitleText.setText(R.string.security_settings_fingerprint_enroll_repeat_title);
|
|
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
|
mSubTitleText.setText(R.string.security_settings_udfps_enroll_start_message);
|
|
} else if (!mHaveShownUdfpsCenterLottie) {
|
|
mHaveShownUdfpsCenterLottie = true;
|
|
// Note: Update string reference when differentiate in between udfps & sfps
|
|
mIllustrationLottie.setContentDescription(
|
|
getString(R.string.security_settings_sfps_enroll_finger_center_title)
|
|
);
|
|
configureEnrollmentStage(R.raw.udfps_center_hint_lottie);
|
|
}
|
|
break;
|
|
|
|
case STAGE_GUIDED:
|
|
mTitleText.setText(R.string.security_settings_fingerprint_enroll_repeat_title);
|
|
if (mIsAccessibilityEnabled || mIllustrationLottie == null) {
|
|
mSubTitleText.setText(
|
|
R.string.security_settings_udfps_enroll_repeat_a11y_message);
|
|
} else if (!mHaveShownUdfpsGuideLottie) {
|
|
mHaveShownUdfpsGuideLottie = true;
|
|
mIllustrationLottie.setContentDescription(
|
|
getString(R.string.security_settings_fingerprint_enroll_repeat_message)
|
|
);
|
|
// TODO(b/228100413) Could customize guided lottie animation
|
|
configureEnrollmentStage(R.raw.udfps_center_hint_lottie);
|
|
}
|
|
break;
|
|
case STAGE_FINGERTIP:
|
|
mTitleText.setText(R.string.security_settings_udfps_enroll_fingertip_title);
|
|
if (!mHaveShownUdfpsTipLottie && mIllustrationLottie != null) {
|
|
mHaveShownUdfpsTipLottie = true;
|
|
mIllustrationLottie.setContentDescription(
|
|
getString(R.string.security_settings_udfps_tip_fingerprint_help)
|
|
);
|
|
configureEnrollmentStage(R.raw.udfps_tip_hint_lottie);
|
|
}
|
|
break;
|
|
case STAGE_LEFT_EDGE:
|
|
mTitleText.setText(R.string.security_settings_udfps_enroll_left_edge_title);
|
|
if (!mHaveShownUdfpsLeftEdgeLottie && mIllustrationLottie != null) {
|
|
mHaveShownUdfpsLeftEdgeLottie = true;
|
|
mIllustrationLottie.setContentDescription(
|
|
getString(R.string.security_settings_udfps_side_fingerprint_help)
|
|
);
|
|
configureEnrollmentStage(R.raw.udfps_left_edge_hint_lottie);
|
|
} else if (mIllustrationLottie == null) {
|
|
if (isStageHalfCompleted()) {
|
|
mSubTitleText.setText(
|
|
R.string.security_settings_fingerprint_enroll_repeat_message);
|
|
} else {
|
|
mSubTitleText.setText(R.string.security_settings_udfps_enroll_edge_message);
|
|
}
|
|
}
|
|
break;
|
|
case STAGE_RIGHT_EDGE:
|
|
mTitleText.setText(R.string.security_settings_udfps_enroll_right_edge_title);
|
|
if (!mHaveShownUdfpsRightEdgeLottie && mIllustrationLottie != null) {
|
|
mHaveShownUdfpsRightEdgeLottie = true;
|
|
mIllustrationLottie.setContentDescription(
|
|
getString(R.string.security_settings_udfps_side_fingerprint_help)
|
|
);
|
|
configureEnrollmentStage(R.raw.udfps_right_edge_hint_lottie);
|
|
|
|
} else if (mIllustrationLottie == null) {
|
|
if (isStageHalfCompleted()) {
|
|
mSubTitleText.setText(
|
|
R.string.security_settings_fingerprint_enroll_repeat_message);
|
|
} else {
|
|
mSubTitleText.setText(R.string.security_settings_udfps_enroll_edge_message);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case STAGE_UNKNOWN:
|
|
default:
|
|
mTitleText.setText(R.string.security_settings_fingerprint_enroll_udfps_title);
|
|
mSubTitleText.setText(R.string.security_settings_udfps_enroll_start_message);
|
|
final CharSequence description = getString(
|
|
R.string.security_settings_udfps_enroll_a11y);
|
|
getActivity().setTitle(description);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private boolean shouldShowLottie() {
|
|
DisplayDensityUtils displayDensity = new DisplayDensityUtils(getContext());
|
|
int currentDensityIndex = displayDensity.getCurrentIndexForDefaultDisplay();
|
|
final int currentDensity = displayDensity.getDefaultDisplayDensityValues()
|
|
[currentDensityIndex];
|
|
final int defaultDensity = displayDensity.getDefaultDensityForDefaultDisplay();
|
|
return defaultDensity == currentDensity;
|
|
}
|
|
|
|
private void updateOrientation(@NonNull RelativeLayout content, int orientation) {
|
|
switch (orientation) {
|
|
case Configuration.ORIENTATION_LANDSCAPE: {
|
|
mIllustrationLottie = null;
|
|
break;
|
|
}
|
|
case Configuration.ORIENTATION_PORTRAIT: {
|
|
if (mShouldShowLottie) {
|
|
mIllustrationLottie = content.findViewById(R.id.illustration_lottie);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
Log.e(TAG, "Error unhandled configuration change");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private int getCurrentStage() {
|
|
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
|
|
|
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
|
return STAGE_UNKNOWN;
|
|
}
|
|
|
|
final int progressSteps = progressLiveData.getSteps() - progressLiveData.getRemaining();
|
|
if (progressSteps < getStageThresholdSteps(0)) {
|
|
return STAGE_CENTER;
|
|
} else if (progressSteps < getStageThresholdSteps(1)) {
|
|
return STAGE_GUIDED;
|
|
} else if (progressSteps < getStageThresholdSteps(2)) {
|
|
return STAGE_FINGERTIP;
|
|
} else if (progressSteps < getStageThresholdSteps(3)) {
|
|
return STAGE_LEFT_EDGE;
|
|
} else {
|
|
return STAGE_RIGHT_EDGE;
|
|
}
|
|
}
|
|
|
|
private boolean isStageHalfCompleted() {
|
|
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
|
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
|
return false;
|
|
}
|
|
|
|
final int progressSteps = progressLiveData.getSteps() - progressLiveData.getRemaining();
|
|
int prevThresholdSteps = 0;
|
|
for (int i = 0; i < mEnrollingViewModel.getEnrollStageCount(); i++) {
|
|
final int thresholdSteps = getStageThresholdSteps(i);
|
|
if (progressSteps >= prevThresholdSteps && progressSteps < thresholdSteps) {
|
|
final int adjustedProgress = progressSteps - prevThresholdSteps;
|
|
final int adjustedThreshold = thresholdSteps - prevThresholdSteps;
|
|
return adjustedProgress >= adjustedThreshold / 2;
|
|
}
|
|
prevThresholdSteps = thresholdSteps;
|
|
}
|
|
|
|
// After last enrollment step.
|
|
return true;
|
|
}
|
|
|
|
private int getStageThresholdSteps(int index) {
|
|
|
|
EnrollmentProgress progressLiveData = mProgressViewModel.getProgressLiveData().getValue();
|
|
|
|
if (progressLiveData == null || progressLiveData.getSteps() == -1) {
|
|
Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
|
|
return 1;
|
|
}
|
|
return Math.round(progressLiveData.getSteps()
|
|
* mEnrollingViewModel.getEnrollStageThreshold(index));
|
|
}
|
|
|
|
private void configureEnrollmentStage(@RawRes int lottie) {
|
|
mSubTitleText.setText("");
|
|
LottieCompositionFactory.fromRawRes(getActivity(), lottie)
|
|
.addListener((c) -> {
|
|
mIllustrationLottie.setComposition(c);
|
|
mIllustrationLottie.setVisibility(View.VISIBLE);
|
|
mIllustrationLottie.playAnimation();
|
|
});
|
|
}
|
|
|
|
private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
|
|
updateProgress(true /* animate */, progress);
|
|
|
|
updateTitleAndDescription();
|
|
|
|
if (mIsAccessibilityEnabled) {
|
|
final int steps = progress.getSteps();
|
|
final int remaining = progress.getRemaining();
|
|
final int percent = (int) (((float) (steps - remaining) / (float) steps) * 100);
|
|
CharSequence announcement = getActivity().getString(
|
|
R.string.security_settings_udfps_enroll_progress_a11y_message, percent);
|
|
mEnrollingViewModel.sendAccessibilityEvent(announcement);
|
|
}
|
|
|
|
}
|
|
|
|
private void onEnrollmentHelp(CharSequence helpString) {
|
|
if (!TextUtils.isEmpty(helpString)) {
|
|
showError(helpString);
|
|
mUdfpsEnrollView.onEnrollmentHelp();
|
|
}
|
|
}
|
|
|
|
private void onEnrollmentError(@NonNull EnrollmentStatusMessage errorMessage) {
|
|
removeEnrollmentObservers();
|
|
|
|
if (mEnrollingViewModel.getOnBackPressed()
|
|
&& errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
|
|
mEnrollingViewModel.onCancelledDueToOnBackPressed();
|
|
} else if (mEnrollingViewModel.getOnSkipPressed()
|
|
&& errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
|
|
mEnrollingViewModel.onCancelledDueToOnSkipPressed();
|
|
} else {
|
|
final int errMsgId = errorMessage.getMsgId();
|
|
mEnrollingViewModel.showErrorDialog(
|
|
new FingerprintEnrollEnrollingViewModel.ErrorDialogData(
|
|
getString(FingerprintErrorDialog.getErrorMessage(errMsgId)),
|
|
getString(FingerprintErrorDialog.getErrorTitle(errMsgId)),
|
|
errMsgId
|
|
));
|
|
mProgressViewModel.cancelEnrollment();
|
|
}
|
|
}
|
|
|
|
private void onAcquired(boolean isAcquiredGood) {
|
|
if (mUdfpsEnrollView != null) {
|
|
mUdfpsEnrollView.onAcquired(isAcquiredGood);
|
|
}
|
|
}
|
|
|
|
private void onPointerDown(int sensorId) {
|
|
if (mUdfpsEnrollView != null) {
|
|
mUdfpsEnrollView.onPointerDown(sensorId);
|
|
}
|
|
}
|
|
|
|
private void onPointerUp(int sensorId) {
|
|
if (mUdfpsEnrollView != null) {
|
|
mUdfpsEnrollView.onPointerUp(sensorId);
|
|
}
|
|
}
|
|
|
|
private void showError(CharSequence error) {
|
|
mTitleText.setText(error);
|
|
mTitleText.setContentDescription(error);
|
|
mSubTitleText.setContentDescription("");
|
|
}
|
|
|
|
private void onRotationChanged(int newRotation) {
|
|
if( (newRotation +2) % 4 == mRotation) {
|
|
mRotation = newRotation;
|
|
configLayout(newRotation);
|
|
}
|
|
}
|
|
|
|
private void configLayout(int newRotation) {
|
|
final Activity activity = getActivity();
|
|
if (newRotation == Surface.ROTATION_270) {
|
|
RelativeLayout.LayoutParams iconLP = new RelativeLayout.LayoutParams(-2, -2);
|
|
iconLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
iconLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view);
|
|
iconLP.topMargin = (int) convertDpToPixel(76.64f, activity);
|
|
iconLP.leftMargin = (int) convertDpToPixel(151.54f, activity);
|
|
mIcon.setLayoutParams(iconLP);
|
|
|
|
RelativeLayout.LayoutParams titleLP = new RelativeLayout.LayoutParams(-1, -2);
|
|
titleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
titleLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view);
|
|
titleLP.topMargin = (int) convertDpToPixel(138f, activity);
|
|
titleLP.leftMargin = (int) convertDpToPixel(144f, activity);
|
|
mTitleText.setLayoutParams(titleLP);
|
|
|
|
RelativeLayout.LayoutParams subtitleLP = new RelativeLayout.LayoutParams(-1, -2);
|
|
subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
subtitleLP.addRule(RelativeLayout.END_OF, R.id.udfps_animation_view);
|
|
subtitleLP.topMargin = (int) convertDpToPixel(198f, activity);
|
|
subtitleLP.leftMargin = (int) convertDpToPixel(144f, activity);
|
|
mSubTitleText.setLayoutParams(subtitleLP);
|
|
} else if (newRotation == Surface.ROTATION_90) {
|
|
DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
|
|
RelativeLayout.LayoutParams iconLP = new RelativeLayout.LayoutParams(-2, -2);
|
|
iconLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
iconLP.addRule(RelativeLayout.ALIGN_PARENT_START);
|
|
iconLP.topMargin = (int) convertDpToPixel(76.64f, activity);
|
|
iconLP.leftMargin = (int) convertDpToPixel(71.99f, activity);
|
|
mIcon.setLayoutParams(iconLP);
|
|
|
|
RelativeLayout.LayoutParams titleLP = new RelativeLayout.LayoutParams(
|
|
metrics.widthPixels / 2, -2);
|
|
titleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
titleLP.addRule(RelativeLayout.ALIGN_PARENT_START, R.id.udfps_animation_view);
|
|
titleLP.topMargin = (int) convertDpToPixel(138f, activity);
|
|
titleLP.leftMargin = (int) convertDpToPixel(66f, activity);
|
|
mTitleText.setLayoutParams(titleLP);
|
|
|
|
RelativeLayout.LayoutParams subtitleLP = new RelativeLayout.LayoutParams(
|
|
metrics.widthPixels / 2, -2);
|
|
subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
|
|
subtitleLP.addRule(RelativeLayout.ALIGN_PARENT_START);
|
|
subtitleLP.topMargin = (int) convertDpToPixel(198f, activity);
|
|
subtitleLP.leftMargin = (int) convertDpToPixel(66f, activity);
|
|
mSubTitleText.setLayoutParams(subtitleLP);
|
|
}
|
|
|
|
if (newRotation == Surface.ROTATION_90 || newRotation == Surface.ROTATION_270) {
|
|
RelativeLayout.LayoutParams skipBtnLP =
|
|
(RelativeLayout.LayoutParams) mSkipBtn.getLayoutParams();
|
|
skipBtnLP.topMargin = (int) convertDpToPixel(26f, activity);
|
|
skipBtnLP.leftMargin = (int) convertDpToPixel(54f, activity);
|
|
mSkipBtn.requestLayout();
|
|
}
|
|
}
|
|
|
|
private float convertDpToPixel(float dp, Context context) {
|
|
return dp * getDensity(context);
|
|
}
|
|
|
|
private float getDensity(Context context) {
|
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
|
return metrics.density;
|
|
}
|
|
|
|
// Give the user a chance to see progress completed before jumping to the next stage.
|
|
private final Runnable mDelayedFinishRunnable = () -> mEnrollingViewModel.onEnrollingDone();
|
|
}
|