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