1 /*
2  * Copyright (C) 2016 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.password;
18 
19 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
20 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
21 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
22 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
23 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
24 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
25 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_SUW;
26 
27 import android.app.Activity;
28 import android.app.AlertDialog;
29 import android.app.Dialog;
30 import android.app.settings.SettingsEnums;
31 import android.content.DialogInterface;
32 import android.os.Bundle;
33 import android.view.View;
34 import android.view.inputmethod.InputMethodManager;
35 
36 import androidx.annotation.NonNull;
37 import androidx.annotation.StringRes;
38 import androidx.fragment.app.FragmentManager;
39 
40 import com.android.internal.widget.LockPatternUtils;
41 import com.android.settings.R;
42 import com.android.settings.Utils;
43 import com.android.settings.biometrics.BiometricUtils;
44 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
45 
46 public class SetupSkipDialog extends InstrumentedDialogFragment
47         implements DialogInterface.OnClickListener {
48 
49     public static final String EXTRA_FRP_SUPPORTED = ":settings:frp_supported";
50 
51     private static final String ARG_FRP_SUPPORTED = "frp_supported";
52     // The key indicates type of screen lock credential types(PIN/Pattern/Password)
53     private static final String ARG_LOCK_CREDENTIAL_TYPE = "lock_credential_type";
54     // The key indicates type of lock screen setup is alphanumeric for password setup.
55     private static final String TAG_SKIP_DIALOG = "skip_dialog";
56     public static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10;
57 
newInstance(@ockPatternUtils.CredentialType int credentialType, boolean isFrpSupported, boolean forFingerprint, boolean forFace, boolean forBiometrics, boolean isSuw)58     public static SetupSkipDialog newInstance(@LockPatternUtils.CredentialType int credentialType,
59             boolean isFrpSupported, boolean forFingerprint, boolean forFace,
60             boolean forBiometrics, boolean isSuw) {
61         SetupSkipDialog dialog = new SetupSkipDialog();
62         Bundle args = new Bundle();
63         args.putInt(ARG_LOCK_CREDENTIAL_TYPE, credentialType);
64         args.putBoolean(ARG_FRP_SUPPORTED, isFrpSupported);
65         args.putBoolean(EXTRA_KEY_FOR_FINGERPRINT, forFingerprint);
66         args.putBoolean(EXTRA_KEY_FOR_FACE, forFace);
67         args.putBoolean(EXTRA_KEY_FOR_BIOMETRICS, forBiometrics);
68         args.putBoolean(EXTRA_KEY_IS_SUW, isSuw);
69         dialog.setArguments(args);
70         return dialog;
71     }
72 
73     @Override
getMetricsCategory()74     public int getMetricsCategory() {
75         return SettingsEnums.DIALOG_FINGERPRINT_SKIP_SETUP;
76     }
77 
78     @Override
onCreateDialog(Bundle savedInstanceState)79     public Dialog onCreateDialog(Bundle savedInstanceState) {
80         return onCreateDialogBuilder().create();
81     }
82 
getBiometricsBuilder( @ockPatternUtils.CredentialType int credentialType, boolean isSuw, boolean hasFace, boolean hasFingerprint)83     private AlertDialog.Builder getBiometricsBuilder(
84             @LockPatternUtils.CredentialType int credentialType, boolean isSuw, boolean hasFace,
85             boolean hasFingerprint) {
86         final boolean isFaceSupported = hasFace && (!isSuw || BiometricUtils.isFaceSupportedInSuw(
87                 getContext()));
88         final int msgResId;
89         final int screenLockResId;
90         switch (credentialType) {
91             case CREDENTIAL_TYPE_PATTERN:
92                 screenLockResId = R.string.unlock_set_unlock_pattern_title;
93                 msgResId = getPatternSkipMessageRes(hasFace && isFaceSupported, hasFingerprint);
94                 break;
95             case CREDENTIAL_TYPE_PASSWORD:
96                 screenLockResId = R.string.unlock_set_unlock_password_title;
97                 msgResId = getPasswordSkipMessageRes(hasFace && isFaceSupported, hasFingerprint);
98                 break;
99             case CREDENTIAL_TYPE_PIN:
100             default:
101                 screenLockResId = R.string.unlock_set_unlock_pin_title;
102                 msgResId = getPinSkipMessageRes(hasFace && isFaceSupported, hasFingerprint);
103                 break;
104         }
105         return new AlertDialog.Builder(getContext())
106                 .setPositiveButton(R.string.skip_lock_screen_dialog_button_label, this)
107                 .setNegativeButton(R.string.cancel_lock_screen_dialog_button_label, this)
108                 .setTitle(getSkipSetupTitle(screenLockResId, hasFingerprint,
109                         hasFace && isFaceSupported))
110                 .setMessage(msgResId);
111     }
112 
113     @NonNull
onCreateDialogBuilder()114     public AlertDialog.Builder onCreateDialogBuilder() {
115         Bundle args = getArguments();
116         final boolean isSuw = args.getBoolean(EXTRA_KEY_IS_SUW);
117         final boolean forBiometrics = args.getBoolean(EXTRA_KEY_FOR_BIOMETRICS);
118         final boolean forFace = args.getBoolean(EXTRA_KEY_FOR_FACE);
119         final boolean forFingerprint = args.getBoolean(EXTRA_KEY_FOR_FINGERPRINT);
120         @LockPatternUtils.CredentialType
121         final int credentialType = args.getInt(ARG_LOCK_CREDENTIAL_TYPE);
122 
123         if (forFace || forFingerprint || forBiometrics) {
124             final boolean hasFace = Utils.hasFaceHardware(getContext());
125             final boolean hasFingerprint = Utils.hasFingerprintHardware(getContext());
126             return getBiometricsBuilder(credentialType, isSuw, hasFace, hasFingerprint);
127         }
128 
129         return new AlertDialog.Builder(getContext())
130                 .setPositiveButton(R.string.skip_anyway_button_label, this)
131                 .setNegativeButton(R.string.go_back_button_label, this)
132                 .setTitle(R.string.lock_screen_intro_skip_title)
133                 .setMessage(args.getBoolean(ARG_FRP_SUPPORTED) ?
134                         R.string.lock_screen_intro_skip_dialog_text_frp :
135                         R.string.lock_screen_intro_skip_dialog_text);
136     }
137 
138     @StringRes
getPatternSkipMessageRes(boolean hasFace, boolean hasFingerprint)139     private int getPatternSkipMessageRes(boolean hasFace, boolean hasFingerprint) {
140         if (hasFace && hasFingerprint) {
141             return R.string.lock_screen_pattern_skip_biometrics_message;
142         } else if (hasFace) {
143             return R.string.lock_screen_pattern_skip_face_message;
144         } else if (hasFingerprint) {
145             return R.string.lock_screen_pattern_skip_fingerprint_message;
146         } else {
147             return R.string.lock_screen_pattern_skip_message;
148         }
149     }
150 
151     @StringRes
getPasswordSkipMessageRes(boolean hasFace, boolean hasFingerprint)152     private int getPasswordSkipMessageRes(boolean hasFace, boolean hasFingerprint) {
153         if (hasFace && hasFingerprint) {
154             return R.string.lock_screen_password_skip_biometrics_message;
155         } else if (hasFace) {
156             return R.string.lock_screen_password_skip_face_message;
157         } else if (hasFingerprint) {
158             return R.string.lock_screen_password_skip_fingerprint_message;
159         } else {
160             return R.string.lock_screen_password_skip_message;
161         }
162     }
163 
164     @StringRes
getPinSkipMessageRes(boolean hasFace, boolean hasFingerprint)165     private int getPinSkipMessageRes(boolean hasFace, boolean hasFingerprint) {
166         if (hasFace && hasFingerprint) {
167             return R.string.lock_screen_pin_skip_biometrics_message;
168         } else if (hasFace) {
169             return R.string.lock_screen_pin_skip_face_message;
170         } else if (hasFingerprint) {
171             return R.string.lock_screen_pin_skip_fingerprint_message;
172         } else {
173             return R.string.lock_screen_pin_skip_message;
174         }
175     }
176 
getSkipSetupTitle(int screenTypeResId, boolean hasFingerprint, boolean hasFace)177     private String getSkipSetupTitle(int screenTypeResId, boolean hasFingerprint,
178             boolean hasFace) {
179         return getString(R.string.lock_screen_skip_setup_title,
180                 BiometricUtils.getCombinedScreenLockOptions(getContext(),
181                         getString(screenTypeResId), hasFingerprint, hasFace));
182     }
183 
184     @Override
onClick(DialogInterface dialog, int button)185     public void onClick(DialogInterface dialog, int button) {
186         Activity activity = getActivity();
187         switch (button) {
188             case DialogInterface.BUTTON_POSITIVE:
189                 activity.setResult(RESULT_SKIP);
190                 activity.finish();
191                 break;
192             case DialogInterface.BUTTON_NEGATIVE:
193                 View view = activity.getCurrentFocus();
194                 if(view != null) {
195                     view.requestFocus();
196                     InputMethodManager imm = (InputMethodManager) activity
197                             .getSystemService(Activity.INPUT_METHOD_SERVICE);
198                     imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
199                 }
200                 break;
201         }
202     }
203 
show(FragmentManager manager)204     public void show(FragmentManager manager) {
205         show(manager, TAG_SKIP_DIALOG);
206     }
207 }