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 static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
     20 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
     21 import static com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED;
     22 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     23 
     24 import android.accessibilityservice.AccessibilityServiceInfo;
     25 import android.app.Activity;
     26 import android.app.AlertDialog;
     27 import android.app.Dialog;
     28 import android.app.DialogFragment;
     29 import android.app.Fragment;
     30 import android.app.FragmentManager;
     31 import android.app.admin.DevicePolicyManager;
     32 import android.content.Context;
     33 import android.content.DialogInterface;
     34 import android.content.Intent;
     35 import android.content.pm.UserInfo;
     36 import android.hardware.fingerprint.Fingerprint;
     37 import android.hardware.fingerprint.FingerprintManager;
     38 import android.hardware.fingerprint.FingerprintManager.RemovalCallback;
     39 import android.os.Bundle;
     40 import android.os.UserHandle;
     41 import android.os.UserManager;
     42 import android.os.storage.StorageManager;
     43 import android.security.KeyStore;
     44 import android.support.v7.preference.Preference;
     45 import android.support.v7.preference.PreferenceScreen;
     46 import android.text.TextUtils;
     47 import android.util.EventLog;
     48 import android.util.Log;
     49 import android.view.accessibility.AccessibilityManager;
     50 import android.widget.TextView;
     51 
     52 import com.android.internal.logging.MetricsProto.MetricsEvent;
     53 import com.android.internal.widget.LockPatternUtils;
     54 import com.android.settings.fingerprint.FingerprintEnrollBase;
     55 import com.android.settings.fingerprint.FingerprintEnrollFindSensor;
     56 import com.android.settingslib.RestrictedLockUtils;
     57 import com.android.settingslib.RestrictedPreference;
     58 
     59 import java.util.List;
     60 
     61 public class ChooseLockGeneric extends SettingsActivity {
     62     public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
     63 
     64     @Override
     65     public Intent getIntent() {
     66         Intent modIntent = new Intent(super.getIntent());
     67         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
     68 
     69         String action = modIntent.getAction();
     70         if (ACTION_SET_NEW_PASSWORD.equals(action)
     71                 || ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) {
     72             modIntent.putExtra(EXTRA_HIDE_DRAWER, true);
     73         }
     74         return modIntent;
     75     }
     76 
     77     @Override
     78     protected boolean isValidFragment(String fragmentName) {
     79         if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true;
     80         return false;
     81     }
     82 
     83     /* package */ Class<? extends Fragment> getFragmentClass() {
     84         return ChooseLockGenericFragment.class;
     85     }
     86 
     87     public static class InternalActivity extends ChooseLockGeneric {
     88     }
     89 
     90     public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
     91         private static final String TAG = "ChooseLockGenericFragment";
     92         private static final int MIN_PASSWORD_LENGTH = 4;
     93         private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
     94         private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
     95         private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
     96         private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
     97         private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
     98         private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed";
     99         private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
    100         private static final String PASSWORD_CONFIRMED = "password_confirmed";
    101         private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
    102         public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
    103         public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs";
    104         public static final String ENCRYPT_REQUESTED_QUALITY = "encrypt_requested_quality";
    105         public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
    106         public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
    107 
    108         private static final int CONFIRM_EXISTING_REQUEST = 100;
    109         private static final int ENABLE_ENCRYPTION_REQUEST = 101;
    110         private static final int CHOOSE_LOCK_REQUEST = 102;
    111         private static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103;
    112         private static final int SKIP_FINGERPRINT_REQUEST = 104;
    113 
    114         private ChooseLockSettingsHelper mChooseLockSettingsHelper;
    115         private DevicePolicyManager mDPM;
    116         private KeyStore mKeyStore;
    117         private boolean mHasChallenge = false;
    118         private long mChallenge;
    119         private boolean mPasswordConfirmed = false;
    120         private boolean mWaitingForConfirmation = false;
    121         private int mEncryptionRequestQuality;
    122         private boolean mEncryptionRequestDisabled;
    123         private boolean mRequirePassword;
    124         private boolean mForChangeCredRequiredForBoot = false;
    125         private String mUserPassword;
    126         private LockPatternUtils mLockPatternUtils;
    127         private FingerprintManager mFingerprintManager;
    128         private int mUserId;
    129         private boolean mHideDrawer = false;
    130         private ManagedLockPasswordProvider mManagedPasswordProvider;
    131         private boolean mIsSetNewPassword = false;
    132 
    133         protected boolean mForFingerprint = false;
    134 
    135         @Override
    136         protected int getMetricsCategory() {
    137             return MetricsEvent.CHOOSE_LOCK_GENERIC;
    138         }
    139 
    140         @Override
    141         public void onCreate(Bundle savedInstanceState) {
    142             super.onCreate(savedInstanceState);
    143 
    144             String chooseLockAction = getActivity().getIntent().getAction();
    145             mFingerprintManager =
    146                 (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE);
    147             mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    148             mKeyStore = KeyStore.getInstance();
    149             mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
    150             mLockPatternUtils = new LockPatternUtils(getActivity());
    151             mIsSetNewPassword = ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
    152                     || ACTION_SET_NEW_PASSWORD.equals(chooseLockAction);
    153 
    154             // Defaults to needing to confirm credentials
    155             final boolean confirmCredentials = getActivity().getIntent()
    156                 .getBooleanExtra(CONFIRM_CREDENTIALS, true);
    157             if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
    158                 mPasswordConfirmed = !confirmCredentials;
    159             }
    160             mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
    161 
    162             mHasChallenge = getActivity().getIntent().getBooleanExtra(
    163                     ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
    164             mChallenge = getActivity().getIntent().getLongExtra(
    165                     ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
    166             mForFingerprint = getActivity().getIntent().getBooleanExtra(
    167                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
    168             mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
    169                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
    170             if (mIsSetNewPassword) {
    171                 // In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user
    172                 // will be asked to confirm the password if one has been set.
    173                 // On fingerprint supported device, fingerprint options are represented in the
    174                 // options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is
    175                 // relaunched to only show options without fingerprint. In this case, we shouldn't
    176                 // ask the user to confirm the password again.
    177                 mPasswordConfirmed = getActivity().getIntent().getBooleanExtra(
    178                         PASSWORD_CONFIRMED, false);
    179             }
    180 
    181             if (savedInstanceState != null) {
    182                 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
    183                 mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);
    184                 mEncryptionRequestQuality = savedInstanceState.getInt(ENCRYPT_REQUESTED_QUALITY);
    185                 mEncryptionRequestDisabled = savedInstanceState.getBoolean(
    186                         ENCRYPT_REQUESTED_DISABLED);
    187             }
    188 
    189             int targetUser = Utils.getSecureTargetUser(
    190                     getActivity().getActivityToken(),
    191                     UserManager.get(getActivity()),
    192                     null,
    193                     getActivity().getIntent().getExtras()).getIdentifier();
    194             if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction)
    195                     || !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) {
    196                 // Always use parent if explicitely requested or if profile challenge is not
    197                 // supported
    198                 Bundle arguments = getArguments();
    199                 mUserId = Utils.getUserIdFromBundle(getContext(), arguments != null ? arguments
    200                         : getActivity().getIntent().getExtras());
    201             } else {
    202                 mUserId = targetUser;
    203             }
    204 
    205             if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
    206                     && Utils.isManagedProfile(UserManager.get(getActivity()), mUserId)
    207                     && mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
    208                 getActivity().setTitle(R.string.lock_settings_picker_title_profile);
    209             }
    210 
    211             mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId);
    212 
    213             if (mPasswordConfirmed) {
    214                 updatePreferencesOrFinish();
    215                 if (mForChangeCredRequiredForBoot) {
    216                     maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
    217                             mUserId), false);
    218                 }
    219             } else if (!mWaitingForConfirmation) {
    220                 ChooseLockSettingsHelper helper =
    221                         new ChooseLockSettingsHelper(this.getActivity(), this);
    222                 boolean managedProfileWithUnifiedLock = Utils
    223                         .isManagedProfile(UserManager.get(getActivity()), mUserId)
    224                         && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
    225                 if (managedProfileWithUnifiedLock
    226                         || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
    227                         getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
    228                     mPasswordConfirmed = true; // no password set, so no need to confirm
    229                     updatePreferencesOrFinish();
    230                 } else {
    231                     mWaitingForConfirmation = true;
    232                 }
    233             }
    234             addHeaderView();
    235         }
    236 
    237         protected void addHeaderView() {
    238             if (mForFingerprint) {
    239                 setHeaderView(R.layout.choose_lock_generic_fingerprint_header);
    240                 if (mIsSetNewPassword) {
    241                     ((TextView) getHeaderView().findViewById(R.id.fingerprint_header_description))
    242                             .setText(R.string.fingerprint_unlock_title);
    243                 }
    244             }
    245         }
    246 
    247         @Override
    248         public boolean onPreferenceTreeClick(Preference preference) {
    249             final String key = preference.getKey();
    250 
    251             if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) {
    252                 // Show the disabling FRP warning only when the user is switching from a secure
    253                 // unlock method to an insecure one
    254                 showFactoryResetProtectionWarningDialog(key);
    255                 return true;
    256             } else if (KEY_SKIP_FINGERPRINT.equals(key)) {
    257                 Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
    258                 chooseLockGenericIntent.setAction(getIntent().getAction());
    259                 chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
    260                 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
    261                 return true;
    262             } else {
    263                 return setUnlockMethod(key);
    264             }
    265         }
    266 
    267         /**
    268          * If the device has encryption already enabled, then ask the user if they
    269          * also want to encrypt the phone with this password.
    270          *
    271          * @param quality
    272          * @param disabled
    273          */
    274         // TODO: why does this take disabled, its always called with a quality higher than
    275         // what makes sense with disabled == true
    276         private void maybeEnableEncryption(int quality, boolean disabled) {
    277             DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
    278             if (UserManager.get(getActivity()).isAdminUser()
    279                     && mUserId == UserHandle.myUserId()
    280                     && LockPatternUtils.isDeviceEncryptionEnabled()
    281                     && !LockPatternUtils.isFileEncryptionEnabled()
    282                     && !dpm.getDoNotAskCredentialsOnBoot()) {
    283                 mEncryptionRequestQuality = quality;
    284                 mEncryptionRequestDisabled = disabled;
    285                 // Get the intent that the encryption interstitial should start for creating
    286                 // the new unlock method.
    287                 Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled);
    288                 unlockMethodIntent.putExtra(
    289                         ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
    290                         mForChangeCredRequiredForBoot);
    291                 final Context context = getActivity();
    292                 // If accessibility is enabled and the user hasn't seen this dialog before, set the
    293                 // default state to agree with that which is compatible with accessibility
    294                 // (password not required).
    295                 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
    296                 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
    297                 Intent intent = getEncryptionInterstitialIntent(context, quality, required,
    298                         unlockMethodIntent);
    299                 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
    300                         mForFingerprint);
    301                 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
    302                 startActivityForResult(
    303                         intent,
    304                         mIsSetNewPassword && mHasChallenge
    305                                 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
    306                                 : ENABLE_ENCRYPTION_REQUEST);
    307             } else {
    308                 if (mForChangeCredRequiredForBoot) {
    309                     // Welp, couldn't change it. Oh well.
    310                     finish();
    311                     return;
    312                 }
    313                 mRequirePassword = false; // device encryption not enabled or not device owner.
    314                 updateUnlockMethodAndFinish(quality, disabled);
    315             }
    316         }
    317 
    318         @Override
    319         public void onActivityResult(int requestCode, int resultCode, Intent data) {
    320             super.onActivityResult(requestCode, resultCode, data);
    321             mWaitingForConfirmation = false;
    322             if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
    323                 mPasswordConfirmed = true;
    324                 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
    325                 updatePreferencesOrFinish();
    326                 if (mForChangeCredRequiredForBoot) {
    327                     if (!TextUtils.isEmpty(mUserPassword)) {
    328                         maybeEnableEncryption(
    329                                 mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
    330                     } else {
    331                         finish();
    332                     }
    333                 }
    334             } else if (requestCode == CHOOSE_LOCK_REQUEST
    335                     || requestCode == ENABLE_ENCRYPTION_REQUEST) {
    336                 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
    337                     getActivity().setResult(resultCode, data);
    338                     finish();
    339                 }
    340             } else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
    341                     && resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
    342                 Intent intent = new Intent(getActivity(), FingerprintEnrollFindSensor.class);
    343                 if (data != null) {
    344                     intent.putExtras(data.getExtras());
    345                 }
    346                 startActivity(intent);
    347                 finish();
    348             } else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
    349                 if (resultCode != RESULT_CANCELED) {
    350                     getActivity().setResult(
    351                             resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data);
    352                     finish();
    353                 }
    354             } else {
    355                 getActivity().setResult(Activity.RESULT_CANCELED);
    356                 finish();
    357             }
    358             if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) {
    359                 finish();
    360             }
    361         }
    362 
    363         @Override
    364         public void onSaveInstanceState(Bundle outState) {
    365             super.onSaveInstanceState(outState);
    366             // Saved so we don't force user to re-enter their password if configuration changes
    367             outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
    368             outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation);
    369             outState.putInt(ENCRYPT_REQUESTED_QUALITY, mEncryptionRequestQuality);
    370             outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled);
    371         }
    372 
    373         private void updatePreferencesOrFinish() {
    374             Intent intent = getActivity().getIntent();
    375             int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
    376             if (quality == -1) {
    377                 // If caller didn't specify password quality, show UI and allow the user to choose.
    378                 quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
    379                 quality = upgradeQuality(quality);
    380                 final boolean hideDisabledPrefs = intent.getBooleanExtra(
    381                         HIDE_DISABLED_PREFS, false);
    382                 final PreferenceScreen prefScreen = getPreferenceScreen();
    383                 if (prefScreen != null) {
    384                     prefScreen.removeAll();
    385                 }
    386                 addPreferences();
    387                 disableUnusablePreferences(quality, hideDisabledPrefs);
    388                 updatePreferenceText();
    389                 updateCurrentPreference();
    390                 updatePreferenceSummaryIfNeeded();
    391             } else {
    392                 updateUnlockMethodAndFinish(quality, false);
    393             }
    394         }
    395 
    396         protected void addPreferences() {
    397             addPreferencesFromResource(R.xml.security_settings_picker);
    398 
    399             // Used for testing purposes
    400             findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none);
    401             findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
    402             findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
    403             findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
    404         }
    405 
    406         private void updatePreferenceText() {
    407             if (mForFingerprint) {
    408                 final String key[] = { KEY_UNLOCK_SET_PATTERN,
    409                         KEY_UNLOCK_SET_PIN,
    410                         KEY_UNLOCK_SET_PASSWORD };
    411                 final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
    412                         R.string.fingerprint_unlock_set_unlock_pin,
    413                         R.string.fingerprint_unlock_set_unlock_password };
    414                 for (int i = 0; i < key.length; i++) {
    415                     Preference pref = findPreference(key[i]);
    416                     if (pref != null) { // can be removed by device admin
    417                         pref.setTitle(res[i]);
    418                     }
    419                 }
    420             }
    421 
    422             if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
    423                 Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED);
    424                 managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
    425             } else {
    426                 removePreference(KEY_UNLOCK_SET_MANAGED);
    427             }
    428 
    429             if (!(mForFingerprint && mIsSetNewPassword)) {
    430                 removePreference(KEY_SKIP_FINGERPRINT);
    431             }
    432         }
    433 
    434         private void updateCurrentPreference() {
    435             String currentKey = getKeyForCurrent();
    436             Preference preference = findPreference(currentKey);
    437             if (preference != null) {
    438                 preference.setSummary(R.string.current_screen_lock);
    439             }
    440         }
    441 
    442         private String getKeyForCurrent() {
    443             final int credentialOwner = UserManager.get(getContext())
    444                     .getCredentialOwnerProfile(mUserId);
    445             if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
    446                 return KEY_UNLOCK_SET_OFF;
    447             }
    448             switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) {
    449                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    450                     return KEY_UNLOCK_SET_PATTERN;
    451                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    452                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
    453                     return KEY_UNLOCK_SET_PIN;
    454                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    455                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    456                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
    457                     return KEY_UNLOCK_SET_PASSWORD;
    458                 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
    459                     return KEY_UNLOCK_SET_MANAGED;
    460                 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
    461                     return KEY_UNLOCK_SET_NONE;
    462             }
    463             return null;
    464         }
    465 
    466         /** increases the quality if necessary */
    467         private int upgradeQuality(int quality) {
    468             quality = upgradeQualityForDPM(quality);
    469             return quality;
    470         }
    471 
    472         private int upgradeQualityForDPM(int quality) {
    473             // Compare min allowed password quality
    474             int minQuality = mDPM.getPasswordQuality(null, mUserId);
    475             if (quality < minQuality) {
    476                 quality = minQuality;
    477             }
    478             return quality;
    479         }
    480 
    481         /***
    482          * Disables preferences that are less secure than required quality. The actual
    483          * implementation is in disableUnusablePreferenceImpl.
    484          *
    485          * @param quality the requested quality.
    486          * @param hideDisabledPrefs if false preferences show why they were disabled; otherwise
    487          * they're not shown at all.
    488          */
    489         protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) {
    490             disableUnusablePreferencesImpl(quality, hideDisabledPrefs);
    491         }
    492 
    493         /***
    494          * Disables preferences that are less secure than required quality.
    495          *
    496          * @param quality the requested quality.
    497          * @param hideDisabled whether to hide disable screen lock options.
    498          */
    499         protected void disableUnusablePreferencesImpl(final int quality,
    500                 boolean hideDisabled) {
    501             final PreferenceScreen entries = getPreferenceScreen();
    502 
    503             int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
    504             EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
    505                     getActivity(), mUserId);
    506             for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) {
    507                 Preference pref = entries.getPreference(i);
    508                 if (pref instanceof RestrictedPreference) {
    509                     final String key = pref.getKey();
    510                     boolean enabled = true;
    511                     boolean visible = true;
    512                     boolean disabledByAdmin = false;
    513                     if (KEY_UNLOCK_SET_OFF.equals(key)) {
    514                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    515                         if (getResources().getBoolean(R.bool.config_hide_none_security_option)) {
    516                             enabled = false;
    517                             visible = false;
    518                         }
    519                         disabledByAdmin = adminEnforcedQuality
    520                                 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    521                     } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
    522                         if (mUserId != UserHandle.myUserId()) {
    523                             // Swipe doesn't make sense for profiles.
    524                             visible = false;
    525                         }
    526                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    527                         disabledByAdmin = adminEnforcedQuality
    528                                 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    529                     } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
    530                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
    531                         disabledByAdmin = adminEnforcedQuality
    532                                 > DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
    533                     } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
    534                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
    535                         disabledByAdmin = adminEnforcedQuality
    536                                 > DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
    537                     } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
    538                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
    539                         disabledByAdmin = adminEnforcedQuality
    540                                 > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
    541                     } else if (KEY_UNLOCK_SET_MANAGED.equals(key)) {
    542                         enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_MANAGED
    543                                 && mManagedPasswordProvider.isManagedPasswordChoosable();
    544                         disabledByAdmin = adminEnforcedQuality
    545                                 > DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
    546                     }
    547                     if (hideDisabled) {
    548                         visible = enabled;
    549                     }
    550                     if (!visible) {
    551                         entries.removePreference(pref);
    552                     } else if (disabledByAdmin && enforcedAdmin != null) {
    553                         ((RestrictedPreference) pref).setDisabledByAdmin(enforcedAdmin);
    554                     } else if (!enabled) {
    555                         // we need to setDisabledByAdmin to null first to disable the padlock
    556                         // in case it was set earlier.
    557                         ((RestrictedPreference) pref).setDisabledByAdmin(null);
    558                         pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
    559                         pref.setEnabled(false);
    560                     } else {
    561                         ((RestrictedPreference) pref).setDisabledByAdmin(null);
    562                     }
    563                 }
    564             }
    565         }
    566 
    567         private void updatePreferenceSummaryIfNeeded() {
    568             // On a default block encrypted device with accessibility, add a warning
    569             // that your data is not credential encrypted
    570             if (!StorageManager.isBlockEncrypted()) {
    571                 return;
    572             }
    573 
    574             if (StorageManager.isNonDefaultBlockEncrypted()) {
    575                 return;
    576             }
    577 
    578             if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList(
    579                     AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
    580                 return;
    581             }
    582 
    583             CharSequence summary = getString(R.string.secure_lock_encryption_warning);
    584 
    585             PreferenceScreen screen = getPreferenceScreen();
    586             final int preferenceCount = screen.getPreferenceCount();
    587             for (int i = 0; i < preferenceCount; i++) {
    588                 Preference preference = screen.getPreference(i);
    589                 switch (preference.getKey()) {
    590                     case KEY_UNLOCK_SET_PATTERN:
    591                     case KEY_UNLOCK_SET_PIN:
    592                     case KEY_UNLOCK_SET_PASSWORD:
    593                     case KEY_UNLOCK_SET_MANAGED: {
    594                         preference.setSummary(summary);
    595                     } break;
    596                 }
    597             }
    598         }
    599 
    600         protected Intent getLockManagedPasswordIntent(boolean requirePassword, String password) {
    601             return mManagedPasswordProvider.createIntent(requirePassword, password);
    602         }
    603 
    604         protected Intent getLockPasswordIntent(Context context, int quality,
    605                 int minLength, final int maxLength,
    606                 boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId) {
    607             return ChooseLockPassword.createIntent(context, quality, minLength,
    608                     maxLength, requirePasswordToDecrypt, confirmCredentials, userId);
    609         }
    610 
    611         protected Intent getLockPasswordIntent(Context context, int quality,
    612                 int minLength, final int maxLength,
    613                 boolean requirePasswordToDecrypt, long challenge, int userId) {
    614             return ChooseLockPassword.createIntent(context, quality, minLength,
    615                     maxLength, requirePasswordToDecrypt, challenge, userId);
    616         }
    617 
    618         protected Intent getLockPasswordIntent(Context context, int quality, int minLength,
    619                 int maxLength, boolean requirePasswordToDecrypt, String password, int userId) {
    620             return ChooseLockPassword.createIntent(context, quality, minLength, maxLength,
    621                     requirePasswordToDecrypt, password, userId);
    622         }
    623 
    624         protected Intent getLockPatternIntent(Context context, final boolean requirePassword,
    625                 final boolean confirmCredentials, int userId) {
    626             return ChooseLockPattern.createIntent(context, requirePassword,
    627                     confirmCredentials, userId);
    628         }
    629 
    630         protected Intent getLockPatternIntent(Context context, final boolean requirePassword,
    631                long challenge, int userId) {
    632             return ChooseLockPattern.createIntent(context, requirePassword, challenge, userId);
    633         }
    634 
    635         protected Intent getLockPatternIntent(Context context, final boolean requirePassword,
    636                 final String pattern, int userId) {
    637             return ChooseLockPattern.createIntent(context, requirePassword, pattern, userId);
    638         }
    639 
    640         protected Intent getEncryptionInterstitialIntent(Context context, int quality,
    641                 boolean required, Intent unlockMethodIntent) {
    642             return EncryptionInterstitial.createStartIntent(context, quality, required,
    643                     unlockMethodIntent);
    644         }
    645 
    646         /**
    647          * Invokes an activity to change the user's pattern, password or PIN based on given quality
    648          * and minimum quality specified by DevicePolicyManager. If quality is
    649          * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared.
    650          *
    651          * @param quality the desired quality. Ignored if DevicePolicyManager requires more security
    652          * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
    653          * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
    654          */
    655         void updateUnlockMethodAndFinish(int quality, boolean disabled) {
    656             // Sanity check. We should never get here without confirming user's existing password.
    657             if (!mPasswordConfirmed) {
    658                 throw new IllegalStateException("Tried to update password without confirming it");
    659             }
    660 
    661             quality = upgradeQuality(quality);
    662             Intent intent = getIntentForUnlockMethod(quality, disabled);
    663             if (intent != null) {
    664                 startActivityForResult(intent,
    665                         mIsSetNewPassword && mHasChallenge
    666                                 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
    667                                 : CHOOSE_LOCK_REQUEST);
    668                 return;
    669             }
    670 
    671             if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    672                 mLockPatternUtils.setSeparateProfileChallengeEnabled(mUserId, true, mUserPassword);
    673                 mChooseLockSettingsHelper.utils().clearLock(mUserId);
    674                 mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
    675                 getActivity().setResult(Activity.RESULT_OK);
    676                 removeAllFingerprintForUserAndFinish(mUserId);
    677             } else {
    678                 removeAllFingerprintForUserAndFinish(mUserId);
    679             }
    680         }
    681 
    682         private Intent getIntentForUnlockMethod(int quality, boolean disabled) {
    683             Intent intent = null;
    684             final Context context = getActivity();
    685             if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
    686                 intent = getLockManagedPasswordIntent(mRequirePassword, mUserPassword);
    687             } else if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
    688                 int minLength = mDPM.getPasswordMinimumLength(null, mUserId);
    689                 if (minLength < MIN_PASSWORD_LENGTH) {
    690                     minLength = MIN_PASSWORD_LENGTH;
    691                 }
    692                 final int maxLength = mDPM.getPasswordMaximumLength(quality);
    693                 if (mHasChallenge) {
    694                     intent = getLockPasswordIntent(context, quality, minLength,
    695                             maxLength, mRequirePassword, mChallenge, mUserId);
    696                 } else {
    697                     intent = getLockPasswordIntent(context, quality, minLength,
    698                             maxLength, mRequirePassword, mUserPassword, mUserId);
    699                 }
    700             } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
    701                 if (mHasChallenge) {
    702                     intent = getLockPatternIntent(context, mRequirePassword,
    703                             mChallenge, mUserId);
    704                 } else {
    705                     intent = getLockPatternIntent(context, mRequirePassword,
    706                             mUserPassword, mUserId);
    707                 }
    708             }
    709             if (intent != null) {
    710                 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
    711             }
    712             return intent;
    713         }
    714 
    715         private void removeAllFingerprintForUserAndFinish(final int userId) {
    716             if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
    717                 if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
    718                     mFingerprintManager.setActiveUser(userId);
    719                     // For the purposes of M and N, groupId is the same as userId.
    720                     final int groupId = userId;
    721                     Fingerprint finger = new Fingerprint(null, groupId, 0, 0);
    722                     mFingerprintManager.remove(finger, userId,
    723                             new RemovalCallback() {
    724                                 @Override
    725                                 public void onRemovalError(Fingerprint fp, int errMsgId,
    726                                         CharSequence errString) {
    727                                     Log.v(TAG, "Fingerprint removed: " + fp.getFingerId());
    728                                     if (fp.getFingerId() == 0) {
    729                                         removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
    730                                     }
    731                                 }
    732 
    733                                 @Override
    734                                 public void onRemovalSucceeded(Fingerprint fingerprint) {
    735                                     if (fingerprint.getFingerId() == 0) {
    736                                         removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
    737                                     }
    738                                 }
    739                             });
    740                 } else {
    741                     // No fingerprints in this user, we may also want to delete managed profile
    742                     // fingerprints
    743                     removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
    744                 }
    745             } else {
    746                 // The removal callback will call finish, once all fingerprints are removed.
    747                 // We need to wait for that to occur, otherwise, the UI will still show that
    748                 // fingerprints exist even though they are (about to) be removed depending on
    749                 // the race condition.
    750                 finish();
    751             }
    752         }
    753 
    754         private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId) {
    755             mFingerprintManager.setActiveUser(UserHandle.myUserId());
    756             final UserManager um = UserManager.get(getActivity());
    757             boolean hasChildProfile = false;
    758             if (!um.getUserInfo(parentUserId).isManagedProfile()) {
    759                 // Current user is primary profile, remove work profile fingerprints if necessary
    760                 final List<UserInfo> profiles = um.getProfiles(parentUserId);
    761                 final int profilesSize = profiles.size();
    762                 for (int i = 0; i < profilesSize; i++) {
    763                     final UserInfo userInfo = profiles.get(i);
    764                     if (userInfo.isManagedProfile() && !mLockPatternUtils
    765                             .isSeparateProfileChallengeEnabled(userInfo.id)) {
    766                         removeAllFingerprintForUserAndFinish(userInfo.id);
    767                         hasChildProfile = true;
    768                         break;
    769                     }
    770                 }
    771             }
    772             if (!hasChildProfile) {
    773                 finish();
    774             }
    775         }
    776 
    777         @Override
    778         public void onDestroy() {
    779             super.onDestroy();
    780         }
    781 
    782         @Override
    783         protected int getHelpResource() {
    784             return R.string.help_url_choose_lockscreen;
    785         }
    786 
    787         private int getResIdForFactoryResetProtectionWarningTitle() {
    788             boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId);
    789             return isProfile ? R.string.unlock_disable_frp_warning_title_profile
    790                     : R.string.unlock_disable_frp_warning_title;
    791         }
    792 
    793         private int getResIdForFactoryResetProtectionWarningMessage() {
    794             boolean hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(mUserId);
    795             boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId);
    796             switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) {
    797                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    798                     if (hasFingerprints && isProfile) {
    799                         return R.string
    800                                 .unlock_disable_frp_warning_content_pattern_fingerprint_profile;
    801                     } else if (hasFingerprints && !isProfile) {
    802                         return R.string.unlock_disable_frp_warning_content_pattern_fingerprint;
    803                     } else if (isProfile) {
    804                         return R.string.unlock_disable_frp_warning_content_pattern_profile;
    805                     } else {
    806                         return R.string.unlock_disable_frp_warning_content_pattern;
    807                     }
    808                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    809                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
    810                     if (hasFingerprints && isProfile) {
    811                         return R.string.unlock_disable_frp_warning_content_pin_fingerprint_profile;
    812                     } else if (hasFingerprints && !isProfile) {
    813                         return R.string.unlock_disable_frp_warning_content_pin_fingerprint;
    814                     } else if (isProfile) {
    815                         return R.string.unlock_disable_frp_warning_content_pin_profile;
    816                     } else {
    817                         return R.string.unlock_disable_frp_warning_content_pin;
    818                     }
    819                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    820                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    821                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
    822                 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
    823                     if (hasFingerprints && isProfile) {
    824                         return R.string
    825                                 .unlock_disable_frp_warning_content_password_fingerprint_profile;
    826                     } else if (hasFingerprints && !isProfile) {
    827                         return R.string.unlock_disable_frp_warning_content_password_fingerprint;
    828                     } else if (isProfile) {
    829                         return R.string.unlock_disable_frp_warning_content_password_profile;
    830                     } else {
    831                         return R.string.unlock_disable_frp_warning_content_password;
    832                     }
    833                 default:
    834                     if (hasFingerprints && isProfile) {
    835                         return R.string
    836                                 .unlock_disable_frp_warning_content_unknown_fingerprint_profile;
    837                     } else if (hasFingerprints && !isProfile) {
    838                         return R.string.unlock_disable_frp_warning_content_unknown_fingerprint;
    839                     } else if (isProfile) {
    840                         return R.string.unlock_disable_frp_warning_content_unknown_profile;
    841                     } else {
    842                         return R.string.unlock_disable_frp_warning_content_unknown;
    843                     }
    844             }
    845         }
    846 
    847         private boolean isUnlockMethodSecure(String unlockMethod) {
    848             return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) ||
    849                     KEY_UNLOCK_SET_NONE.equals(unlockMethod));
    850         }
    851 
    852         private boolean setUnlockMethod(String unlockMethod) {
    853             EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
    854 
    855             if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) {
    856                 updateUnlockMethodAndFinish(
    857                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ );
    858             } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) {
    859                 updateUnlockMethodAndFinish(
    860                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ );
    861             } else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) {
    862                 maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false);
    863             } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) {
    864                 maybeEnableEncryption(
    865                         DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
    866             } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) {
    867                 maybeEnableEncryption(
    868                         DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
    869             } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) {
    870                 maybeEnableEncryption(
    871                         DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
    872             } else {
    873                 Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
    874                 return false;
    875             }
    876             return true;
    877         }
    878 
    879         private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
    880             int title = getResIdForFactoryResetProtectionWarningTitle();
    881             int message = getResIdForFactoryResetProtectionWarningMessage();
    882             FactoryResetProtectionWarningDialog dialog =
    883                     FactoryResetProtectionWarningDialog.newInstance(
    884                             title, message, unlockMethodToSet);
    885             dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG);
    886         }
    887 
    888         public static class FactoryResetProtectionWarningDialog extends DialogFragment {
    889 
    890             private static final String ARG_TITLE_RES = "titleRes";
    891             private static final String ARG_MESSAGE_RES = "messageRes";
    892             private static final String ARG_UNLOCK_METHOD_TO_SET = "unlockMethodToSet";
    893 
    894             public static FactoryResetProtectionWarningDialog newInstance(
    895                     int titleRes, int messageRes, String unlockMethodToSet) {
    896                 FactoryResetProtectionWarningDialog frag =
    897                         new FactoryResetProtectionWarningDialog();
    898                 Bundle args = new Bundle();
    899                 args.putInt(ARG_TITLE_RES, titleRes);
    900                 args.putInt(ARG_MESSAGE_RES, messageRes);
    901                 args.putString(ARG_UNLOCK_METHOD_TO_SET, unlockMethodToSet);
    902                 frag.setArguments(args);
    903                 return frag;
    904             }
    905 
    906             @Override
    907             public void show(FragmentManager manager, String tag) {
    908                 if (manager.findFragmentByTag(tag) == null) {
    909                     // Prevent opening multiple dialogs if tapped on button quickly
    910                     super.show(manager, tag);
    911                 }
    912             }
    913 
    914             @Override
    915             public Dialog onCreateDialog(Bundle savedInstanceState) {
    916                 final Bundle args = getArguments();
    917 
    918                 return new AlertDialog.Builder(getActivity())
    919                         .setTitle(args.getInt(ARG_TITLE_RES))
    920                         .setMessage(args.getInt(ARG_MESSAGE_RES))
    921                         .setPositiveButton(R.string.unlock_disable_frp_warning_ok,
    922                                 new DialogInterface.OnClickListener() {
    923                                     @Override
    924                                     public void onClick(DialogInterface dialog, int whichButton) {
    925                                         ((ChooseLockGenericFragment) getParentFragment())
    926                                                 .setUnlockMethod(
    927                                                         args.getString(ARG_UNLOCK_METHOD_TO_SET));
    928                                     }
    929                                 }
    930                         )
    931                         .setNegativeButton(R.string.cancel,
    932                                 new DialogInterface.OnClickListener() {
    933                                     @Override
    934                                     public void onClick(DialogInterface dialog, int whichButton) {
    935                                         dismiss();
    936                                     }
    937                                 }
    938                         )
    939                         .create();
    940             }
    941         }
    942     }
    943 }
    944