• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 package com.android.settings.biometrics.fingerprint;
18 
19 import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
20 import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
21 import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.KEY_STATE_CANCELED;
22 
23 import android.app.Activity;
24 import android.app.Dialog;
25 import android.app.settings.SettingsEnums;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.hardware.biometrics.BiometricConstants;
29 import android.hardware.fingerprint.FingerprintManager;
30 import android.os.Bundle;
31 
32 import androidx.appcompat.app.AlertDialog;
33 import androidx.fragment.app.FragmentManager;
34 
35 import com.android.settings.R;
36 import com.android.settings.biometrics.BiometricEnrollBase;
37 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
38 
39 /** Fingerprint error dialog, will be shown when an error occurs during fingerprint enrollment. */
40 public class FingerprintErrorDialog extends InstrumentedDialogFragment {
41 
42     public static final String KEY_ERROR_MSG = "error_msg";
43     public static final String KEY_ERROR_TITLE = "error_title";
44     public static final String KEY_ERROR_ID = "error_id";
45     public static final String KEY_UDFPS = "is_udfps";
46 
47     @Override
onCreateDialog(Bundle savedInstanceState)48     public Dialog onCreateDialog(Bundle savedInstanceState) {
49         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
50         final CharSequence errorString = getArguments().getCharSequence(KEY_ERROR_MSG);
51         final CharSequence errorTitle = getArguments().getCharSequence(KEY_ERROR_TITLE);
52         final int errMsgId = getArguments().getInt(KEY_ERROR_ID);
53         final boolean canAssumeUdfps = getArguments().getBoolean(KEY_UDFPS, false);
54         final boolean wasTimeout = errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
55 
56         builder.setTitle(errorTitle)
57                 .setMessage(errorString)
58                 .setCancelable(false)
59                 .setPositiveButton(
60                         R.string.security_settings_fingerprint_enroll_dialog_ok,
61                         new DialogInterface.OnClickListener() {
62                             @Override
63                             public void onClick(DialogInterface dialog, int which) {
64                                 dialog.dismiss();
65                                 final Activity activity = getActivity();
66                                 if (wasTimeout && !canAssumeUdfps) {
67                                     activity.setResult(RESULT_TIMEOUT);
68                                 } else {
69                                     activity.setResult(RESULT_FINISHED);
70                                 }
71                                 activity.finish();
72                             }
73                         });
74         if (wasTimeout && canAssumeUdfps) {
75             builder.setPositiveButton(
76                             R.string.security_settings_fingerprint_enroll_dialog_try_again,
77                             new DialogInterface.OnClickListener() {
78                                 @Override
79                                 public void onClick(DialogInterface dialog, int which) {
80                                     dialog.dismiss();
81                                     final Activity activity = getActivity();
82                                     final Intent intent = activity.getIntent();
83                                     intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
84                                     intent.putExtra(KEY_STATE_CANCELED, false);
85                                     activity.startActivity(intent);
86                                     activity.finish();
87                                 }
88                             })
89                     .setNegativeButton(
90                             R.string.security_settings_fingerprint_enroll_dialog_ok,
91                             new DialogInterface.OnClickListener() {
92                                 @Override
93                                 public void onClick(DialogInterface dialog, int which) {
94                                     dialog.dismiss();
95                                     final Activity activity = getActivity();
96                                     activity.setResult(RESULT_TIMEOUT);
97                                     activity.finish();
98                                 }
99                             });
100         }
101         final AlertDialog dialog = builder.create();
102         dialog.setCanceledOnTouchOutside(false);
103         return dialog;
104     }
105 
showErrorDialog(BiometricEnrollBase host, int errMsgId, boolean canAssumeUdfps)106     public static void showErrorDialog(BiometricEnrollBase host, int errMsgId,
107             boolean canAssumeUdfps) {
108         if (host.isFinishing()) {
109             return;
110         }
111         final FragmentManager fragmentManager = host.getSupportFragmentManager();
112         if (fragmentManager.isDestroyed() || fragmentManager.isStateSaved()) {
113             return;
114         }
115         CharSequence errMsg = host.getText(getErrorMessage(errMsgId));
116         final CharSequence errTitle = host.getText(getErrorTitle(errMsgId));
117         if (!canAssumeUdfps
118                 && errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
119             errMsg = host.getText(getErrorMessage(BiometricConstants.BIOMETRIC_ERROR_CANCELED));
120         }
121         final FingerprintErrorDialog dialog = newInstance(errMsg, errTitle,
122                 errMsgId, canAssumeUdfps);
123         dialog.show(fragmentManager, FingerprintErrorDialog.class.getName());
124     }
125 
getErrorMessage(int errMsgId)126     private static int getErrorMessage(int errMsgId) {
127         switch (errMsgId) {
128             case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
129                 // This message happens when the underlying crypto layer decides to revoke
130                 // the enrollment auth token.
131                 return R.string.security_settings_fingerprint_enroll_error_timeout_dialog_message;
132             case FingerprintManager.FINGERPRINT_ERROR_BAD_CALIBRATION:
133                 return R.string.security_settings_fingerprint_bad_calibration;
134             default:
135                 // There's nothing specific to tell the user about. Ask them to try again.
136                 return R.string.security_settings_fingerprint_enroll_error_generic_dialog_message;
137         }
138     }
139 
getErrorTitle(int errMsgId)140     private static int getErrorTitle(int errMsgId) {
141         switch (errMsgId) {
142             case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
143                 return R.string
144                         .security_settings_fingerprint_enroll_error_unable_to_process_dialog_title;
145             default:
146                 return R.string.security_settings_fingerprint_enroll_error_dialog_title;
147         }
148     }
149 
newInstance(CharSequence msg, CharSequence title, int msgId, boolean canAssumeUdfps)150     private static FingerprintErrorDialog newInstance(CharSequence msg, CharSequence title,
151             int msgId, boolean canAssumeUdfps) {
152         final FingerprintErrorDialog dialog = new FingerprintErrorDialog();
153         final Bundle args = new Bundle();
154         args.putCharSequence(KEY_ERROR_MSG, msg);
155         args.putCharSequence(KEY_ERROR_TITLE, title);
156         args.putInt(KEY_ERROR_ID, msgId);
157         args.putBoolean(KEY_UDFPS, canAssumeUdfps);
158         dialog.setArguments(args);
159         return dialog;
160     }
161 
162     @Override
getMetricsCategory()163     public int getMetricsCategory() {
164         return SettingsEnums.DIALOG_FINGERPINT_ERROR;
165     }
166 }
167