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