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