1 /* 2 * Copyright (C) 2017 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.screenlock; 18 19 import static android.app.admin.DevicePolicyResources.Strings.Settings.DISABLED_BY_IT_ADMIN_TITLE; 20 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 21 22 import android.app.admin.DevicePolicyManager; 23 import android.content.Context; 24 import android.os.UserHandle; 25 import android.provider.Settings; 26 import android.text.TextUtils; 27 import android.util.Log; 28 29 import androidx.preference.Preference; 30 31 import com.android.internal.widget.LockPatternUtils; 32 import com.android.settings.R; 33 import com.android.settings.core.PreferenceControllerMixin; 34 import com.android.settings.display.TimeoutListPreference; 35 import com.android.settings.overlay.FeatureFactory; 36 import com.android.settings.security.trustagent.TrustAgentManager; 37 import com.android.settingslib.RestrictedLockUtils; 38 import com.android.settingslib.RestrictedLockUtilsInternal; 39 import com.android.settingslib.core.AbstractPreferenceController; 40 41 public class LockAfterTimeoutPreferenceController extends AbstractPreferenceController 42 implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { 43 44 private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout"; 45 46 private final int mUserId; 47 private final LockPatternUtils mLockPatternUtils; 48 private final TrustAgentManager mTrustAgentManager; 49 private final DevicePolicyManager mDPM; 50 LockAfterTimeoutPreferenceController(Context context, int userId, LockPatternUtils lockPatternUtils)51 public LockAfterTimeoutPreferenceController(Context context, int userId, 52 LockPatternUtils lockPatternUtils) { 53 super(context); 54 mUserId = userId; 55 mLockPatternUtils = lockPatternUtils; 56 mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 57 mTrustAgentManager = FeatureFactory.getFactory(context) 58 .getSecurityFeatureProvider().getTrustAgentManager(); 59 } 60 61 @Override isAvailable()62 public boolean isAvailable() { 63 if (!mLockPatternUtils.isSecure(mUserId)) { 64 return false; 65 } 66 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) { 67 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 68 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 69 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 70 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 71 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 72 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 73 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 74 return true; 75 default: 76 return false; 77 } 78 } 79 80 @Override getPreferenceKey()81 public String getPreferenceKey() { 82 return KEY_LOCK_AFTER_TIMEOUT; 83 } 84 85 @Override updateState(Preference preference)86 public void updateState(Preference preference) { 87 setupLockAfterPreference((TimeoutListPreference) preference); 88 updateLockAfterPreferenceSummary((TimeoutListPreference) preference); 89 } 90 91 @Override onPreferenceChange(Preference preference, Object newValue)92 public boolean onPreferenceChange(Preference preference, Object newValue) { 93 try { 94 final int timeout = Integer.parseInt((String) newValue); 95 Settings.Secure.putInt(mContext.getContentResolver(), 96 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout); 97 updateState(preference); 98 } catch (NumberFormatException e) { 99 Log.e(TAG, "could not persist lockAfter timeout setting", e); 100 } 101 return true; 102 } 103 setupLockAfterPreference(TimeoutListPreference preference)104 private void setupLockAfterPreference(TimeoutListPreference preference) { 105 // Compatible with pre-Froyo 106 long currentTimeout = Settings.Secure.getLong(mContext.getContentResolver(), 107 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 108 preference.setValue(String.valueOf(currentTimeout)); 109 if (mDPM != null) { 110 final RestrictedLockUtils.EnforcedAdmin admin = 111 RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext); 112 final long adminTimeout = 113 mDPM.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId()); 114 final long displayTimeout = Math.max(0, 115 Settings.System.getInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, 0)); 116 // This setting is a secondary to display timeout when a device policy is enforced. 117 // As such, maxLockTimeout = adminTimeout - displayTimeout. 118 // If there isn't enough time, shows "immediately" setting. 119 final long maxTimeout = Math.max(0, adminTimeout - displayTimeout); 120 preference.removeUnusableTimeouts(maxTimeout, admin); 121 } 122 } 123 updateLockAfterPreferenceSummary(TimeoutListPreference preference)124 private void updateLockAfterPreferenceSummary(TimeoutListPreference preference) { 125 final CharSequence summary; 126 if (preference.isDisabledByAdmin()) { 127 summary = mDPM.getResources().getString(DISABLED_BY_IT_ADMIN_TITLE, 128 () -> mContext.getString(R.string.disabled_by_policy_title)); 129 } else { 130 // Update summary message with current value 131 long currentTimeout = Settings.Secure.getLong(mContext.getContentResolver(), 132 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 133 final CharSequence[] entries = preference.getEntries(); 134 final CharSequence[] values = preference.getEntryValues(); 135 int best = 0; 136 for (int i = 0; i < values.length; i++) { 137 long timeout = Long.valueOf(values[i].toString()); 138 if (currentTimeout >= timeout) { 139 best = i; 140 } 141 } 142 143 final CharSequence trustAgentLabel = mTrustAgentManager 144 .getActiveTrustAgentLabel(mContext, mLockPatternUtils); 145 if (!TextUtils.isEmpty(trustAgentLabel)) { 146 if (Long.valueOf(values[best].toString()) == 0) { 147 summary = mContext.getString(R.string.lock_immediately_summary_with_exception, 148 trustAgentLabel); 149 } else { 150 summary = mContext.getString(R.string.lock_after_timeout_summary_with_exception, 151 entries[best], trustAgentLabel); 152 } 153 } else { 154 summary = mContext.getString(R.string.lock_after_timeout_summary, entries[best]); 155 } 156 } 157 preference.setSummary(summary); 158 } 159 } 160