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