Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2018 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.security;
     18 
     19 import android.app.admin.DevicePolicyManager;
     20 import android.content.Context;
     21 import android.os.UserHandle;
     22 import android.os.UserManager;
     23 import android.os.storage.StorageManager;
     24 import android.support.v7.preference.Preference;
     25 import android.support.v7.preference.PreferenceScreen;
     26 import android.text.TextUtils;
     27 
     28 import com.android.internal.widget.LockPatternUtils;
     29 import com.android.settings.R;
     30 import com.android.settings.Utils;
     31 import com.android.settings.core.PreferenceControllerMixin;
     32 import com.android.settings.core.SubSettingLauncher;
     33 import com.android.settings.overlay.FeatureFactory;
     34 import com.android.settings.password.ChooseLockGeneric;
     35 import com.android.settings.security.screenlock.ScreenLockSettings;
     36 import com.android.settings.widget.GearPreference;
     37 import com.android.settingslib.RestrictedLockUtils;
     38 import com.android.settingslib.RestrictedPreference;
     39 import com.android.settingslib.core.AbstractPreferenceController;
     40 
     41 public class ChangeScreenLockPreferenceController extends AbstractPreferenceController implements
     42         PreferenceControllerMixin, GearPreference.OnGearClickListener {
     43 
     44     private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
     45 
     46     protected final DevicePolicyManager mDPM;
     47     protected final SecuritySettings mHost;
     48     protected final UserManager mUm;
     49     protected final LockPatternUtils mLockPatternUtils;
     50 
     51     protected final int mUserId = UserHandle.myUserId();
     52     protected final int mProfileChallengeUserId;
     53 
     54     protected RestrictedPreference mPreference;
     55 
     56     public ChangeScreenLockPreferenceController(Context context, SecuritySettings host) {
     57         super(context);
     58         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
     59         mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
     60         mLockPatternUtils = FeatureFactory.getFactory(context)
     61                 .getSecurityFeatureProvider()
     62                 .getLockPatternUtils(context);
     63         mHost = host;
     64         mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId);
     65     }
     66 
     67     @Override
     68     public boolean isAvailable() {
     69         return mContext.getResources().getBoolean(R.bool.config_show_unlock_set_or_change);
     70     }
     71 
     72     @Override
     73     public String getPreferenceKey() {
     74         return KEY_UNLOCK_SET_OR_CHANGE;
     75     }
     76 
     77     @Override
     78     public void displayPreference(PreferenceScreen screen) {
     79         super.displayPreference(screen);
     80         mPreference = (RestrictedPreference) screen.findPreference(getPreferenceKey());
     81     }
     82 
     83     @Override
     84     public void updateState(Preference preference) {
     85         if (mPreference != null && mPreference instanceof GearPreference) {
     86             if (mLockPatternUtils.isSecure(mUserId)
     87                     || !mLockPatternUtils.isLockScreenDisabled(mUserId)) {
     88                 ((GearPreference) mPreference).setOnGearClickListener(this);
     89             } else {
     90                 ((GearPreference) mPreference).setOnGearClickListener(null);
     91             }
     92         }
     93 
     94         updateSummary(preference, mUserId);
     95         disableIfPasswordQualityManaged(mUserId);
     96         if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) {
     97             // PO may disallow to change password for the profile, but screen lock and managed
     98             // profile's lock is the same. Disable main "Screen lock" menu.
     99             disableIfPasswordQualityManaged(mProfileChallengeUserId);
    100         }
    101     }
    102 
    103     @Override
    104     public void onGearClick(GearPreference p) {
    105         if (TextUtils.equals(p.getKey(), getPreferenceKey())) {
    106             new SubSettingLauncher(mContext)
    107                     .setDestination(ScreenLockSettings.class.getName())
    108                     .setSourceMetricsCategory(mHost.getMetricsCategory())
    109                     .launch();
    110         }
    111     }
    112 
    113     @Override
    114     public boolean handlePreferenceTreeClick(Preference preference) {
    115         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
    116             return super.handlePreferenceTreeClick(preference);
    117         }
    118         // TODO(b/35930129): Remove once existing password can be passed into vold directly.
    119         // Currently we need this logic to ensure that the QUIET_MODE is off for any work
    120         // profile with unified challenge on FBE-enabled devices. Otherwise, vold would not be
    121         // able to complete the operation due to the lack of (old) encryption key.
    122         if (mProfileChallengeUserId != UserHandle.USER_NULL
    123                 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)
    124                 && StorageManager.isFileEncryptedNativeOnly()) {
    125             if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) {
    126                 return false;
    127             }
    128         }
    129 
    130         new SubSettingLauncher(mContext)
    131                 .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName())
    132                 .setTitle(R.string.lock_settings_picker_title)
    133                 .setSourceMetricsCategory(mHost.getMetricsCategory())
    134                 .launch();
    135         return true;
    136     }
    137 
    138     protected void updateSummary(Preference preference, int userId) {
    139         if (!mLockPatternUtils.isSecure(userId)) {
    140             if (userId == mProfileChallengeUserId
    141                     || mLockPatternUtils.isLockScreenDisabled(userId)) {
    142                 preference.setSummary(R.string.unlock_set_unlock_mode_off);
    143             } else {
    144                 preference.setSummary(R.string.unlock_set_unlock_mode_none);
    145             }
    146         } else {
    147             switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(userId)) {
    148                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    149                     preference.setSummary(R.string.unlock_set_unlock_mode_pattern);
    150                     break;
    151                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    152                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
    153                     preference.setSummary(R.string.unlock_set_unlock_mode_pin);
    154                     break;
    155                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    156                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    157                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
    158                 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
    159                     preference.setSummary(R.string.unlock_set_unlock_mode_password);
    160                     break;
    161             }
    162         }
    163         mPreference.setEnabled(true);
    164     }
    165 
    166     /**
    167      * Sets the preference as disabled by admin if PASSWORD_QUALITY_MANAGED is set.
    168      * The preference must be a RestrictedPreference.
    169      * <p/>
    170      * DO or PO installed in the user may disallow to change password.
    171      */
    172     void disableIfPasswordQualityManaged(int userId) {
    173         final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils
    174                 .checkIfPasswordQualityIsSet(mContext, userId);
    175         final DevicePolicyManager dpm = (DevicePolicyManager) mContext
    176                 .getSystemService(Context.DEVICE_POLICY_SERVICE);
    177         if (admin != null && dpm.getPasswordQuality(admin.component, userId)
    178                 == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
    179             mPreference.setDisabledByAdmin(admin);
    180         }
    181     }
    182 }
    183