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