2 * Copyright (C) 2018 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.settings.biometrics.face;
19 import android.content.Intent;
20 import android.hardware.face.FaceManager;
21 import android.os.Bundle;
22 import android.text.TextUtils;
23 import android.util.Log;
24 import android.view.View;
25 import android.view.animation.AnimationUtils;
26 import android.view.animation.Interpolator;
27 import android.widget.TextView;
29 import com.android.internal.logging.nano.MetricsProto;
30 import com.android.settings.R;
31 import com.android.settings.biometrics.BiometricEnrollBase;
32 import com.android.settings.biometrics.BiometricEnrollSidecar;
33 import com.android.settings.biometrics.BiometricErrorDialog;
34 import com.android.settings.biometrics.BiometricsEnrollEnrolling;
36 import java.util.ArrayList;
38 import com.google.android.setupcompat.item.FooterButton;
39 import com.google.android.setupcompat.template.ButtonFooterMixin;
41 public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
43 private static final String TAG = "FaceEnrollEnrolling";
44 private static final boolean DEBUG = true;
45 private static final String TAG_FACE_PREVIEW = "tag_preview";
47 private TextView mErrorText;
48 private Interpolator mLinearOutSlowInInterpolator;
49 private FaceEnrollPreviewFragment mPreviewFragment;
51 private ArrayList<Integer> mDisabledFeatures = new ArrayList<>();
53 private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
55 public void onEnrolled() {
56 FaceEnrollEnrolling.this.launchFinish(mToken);
60 public static class FaceErrorDialog extends BiometricErrorDialog {
61 static FaceErrorDialog newInstance(CharSequence msg, int msgId) {
62 FaceErrorDialog dialog = new FaceErrorDialog();
63 Bundle args = new Bundle();
64 args.putCharSequence(KEY_ERROR_MSG, msg);
65 args.putInt(KEY_ERROR_ID, msgId);
66 dialog.setArguments(args);
71 public int getMetricsCategory() {
72 return MetricsProto.MetricsEvent.DIALOG_FACE_ERROR;
76 public int getTitleResId() {
77 return R.string.security_settings_face_enroll_error_dialog_title;
81 public int getOkButtonTextResId() {
82 return R.string.security_settings_face_enroll_dialog_ok;
87 protected void onCreate(Bundle savedInstanceState) {
88 super.onCreate(savedInstanceState);
89 setContentView(R.layout.face_enroll_enrolling);
90 setHeaderText(R.string.security_settings_face_enroll_repeat_title);
91 mErrorText = findViewById(R.id.error_text);
92 mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
93 this, android.R.interpolator.linear_out_slow_in);
95 mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
96 mButtonFooterMixin.setSecondaryButton(
99 R.string.security_settings_face_enroll_enrolling_skip,
100 this::onSkipButtonClick,
101 FooterButton.ButtonType.SKIP,
102 R.style.SuwGlifButton_Secondary)
105 if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_DIVERSITY, true)) {
106 mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_REQUIRE_DIVERSITY);
108 if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_VISION, true)) {
109 mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_ATTENTION);
116 public void startEnrollment() {
117 super.startEnrollment();
118 mPreviewFragment = (FaceEnrollPreviewFragment) getSupportFragmentManager()
119 .findFragmentByTag(TAG_FACE_PREVIEW);
120 if (mPreviewFragment == null) {
121 mPreviewFragment = new FaceEnrollPreviewFragment();
122 getSupportFragmentManager().beginTransaction().add(mPreviewFragment, TAG_FACE_PREVIEW)
123 .commitAllowingStateLoss();
125 mPreviewFragment.setListener(mListener);
129 protected Intent getFinishIntent() {
130 return new Intent(this, FaceEnrollFinish.class);
134 protected BiometricEnrollSidecar getSidecar() {
135 final int[] disabledFeatures = new int[mDisabledFeatures.size()];
136 for (int i = 0; i < mDisabledFeatures.size(); i++) {
137 disabledFeatures[i] = mDisabledFeatures.get(i);
140 return new FaceEnrollSidecar(disabledFeatures);
144 protected boolean shouldStartAutomatically() {
149 public int getMetricsCategory() {
150 return MetricsProto.MetricsEvent.FACE_ENROLL_ENROLLING;
154 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
155 if (!TextUtils.isEmpty(helpString)) {
156 showError(helpString);
158 mPreviewFragment.onEnrollmentHelp(helpMsgId, helpString);
162 public void onEnrollmentError(int errMsgId, CharSequence errString) {
165 case FaceManager.FACE_ERROR_TIMEOUT:
166 msgId = R.string.security_settings_face_enroll_error_timeout_dialog_message;
169 msgId = R.string.security_settings_face_enroll_error_generic_dialog_message;
172 mPreviewFragment.onEnrollmentError(errMsgId, errString);
173 showErrorDialog(getText(msgId), errMsgId);
177 public void onEnrollmentProgressChange(int steps, int remaining) {
179 Log.v(TAG, "Steps: " + steps + " Remaining: " + remaining);
181 mPreviewFragment.onEnrollmentProgressChange(steps, remaining);
183 // TODO: Update the actual animation
184 showError("Steps: " + steps + " Remaining: " + remaining);
186 // TODO: Have this match any animations that UX comes up with
187 if (remaining == 0) {
188 launchFinish(mToken);
192 private void showErrorDialog(CharSequence msg, int msgId) {
193 BiometricErrorDialog dialog = FaceErrorDialog.newInstance(msg, msgId);
194 dialog.show(getSupportFragmentManager(), FaceErrorDialog.class.getName());
197 private void showError(CharSequence error) {
198 mErrorText.setText(error);
199 if (mErrorText.getVisibility() == View.INVISIBLE) {
200 mErrorText.setVisibility(View.VISIBLE);
201 mErrorText.setTranslationY(getResources().getDimensionPixelSize(
202 R.dimen.fingerprint_error_text_appear_distance));
203 mErrorText.setAlpha(0f);
208 .setInterpolator(mLinearOutSlowInInterpolator)
211 mErrorText.animate().cancel();
212 mErrorText.setAlpha(1f);
213 mErrorText.setTranslationY(0f);