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