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