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