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