• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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