Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings;
     18 
     19 import android.accessibilityservice.AccessibilityServiceInfo;
     20 import android.app.Activity;
     21 import android.app.AlertDialog;
     22 import android.app.Dialog;
     23 import android.app.DialogFragment;
     24 import android.app.Fragment;
     25 import android.app.FragmentManager;
     26 import android.app.admin.DevicePolicyManager;
     27 import android.content.Context;
     28 import android.content.DialogInterface;
     29 import android.content.Intent;
     30 import android.os.Bundle;
     31 import android.os.Process;
     32 import android.os.UserHandle;
     33 import android.preference.Preference;
     34 import android.preference.PreferenceScreen;
     35 import android.security.KeyStore;
     36 import android.hardware.fingerprint.Fingerprint;
     37 import android.hardware.fingerprint.FingerprintManager;
     38 import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
     39 import android.util.EventLog;
     40 import android.util.Log;
     41 import android.view.LayoutInflater;
     42 import android.view.View;
     43 import android.view.accessibility.AccessibilityManager;
     44 import android.widget.ListView;
     45 import android.widget.Toast;
     46 
     47 import com.android.internal.logging.MetricsLogger;
     48 import com.android.internal.widget.LockPatternUtils;
     49 
     50 public class ChooseLockGeneric extends SettingsActivity {
     51     public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
     52 
     53     @Override
     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