ChooseLockGeneric.java revision 5a1dbf815222ef0bf9d89fb124b759353238d065
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 17package com.android.settings; 18 19import android.accessibilityservice.AccessibilityServiceInfo; 20import android.app.Activity; 21import android.app.AlertDialog; 22import android.app.Dialog; 23import android.app.DialogFragment; 24import android.app.Fragment; 25import android.app.FragmentManager; 26import android.app.admin.DevicePolicyManager; 27import android.content.Context; 28import android.content.DialogInterface; 29import android.content.Intent; 30import android.hardware.fingerprint.Fingerprint; 31import android.hardware.fingerprint.FingerprintManager; 32import android.hardware.fingerprint.FingerprintManager.RemovalCallback; 33import android.os.Bundle; 34import android.os.Process; 35import android.os.UserHandle; 36import android.os.UserManager; 37import android.os.storage.StorageManager; 38import android.security.KeyStore; 39import android.support.v7.preference.Preference; 40import android.support.v7.preference.PreferenceScreen; 41import android.text.TextUtils; 42import android.util.EventLog; 43import android.util.Log; 44import android.view.View; 45import android.view.accessibility.AccessibilityManager; 46import android.widget.Toast; 47 48import com.android.internal.logging.MetricsProto.MetricsEvent; 49import com.android.internal.widget.LockPatternUtils; 50import com.android.settingslib.RestrictedLockUtils; 51import com.android.settingslib.RestrictedPreference; 52 53import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 54 55public class ChooseLockGeneric extends SettingsActivity { 56 public static final String CONFIRM_CREDENTIALS = "confirm_credentials"; 57 58 @Override 59 public Intent getIntent() { 60 Intent modIntent = new Intent(super.getIntent()); 61 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName()); 62 63 String action = modIntent.getAction(); 64 if (DevicePolicyManager.ACTION_SET_NEW_PASSWORD.equals(action) 65 || DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) { 66 modIntent.putExtra(EXTRA_HIDE_DRAWER, true); 67 } 68 return modIntent; 69 } 70 71 @Override 72 protected boolean isValidFragment(String fragmentName) { 73 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true; 74 return false; 75 } 76 77 /* package */ Class<? extends Fragment> getFragmentClass() { 78 return ChooseLockGenericFragment.class; 79 } 80 81 public static class InternalActivity extends ChooseLockGeneric { 82 } 83 84 public static class ChooseLockGenericFragment extends SettingsPreferenceFragment { 85 private static final String TAG = "ChooseLockGenericFragment"; 86 private static final int MIN_PASSWORD_LENGTH = 4; 87 private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off"; 88 private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none"; 89 private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin"; 90 private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password"; 91 private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern"; 92 private static final String PASSWORD_CONFIRMED = "password_confirmed"; 93 private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation"; 94 public static final String MINIMUM_QUALITY_KEY = "minimum_quality"; 95 public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs"; 96 public static final String ENCRYPT_REQUESTED_QUALITY = "encrypt_requested_quality"; 97 public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled"; 98 public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog"; 99 100 private static final int CONFIRM_EXISTING_REQUEST = 100; 101 private static final int ENABLE_ENCRYPTION_REQUEST = 101; 102 private static final int CHOOSE_LOCK_REQUEST = 102; 103 104 private ChooseLockSettingsHelper mChooseLockSettingsHelper; 105 private DevicePolicyManager mDPM; 106 private KeyStore mKeyStore; 107 private boolean mHasChallenge = false; 108 private long mChallenge; 109 private boolean mPasswordConfirmed = false; 110 private boolean mWaitingForConfirmation = false; 111 private int mEncryptionRequestQuality; 112 private boolean mEncryptionRequestDisabled; 113 private boolean mRequirePassword; 114 private boolean mForChangeCredRequiredForBoot = false; 115 private String mUserPassword; 116 private LockPatternUtils mLockPatternUtils; 117 private FingerprintManager mFingerprintManager; 118 private int mUserId; 119 private boolean mHideDrawer = false; 120 private RemovalCallback mRemovalCallback = new RemovalCallback() { 121 122 @Override 123 public void onRemovalSucceeded(Fingerprint fingerprint) { 124 Log.v(TAG, "Fingerprint removed: " + fingerprint.getFingerId()); 125 if (mFingerprintManager.getEnrolledFingerprints().size() == 0) { 126 finish(); 127 } 128 } 129 130 @Override 131 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { 132 Activity activity = getActivity(); 133 if (activity != null) { 134 Toast.makeText(getActivity(), errString, Toast.LENGTH_SHORT); 135 } 136 finish(); 137 } 138 }; 139 140 protected boolean mForFingerprint = false; 141 142 @Override 143 protected int getMetricsCategory() { 144 return MetricsEvent.CHOOSE_LOCK_GENERIC; 145 } 146 147 @Override 148 public void onCreate(Bundle savedInstanceState) { 149 super.onCreate(savedInstanceState); 150 151 mFingerprintManager = 152 (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE); 153 mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 154 mKeyStore = KeyStore.getInstance(); 155 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity()); 156 mLockPatternUtils = new LockPatternUtils(getActivity()); 157 158 // Defaults to needing to confirm credentials 159 final boolean confirmCredentials = getActivity().getIntent() 160 .getBooleanExtra(CONFIRM_CREDENTIALS, true); 161 if (getActivity() instanceof ChooseLockGeneric.InternalActivity) { 162 mPasswordConfirmed = !confirmCredentials; 163 } 164 mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); 165 166 mHasChallenge = getActivity().getIntent().getBooleanExtra( 167 ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); 168 mChallenge = getActivity().getIntent().getLongExtra( 169 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); 170 mForFingerprint = getActivity().getIntent().getBooleanExtra( 171 ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); 172 mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean( 173 ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT); 174 175 if (savedInstanceState != null) { 176 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); 177 mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); 178 mEncryptionRequestQuality = savedInstanceState.getInt(ENCRYPT_REQUESTED_QUALITY); 179 mEncryptionRequestDisabled = savedInstanceState.getBoolean( 180 ENCRYPT_REQUESTED_DISABLED); 181 } 182 183 int targetUser = Utils.getSecureTargetUser( 184 getActivity().getActivityToken(), 185 UserManager.get(getActivity()), 186 null, 187 getActivity().getIntent().getExtras()).getIdentifier(); 188 if (DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals( 189 getActivity().getIntent().getAction()) || 190 !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) { 191 // Always use parent if explicitely requested or if profile challenge is not 192 // supported 193 Bundle arguments = getArguments(); 194 mUserId = Utils.getUserIdFromBundle(getContext(), arguments != null ? arguments 195 : getActivity().getIntent().getExtras()); 196 } else { 197 mUserId = targetUser; 198 } 199 200 if (mPasswordConfirmed) { 201 updatePreferencesOrFinish(); 202 if (mForChangeCredRequiredForBoot) { 203 maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality( 204 mUserId), false); 205 } 206 } else if (!mWaitingForConfirmation) { 207 ChooseLockSettingsHelper helper = 208 new ChooseLockSettingsHelper(this.getActivity(), this); 209 if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, 210 getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) { 211 mPasswordConfirmed = true; // no password set, so no need to confirm 212 updatePreferencesOrFinish(); 213 } else { 214 mWaitingForConfirmation = true; 215 } 216 } 217 addHeaderView(); 218 } 219 220 protected void addHeaderView() { 221 if (mForFingerprint) { 222 setHeaderView(R.layout.choose_lock_generic_fingerprint_header); 223 } 224 } 225 226 @Override 227 public boolean onPreferenceTreeClick(Preference preference) { 228 final String key = preference.getKey(); 229 230 if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) { 231 // Show the disabling FRP warning only when the user is switching from a secure 232 // unlock method to an insecure one 233 showFactoryResetProtectionWarningDialog(key); 234 return true; 235 } else { 236 return setUnlockMethod(key); 237 } 238 } 239 240 /** 241 * If the device has encryption already enabled, then ask the user if they 242 * also want to encrypt the phone with this password. 243 * 244 * @param quality 245 * @param disabled 246 */ 247 // TODO: why does this take disabled, its always called with a quality higher than 248 // what makes sense with disabled == true 249 private void maybeEnableEncryption(int quality, boolean disabled) { 250 DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE); 251 if (UserManager.get(getActivity()).isAdminUser() 252 && mUserId == UserHandle.myUserId() 253 && LockPatternUtils.isDeviceEncryptionEnabled() 254 && !LockPatternUtils.isFileEncryptionEnabled() 255 && !dpm.getDoNotAskCredentialsOnBoot()) { 256 mEncryptionRequestQuality = quality; 257 mEncryptionRequestDisabled = disabled; 258 // Get the intent that the encryption interstitial should start for creating 259 // the new unlock method. 260 Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled); 261 unlockMethodIntent.putExtra( 262 ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, 263 mForChangeCredRequiredForBoot); 264 final Context context = getActivity(); 265 // If accessibility is enabled and the user hasn't seen this dialog before, set the 266 // default state to agree with that which is compatible with accessibility 267 // (password not required). 268 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled(); 269 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn); 270 Intent intent = getEncryptionInterstitialIntent(context, quality, required, 271 unlockMethodIntent); 272 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, 273 mForFingerprint); 274 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); 275 startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST); 276 } else { 277 if (mForChangeCredRequiredForBoot) { 278 // Welp, couldn't change it. Oh well. 279 finish(); 280 return; 281 } 282 mRequirePassword = false; // device encryption not enabled or not device owner. 283 updateUnlockMethodAndFinish(quality, disabled); 284 } 285 } 286 287 @Override 288 public void onActivityResult(int requestCode, int resultCode, Intent data) { 289 super.onActivityResult(requestCode, resultCode, data); 290 mWaitingForConfirmation = false; 291 if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { 292 mPasswordConfirmed = true; 293 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 294 updatePreferencesOrFinish(); 295 if (mForChangeCredRequiredForBoot) { 296 if (!TextUtils.isEmpty(mUserPassword)) { 297 maybeEnableEncryption( 298 mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false); 299 } else { 300 finish(); 301 } 302 } 303 } else if (requestCode == CHOOSE_LOCK_REQUEST 304 || requestCode == ENABLE_ENCRYPTION_REQUEST) { 305 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) { 306 getActivity().setResult(resultCode, data); 307 finish(); 308 } 309 } else { 310 getActivity().setResult(Activity.RESULT_CANCELED); 311 finish(); 312 } 313 if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) { 314 finish(); 315 } 316 } 317 318 @Override 319 public void onSaveInstanceState(Bundle outState) { 320 super.onSaveInstanceState(outState); 321 // Saved so we don't force user to re-enter their password if configuration changes 322 outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed); 323 outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation); 324 outState.putInt(ENCRYPT_REQUESTED_QUALITY, mEncryptionRequestQuality); 325 outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled); 326 } 327 328 private void updatePreferencesOrFinish() { 329 Intent intent = getActivity().getIntent(); 330 int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1); 331 if (quality == -1) { 332 // If caller didn't specify password quality, show UI and allow the user to choose. 333 quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1); 334 quality = upgradeQuality(quality); 335 final boolean hideDisabledPrefs = intent.getBooleanExtra( 336 HIDE_DISABLED_PREFS, false); 337 final PreferenceScreen prefScreen = getPreferenceScreen(); 338 if (prefScreen != null) { 339 prefScreen.removeAll(); 340 } 341 addPreferences(); 342 disableUnusablePreferences(quality, hideDisabledPrefs); 343 updatePreferenceText(); 344 updateCurrentPreference(); 345 updatePreferenceSummaryIfNeeded(); 346 } else { 347 updateUnlockMethodAndFinish(quality, false); 348 } 349 } 350 351 protected void addPreferences() { 352 addPreferencesFromResource(R.xml.security_settings_picker); 353 } 354 355 private void updatePreferenceText() { 356 if (mForFingerprint) { 357 Preference pattern = findPreference(KEY_UNLOCK_SET_PATTERN); 358 pattern.setTitle(R.string.fingerprint_unlock_set_unlock_pattern); 359 360 Preference pin = findPreference(KEY_UNLOCK_SET_PIN); 361 pin.setTitle(R.string.fingerprint_unlock_set_unlock_pin); 362 363 Preference password = findPreference(KEY_UNLOCK_SET_PASSWORD); 364 password.setTitle(R.string.fingerprint_unlock_set_unlock_password); 365 } 366 } 367 368 private void updateCurrentPreference() { 369 String currentKey = getKeyForCurrent(); 370 Preference preference = findPreference(currentKey); 371 if (preference != null) { 372 preference.setSummary(R.string.current_screen_lock); 373 } 374 } 375 376 private String getKeyForCurrent() { 377 final int credentialOwner = UserManager.get(getContext()) 378 .getCredentialOwnerProfile(mUserId); 379 if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) { 380 return KEY_UNLOCK_SET_OFF; 381 } 382 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) { 383 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 384 return KEY_UNLOCK_SET_PATTERN; 385 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 386 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 387 return KEY_UNLOCK_SET_PIN; 388 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 389 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 390 return KEY_UNLOCK_SET_PASSWORD; 391 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 392 return KEY_UNLOCK_SET_NONE; 393 } 394 return null; 395 } 396 397 /** increases the quality if necessary */ 398 private int upgradeQuality(int quality) { 399 quality = upgradeQualityForDPM(quality); 400 return quality; 401 } 402 403 private int upgradeQualityForDPM(int quality) { 404 // Compare min allowed password quality 405 int minQuality = mDPM.getPasswordQuality(null, mUserId); 406 if (quality < minQuality) { 407 quality = minQuality; 408 } 409 return quality; 410 } 411 412 /*** 413 * Disables preferences that are less secure than required quality. The actual 414 * implementation is in disableUnusablePreferenceImpl. 415 * 416 * @param quality the requested quality. 417 * @param hideDisabledPrefs if false preferences show why they were disabled; otherwise 418 * they're not shown at all. 419 */ 420 protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) { 421 disableUnusablePreferencesImpl(quality, hideDisabledPrefs); 422 } 423 424 /*** 425 * Disables preferences that are less secure than required quality. 426 * 427 * @param quality the requested quality. 428 * @param hideDisabled whether to hide disable screen lock options. 429 */ 430 protected void disableUnusablePreferencesImpl(final int quality, 431 boolean hideDisabled) { 432 final PreferenceScreen entries = getPreferenceScreen(); 433 434 int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId); 435 EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet( 436 getActivity(), mUserId); 437 for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) { 438 Preference pref = entries.getPreference(i); 439 if (pref instanceof RestrictedPreference) { 440 final String key = pref.getKey(); 441 boolean enabled = true; 442 boolean visible = true; 443 boolean disabledByAdmin = false; 444 if (KEY_UNLOCK_SET_OFF.equals(key)) { 445 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 446 if (getResources().getBoolean(R.bool.config_hide_none_security_option)) { 447 enabled = false; 448 visible = false; 449 } 450 disabledByAdmin = adminEnforcedQuality 451 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 452 } else if (KEY_UNLOCK_SET_NONE.equals(key)) { 453 if (mUserId != UserHandle.myUserId()) { 454 // Swipe doesn't make sense for profiles. 455 visible = false; 456 } 457 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 458 disabledByAdmin = adminEnforcedQuality 459 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 460 } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) { 461 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 462 disabledByAdmin = adminEnforcedQuality 463 > DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 464 } else if (KEY_UNLOCK_SET_PIN.equals(key)) { 465 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 466 disabledByAdmin = adminEnforcedQuality 467 > DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 468 } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) { 469 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 470 disabledByAdmin = adminEnforcedQuality 471 > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 472 } 473 if (hideDisabled) { 474 visible = enabled; 475 } 476 if (!visible) { 477 entries.removePreference(pref); 478 } else if (disabledByAdmin && enforcedAdmin != null) { 479 ((RestrictedPreference) pref).setDisabledByAdmin(enforcedAdmin); 480 } else if (!enabled) { 481 // we need to setDisabledByAdmin to null first to disable the padlock 482 // in case it was set earlier. 483 ((RestrictedPreference) pref).setDisabledByAdmin(null); 484 pref.setSummary(R.string.unlock_set_unlock_disabled_summary); 485 pref.setEnabled(false); 486 } else { 487 ((RestrictedPreference) pref).setDisabledByAdmin(null); 488 } 489 } 490 } 491 } 492 493 private void updatePreferenceSummaryIfNeeded() { 494 // On a default block encrypted device with accessibility, add a warning 495 // that your data is not credential encrypted 496 if (!StorageManager.isBlockEncrypted()) { 497 return; 498 } 499 500 if (StorageManager.isNonDefaultBlockEncrypted()) { 501 return; 502 } 503 504 if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList( 505 AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) { 506 return; 507 } 508 509 CharSequence summary = getString(R.string.secure_lock_encryption_warning); 510 511 PreferenceScreen screen = getPreferenceScreen(); 512 final int preferenceCount = screen.getPreferenceCount(); 513 for (int i = 0; i < preferenceCount; i++) { 514 Preference preference = screen.getPreference(i); 515 switch (preference.getKey()) { 516 case KEY_UNLOCK_SET_PATTERN: 517 case KEY_UNLOCK_SET_PIN: 518 case KEY_UNLOCK_SET_PASSWORD: { 519 preference.setSummary(summary); 520 } break; 521 } 522 } 523 } 524 525 protected Intent getLockPasswordIntent(Context context, int quality, 526 int minLength, final int maxLength, 527 boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId) { 528 return ChooseLockPassword.createIntent(context, quality, minLength, 529 maxLength, requirePasswordToDecrypt, confirmCredentials, userId); 530 } 531 532 protected Intent getLockPasswordIntent(Context context, int quality, 533 int minLength, final int maxLength, 534 boolean requirePasswordToDecrypt, long challenge, int userId) { 535 return ChooseLockPassword.createIntent(context, quality, minLength, 536 maxLength, requirePasswordToDecrypt, challenge, userId); 537 } 538 539 protected Intent getLockPasswordIntent(Context context, int quality, int minLength, 540 int maxLength, boolean requirePasswordToDecrypt, String password, int userId) { 541 return ChooseLockPassword.createIntent(context, quality, minLength, maxLength, 542 requirePasswordToDecrypt, password, userId); 543 } 544 545 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 546 final boolean confirmCredentials, int userId) { 547 return ChooseLockPattern.createIntent(context, requirePassword, 548 confirmCredentials, userId); 549 } 550 551 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 552 long challenge, int userId) { 553 return ChooseLockPattern.createIntent(context, requirePassword, challenge, userId); 554 } 555 556 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 557 final String pattern, int userId) { 558 return ChooseLockPattern.createIntent(context, requirePassword, pattern, userId); 559 } 560 561 protected Intent getEncryptionInterstitialIntent(Context context, int quality, 562 boolean required, Intent unlockMethodIntent) { 563 return EncryptionInterstitial.createStartIntent(context, quality, required, 564 unlockMethodIntent); 565 } 566 567 /** 568 * Invokes an activity to change the user's pattern, password or PIN based on given quality 569 * and minimum quality specified by DevicePolicyManager. If quality is 570 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared. 571 * 572 * @param quality the desired quality. Ignored if DevicePolicyManager requires more security 573 * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is 574 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED} 575 */ 576 void updateUnlockMethodAndFinish(int quality, boolean disabled) { 577 // Sanity check. We should never get here without confirming user's existing password. 578 if (!mPasswordConfirmed) { 579 throw new IllegalStateException("Tried to update password without confirming it"); 580 } 581 582 quality = upgradeQuality(quality); 583 Intent intent = getIntentForUnlockMethod(quality, disabled); 584 if (intent != null) { 585 startActivityForResult(intent, CHOOSE_LOCK_REQUEST); 586 return; 587 } 588 589 if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 590 mLockPatternUtils.setSeparateProfileChallengeEnabled(mUserId, true); 591 mChooseLockSettingsHelper.utils().clearLock(mUserId); 592 mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId); 593 removeAllFingerprintTemplatesAndFinish(); 594 getActivity().setResult(Activity.RESULT_OK); 595 } else { 596 removeAllFingerprintTemplatesAndFinish(); 597 } 598 } 599 600 private Intent getIntentForUnlockMethod(int quality, boolean disabled) { 601 Intent intent = null; 602 final Context context = getActivity(); 603 if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { 604 int minLength = mDPM.getPasswordMinimumLength(null, mUserId); 605 if (minLength < MIN_PASSWORD_LENGTH) { 606 minLength = MIN_PASSWORD_LENGTH; 607 } 608 final int maxLength = mDPM.getPasswordMaximumLength(quality); 609 if (mHasChallenge) { 610 intent = getLockPasswordIntent(context, quality, minLength, 611 maxLength, mRequirePassword, mChallenge, mUserId); 612 } else { 613 intent = getLockPasswordIntent(context, quality, minLength, 614 maxLength, mRequirePassword, mUserPassword, mUserId); 615 } 616 } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 617 if (mHasChallenge) { 618 intent = getLockPatternIntent(context, mRequirePassword, 619 mChallenge, mUserId); 620 } else { 621 intent = getLockPatternIntent(context, mRequirePassword, 622 mUserPassword, mUserId); 623 } 624 } 625 if (intent != null) { 626 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); 627 } 628 return intent; 629 } 630 631 private void removeAllFingerprintTemplatesAndFinish() { 632 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected() 633 && mFingerprintManager.hasEnrolledFingerprints(mUserId)) { 634 mFingerprintManager.setActiveUser(mUserId); 635 mFingerprintManager.remove( 636 new Fingerprint(null, mUserId, 0, 0), mUserId, 637 new RemovalCallback() { 638 @Override 639 public void onRemovalError(Fingerprint fp, int errMsgId, 640 CharSequence errString) { 641 mRemovalCallback.onRemovalError(fp, errMsgId, errString); 642 mFingerprintManager.setActiveUser(UserHandle.myUserId()); 643 } 644 645 @Override 646 public void onRemovalSucceeded(Fingerprint fingerprint) { 647 mRemovalCallback.onRemovalSucceeded(fingerprint); 648 mFingerprintManager.setActiveUser(UserHandle.myUserId()); 649 } 650 }); 651 } else { 652 // The removal callback will call finish, once all fingerprints are removed. 653 // We need to wait for that to occur, otherwise, the UI will still show that 654 // fingerprints exist even though they are (about to) be removed depending on 655 // the race condition. 656 finish(); 657 } 658 } 659 660 @Override 661 public void onDestroy() { 662 super.onDestroy(); 663 } 664 665 @Override 666 protected int getHelpResource() { 667 return R.string.help_url_choose_lockscreen; 668 } 669 670 private int getResIdForFactoryResetProtectionWarningTitle() { 671 boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId); 672 return isProfile ? R.string.unlock_disable_frp_warning_title_profile 673 : R.string.unlock_disable_frp_warning_title; 674 } 675 676 private int getResIdForFactoryResetProtectionWarningMessage() { 677 boolean hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(mUserId); 678 boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId); 679 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) { 680 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 681 if (hasFingerprints && isProfile) { 682 return R.string 683 .unlock_disable_frp_warning_content_pattern_fingerprint_profile; 684 } else if (hasFingerprints && !isProfile) { 685 return R.string.unlock_disable_frp_warning_content_pattern_fingerprint; 686 } else if (isProfile) { 687 return R.string.unlock_disable_frp_warning_content_pattern_profile; 688 } else { 689 return R.string.unlock_disable_frp_warning_content_pattern; 690 } 691 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 692 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 693 if (hasFingerprints && isProfile) { 694 return R.string.unlock_disable_frp_warning_content_pin_fingerprint_profile; 695 } else if (hasFingerprints && !isProfile) { 696 return R.string.unlock_disable_frp_warning_content_pin_fingerprint; 697 } else if (isProfile) { 698 return R.string.unlock_disable_frp_warning_content_pin_profile; 699 } else { 700 return R.string.unlock_disable_frp_warning_content_pin; 701 } 702 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 703 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 704 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 705 if (hasFingerprints && isProfile) { 706 return R.string 707 .unlock_disable_frp_warning_content_password_fingerprint_profile; 708 } else if (hasFingerprints && !isProfile) { 709 return R.string.unlock_disable_frp_warning_content_password_fingerprint; 710 } else if (isProfile) { 711 return R.string.unlock_disable_frp_warning_content_password_profile; 712 } else { 713 return R.string.unlock_disable_frp_warning_content_password; 714 } 715 default: 716 if (hasFingerprints && isProfile) { 717 return R.string 718 .unlock_disable_frp_warning_content_unknown_fingerprint_profile; 719 } else if (hasFingerprints && !isProfile) { 720 return R.string.unlock_disable_frp_warning_content_unknown_fingerprint; 721 } else if (isProfile) { 722 return R.string.unlock_disable_frp_warning_content_unknown_profile; 723 } else { 724 return R.string.unlock_disable_frp_warning_content_unknown; 725 } 726 } 727 } 728 729 private boolean isUnlockMethodSecure(String unlockMethod) { 730 return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) || 731 KEY_UNLOCK_SET_NONE.equals(unlockMethod)); 732 } 733 734 private boolean setUnlockMethod(String unlockMethod) { 735 EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod); 736 737 if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) { 738 updateUnlockMethodAndFinish( 739 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ ); 740 } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) { 741 updateUnlockMethodAndFinish( 742 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ ); 743 } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) { 744 maybeEnableEncryption( 745 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false); 746 } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) { 747 maybeEnableEncryption( 748 DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false); 749 } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) { 750 maybeEnableEncryption( 751 DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false); 752 } else { 753 Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod); 754 return false; 755 } 756 return true; 757 } 758 759 private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) { 760 int title = getResIdForFactoryResetProtectionWarningTitle(); 761 int message = getResIdForFactoryResetProtectionWarningMessage(); 762 FactoryResetProtectionWarningDialog dialog = 763 FactoryResetProtectionWarningDialog.newInstance( 764 title, message, unlockMethodToSet); 765 dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG); 766 } 767 768 public static class FactoryResetProtectionWarningDialog extends DialogFragment { 769 770 private static final String ARG_TITLE_RES = "titleRes"; 771 private static final String ARG_MESSAGE_RES = "messageRes"; 772 private static final String ARG_UNLOCK_METHOD_TO_SET = "unlockMethodToSet"; 773 774 public static FactoryResetProtectionWarningDialog newInstance( 775 int titleRes, int messageRes, String unlockMethodToSet) { 776 FactoryResetProtectionWarningDialog frag = 777 new FactoryResetProtectionWarningDialog(); 778 Bundle args = new Bundle(); 779 args.putInt(ARG_TITLE_RES, titleRes); 780 args.putInt(ARG_MESSAGE_RES, messageRes); 781 args.putString(ARG_UNLOCK_METHOD_TO_SET, unlockMethodToSet); 782 frag.setArguments(args); 783 return frag; 784 } 785 786 @Override 787 public void show(FragmentManager manager, String tag) { 788 if (manager.findFragmentByTag(tag) == null) { 789 // Prevent opening multiple dialogs if tapped on button quickly 790 super.show(manager, tag); 791 } 792 } 793 794 @Override 795 public Dialog onCreateDialog(Bundle savedInstanceState) { 796 final Bundle args = getArguments(); 797 798 return new AlertDialog.Builder(getActivity()) 799 .setTitle(args.getInt(ARG_TITLE_RES)) 800 .setMessage(args.getInt(ARG_MESSAGE_RES)) 801 .setPositiveButton(R.string.unlock_disable_frp_warning_ok, 802 new DialogInterface.OnClickListener() { 803 @Override 804 public void onClick(DialogInterface dialog, int whichButton) { 805 ((ChooseLockGenericFragment) getParentFragment()) 806 .setUnlockMethod( 807 args.getString(ARG_UNLOCK_METHOD_TO_SET)); 808 } 809 } 810 ) 811 .setNegativeButton(R.string.cancel, 812 new DialogInterface.OnClickListener() { 813 @Override 814 public void onClick(DialogInterface dialog, int whichButton) { 815 dismiss(); 816 } 817 } 818 ) 819 .create(); 820 } 821 } 822 } 823} 824