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