• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
20 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
21 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
22 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
23 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
24 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
25 
26 import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED;
27 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
28 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY;
29 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN;
30 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
31 
32 import android.accessibilityservice.AccessibilityServiceInfo;
33 import android.app.Activity;
34 import android.app.Dialog;
35 import android.app.admin.DevicePolicyManager;
36 import android.app.admin.DevicePolicyManager.PasswordComplexity;
37 import android.app.settings.SettingsEnums;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.hardware.face.FaceManager;
41 import android.hardware.fingerprint.FingerprintManager;
42 import android.os.Bundle;
43 import android.os.UserHandle;
44 import android.os.UserManager;
45 import android.os.storage.StorageManager;
46 import android.service.persistentdata.PersistentDataBlockManager;
47 import android.text.TextUtils;
48 import android.util.EventLog;
49 import android.util.Log;
50 import android.view.LayoutInflater;
51 import android.view.View;
52 import android.view.ViewGroup;
53 import android.view.accessibility.AccessibilityManager;
54 import android.widget.TextView;
55 
56 import androidx.annotation.StringRes;
57 import androidx.annotation.VisibleForTesting;
58 import androidx.appcompat.app.AlertDialog;
59 import androidx.fragment.app.Fragment;
60 import androidx.fragment.app.FragmentManager;
61 import androidx.preference.Preference;
62 import androidx.preference.PreferenceScreen;
63 
64 import com.android.internal.widget.LockPatternUtils;
65 import com.android.internal.widget.LockscreenCredential;
66 import com.android.settings.EncryptionInterstitial;
67 import com.android.settings.EventLogTags;
68 import com.android.settings.LinkifyUtils;
69 import com.android.settings.R;
70 import com.android.settings.SettingsActivity;
71 import com.android.settings.SettingsPreferenceFragment;
72 import com.android.settings.Utils;
73 import com.android.settings.biometrics.BiometricEnrollActivity;
74 import com.android.settings.biometrics.BiometricEnrollBase;
75 import com.android.settings.core.SubSettingLauncher;
76 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
77 import com.android.settings.search.SearchFeatureProvider;
78 import com.android.settingslib.RestrictedPreference;
79 
80 import com.google.android.setupcompat.util.WizardManagerHelper;
81 
82 public class ChooseLockGeneric extends SettingsActivity {
83     public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
84 
85     @Override
getIntent()86     public Intent getIntent() {
87         Intent modIntent = new Intent(super.getIntent());
88         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
89         return modIntent;
90     }
91 
92     @Override
isValidFragment(String fragmentName)93     protected boolean isValidFragment(String fragmentName) {
94         if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true;
95         return false;
96     }
97 
getFragmentClass()98     /* package */ Class<? extends Fragment> getFragmentClass() {
99         return ChooseLockGenericFragment.class;
100     }
101 
102     public static class InternalActivity extends ChooseLockGeneric {
103     }
104 
105     public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
106 
107         private static final String TAG = "ChooseLockGenericFragment";
108         private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
109         private static final String KEY_SKIP_FACE = "unlock_skip_face";
110         private static final String KEY_SKIP_BIOMETRICS = "unlock_skip_biometrics";
111         private static final String PASSWORD_CONFIRMED = "password_confirmed";
112         private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
113         public static final String HIDE_INSECURE_OPTIONS = "hide_insecure_options";
114         public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
115         public static final String KEY_LOCK_SETTINGS_FOOTER ="lock_settings_footer";
116 
117         /**
118          * Boolean extra determining whether a "screen lock options" button should be shown. This
119          * extra is both sent and received by ChooseLockGeneric.
120          *
121          * When this extra is false, nothing will be done.
122          * When ChooseLockGeneric receives this extra set as true, and if ChooseLockGeneric is
123          * starting ChooseLockPassword or ChooseLockPattern automatically without user interaction,
124          * ChooseLockGeneric will set this extra to true when starting ChooseLockPassword/Pattern.
125          *
126          * This gives the user the choice to select a different screen lock type, even if
127          * ChooseLockGeneric selected a default.
128          */
129         public static final String EXTRA_SHOW_OPTIONS_BUTTON = "show_options_button";
130 
131         /**
132          * Original intent extras used to start this activity. This is passed to ChooseLockPassword
133          * when the "screen lock options" button is shown, so that when that button is clicked,
134          * ChooseLockGeneric can be relaunched with the same extras.
135          */
136         public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
137 
138         @VisibleForTesting
139         static final int CONFIRM_EXISTING_REQUEST = 100;
140         @VisibleForTesting
141         static final int ENABLE_ENCRYPTION_REQUEST = 101;
142         @VisibleForTesting
143         static final int CHOOSE_LOCK_REQUEST = 102;
144         @VisibleForTesting
145         static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103;
146         @VisibleForTesting
147         static final int SKIP_FINGERPRINT_REQUEST = 104;
148 
149         private LockPatternUtils mLockPatternUtils;
150         private DevicePolicyManager mDpm;
151         private boolean mRequestGatekeeperPasswordHandle = false;
152         private boolean mPasswordConfirmed = false;
153         private boolean mWaitingForConfirmation = false;
154         private boolean mForChangeCredRequiredForBoot = false;
155         private LockscreenCredential mUserPassword;
156         private FingerprintManager mFingerprintManager;
157         private FaceManager mFaceManager;
158         private int mUserId;
159         private boolean mIsManagedProfile;
160         private ManagedLockPasswordProvider mManagedPasswordProvider;
161         /**
162          * Whether the activity is launched by admins via
163          * {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} or
164          * {@link DevicePolicyManager#ACTION_SET_NEW_PARENT_PROFILE_PASSWORD}
165          */
166         private boolean mIsSetNewPassword = false;
167         private UserManager mUserManager;
168         private ChooseLockGenericController mController;
169         private int mUnificationProfileId = UserHandle.USER_NULL;
170         private LockscreenCredential mUnificationProfileCredential;
171 
172         /**
173          * From intent extra {@link ChooseLockSettingsHelper#EXTRA_KEY_REQUESTED_MIN_COMPLEXITY}.
174          * Only contains complexity requested by calling app, not complexity enforced by device
175          * admins.
176          */
177         @PasswordComplexity private int mRequestedMinComplexity;
178 
179         /** From intent extra {@link ChooseLockSettingsHelper#EXTRA_KEY_CALLER_APP_NAME}. */
180         private String mCallerAppName = null;
181 
182         /**
183          * The value from the intent extra {@link
184          * ChooseLockSettingsHelper#EXTRA_KEY_IS_CALLING_APP_ADMIN}.
185          */
186         private boolean mIsCallingAppAdmin;
187 
188         protected boolean mForFingerprint = false;
189         protected boolean mForFace = false;
190         protected boolean mForBiometrics = false;
191 
192         private boolean mOnlyEnforceDevicePasswordRequirement = false;
193 
194         @Override
getMetricsCategory()195         public int getMetricsCategory() {
196             return SettingsEnums.CHOOSE_LOCK_GENERIC;
197         }
198 
199         @Override
onCreate(Bundle savedInstanceState)200         public void onCreate(Bundle savedInstanceState) {
201             super.onCreate(savedInstanceState);
202             final Activity activity = getActivity();
203             final Bundle arguments = getArguments();
204             if (!WizardManagerHelper.isDeviceProvisioned(activity)
205                     && !canRunBeforeDeviceProvisioned()) {
206                 Log.i(TAG, "Refusing to start because device is not provisioned");
207                 activity.finish();
208                 return;
209             }
210             final Intent intent = activity.getIntent();
211             String chooseLockAction = intent.getAction();
212             mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
213             mFaceManager = Utils.getFaceManagerOrNull(activity);
214             mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
215             mLockPatternUtils = new LockPatternUtils(activity);
216             mIsSetNewPassword = ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
217                     || ACTION_SET_NEW_PASSWORD.equals(chooseLockAction);
218 
219             // Defaults to needing to confirm credentials
220             final boolean confirmCredentials = intent
221                 .getBooleanExtra(CONFIRM_CREDENTIALS, true);
222             if (activity instanceof ChooseLockGeneric.InternalActivity) {
223                 mPasswordConfirmed = !confirmCredentials;
224                 mUserPassword = intent.getParcelableExtra(
225                         ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
226             } else if (arguments != null) {
227                 mUserPassword = (LockscreenCredential) arguments.getParcelable(
228                         ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
229                 mPasswordConfirmed = mUserPassword != null;
230             }
231 
232             mRequestGatekeeperPasswordHandle = intent.getBooleanExtra(
233                     ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
234             mForFingerprint = intent.getBooleanExtra(
235                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
236             mForFace = intent.getBooleanExtra(
237                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
238             mForBiometrics = intent.getBooleanExtra(
239                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
240 
241             mRequestedMinComplexity = intent.getIntExtra(
242                     EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
243             mOnlyEnforceDevicePasswordRequirement = intent.getBooleanExtra(
244                     ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY, false);
245 
246             mIsCallingAppAdmin = intent
247                     .getBooleanExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, /* defValue= */ false);
248             mForChangeCredRequiredForBoot = arguments != null && arguments.getBoolean(
249                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
250             mUserManager = UserManager.get(activity);
251 
252             if (arguments != null) {
253                 mUnificationProfileCredential = (LockscreenCredential) arguments.getParcelable(
254                         ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL);
255                 mUnificationProfileId = arguments.getInt(
256                         ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID,
257                         UserHandle.USER_NULL);
258             }
259 
260             if (savedInstanceState != null) {
261                 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
262                 mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);
263                 mUserPassword = savedInstanceState.getParcelable(
264                         ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
265             }
266 
267             // a) If this is started from other user, use that user id.
268             // b) If this is started from the same user, read the extra if this is launched
269             //    from Settings app itself.
270             // c) Otherwise, use UserHandle.myUserId().
271             mUserId = Utils.getSecureTargetUser(
272                     activity.getActivityToken(),
273                     UserManager.get(activity),
274                     arguments,
275                     intent.getExtras()).getIdentifier();
276             mIsManagedProfile = UserManager.get(getActivity()).isManagedProfile(mUserId);
277             mController = new ChooseLockGenericController.Builder(
278                     getContext(), mUserId, mLockPatternUtils)
279                     .setAppRequestedMinComplexity(mRequestedMinComplexity)
280                     .setEnforceDevicePasswordRequirementOnly(mOnlyEnforceDevicePasswordRequirement)
281                     .setProfileToUnify(mUnificationProfileId)
282                     .setHideInsecureScreenLockTypes(alwaysHideInsecureScreenLockTypes()
283                             || intent.getBooleanExtra(HIDE_INSECURE_OPTIONS, false))
284                     .build();
285 
286             // If the complexity is provided by the admin, do not get the caller app's name.
287             // If the app requires, for example, low complexity, and the admin requires high
288             // complexity, it does not make sense to show a footer telling the user it's the app
289             // requesting a particular complexity because the admin-set complexity will override it.
290             mCallerAppName = mController.isComplexityProvidedByAdmin() ? null :
291                     intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME);
292 
293             mManagedPasswordProvider = ManagedLockPasswordProvider.get(activity, mUserId);
294 
295             if (mPasswordConfirmed) {
296                 updatePreferencesOrFinish(savedInstanceState != null);
297                 if (mForChangeCredRequiredForBoot) {
298                     maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
299                             mUserId), false);
300                 }
301             } else if (!mWaitingForConfirmation) {
302                 final ChooseLockSettingsHelper.Builder builder =
303                         new ChooseLockSettingsHelper.Builder(activity, this);
304                 builder.setRequestCode(CONFIRM_EXISTING_REQUEST)
305                         .setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
306                         .setReturnCredentials(true)
307                         .setUserId(mUserId);
308                 boolean managedProfileWithUnifiedLock =
309                         mIsManagedProfile
310                         && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
311                 boolean skipConfirmation = managedProfileWithUnifiedLock && !mIsSetNewPassword;
312                 if (skipConfirmation || !builder.show()) {
313                     mPasswordConfirmed = true; // no password set, so no need to confirm
314                     updatePreferencesOrFinish(savedInstanceState != null);
315                 } else {
316                     mWaitingForConfirmation = true;
317                 }
318             }
319             addHeaderView();
320         }
321 
322         @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)323         public View onCreateView(LayoutInflater inflater, ViewGroup container,
324                 Bundle savedInstanceState) {
325             updateActivityTitle();
326             return super.onCreateView(inflater, container, savedInstanceState);
327         }
328 
alwaysHideInsecureScreenLockTypes()329         protected boolean alwaysHideInsecureScreenLockTypes() {
330             return false;
331         }
332 
updateActivityTitle()333         private void updateActivityTitle() {
334             if (mLockPatternUtils == null) {
335                 // mLockPatternUtils will be uninitialized if ChooseLockGenericFragment.onCreate()
336                 // finishes early.
337                 return;
338             }
339             final boolean updateExistingLock;
340             if (mIsManagedProfile) {
341                 // Going from unified challenge -> separate challenge is considered as adding
342                 // a new lock to the profile, while if the profile already has a separate challenge
343                 // it's an update.
344                 updateExistingLock = mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
345                 if (updateExistingLock) {
346                     getActivity().setTitle(R.string.lock_settings_picker_update_profile_lock_title);
347                 } else {
348                     getActivity().setTitle(R.string.lock_settings_picker_new_profile_lock_title);
349                 }
350             } else {
351                 updateExistingLock = mLockPatternUtils.isSecure(mUserId);
352                 if (updateExistingLock) {
353                     getActivity().setTitle(R.string.lock_settings_picker_update_lock_title);
354                 } else {
355                     getActivity().setTitle(R.string.lock_settings_picker_new_lock_title);
356                 }
357             }
358         }
359 
canRunBeforeDeviceProvisioned()360         protected boolean canRunBeforeDeviceProvisioned() {
361             PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
362                     getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
363 
364             // Can only run during setup if factory reset protection has already been cleared
365             // or if the device does not support FRP.
366             return (pdbm == null || pdbm.getDataBlockSize() == 0);
367         }
368 
getInternalActivityClass()369         protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
370             return ChooseLockGeneric.InternalActivity.class;
371         }
372 
addHeaderView()373         protected void addHeaderView() {
374             setHeaderView(R.layout.choose_lock_generic_biometric_header);
375             TextView textView = getHeaderView().findViewById(R.id.biometric_header_description);
376 
377             if (mForFingerprint) {
378                 if (mIsSetNewPassword) {
379                     textView.setText(R.string.fingerprint_unlock_title);
380                 } else {
381                     textView.setText(R.string.lock_settings_picker_biometric_message);
382                 }
383             } else if (mForFace) {
384                 if (mIsSetNewPassword) {
385                     textView.setText(R.string.face_unlock_title);
386                 } else {
387                     textView.setText(R.string.lock_settings_picker_biometric_message);
388                 }
389             } else if (mForBiometrics) {
390                 if (mIsSetNewPassword) {
391                     textView.setText(R.string.biometrics_unlock_title);
392                 } else {
393                     textView.setText(R.string.lock_settings_picker_biometric_message);
394                 }
395             } else {
396                 if (mIsManagedProfile) {
397                     textView.setText(R.string.lock_settings_picker_profile_message);
398                 } else {
399                     int profileUserId = Utils.getManagedProfileId(mUserManager, mUserId);
400                     if (mController.isScreenLockRestrictedByAdmin()
401                             && profileUserId != UserHandle.USER_NULL) {
402                         final StringBuilder description = new StringBuilder(getText(
403                                 R.string.lock_settings_picker_admin_restricted_personal_message));
404                         final LinkifyUtils.OnClickListener clickListener = () -> {
405                             final Bundle extras = new Bundle();
406                             extras.putInt(Intent.EXTRA_USER_ID, profileUserId);
407                             if (mUserPassword != null) {
408                                 extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
409                                         mUserPassword);
410                             }
411                             new SubSettingLauncher(getActivity())
412                                     .setDestination(ChooseLockGenericFragment.class.getName())
413                                     .setSourceMetricsCategory(getMetricsCategory())
414                                     .setArguments(extras)
415                                     .launch();
416                             finish();
417                         };
418                         LinkifyUtils.linkify(textView, description, clickListener);
419                     } else {
420                         textView.setText("");
421                     }
422                 }
423             }
424         }
425 
426         @Override
onPreferenceTreeClick(Preference preference)427         public boolean onPreferenceTreeClick(Preference preference) {
428             writePreferenceClickMetric(preference);
429 
430             final String key = preference.getKey();
431             if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) {
432                 // Show the disabling FRP warning only when the user is switching from a secure
433                 // unlock method to an insecure one
434                 showFactoryResetProtectionWarningDialog(key);
435                 return true;
436             } else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)
437                     || KEY_SKIP_BIOMETRICS.equals(key)) {
438                 Intent chooseLockGenericIntent = new Intent(getActivity(),
439                     getInternalActivityClass());
440                 chooseLockGenericIntent.setAction(getIntent().getAction());
441                 // Forward the target user id to  ChooseLockGeneric.
442                 chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
443                 chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
444                 chooseLockGenericIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY,
445                         mRequestedMinComplexity);
446                 chooseLockGenericIntent.putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY,
447                         mOnlyEnforceDevicePasswordRequirement);
448                 chooseLockGenericIntent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName);
449                 if (mUserPassword != null) {
450                     chooseLockGenericIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
451                             mUserPassword);
452                 }
453                 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
454                 return true;
455             } else {
456                 return setUnlockMethod(key);
457             }
458         }
459 
460         /**
461          * If the device has encryption already enabled, then ask the user if they
462          * also want to encrypt the phone with this password.
463          *
464          * @param quality
465          * @param disabled
466          */
467         // TODO: why does this take disabled, its always called with a quality higher than
468         //  what makes sense with disabled == true
maybeEnableEncryption(int quality, boolean disabled)469         private void maybeEnableEncryption(int quality, boolean disabled) {
470             DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
471             if (UserManager.get(getActivity()).isAdminUser()
472                     && mUserId == UserHandle.myUserId()
473                     && LockPatternUtils.isDeviceEncryptionEnabled()
474                     && !LockPatternUtils.isFileEncryptionEnabled()
475                     && !dpm.getDoNotAskCredentialsOnBoot()) {
476                 // Get the intent that the encryption interstitial should start for creating
477                 // the new unlock method.
478                 Intent unlockMethodIntent = getIntentForUnlockMethod(quality);
479                 unlockMethodIntent.putExtra(
480                         ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
481                         mForChangeCredRequiredForBoot);
482                 final Context context = getActivity();
483                 // If accessibility is enabled and the user hasn't seen this dialog before, set the
484                 // default state to agree with that which is compatible with accessibility
485                 // (password not required).
486                 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
487                 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
488                 Intent intent = getEncryptionInterstitialIntent(context, quality, required,
489                         unlockMethodIntent);
490                 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
491                         mForFingerprint);
492                 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, mForFace);
493                 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, mForBiometrics);
494                 // If the caller requested Gatekeeper Password to be returned, we assume it came
495                 // from biometric enrollment. This should be cleaned up, since requesting
496                 // Gatekeeper Password should not imply it came from biometric setup/settings.
497                 startActivityForResult(
498                         intent,
499                         mIsSetNewPassword && mRequestGatekeeperPasswordHandle
500                                 ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
501                                 : ENABLE_ENCRYPTION_REQUEST);
502             } else {
503                 if (mForChangeCredRequiredForBoot) {
504                     // Welp, couldn't change it. Oh well.
505                     finish();
506                     return;
507                 }
508                 updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
509             }
510         }
511 
512         @Override
onActivityResult(int requestCode, int resultCode, Intent data)513         public void onActivityResult(int requestCode, int resultCode, Intent data) {
514             super.onActivityResult(requestCode, resultCode, data);
515             mWaitingForConfirmation = false;
516             if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
517                 mPasswordConfirmed = true;
518                 mUserPassword = data != null
519                     ? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
520                     : null;
521                 updatePreferencesOrFinish(false /* isRecreatingActivity */);
522                 if (mForChangeCredRequiredForBoot) {
523                     if (mUserPassword != null && !mUserPassword.isNone()) {
524                         maybeEnableEncryption(
525                                 mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
526                     } else {
527                         finish();
528                     }
529                 }
530             } else if (requestCode == CHOOSE_LOCK_REQUEST
531                     || requestCode == ENABLE_ENCRYPTION_REQUEST) {
532                 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
533                     getActivity().setResult(resultCode, data);
534                     finish();
535                 } else {
536                     // If PASSWORD_TYPE_KEY is set, this activity is used as a trampoline to start
537                     // the actual password enrollment. If the result is canceled, which means the
538                     // user pressed back, finish the activity with result canceled.
539                     int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
540                     if (quality != -1) {
541                         getActivity().setResult(RESULT_CANCELED, data);
542                         finish();
543                     }
544                 }
545             } else if (requestCode == CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
546                     && resultCode == BiometricEnrollBase.RESULT_FINISHED) {
547                 Intent intent = getBiometricEnrollIntent(getActivity());
548                 if (data != null) {
549                     // ChooseLockGeneric should have requested for a Gatekeeper Password Handle to
550                     // be returned, so that biometric enrollment(s) can subsequently request
551                     // Gatekeeper to create HardwareAuthToken(s) wrapping biometric-specific
552                     // challenges. Send the extras (including the GK Password) to the enrollment
553                     // activity.
554                     intent.putExtras(data.getExtras());
555                 }
556                 // Forward the target user id to fingerprint setup page.
557                 intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
558                 startActivity(intent);
559                 finish();
560             } else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
561                 if (resultCode != RESULT_CANCELED) {
562                     getActivity().setResult(
563                             resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data);
564                     finish();
565                 }
566             } else if (requestCode == SearchFeatureProvider.REQUEST_CODE) {
567                 return;
568             } else {
569                 getActivity().setResult(Activity.RESULT_CANCELED);
570                 finish();
571             }
572             if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) {
573                 finish();
574             }
575         }
576 
getBiometricEnrollIntent(Context context)577         protected Intent getBiometricEnrollIntent(Context context) {
578             final Intent intent =
579                     new Intent(context, BiometricEnrollActivity.InternalActivity.class);
580             intent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, true);
581             return intent;
582         }
583 
584         @Override
onSaveInstanceState(Bundle outState)585         public void onSaveInstanceState(Bundle outState) {
586             super.onSaveInstanceState(outState);
587             // Saved so we don't force user to re-enter their password if configuration changes
588             outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
589             outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation);
590             if (mUserPassword != null) {
591                 outState.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
592                         mUserPassword.duplicate());
593             }
594         }
595 
596         @VisibleForTesting
updatePreferencesOrFinish(boolean isRecreatingActivity)597         void updatePreferencesOrFinish(boolean isRecreatingActivity) {
598             Intent intent = getActivity().getIntent();
599             int quality = -1;
600             if (StorageManager.isFileEncryptedNativeOrEmulated()) {
601                 quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
602             } else {
603                 // For non-file encrypted devices we need to show encryption interstitial, so always
604                 // show the lock type picker and ignore PASSWORD_TYPE_KEY.
605                 Log.i(TAG, "Ignoring PASSWORD_TYPE_KEY because device is not file encrypted");
606             }
607             if (quality == -1) {
608                 // If caller didn't specify password quality, show UI and allow the user to choose.
609                 final PreferenceScreen prefScreen = getPreferenceScreen();
610                 if (prefScreen != null) {
611                     prefScreen.removeAll();
612                 }
613                 addPreferences();
614                 disableUnusablePreferences();
615                 updatePreferenceText();
616                 updateCurrentPreference();
617                 updatePreferenceSummaryIfNeeded();
618             } else if (!isRecreatingActivity) {
619                 // Don't start the activity again if we are recreated for configuration change
620                 updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
621             }
622         }
623 
addPreferences()624         protected void addPreferences() {
625             addPreferencesFromResource(R.xml.security_settings_picker);
626 
627             final Preference footer = findPreference(KEY_LOCK_SETTINGS_FOOTER);
628             if (!TextUtils.isEmpty(mCallerAppName) && !mIsCallingAppAdmin) {
629                 footer.setVisible(true);
630                 footer.setTitle(getFooterString());
631             } else {
632                 footer.setVisible(false);
633             }
634 
635             // Used for testing purposes
636             findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
637             findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
638             findPreference(KEY_SKIP_FACE).setViewId(R.id.lock_none);
639             findPreference(KEY_SKIP_BIOMETRICS).setViewId(R.id.lock_none);
640             findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
641             findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
642         }
643 
getFooterString()644         private String getFooterString() {
645             @StringRes int stringId;
646             switch (mController.getAggregatedPasswordComplexity()) {
647                 case PASSWORD_COMPLEXITY_HIGH:
648                     stringId = R.string.unlock_footer_high_complexity_requested;
649                     break;
650                 case PASSWORD_COMPLEXITY_MEDIUM:
651                     stringId = R.string.unlock_footer_medium_complexity_requested;
652                     break;
653                 case PASSWORD_COMPLEXITY_LOW:
654                     stringId = R.string.unlock_footer_low_complexity_requested;
655                     break;
656                 case PASSWORD_COMPLEXITY_NONE:
657                 default:
658                     stringId = R.string.unlock_footer_none_complexity_requested;
659                     break;
660             }
661 
662             return getResources().getString(stringId, mCallerAppName);
663         }
664 
updatePreferenceText()665         private void updatePreferenceText() {
666             if (mForFingerprint) {
667                 setPreferenceTitle(ScreenLockType.PATTERN,
668                         R.string.fingerprint_unlock_set_unlock_pattern);
669                 setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
670                 setPreferenceTitle(ScreenLockType.PASSWORD,
671                         R.string.fingerprint_unlock_set_unlock_password);
672             } else if (mForFace) {
673                 setPreferenceTitle(ScreenLockType.PATTERN,
674                         R.string.face_unlock_set_unlock_pattern);
675                 setPreferenceTitle(ScreenLockType.PIN, R.string.face_unlock_set_unlock_pin);
676                 setPreferenceTitle(ScreenLockType.PASSWORD,
677                         R.string.face_unlock_set_unlock_password);
678             } else if (mForBiometrics) {
679                 setPreferenceTitle(ScreenLockType.PATTERN,
680                         R.string.biometrics_unlock_set_unlock_pattern);
681                 setPreferenceTitle(ScreenLockType.PIN, R.string.biometrics_unlock_set_unlock_pin);
682                 setPreferenceTitle(ScreenLockType.PASSWORD,
683                         R.string.biometrics_unlock_set_unlock_password);
684             }
685 
686             if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
687                 setPreferenceTitle(ScreenLockType.MANAGED,
688                         mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
689             } else {
690                 removePreference(ScreenLockType.MANAGED.preferenceKey);
691             }
692 
693             if (!(mForFingerprint && mIsSetNewPassword)) {
694                 removePreference(KEY_SKIP_FINGERPRINT);
695             }
696             if (!(mForFace && mIsSetNewPassword)) {
697                 removePreference(KEY_SKIP_FACE);
698             }
699             if (!(mForBiometrics && mIsSetNewPassword)) {
700                 removePreference(KEY_SKIP_BIOMETRICS);
701             }
702         }
703 
setPreferenceTitle(ScreenLockType lock, @StringRes int title)704         private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
705             Preference preference = findPreference(lock.preferenceKey);
706             if (preference != null) {
707                 preference.setTitle(title);
708             }
709         }
710 
setPreferenceTitle(ScreenLockType lock, CharSequence title)711         private void setPreferenceTitle(ScreenLockType lock, CharSequence title) {
712             Preference preference = findPreference(lock.preferenceKey);
713             if (preference != null) {
714                 preference.setTitle(title);
715             }
716         }
717 
setPreferenceSummary(ScreenLockType lock, @StringRes int summary)718         private void setPreferenceSummary(ScreenLockType lock, @StringRes int summary) {
719             Preference preference = findPreference(lock.preferenceKey);
720             if (preference != null) {
721                 preference.setSummary(summary);
722             }
723         }
724 
updateCurrentPreference()725         private void updateCurrentPreference() {
726             String currentKey = getKeyForCurrent();
727             Preference preference = findPreference(currentKey);
728             if (preference != null) {
729                 preference.setSummary(R.string.current_screen_lock);
730             }
731         }
732 
getKeyForCurrent()733         private String getKeyForCurrent() {
734             final int credentialOwner = UserManager.get(getContext())
735                     .getCredentialOwnerProfile(mUserId);
736             if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
737                 return ScreenLockType.NONE.preferenceKey;
738             }
739             ScreenLockType lock =
740                     ScreenLockType.fromQuality(
741                             mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
742             return lock != null ? lock.preferenceKey : null;
743         }
744 
745         /***
746          * Disables preferences that are less secure than required quality.
747          *
748          */
disableUnusablePreferences()749         private void disableUnusablePreferences() {
750             final PreferenceScreen entries = getPreferenceScreen();
751 
752             for (ScreenLockType lock : ScreenLockType.values()) {
753                 String key = lock.preferenceKey;
754                 Preference pref = findPreference(key);
755                 if (pref instanceof RestrictedPreference) {
756                     boolean visible = mController.isScreenLockVisible(lock);
757                     boolean enabled = mController.isScreenLockEnabled(lock);
758                     if (!visible) {
759                         entries.removePreference(pref);
760                     } else if (!enabled) {
761                         pref.setEnabled(false);
762                     }
763                 }
764             }
765         }
766 
updatePreferenceSummaryIfNeeded()767         private void updatePreferenceSummaryIfNeeded() {
768             // On a default block encrypted device with accessibility, add a warning
769             // that your data is not credential encrypted
770             if (!StorageManager.isBlockEncrypted()) {
771                 return;
772             }
773 
774             if (StorageManager.isNonDefaultBlockEncrypted()) {
775                 return;
776             }
777 
778             if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList(
779                     AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
780                 return;
781             }
782 
783             setPreferenceSummary(ScreenLockType.PATTERN, R.string.secure_lock_encryption_warning);
784             setPreferenceSummary(ScreenLockType.PIN, R.string.secure_lock_encryption_warning);
785             setPreferenceSummary(ScreenLockType.PASSWORD, R.string.secure_lock_encryption_warning);
786             setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
787         }
788 
getLockManagedPasswordIntent(LockscreenCredential password)789         protected Intent getLockManagedPasswordIntent(LockscreenCredential password) {
790             return mManagedPasswordProvider.createIntent(false, password);
791         }
792 
getLockPasswordIntent(int quality)793         protected Intent getLockPasswordIntent(int quality) {
794             ChooseLockPassword.IntentBuilder builder =
795                     new ChooseLockPassword.IntentBuilder(getContext())
796                             .setPasswordType(quality)
797                             .setPasswordRequirement(
798                                     mController.getAggregatedPasswordComplexity(),
799                                     mController.getAggregatedPasswordMetrics())
800                             .setForFingerprint(mForFingerprint)
801                             .setForFace(mForFace)
802                             .setForBiometrics(mForBiometrics)
803                             .setUserId(mUserId)
804                             .setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
805             if (mUserPassword != null) {
806                 builder.setPassword(mUserPassword);
807             }
808             if (mUnificationProfileId != UserHandle.USER_NULL) {
809                 builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
810             }
811             return builder.build();
812         }
813 
getLockPatternIntent()814         protected Intent getLockPatternIntent() {
815             ChooseLockPattern.IntentBuilder builder =
816                     new ChooseLockPattern.IntentBuilder(getContext())
817                             .setForFingerprint(mForFingerprint)
818                             .setForFace(mForFace)
819                             .setForBiometrics(mForBiometrics)
820                             .setUserId(mUserId)
821                             .setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
822             if (mUserPassword != null) {
823                 builder.setPattern(mUserPassword);
824             }
825             if (mUnificationProfileId != UserHandle.USER_NULL) {
826                 builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
827             }
828             return builder.build();
829         }
830 
getEncryptionInterstitialIntent(Context context, int quality, boolean required, Intent unlockMethodIntent)831         protected Intent getEncryptionInterstitialIntent(Context context, int quality,
832                 boolean required, Intent unlockMethodIntent) {
833             return EncryptionInterstitial.createStartIntent(context, quality, required,
834                     unlockMethodIntent);
835         }
836 
837         /**
838          * Invokes an activity to change the user's pattern, password or PIN based on given quality
839          * and minimum quality specified by DevicePolicyManager. If quality is
840          * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared.
841          *
842          * @param quality the desired quality. Ignored if DevicePolicyManager requires more security
843          * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
844          * @param chooseLockSkipped whether or not this activity is skipped. This is true when this
845          * activity was not shown to the user at all, instead automatically proceeding based on
846          * the given intent extras, typically {@link LockPatternUtils#PASSWORD_TYPE_KEY}.
847          * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
848          */
updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped)849         void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
850             // We should never get here without confirming user's existing password.
851             if (!mPasswordConfirmed) {
852                 throw new IllegalStateException("Tried to update password without confirming it");
853             }
854 
855             quality = mController.upgradeQuality(quality);
856             Intent intent = getIntentForUnlockMethod(quality);
857             if (intent != null) {
858                 if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
859                     intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
860                 }
861                 intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
862                 // If the caller requested Gatekeeper Password Handle to be returned, we assume it
863                 // came from biometric enrollment. onActivityResult will put the LockSettingsService
864                 // into the extras and launch biometric enrollment. This should be cleaned up,
865                 // since requesting a Gatekeeper Password Handle should not imply it came from
866                 // biometric setup/settings.
867                 startActivityForResult(intent,
868                         mIsSetNewPassword && mRequestGatekeeperPasswordHandle
869                                 ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
870                                 : CHOOSE_LOCK_REQUEST);
871                 return;
872             }
873 
874             if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
875                 // Clearing of user biometrics when screen lock is cleared is done at
876                 // LockSettingsService.removeBiometricsForUser().
877                 if (mUserPassword != null) {
878                     // No need to call setLockCredential if the user currently doesn't
879                     // have a password
880                     mLockPatternUtils.setLockCredential(
881                             LockscreenCredential.createNone(), mUserPassword, mUserId);
882                 }
883                 mLockPatternUtils.setLockScreenDisabled(disabled, mUserId);
884                 getActivity().setResult(Activity.RESULT_OK);
885                 finish();
886             }
887         }
888 
getIntentForUnlockMethod(int quality)889         private Intent getIntentForUnlockMethod(int quality) {
890             Intent intent = null;
891             if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
892                 intent = getLockManagedPasswordIntent(mUserPassword);
893             } else if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
894                 intent = getLockPasswordIntent(quality);
895             } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
896                 intent = getLockPatternIntent();
897             }
898             return intent;
899         }
900 
901         @Override
onDestroy()902         public void onDestroy() {
903             super.onDestroy();
904             if (mUserPassword != null) {
905                 mUserPassword.zeroize();
906             }
907             // Force a garbage collection immediately to remove remnant of user password shards
908             // from memory.
909             System.gc();
910             System.runFinalization();
911             System.gc();
912         }
913 
914         @Override
getHelpResource()915         public int getHelpResource() {
916             return R.string.help_url_choose_lockscreen;
917         }
918 
getResIdForFactoryResetProtectionWarningTitle()919         private int getResIdForFactoryResetProtectionWarningTitle() {
920             return mIsManagedProfile ? R.string.unlock_disable_frp_warning_title_profile
921                     : R.string.unlock_disable_frp_warning_title;
922         }
923 
getResIdForFactoryResetProtectionWarningMessage()924         private int getResIdForFactoryResetProtectionWarningMessage() {
925             final boolean hasFingerprints;
926             final boolean hasFace;
927             if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
928                 hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(mUserId);
929             } else {
930                 hasFingerprints = false;
931             }
932 
933             if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
934                 hasFace = mFaceManager.hasEnrolledTemplates(mUserId);
935             } else {
936                 hasFace = false;
937             }
938 
939             switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) {
940                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
941                     if (hasFingerprints && hasFace) {
942                         return R.string.unlock_disable_frp_warning_content_pattern_face_fingerprint;
943                     } else if (hasFingerprints) {
944                         return R.string.unlock_disable_frp_warning_content_pattern_fingerprint;
945                     } else if (hasFace) {
946                         return R.string.unlock_disable_frp_warning_content_pattern_face;
947                     } else {
948                         return R.string.unlock_disable_frp_warning_content_pattern;
949                     }
950                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
951                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
952                     if (hasFingerprints && hasFace) {
953                         return R.string.unlock_disable_frp_warning_content_pin_face_fingerprint;
954                     } else if (hasFingerprints) {
955                         return R.string.unlock_disable_frp_warning_content_pin_fingerprint;
956                     } else if (hasFace) {
957                         return R.string.unlock_disable_frp_warning_content_pin_face;
958                     } else {
959                         return R.string.unlock_disable_frp_warning_content_pin;
960                     }
961                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
962                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
963                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
964                 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
965                     if (hasFingerprints && hasFace) {
966                         return R.string
967                                 .unlock_disable_frp_warning_content_password_face_fingerprint;
968                     } else if (hasFingerprints) {
969                         return R.string.unlock_disable_frp_warning_content_password_fingerprint;
970                     } else if (hasFace) {
971                         return R.string.unlock_disable_frp_warning_content_password_face;
972                     } else {
973                         return R.string.unlock_disable_frp_warning_content_password;
974                     }
975                 default:
976                     if (hasFingerprints && hasFace) {
977                         return R.string.unlock_disable_frp_warning_content_unknown_face_fingerprint;
978                     } else if (hasFingerprints) {
979                         return R.string.unlock_disable_frp_warning_content_unknown_fingerprint;
980                     } else if (hasFace) {
981                         return R.string.unlock_disable_frp_warning_content_unknown_face;
982                     } else {
983                         return R.string.unlock_disable_frp_warning_content_unknown;
984                     }
985             }
986         }
987 
isUnlockMethodSecure(String unlockMethod)988         private boolean isUnlockMethodSecure(String unlockMethod) {
989             return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
990                     ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
991         }
992 
setUnlockMethod(String unlockMethod)993         private boolean setUnlockMethod(String unlockMethod) {
994             EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
995 
996             ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
997             if (lock != null) {
998                 switch (lock) {
999                     case NONE:
1000                     case SWIPE:
1001                         updateUnlockMethodAndFinish(
1002                                 lock.defaultQuality,
1003                                 lock == ScreenLockType.NONE,
1004                                 false /* chooseLockSkipped */);
1005                         return true;
1006                     case PATTERN:
1007                     case PIN:
1008                     case PASSWORD:
1009                     case MANAGED:
1010                         maybeEnableEncryption(lock.defaultQuality, false);
1011                         return true;
1012                 }
1013             }
1014             Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
1015             return false;
1016         }
1017 
showFactoryResetProtectionWarningDialog(String unlockMethodToSet)1018         private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
1019             int title = getResIdForFactoryResetProtectionWarningTitle();
1020             int message = getResIdForFactoryResetProtectionWarningMessage();
1021             FactoryResetProtectionWarningDialog dialog =
1022                     FactoryResetProtectionWarningDialog.newInstance(
1023                             title, message, unlockMethodToSet);
1024             dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG);
1025         }
1026 
1027         public static class FactoryResetProtectionWarningDialog extends InstrumentedDialogFragment {
1028 
1029             private static final String ARG_TITLE_RES = "titleRes";
1030             private static final String ARG_MESSAGE_RES = "messageRes";
1031             private static final String ARG_UNLOCK_METHOD_TO_SET = "unlockMethodToSet";
1032 
newInstance( int titleRes, int messageRes, String unlockMethodToSet)1033             public static FactoryResetProtectionWarningDialog newInstance(
1034                     int titleRes, int messageRes, String unlockMethodToSet) {
1035                 FactoryResetProtectionWarningDialog frag =
1036                         new FactoryResetProtectionWarningDialog();
1037                 Bundle args = new Bundle();
1038                 args.putInt(ARG_TITLE_RES, titleRes);
1039                 args.putInt(ARG_MESSAGE_RES, messageRes);
1040                 args.putString(ARG_UNLOCK_METHOD_TO_SET, unlockMethodToSet);
1041                 frag.setArguments(args);
1042                 return frag;
1043             }
1044 
1045             @Override
show(FragmentManager manager, String tag)1046             public void show(FragmentManager manager, String tag) {
1047                 if (manager.findFragmentByTag(tag) == null) {
1048                     // Prevent opening multiple dialogs if tapped on button quickly
1049                     super.show(manager, tag);
1050                 }
1051             }
1052 
1053             @Override
onCreateDialog(Bundle savedInstanceState)1054             public Dialog onCreateDialog(Bundle savedInstanceState) {
1055                 final Bundle args = getArguments();
1056 
1057                 return new AlertDialog.Builder(getActivity())
1058                         .setTitle(args.getInt(ARG_TITLE_RES))
1059                         .setMessage(args.getInt(ARG_MESSAGE_RES))
1060                         .setPositiveButton(R.string.unlock_disable_frp_warning_ok,
1061                                 (dialog, whichButton) -> {
1062                                     String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
1063                                     ((ChooseLockGenericFragment) getParentFragment())
1064                                             .setUnlockMethod(unlockMethod);
1065                                 })
1066                         .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
1067                         .create();
1068             }
1069 
1070             @Override
getMetricsCategory()1071             public int getMetricsCategory() {
1072                 return SettingsEnums.DIALOG_FRP;
1073             }
1074         }
1075     }
1076 }
1077