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