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