1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings; 18 19 import android.accessibilityservice.AccessibilityServiceInfo; 20 import android.app.Activity; 21 import android.app.AlertDialog; 22 import android.app.Dialog; 23 import android.app.DialogFragment; 24 import android.app.Fragment; 25 import android.app.FragmentManager; 26 import android.app.admin.DevicePolicyManager; 27 import android.content.Context; 28 import android.content.DialogInterface; 29 import android.content.Intent; 30 import android.os.Bundle; 31 import android.os.Process; 32 import android.os.UserHandle; 33 import android.preference.Preference; 34 import android.preference.PreferenceScreen; 35 import android.security.KeyStore; 36 import android.hardware.fingerprint.Fingerprint; 37 import android.hardware.fingerprint.FingerprintManager; 38 import android.hardware.fingerprint.FingerprintManager.RemovalCallback; 39 import android.util.EventLog; 40 import android.util.Log; 41 import android.view.LayoutInflater; 42 import android.view.View; 43 import android.view.accessibility.AccessibilityManager; 44 import android.widget.ListView; 45 import android.widget.Toast; 46 47 import com.android.internal.logging.MetricsLogger; 48 import com.android.internal.widget.LockPatternUtils; 49 50 public class ChooseLockGeneric extends SettingsActivity { 51 public static final String CONFIRM_CREDENTIALS = "confirm_credentials"; 52 53 @Override getIntent()54 public Intent getIntent() { 55 Intent modIntent = new Intent(super.getIntent()); 56 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName()); 57 return modIntent; 58 } 59 60 @Override isValidFragment(String fragmentName)61 protected boolean isValidFragment(String fragmentName) { 62 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true; 63 return false; 64 } 65 getFragmentClass()66 /* package */ Class<? extends Fragment> getFragmentClass() { 67 return ChooseLockGenericFragment.class; 68 } 69 70 public static class InternalActivity extends ChooseLockGeneric { 71 } 72 73 public static class ChooseLockGenericFragment extends SettingsPreferenceFragment { 74 private static final String TAG = "ChooseLockGenericFragment"; 75 private static final int MIN_PASSWORD_LENGTH = 4; 76 private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off"; 77 private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none"; 78 private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin"; 79 private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password"; 80 private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern"; 81 private static final String PASSWORD_CONFIRMED = "password_confirmed"; 82 private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation"; 83 public static final String MINIMUM_QUALITY_KEY = "minimum_quality"; 84 public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs"; 85 public static final String ENCRYPT_REQUESTED_QUALITY = "encrypt_requested_quality"; 86 public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled"; 87 public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog"; 88 89 private static final int CONFIRM_EXISTING_REQUEST = 100; 90 private static final int ENABLE_ENCRYPTION_REQUEST = 101; 91 private static final int CHOOSE_LOCK_REQUEST = 102; 92 93 private ChooseLockSettingsHelper mChooseLockSettingsHelper; 94 private DevicePolicyManager mDPM; 95 private KeyStore mKeyStore; 96 private boolean mHasChallenge = false; 97 private long mChallenge; 98 private boolean mPasswordConfirmed = false; 99 private boolean mWaitingForConfirmation = false; 100 private int mEncryptionRequestQuality; 101 private boolean mEncryptionRequestDisabled; 102 private boolean mRequirePassword; 103 private boolean mForFingerprint = false; 104 private String mUserPassword; 105 private LockPatternUtils mLockPatternUtils; 106 private FingerprintManager mFingerprintManager; 107 private RemovalCallback mRemovalCallback = new RemovalCallback() { 108 109 @Override 110 public void onRemovalSucceeded(Fingerprint fingerprint) { 111 Log.v(TAG, "Fingerprint removed: " + fingerprint.getFingerId()); 112 if (mFingerprintManager.getEnrolledFingerprints().size() == 0) { 113 finish(); 114 } 115 } 116 117 @Override 118 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { 119 Activity activity = getActivity(); 120 if (activity != null) { 121 Toast.makeText(getActivity(), errString, Toast.LENGTH_SHORT); 122 } 123 finish(); 124 } 125 }; 126 127 @Override getMetricsCategory()128 protected int getMetricsCategory() { 129 return MetricsLogger.CHOOSE_LOCK_GENERIC; 130 } 131 132 @Override onCreate(Bundle savedInstanceState)133 public void onCreate(Bundle savedInstanceState) { 134 super.onCreate(savedInstanceState); 135 136 mFingerprintManager = 137 (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE); 138 mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 139 mKeyStore = KeyStore.getInstance(); 140 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity()); 141 mLockPatternUtils = new LockPatternUtils(getActivity()); 142 143 // Defaults to needing to confirm credentials 144 final boolean confirmCredentials = getActivity().getIntent() 145 .getBooleanExtra(CONFIRM_CREDENTIALS, true); 146 if (getActivity() instanceof ChooseLockGeneric.InternalActivity) { 147 mPasswordConfirmed = !confirmCredentials; 148 } 149 150 mHasChallenge = getActivity().getIntent().getBooleanExtra( 151 ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); 152 mChallenge = getActivity().getIntent().getLongExtra( 153 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); 154 mForFingerprint = getActivity().getIntent().getBooleanExtra( 155 ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); 156 157 if (savedInstanceState != null) { 158 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); 159 mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); 160 mEncryptionRequestQuality = savedInstanceState.getInt(ENCRYPT_REQUESTED_QUALITY); 161 mEncryptionRequestDisabled = savedInstanceState.getBoolean( 162 ENCRYPT_REQUESTED_DISABLED); 163 } 164 165 if (mPasswordConfirmed) { 166 updatePreferencesOrFinish(); 167 } else if (!mWaitingForConfirmation) { 168 ChooseLockSettingsHelper helper = 169 new ChooseLockSettingsHelper(this.getActivity(), this); 170 if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, 171 getString(R.string.unlock_set_unlock_launch_picker_title), true)) { 172 mPasswordConfirmed = true; // no password set, so no need to confirm 173 updatePreferencesOrFinish(); 174 } else { 175 mWaitingForConfirmation = true; 176 } 177 } 178 } 179 180 @Override onViewCreated(View view, Bundle savedInstanceState)181 public void onViewCreated(View view, Bundle savedInstanceState) { 182 super.onViewCreated(view, savedInstanceState); 183 if (mForFingerprint) { 184 final LayoutInflater inflater = LayoutInflater.from(getContext()); 185 final ListView listView = getListView(); 186 final View fingerprintHeader = inflater.inflate( 187 R.layout.choose_lock_generic_fingerprint_header, listView, false); 188 listView.addHeaderView(fingerprintHeader, null, false); 189 } 190 } 191 192 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)193 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 194 Preference preference) { 195 final String key = preference.getKey(); 196 197 if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(UserHandle.myUserId())) { 198 // Show the disabling FRP warning only when the user is switching from a secure 199 // unlock method to an insecure one 200 showFactoryResetProtectionWarningDialog(key); 201 return true; 202 } else { 203 return setUnlockMethod(key); 204 } 205 } 206 207 /** 208 * If the device has encryption already enabled, then ask the user if they 209 * also want to encrypt the phone with this password. 210 * 211 * @param quality 212 * @param disabled 213 */ 214 // TODO: why does this take disabled, its always called with a quality higher than 215 // what makes sense with disabled == true maybeEnableEncryption(int quality, boolean disabled)216 private void maybeEnableEncryption(int quality, boolean disabled) { 217 DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE); 218 if (Process.myUserHandle().isOwner() && LockPatternUtils.isDeviceEncryptionEnabled() 219 && !dpm.getDoNotAskCredentialsOnBoot()) { 220 mEncryptionRequestQuality = quality; 221 mEncryptionRequestDisabled = disabled; 222 final Context context = getActivity(); 223 // If accessibility is enabled and the user hasn't seen this dialog before, set the 224 // default state to agree with that which is compatible with accessibility 225 // (password not required). 226 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled(); 227 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn); 228 Intent intent = getEncryptionInterstitialIntent(context, quality, required); 229 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, 230 mForFingerprint); 231 startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST); 232 } else { 233 mRequirePassword = false; // device encryption not enabled or not device owner. 234 updateUnlockMethodAndFinish(quality, disabled); 235 } 236 } 237 238 @Override onActivityResult(int requestCode, int resultCode, Intent data)239 public void onActivityResult(int requestCode, int resultCode, Intent data) { 240 super.onActivityResult(requestCode, resultCode, data); 241 mWaitingForConfirmation = false; 242 if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { 243 mPasswordConfirmed = true; 244 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 245 updatePreferencesOrFinish(); 246 } else if (requestCode == ENABLE_ENCRYPTION_REQUEST 247 && resultCode == Activity.RESULT_OK) { 248 mRequirePassword = data.getBooleanExtra( 249 EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); 250 updateUnlockMethodAndFinish(mEncryptionRequestQuality, mEncryptionRequestDisabled); 251 } else if (requestCode == CHOOSE_LOCK_REQUEST) { 252 getActivity().setResult(resultCode, data); 253 finish(); 254 } else { 255 getActivity().setResult(Activity.RESULT_CANCELED); 256 finish(); 257 } 258 } 259 260 @Override onSaveInstanceState(Bundle outState)261 public void onSaveInstanceState(Bundle outState) { 262 super.onSaveInstanceState(outState); 263 // Saved so we don't force user to re-enter their password if configuration changes 264 outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed); 265 outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation); 266 outState.putInt(ENCRYPT_REQUESTED_QUALITY, mEncryptionRequestQuality); 267 outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled); 268 } 269 updatePreferencesOrFinish()270 private void updatePreferencesOrFinish() { 271 Intent intent = getActivity().getIntent(); 272 int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1); 273 if (quality == -1) { 274 // If caller didn't specify password quality, show UI and allow the user to choose. 275 quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1); 276 quality = upgradeQuality(quality); 277 final boolean hideDisabledPrefs = intent.getBooleanExtra( 278 HIDE_DISABLED_PREFS, false); 279 final PreferenceScreen prefScreen = getPreferenceScreen(); 280 if (prefScreen != null) { 281 prefScreen.removeAll(); 282 } 283 addPreferencesFromResource(R.xml.security_settings_picker); 284 disableUnusablePreferences(quality, hideDisabledPrefs); 285 updateCurrentPreference(); 286 updatePreferenceSummaryIfNeeded(); 287 } else { 288 updateUnlockMethodAndFinish(quality, false); 289 } 290 } 291 updateCurrentPreference()292 private void updateCurrentPreference() { 293 String currentKey = getKeyForCurrent(); 294 Preference preference = findPreference(currentKey); 295 if (preference != null) { 296 preference.setSummary(R.string.current_screen_lock); 297 } 298 } 299 getKeyForCurrent()300 private String getKeyForCurrent() { 301 if (mLockPatternUtils.isLockScreenDisabled(UserHandle.myUserId())) { 302 return KEY_UNLOCK_SET_OFF; 303 } 304 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId())) { 305 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 306 return KEY_UNLOCK_SET_PATTERN; 307 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 308 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 309 return KEY_UNLOCK_SET_PIN; 310 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 311 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 312 return KEY_UNLOCK_SET_PASSWORD; 313 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 314 return KEY_UNLOCK_SET_NONE; 315 } 316 return null; 317 } 318 319 /** increases the quality if necessary */ upgradeQuality(int quality)320 private int upgradeQuality(int quality) { 321 quality = upgradeQualityForDPM(quality); 322 return quality; 323 } 324 upgradeQualityForDPM(int quality)325 private int upgradeQualityForDPM(int quality) { 326 // Compare min allowed password quality 327 int minQuality = mDPM.getPasswordQuality(null); 328 if (quality < minQuality) { 329 quality = minQuality; 330 } 331 return quality; 332 } 333 334 /*** 335 * Disables preferences that are less secure than required quality. The actual 336 * implementation is in disableUnusablePreferenceImpl. 337 * 338 * @param quality the requested quality. 339 * @param hideDisabledPrefs if false preferences show why they were disabled; otherwise 340 * they're not shown at all. 341 */ disableUnusablePreferences(final int quality, boolean hideDisabledPrefs)342 protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) { 343 disableUnusablePreferencesImpl(quality, hideDisabledPrefs); 344 } 345 346 /*** 347 * Disables preferences that are less secure than required quality. 348 * 349 * @param quality the requested quality. 350 * @param hideDisabled whether to hide disable screen lock options. 351 */ disableUnusablePreferencesImpl(final int quality, boolean hideDisabled)352 protected void disableUnusablePreferencesImpl(final int quality, 353 boolean hideDisabled) { 354 final PreferenceScreen entries = getPreferenceScreen(); 355 356 for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) { 357 Preference pref = entries.getPreference(i); 358 if (pref instanceof PreferenceScreen) { 359 final String key = pref.getKey(); 360 boolean enabled = true; 361 boolean visible = true; 362 if (KEY_UNLOCK_SET_OFF.equals(key)) { 363 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 364 if (getResources().getBoolean(R.bool.config_hide_none_security_option)) { 365 enabled = false; 366 visible = false; 367 } 368 } else if (KEY_UNLOCK_SET_NONE.equals(key)) { 369 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 370 } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) { 371 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 372 } else if (KEY_UNLOCK_SET_PIN.equals(key)) { 373 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 374 } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) { 375 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 376 } 377 if (hideDisabled) { 378 visible = enabled; 379 } 380 if (!visible) { 381 entries.removePreference(pref); 382 } else if (!enabled) { 383 pref.setSummary(R.string.unlock_set_unlock_disabled_summary); 384 pref.setEnabled(false); 385 } 386 } 387 } 388 } 389 updatePreferenceSummaryIfNeeded()390 private void updatePreferenceSummaryIfNeeded() { 391 if (LockPatternUtils.isDeviceEncrypted()) { 392 return; 393 } 394 395 if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList( 396 AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) { 397 return; 398 } 399 400 CharSequence summary = getString(R.string.secure_lock_encryption_warning); 401 402 PreferenceScreen screen = getPreferenceScreen(); 403 final int preferenceCount = screen.getPreferenceCount(); 404 for (int i = 0; i < preferenceCount; i++) { 405 Preference preference = screen.getPreference(i); 406 switch (preference.getKey()) { 407 case KEY_UNLOCK_SET_PATTERN: 408 case KEY_UNLOCK_SET_PIN: 409 case KEY_UNLOCK_SET_PASSWORD: { 410 preference.setSummary(summary); 411 } break; 412 } 413 } 414 } 415 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, boolean confirmCredentials)416 protected Intent getLockPasswordIntent(Context context, int quality, 417 int minLength, final int maxLength, 418 boolean requirePasswordToDecrypt, boolean confirmCredentials) { 419 return ChooseLockPassword.createIntent(context, quality, minLength, 420 maxLength, requirePasswordToDecrypt, confirmCredentials); 421 } 422 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge)423 protected Intent getLockPasswordIntent(Context context, int quality, 424 int minLength, final int maxLength, 425 boolean requirePasswordToDecrypt, long challenge) { 426 return ChooseLockPassword.createIntent(context, quality, minLength, 427 maxLength, requirePasswordToDecrypt, challenge); 428 } 429 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, String password)430 protected Intent getLockPasswordIntent(Context context, int quality, int minLength, 431 final int maxLength, boolean requirePasswordToDecrypt, String password) { 432 return ChooseLockPassword.createIntent(context, quality, minLength, maxLength, 433 requirePasswordToDecrypt, password); 434 } 435 getLockPatternIntent(Context context, final boolean requirePassword, final boolean confirmCredentials)436 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 437 final boolean confirmCredentials) { 438 return ChooseLockPattern.createIntent(context, requirePassword, 439 confirmCredentials); 440 } 441 getLockPatternIntent(Context context, final boolean requirePassword, long challenge)442 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 443 long challenge) { 444 return ChooseLockPattern.createIntent(context, requirePassword, challenge); 445 } 446 getLockPatternIntent(Context context, final boolean requirePassword, final String pattern)447 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 448 final String pattern) { 449 return ChooseLockPattern.createIntent(context, requirePassword, pattern); 450 } 451 getEncryptionInterstitialIntent(Context context, int quality, boolean required)452 protected Intent getEncryptionInterstitialIntent(Context context, int quality, 453 boolean required) { 454 return EncryptionInterstitial.createStartIntent(context, quality, required); 455 } 456 457 /** 458 * Invokes an activity to change the user's pattern, password or PIN based on given quality 459 * and minimum quality specified by DevicePolicyManager. If quality is 460 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared. 461 * 462 * @param quality the desired quality. Ignored if DevicePolicyManager requires more security 463 * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is 464 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED} 465 */ updateUnlockMethodAndFinish(int quality, boolean disabled)466 void updateUnlockMethodAndFinish(int quality, boolean disabled) { 467 // Sanity check. We should never get here without confirming user's existing password. 468 if (!mPasswordConfirmed) { 469 throw new IllegalStateException("Tried to update password without confirming it"); 470 } 471 472 quality = upgradeQuality(quality); 473 474 final Context context = getActivity(); 475 if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { 476 int minLength = mDPM.getPasswordMinimumLength(null); 477 if (minLength < MIN_PASSWORD_LENGTH) { 478 minLength = MIN_PASSWORD_LENGTH; 479 } 480 final int maxLength = mDPM.getPasswordMaximumLength(quality); 481 Intent intent; 482 if (mHasChallenge) { 483 intent = getLockPasswordIntent(context, quality, minLength, 484 maxLength, mRequirePassword, mChallenge); 485 } else { 486 intent = getLockPasswordIntent(context, quality, minLength, 487 maxLength, mRequirePassword, mUserPassword); 488 } 489 startActivityForResult(intent, CHOOSE_LOCK_REQUEST); 490 } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 491 Intent intent; 492 if (mHasChallenge) { 493 intent = getLockPatternIntent(context, mRequirePassword, 494 mChallenge); 495 } else { 496 intent = getLockPatternIntent(context, mRequirePassword, 497 mUserPassword); 498 } 499 startActivityForResult(intent, CHOOSE_LOCK_REQUEST); 500 } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 501 mChooseLockSettingsHelper.utils().clearLock(UserHandle.myUserId()); 502 mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, 503 UserHandle.myUserId()); 504 removeAllFingerprintTemplatesAndFinish(); 505 getActivity().setResult(Activity.RESULT_OK); 506 } else { 507 removeAllFingerprintTemplatesAndFinish(); 508 } 509 } 510 removeAllFingerprintTemplatesAndFinish()511 private void removeAllFingerprintTemplatesAndFinish() { 512 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected() 513 && mFingerprintManager.getEnrolledFingerprints().size() > 0) { 514 mFingerprintManager.remove(new Fingerprint(null, 0, 0, 0), mRemovalCallback); 515 } else { 516 finish(); 517 } 518 } 519 520 @Override onDestroy()521 public void onDestroy() { 522 super.onDestroy(); 523 } 524 525 @Override getHelpResource()526 protected int getHelpResource() { 527 return R.string.help_url_choose_lockscreen; 528 } 529 getResIdForFactoryResetProtectionWarningMessage()530 private int getResIdForFactoryResetProtectionWarningMessage() { 531 boolean hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(); 532 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId())) { 533 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 534 return hasFingerprints 535 ? R.string.unlock_disable_frp_warning_content_pattern_fingerprint 536 : R.string.unlock_disable_frp_warning_content_pattern; 537 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 538 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 539 return hasFingerprints 540 ? R.string.unlock_disable_frp_warning_content_pin_fingerprint 541 : R.string.unlock_disable_frp_warning_content_pin; 542 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 543 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 544 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 545 return hasFingerprints 546 ? R.string.unlock_disable_frp_warning_content_password_fingerprint 547 : R.string.unlock_disable_frp_warning_content_password; 548 default: 549 return hasFingerprints 550 ? R.string.unlock_disable_frp_warning_content_unknown_fingerprint 551 : R.string.unlock_disable_frp_warning_content_unknown; 552 } 553 } 554 isUnlockMethodSecure(String unlockMethod)555 private boolean isUnlockMethodSecure(String unlockMethod) { 556 return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) || 557 KEY_UNLOCK_SET_NONE.equals(unlockMethod)); 558 } 559 setUnlockMethod(String unlockMethod)560 private boolean setUnlockMethod(String unlockMethod) { 561 EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod); 562 563 if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) { 564 updateUnlockMethodAndFinish( 565 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ ); 566 } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) { 567 updateUnlockMethodAndFinish( 568 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ ); 569 } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) { 570 maybeEnableEncryption( 571 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false); 572 } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) { 573 maybeEnableEncryption( 574 DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false); 575 } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) { 576 maybeEnableEncryption( 577 DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false); 578 } else { 579 Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod); 580 return false; 581 } 582 return true; 583 } 584 showFactoryResetProtectionWarningDialog(String unlockMethodToSet)585 private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) { 586 int message = getResIdForFactoryResetProtectionWarningMessage(); 587 FactoryResetProtectionWarningDialog dialog = 588 FactoryResetProtectionWarningDialog.newInstance(message, unlockMethodToSet); 589 dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG); 590 } 591 592 public static class FactoryResetProtectionWarningDialog extends DialogFragment { 593 594 private static final String ARG_MESSAGE_RES = "messageRes"; 595 private static final String ARG_UNLOCK_METHOD_TO_SET = "unlockMethodToSet"; 596 newInstance(int messageRes, String unlockMethodToSet)597 public static FactoryResetProtectionWarningDialog newInstance(int messageRes, 598 String unlockMethodToSet) { 599 FactoryResetProtectionWarningDialog frag = 600 new FactoryResetProtectionWarningDialog(); 601 Bundle args = new Bundle(); 602 args.putInt(ARG_MESSAGE_RES, messageRes); 603 args.putString(ARG_UNLOCK_METHOD_TO_SET, unlockMethodToSet); 604 frag.setArguments(args); 605 return frag; 606 } 607 608 @Override show(FragmentManager manager, String tag)609 public void show(FragmentManager manager, String tag) { 610 if (manager.findFragmentByTag(tag) == null) { 611 // Prevent opening multiple dialogs if tapped on button quickly 612 super.show(manager, tag); 613 } 614 } 615 616 @Override onCreateDialog(Bundle savedInstanceState)617 public Dialog onCreateDialog(Bundle savedInstanceState) { 618 final Bundle args = getArguments(); 619 620 return new AlertDialog.Builder(getActivity()) 621 .setTitle(R.string.unlock_disable_frp_warning_title) 622 .setMessage(args.getInt(ARG_MESSAGE_RES)) 623 .setPositiveButton(R.string.unlock_disable_frp_warning_ok, 624 new DialogInterface.OnClickListener() { 625 @Override 626 public void onClick(DialogInterface dialog, int whichButton) { 627 ((ChooseLockGenericFragment) getParentFragment()) 628 .setUnlockMethod( 629 args.getString(ARG_UNLOCK_METHOD_TO_SET)); 630 } 631 } 632 ) 633 .setNegativeButton(R.string.cancel, 634 new DialogInterface.OnClickListener() { 635 @Override 636 public void onClick(DialogInterface dialog, int whichButton) { 637 dismiss(); 638 } 639 } 640 ) 641 .create(); 642 } 643 } 644 } 645 } 646