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