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