blob: 412b4d2dc95c457949ec91b23145d53ae1c08da9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package com.android.internal.widget;
18
Jim Miller78c48f62013-03-01 15:28:33 -080019import android.Manifest;
Amith Yamasani4b4b9542012-09-14 13:36:29 -070020import android.app.ActivityManagerNative;
Adrian Roosedad7b22014-07-13 14:38:22 +020021import android.app.AlarmManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080022import android.app.admin.DevicePolicyManager;
Adrian Roos82142c22014-03-27 14:56:59 +010023import android.app.trust.TrustManager;
Jim Miller51117262012-11-04 17:58:09 -080024import android.appwidget.AppWidgetManager;
Adrian Roos82142c22014-03-27 14:56:59 +010025import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.ContentResolver;
Jim Miller31f90b62010-01-20 13:35:20 -080027import android.content.Context;
Steven Ross329979c2011-09-28 11:42:56 -040028import android.content.Intent;
Danielle Millett58396982011-09-30 13:55:07 -040029import android.content.pm.PackageManager;
Adam Lesinski61d94092014-09-15 15:27:19 -070030import android.content.pm.UserInfo;
Paul Lawrence3a5a0be2014-09-25 09:26:34 -070031import android.os.AsyncTask;
Jason parksf7b3cd42011-01-27 09:28:25 -060032import android.os.IBinder;
Jim Miller69ac9882010-02-24 15:35:05 -080033import android.os.RemoteException;
34import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.SystemClock;
Jim Miller6848dc82014-10-13 18:51:53 -070036import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070037import android.os.UserHandle;
Adam Lesinski61d94092014-09-15 15:27:19 -070038import android.os.UserManager;
Jason parksf7b3cd42011-01-27 09:28:25 -060039import android.os.storage.IMountService;
Paul Lawrence8e397362014-01-27 15:22:30 -080040import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.provider.Settings;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070042import android.telecom.TelecomManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.text.TextUtils;
44import android.util.Log;
Jim Miller51117262012-11-04 17:58:09 -080045import android.view.IWindowManager;
John Wang0f7b3f82011-05-31 11:20:55 -070046import android.view.View;
Jim Miller69ac9882010-02-24 15:35:05 -080047import android.widget.Button;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
Michael Jurka1254f2f2012-10-25 11:44:31 -070049import com.android.internal.R;
Michael Jurka1254f2f2012-10-25 11:44:31 -070050import com.google.android.collect.Lists;
Michael Jurkaaa2859a2012-10-24 12:46:49 -070051
Brian Carlstrom929a1c22011-02-01 21:54:09 -080052import java.security.MessageDigest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import java.security.NoSuchAlgorithmException;
Jim Miller11b019d2010-01-20 16:34:45 -080054import java.security.SecureRandom;
Adrian Roos82142c22014-03-27 14:56:59 +010055import java.util.ArrayList;
56import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import java.util.List;
58
59/**
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070060 * Utilities for the lock pattern and its settings.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 */
62public class LockPatternUtils {
63
64 private static final String TAG = "LockPatternUtils";
Brian Colonnaa0ee0042014-07-16 13:50:47 -040065 private static final boolean DEBUG = false;
Jim Miller69aa4a92009-12-22 19:03:28 -080066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 /**
68 * The maximum number of incorrect attempts before the user is prevented
69 * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
70 */
71 public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5;
72
73 /**
74 * The number of incorrect attempts before which we fall back on an alternative
75 * method of verifying the user, and resetting their lock pattern.
76 */
77 public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
78
79 /**
80 * How long the user is prevented from trying again after entering the
81 * wrong pattern too many times.
82 */
83 public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L;
84
85 /**
86 * The interval of the countdown for showing progress of the lockout.
87 */
88 public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
89
Jim Miller4f369952011-08-19 18:29:22 -070090
91 /**
92 * This dictates when we start telling the user that continued failed attempts will wipe
93 * their device.
94 */
95 public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
96
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 /**
98 * The minimum number of dots in a valid pattern.
99 */
100 public static final int MIN_LOCK_PATTERN_SIZE = 4;
101
102 /**
103 * The minimum number of dots the user must include in a wrong pattern
104 * attempt for it to be counted against the counts that affect
105 * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
106 */
Jim Miller4f369952011-08-19 18:29:22 -0700107 public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
Danielle Millett925a7d82012-03-19 18:02:20 -0400109 /**
Adam Cohenf7522022012-10-03 20:03:18 -0700110 * Tells the keyguard to show the user switcher when the keyguard is created.
111 */
112 public static final String KEYGUARD_SHOW_USER_SWITCHER = "showuserswitcher";
113
114 /**
115 * Tells the keyguard to show the security challenge when the keyguard is created.
116 */
117 public static final String KEYGUARD_SHOW_SECURITY_CHALLENGE = "showsecuritychallenge";
118
119 /**
Michael Jurka76017ca2012-11-06 16:21:09 -0800120 * Tells the keyguard to show the widget with the specified id when the keyguard is created.
121 */
122 public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget";
123
124 /**
Danielle Millett925a7d82012-03-19 18:02:20 -0400125 * The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
126 * be used
127 */
128 public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
129
Michael Jurka1254f2f2012-10-25 11:44:31 -0700130 /**
131 * Pseudo-appwidget id we use to represent the default clock status widget
132 */
133 public static final int ID_DEFAULT_STATUS_WIDGET = -2;
134
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800135 public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
136 public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
137 public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
Jim Miller69aa4a92009-12-22 19:03:28 -0800138 public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
Jim Miller6edf2632011-09-05 16:03:14 -0700139 public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800140 public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
141 public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
142 public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
Jim Miller6edf2632011-09-05 16:03:14 -0700143 public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
144 = "lockscreen.biometric_weak_fallback";
Danielle Millett7a072192011-10-03 17:36:01 -0400145 public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
146 = "lockscreen.biometricweakeverchosen";
Jim Millera4edd152012-01-06 18:24:04 -0800147 public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
148 = "lockscreen.power_button_instantly_locks";
Jim Millerf45bb402013-08-20 18:58:32 -0700149 public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800151 public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700152
Jim Miller187ec582013-04-15 18:27:54 -0700153 private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
154 private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
155 Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
156
Adrian Roos82142c22014-03-27 14:56:59 +0100157 private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
158
Jim Miller85516d02014-01-31 17:08:37 -0800159 // Maximum allowed number of repeated or ordered characters in a sequence before we'll
160 // consider it a complex PIN/password.
161 public static final int MAX_ALLOWED_SEQUENCE = 3;
162
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800163 private final Context mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 private final ContentResolver mContentResolver;
Jim Miller31f90b62010-01-20 13:35:20 -0800165 private DevicePolicyManager mDevicePolicyManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700166 private ILockSettings mLockSettingsService;
Jim Milleree82f8f2012-10-01 16:26:18 -0700167
Jim Miller78c48f62013-03-01 15:28:33 -0800168 private final boolean mMultiUserMode;
169
Jim Milleree82f8f2012-10-01 16:26:18 -0700170 // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
171 private static volatile int sCurrentUserId = UserHandle.USER_NULL;
Dianne Hackbornde4c26f2011-07-17 13:42:47 -0700172
Jim Millercd709882010-03-25 18:24:02 -0700173 public DevicePolicyManager getDevicePolicyManager() {
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800174 if (mDevicePolicyManager == null) {
175 mDevicePolicyManager =
176 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
177 if (mDevicePolicyManager == null) {
178 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
179 new IllegalStateException("Stack trace:"));
180 }
181 }
182 return mDevicePolicyManager;
183 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700184
Adrian Roos82142c22014-03-27 14:56:59 +0100185 private TrustManager getTrustManager() {
186 TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
187 if (trust == null) {
188 Log.e(TAG, "Can't get TrustManagerService: is it running?",
189 new IllegalStateException("Stack trace:"));
190 }
191 return trust;
192 }
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 /**
195 * @param contentResolver Used to look up and save settings.
196 */
Jim Miller31f90b62010-01-20 13:35:20 -0800197 public LockPatternUtils(Context context) {
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800198 mContext = context;
Jim Miller31f90b62010-01-20 13:35:20 -0800199 mContentResolver = context.getContentResolver();
Jim Miller78c48f62013-03-01 15:28:33 -0800200
201 // If this is being called by the system or by an application like keyguard that
202 // has permision INTERACT_ACROSS_USERS, then LockPatternUtils will operate in multi-user
203 // mode where calls are for the current user rather than the user of the calling process.
204 mMultiUserMode = context.checkCallingOrSelfPermission(
205 Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700206 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800207
Amith Yamasani52c489c2012-03-28 11:42:42 -0700208 private ILockSettings getLockSettings() {
209 if (mLockSettingsService == null) {
Adrian Roos4f788452014-05-22 20:45:59 +0200210 mLockSettingsService = LockPatternUtilsCache.getInstance(
211 ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")));
Brad Fitzpatrick90881002010-08-23 18:30:08 -0700212 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700213 return mLockSettingsService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 }
215
Jim Miller31f90b62010-01-20 13:35:20 -0800216 public int getRequestedMinimumPasswordLength() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700217 return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800218 }
219
Jim Miller31f90b62010-01-20 13:35:20 -0800220 /**
221 * Gets the device policy password mode. If the mode is non-specific, returns
222 * MODE_PATTERN which allows the user to choose anything.
Jim Miller31f90b62010-01-20 13:35:20 -0800223 */
Jim Millercd709882010-03-25 18:24:02 -0700224 public int getRequestedPasswordQuality() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700225 return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800226 }
227
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700228 public int getRequestedPasswordHistoryLength() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700229 return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId());
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700230 }
231
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700232 public int getRequestedPasswordMinimumLetters() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700233 return getDevicePolicyManager().getPasswordMinimumLetters(null,
234 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700235 }
236
237 public int getRequestedPasswordMinimumUpperCase() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700238 return getDevicePolicyManager().getPasswordMinimumUpperCase(null,
239 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700240 }
241
242 public int getRequestedPasswordMinimumLowerCase() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700243 return getDevicePolicyManager().getPasswordMinimumLowerCase(null,
244 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700245 }
246
247 public int getRequestedPasswordMinimumNumeric() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700248 return getDevicePolicyManager().getPasswordMinimumNumeric(null,
249 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700250 }
251
252 public int getRequestedPasswordMinimumSymbols() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700253 return getDevicePolicyManager().getPasswordMinimumSymbols(null,
254 getCurrentOrCallingUserId());
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700255 }
256
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700257 public int getRequestedPasswordMinimumNonLetter() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700258 return getDevicePolicyManager().getPasswordMinimumNonLetter(null,
259 getCurrentOrCallingUserId());
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700260 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700261
Jim Miller31f90b62010-01-20 13:35:20 -0800262 public void reportFailedPasswordAttempt() {
Adrian Roos4f994eb2014-07-23 15:45:05 +0200263 int userId = getCurrentOrCallingUserId();
264 getDevicePolicyManager().reportFailedPasswordAttempt(userId);
265 getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
266 getTrustManager().reportRequireCredentialEntry(userId);
Jim Miller31f90b62010-01-20 13:35:20 -0800267 }
268
269 public void reportSuccessfulPasswordAttempt() {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700270 getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
Adrian Roos82142c22014-03-27 14:56:59 +0100271 getTrustManager().reportUnlockAttempt(true /* authenticated */,
272 getCurrentOrCallingUserId());
Jim Miller31f90b62010-01-20 13:35:20 -0800273 }
274
Amith Yamasani52c489c2012-03-28 11:42:42 -0700275 public void setCurrentUser(int userId) {
Jim Milleree82f8f2012-10-01 16:26:18 -0700276 sCurrentUserId = userId;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700277 }
278
Amith Yamasanif882f1a2012-04-10 15:13:39 -0700279 public int getCurrentUser() {
Jim Milleree82f8f2012-10-01 16:26:18 -0700280 if (sCurrentUserId != UserHandle.USER_NULL) {
Jim Miller25645d82012-09-21 14:47:54 -0700281 // Someone is regularly updating using setCurrentUser() use that value.
Jim Milleree82f8f2012-10-01 16:26:18 -0700282 return sCurrentUserId;
Jim Miller25645d82012-09-21 14:47:54 -0700283 }
284 try {
285 return ActivityManagerNative.getDefault().getCurrentUser().id;
286 } catch (RemoteException re) {
287 return UserHandle.USER_OWNER;
Amith Yamasanif882f1a2012-04-10 15:13:39 -0700288 }
289 }
290
Amith Yamasani52c489c2012-03-28 11:42:42 -0700291 public void removeUser(int userId) {
Jim Miller25645d82012-09-21 14:47:54 -0700292 try {
293 getLockSettings().removeUser(userId);
294 } catch (RemoteException re) {
295 Log.e(TAG, "Couldn't remove lock settings for user " + userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700296 }
297 }
298
299 private int getCurrentOrCallingUserId() {
Jim Miller78c48f62013-03-01 15:28:33 -0800300 if (mMultiUserMode) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700301 // TODO: This is a little inefficient. See if all users of this are able to
302 // handle USER_CURRENT and pass that instead.
303 return getCurrentUser();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700304 } else {
Jim Miller78c48f62013-03-01 15:28:33 -0800305 return UserHandle.getCallingUserId();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700306 }
307 }
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 /**
310 * Check to see if a pattern matches the saved pattern. If no pattern exists,
311 * always returns true.
312 * @param pattern The pattern to check.
Jim Miller69aa4a92009-12-22 19:03:28 -0800313 * @return Whether the pattern matches the stored one.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 */
315 public boolean checkPattern(List<LockPatternView.Cell> pattern) {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700316 final int userId = getCurrentOrCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 try {
Jim Millerde1af082013-09-11 14:58:26 -0700318 return getLockSettings().checkPattern(patternToString(pattern), userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700319 } catch (RemoteException re) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 return true;
321 }
322 }
323
324 /**
Jim Miller69aa4a92009-12-22 19:03:28 -0800325 * Check to see if a password matches the saved password. If no password exists,
326 * always returns true.
327 * @param password The password to check.
328 * @return Whether the password matches the stored one.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 */
Jim Miller69aa4a92009-12-22 19:03:28 -0800330 public boolean checkPassword(String password) {
Kenny Rootdf8bfe02012-09-21 15:00:25 -0700331 final int userId = getCurrentOrCallingUserId();
Jim Miller69aa4a92009-12-22 19:03:28 -0800332 try {
Jim Millerde1af082013-09-11 14:58:26 -0700333 return getLockSettings().checkPassword(password, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700334 } catch (RemoteException re) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800335 return true;
336 }
337 }
338
339 /**
Paul Lawrence945490c2014-03-27 16:37:28 +0000340 * Check to see if vold already has the password.
341 * Note that this also clears vold's copy of the password.
342 * @return Whether the vold password matches or not.
343 */
344 public boolean checkVoldPassword() {
345 final int userId = getCurrentOrCallingUserId();
346 try {
347 return getLockSettings().checkVoldPassword(userId);
348 } catch (RemoteException re) {
349 return false;
350 }
351 }
352
353 /**
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700354 * Check to see if a password matches any of the passwords stored in the
355 * password history.
356 *
357 * @param password The password to check.
358 * @return Whether the password matches any in the history.
359 */
360 public boolean checkPasswordHistory(String password) {
Geoffrey Borggaard987672d22014-07-18 16:47:18 -0400361 String passwordHashString = new String(
362 passwordToHash(password, getCurrentOrCallingUserId()));
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700363 String passwordHistory = getString(PASSWORD_HISTORY_KEY);
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700364 if (passwordHistory == null) {
365 return false;
366 }
367 // Password History may be too long...
368 int passwordHashLength = passwordHashString.length();
369 int passwordHistoryLength = getRequestedPasswordHistoryLength();
370 if(passwordHistoryLength == 0) {
371 return false;
372 }
373 int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
374 + passwordHistoryLength - 1;
375 if (passwordHistory.length() > neededPasswordHistoryLength) {
376 passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
377 }
378 return passwordHistory.contains(passwordHashString);
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700379 }
380
381 /**
Jim Miller69aa4a92009-12-22 19:03:28 -0800382 * Check to see if the user has stored a lock pattern.
383 * @return Whether a saved pattern exists.
384 */
385 public boolean savedPatternExists() {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700386 try {
387 return getLockSettings().havePattern(getCurrentOrCallingUserId());
388 } catch (RemoteException re) {
389 return false;
390 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800391 }
392
393 /**
394 * Check to see if the user has stored a lock pattern.
395 * @return Whether a saved pattern exists.
396 */
397 public boolean savedPasswordExists() {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700398 try {
399 return getLockSettings().havePassword(getCurrentOrCallingUserId());
400 } catch (RemoteException re) {
401 return false;
402 }
Jim Miller69aa4a92009-12-22 19:03:28 -0800403 }
404
405 /**
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700406 * Return true if the user has ever chosen a pattern. This is true even if the pattern is
407 * currently cleared.
408 *
409 * @return True if the user has ever chosen a pattern.
410 */
411 public boolean isPatternEverChosen() {
Jim Millera4edd152012-01-06 18:24:04 -0800412 return getBoolean(PATTERN_EVER_CHOSEN_KEY, false);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700413 }
414
415 /**
Danielle Millett7a072192011-10-03 17:36:01 -0400416 * Return true if the user has ever chosen biometric weak. This is true even if biometric
417 * weak is not current set.
418 *
419 * @return True if the user has ever chosen biometric weak.
420 */
421 public boolean isBiometricWeakEverChosen() {
Jim Millera4edd152012-01-06 18:24:04 -0800422 return getBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, false);
Danielle Millett7a072192011-10-03 17:36:01 -0400423 }
424
425 /**
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700426 * Used by device policy manager to validate the current password
427 * information it has.
428 */
429 public int getActivePasswordQuality() {
Jim Millercd709882010-03-25 18:24:02 -0700430 int activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Danielle Millettc8fb5322011-10-04 12:18:51 -0400431 // Note we don't want to use getKeyguardStoredPasswordQuality() because we want this to
432 // return biometric_weak if that is being used instead of the backup
433 int quality =
434 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
435 switch (quality) {
Jim Millercd709882010-03-25 18:24:02 -0700436 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700437 if (isLockPatternEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700438 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700439 }
Jim Millercd709882010-03-25 18:24:02 -0700440 break;
Danielle Millettc8fb5322011-10-04 12:18:51 -0400441 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
442 if (isBiometricWeakInstalled()) {
443 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
444 }
445 break;
Jim Millercd709882010-03-25 18:24:02 -0700446 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700447 if (isLockPasswordEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700448 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700449 }
Jim Millercd709882010-03-25 18:24:02 -0700450 break;
Jim Miller85516d02014-01-31 17:08:37 -0800451 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
452 if (isLockPasswordEnabled()) {
453 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
454 }
455 break;
Jim Millercd709882010-03-25 18:24:02 -0700456 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700457 if (isLockPasswordEnabled()) {
Jim Millercd709882010-03-25 18:24:02 -0700458 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700459 }
Jim Millercd709882010-03-25 18:24:02 -0700460 break;
461 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
462 if (isLockPasswordEnabled()) {
463 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
464 }
465 break;
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700466 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
467 if (isLockPasswordEnabled()) {
468 activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
469 }
470 break;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700471 }
Danielle Millettc8fb5322011-10-04 12:18:51 -0400472
Jim Millercd709882010-03-25 18:24:02 -0700473 return activePasswordQuality;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700474 }
Jim Millercd709882010-03-25 18:24:02 -0700475
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700476 /**
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800477 * Clear any lock pattern or password.
478 */
Steven Ross329979c2011-09-28 11:42:56 -0400479 public void clearLock(boolean isFallback) {
480 if(!isFallback) deleteGallery();
Jim Millercd709882010-03-25 18:24:02 -0700481 saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800482 setLockPatternEnabled(false);
483 saveLockPattern(null);
Jim Miller93708af2012-01-25 18:26:12 -0800484 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
Jim Miller6edf2632011-09-05 16:03:14 -0700485 setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
Adrian Roos4b9e3242014-08-20 23:36:25 +0200486 onAfterChangingPassword();
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800487 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800488
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800489 /**
Jim Miller2a98a4c2010-11-19 18:49:26 -0800490 * Disable showing lock screen at all when the DevicePolicyManager allows it.
491 * This is only meaningful if pattern, pin or password are not set.
492 *
493 * @param disable Disables lock screen when true
494 */
495 public void setLockScreenDisabled(boolean disable) {
496 setLong(DISABLE_LOCKSCREEN_KEY, disable ? 1 : 0);
497 }
498
499 /**
500 * Determine if LockScreen can be disabled. This is used, for example, to tell if we should
501 * show LockScreen or go straight to the home screen.
502 *
503 * @return true if lock screen is can be disabled
504 */
505 public boolean isLockScreenDisabled() {
Adam Lesinski61d94092014-09-15 15:27:19 -0700506 if (!isSecure() && getLong(DISABLE_LOCKSCREEN_KEY, 0) != 0) {
507 // Check if the number of switchable users forces the lockscreen.
508 final List<UserInfo> users = UserManager.get(mContext).getUsers(true);
509 final int userCount = users.size();
510 int switchableUsers = 0;
511 for (int i = 0; i < userCount; i++) {
512 if (users.get(i).supportsSwitchTo()) {
513 switchableUsers++;
514 }
515 }
516 return switchableUsers < 2;
517 }
518 return false;
Jim Miller2a98a4c2010-11-19 18:49:26 -0800519 }
520
521 /**
Steven Ross3553c292011-09-30 15:48:40 -0400522 * Calls back SetupFaceLock to delete the temporary gallery file
Steven Ross329979c2011-09-28 11:42:56 -0400523 */
524 public void deleteTempGallery() {
Danielle Millett574e49e2012-03-27 16:17:10 -0400525 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
Steven Ross3553c292011-09-30 15:48:40 -0400526 intent.putExtra("deleteTempGallery", true);
Danielle Millett574e49e2012-03-27 16:17:10 -0400527 mContext.sendBroadcast(intent);
Steven Ross329979c2011-09-28 11:42:56 -0400528 }
529
530 /**
531 * Calls back SetupFaceLock to delete the gallery file when the lock type is changed
532 */
533 void deleteGallery() {
Danielle Millett58396982011-09-30 13:55:07 -0400534 if(usingBiometricWeak()) {
Danielle Millett574e49e2012-03-27 16:17:10 -0400535 Intent intent = new Intent().setAction("com.android.facelock.DELETE_GALLERY");
Steven Ross329979c2011-09-28 11:42:56 -0400536 intent.putExtra("deleteGallery", true);
Danielle Millett574e49e2012-03-27 16:17:10 -0400537 mContext.sendBroadcast(intent);
Steven Ross329979c2011-09-28 11:42:56 -0400538 }
539 }
540
541 /**
Jim Miller6edf2632011-09-05 16:03:14 -0700542 * Save a lock pattern.
543 * @param pattern The new pattern to save.
Danielle Millett2364a222011-12-21 17:02:32 -0500544 */
545 public void saveLockPattern(List<LockPatternView.Cell> pattern) {
546 this.saveLockPattern(pattern, false);
547 }
548
549 /**
550 * Save a lock pattern.
551 * @param pattern The new pattern to save.
Jim Miller6edf2632011-09-05 16:03:14 -0700552 * @param isFallback Specifies if this is a fallback to biometric weak
553 */
554 public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 try {
Adrian Roos82142c22014-03-27 14:56:59 +0100556 int userId = getCurrentOrCallingUserId();
557 getLockSettings().setLockPattern(patternToString(pattern), userId);
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800558 DevicePolicyManager dpm = getDevicePolicyManager();
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800559 if (pattern != null) {
Jim Miller6848dc82014-10-13 18:51:53 -0700560 // Update the device encryption password.
561 if (userId == UserHandle.USER_OWNER
562 && LockPatternUtils.isDeviceEncryptionEnabled()) {
563 final ContentResolver cr = mContext.getContentResolver();
564 final boolean required = Settings.Global.getInt(cr,
565 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, 1) == 1 ? true : false;
566 if (!required) {
567 clearEncryptionPassword();
568 } else {
569 String stringPattern = patternToString(pattern);
570 updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
571 }
Paul Lawrence8e397362014-01-27 15:22:30 -0800572 }
573
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800574 setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
Jim Miller6edf2632011-09-05 16:03:14 -0700575 if (!isFallback) {
Steven Ross329979c2011-09-28 11:42:56 -0400576 deleteGallery();
Jim Miller6edf2632011-09-05 16:03:14 -0700577 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Danielle Millett2364a222011-12-21 17:02:32 -0500578 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
Adrian Roos82142c22014-03-27 14:56:59 +0100579 pattern.size(), 0, 0, 0, 0, 0, 0, userId);
Jim Miller6edf2632011-09-05 16:03:14 -0700580 } else {
581 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
582 setLong(PASSWORD_TYPE_ALTERNATE_KEY,
583 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
Danielle Millett044a0a72011-11-07 15:42:12 -0500584 finishBiometricWeak();
Danielle Millett2364a222011-12-21 17:02:32 -0500585 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
Adrian Roos82142c22014-03-27 14:56:59 +0100586 0, 0, 0, 0, 0, 0, 0, userId);
Jim Miller6edf2632011-09-05 16:03:14 -0700587 }
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800588 } else {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700589 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
Adrian Roos82142c22014-03-27 14:56:59 +0100590 0, 0, 0, 0, 0, userId);
Jim Miller31f90b62010-01-20 13:35:20 -0800591 }
Adrian Roos4b9e3242014-08-20 23:36:25 +0200592 onAfterChangingPassword();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700593 } catch (RemoteException re) {
594 Log.e(TAG, "Couldn't save lock pattern " + re);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 }
596 }
597
Paul Lawrencee51dcf92014-03-18 10:56:00 -0700598 private void updateCryptoUserInfo() {
599 int userId = getCurrentOrCallingUserId();
600 if (userId != UserHandle.USER_OWNER) {
601 return;
602 }
603
604 final String ownerInfo = isOwnerInfoEnabled() ? getOwnerInfo(userId) : "";
605
606 IBinder service = ServiceManager.getService("mount");
607 if (service == null) {
608 Log.e(TAG, "Could not find the mount service to update the user info");
609 return;
610 }
611
612 IMountService mountService = IMountService.Stub.asInterface(service);
613 try {
614 Log.d(TAG, "Setting owner info");
Elliott Hughesf839b4f2014-09-26 12:30:47 -0700615 mountService.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
Paul Lawrencee51dcf92014-03-18 10:56:00 -0700616 } catch (RemoteException e) {
617 Log.e(TAG, "Error changing user info", e);
618 }
619 }
620
Jim Miller187ec582013-04-15 18:27:54 -0700621 public void setOwnerInfo(String info, int userId) {
622 setString(LOCK_SCREEN_OWNER_INFO, info, userId);
Paul Lawrencee51dcf92014-03-18 10:56:00 -0700623 updateCryptoUserInfo();
Jim Miller187ec582013-04-15 18:27:54 -0700624 }
625
626 public void setOwnerInfoEnabled(boolean enabled) {
627 setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled);
Paul Lawrencee51dcf92014-03-18 10:56:00 -0700628 updateCryptoUserInfo();
Jim Miller187ec582013-04-15 18:27:54 -0700629 }
630
631 public String getOwnerInfo(int userId) {
632 return getString(LOCK_SCREEN_OWNER_INFO);
633 }
634
635 public boolean isOwnerInfoEnabled() {
636 return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false);
637 }
638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 /**
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700640 * Compute the password quality from the given password string.
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800641 */
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700642 static public int computePasswordQuality(String password) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800643 boolean hasDigit = false;
644 boolean hasNonDigit = false;
645 final int len = password.length();
646 for (int i = 0; i < len; i++) {
647 if (Character.isDigit(password.charAt(i))) {
648 hasDigit = true;
649 } else {
650 hasNonDigit = true;
651 }
652 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800653
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700654 if (hasNonDigit && hasDigit) {
655 return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800656 }
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800657 if (hasNonDigit) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700658 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800659 }
660 if (hasDigit) {
Jim Miller85516d02014-01-31 17:08:37 -0800661 return maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
662 ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
663 : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800664 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700665 return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800666 }
Jim Miller5b0fb3a2010-02-23 13:46:35 -0800667
Jim Miller85516d02014-01-31 17:08:37 -0800668 private static int categoryChar(char c) {
669 if ('a' <= c && c <= 'z') return 0;
670 if ('A' <= c && c <= 'Z') return 1;
671 if ('0' <= c && c <= '9') return 2;
672 return 3;
673 }
674
675 private static int maxDiffCategory(int category) {
676 if (category == 0 || category == 1) return 1;
677 else if (category == 2) return 10;
678 return 0;
679 }
680
681 /*
682 * Returns the maximum length of a sequential characters. A sequence is defined as
683 * monotonically increasing characters with a constant interval or the same character repeated.
684 *
685 * For example:
686 * maxLengthSequence("1234") == 4
687 * maxLengthSequence("1234abc") == 4
688 * maxLengthSequence("aabc") == 3
689 * maxLengthSequence("qwertyuio") == 1
690 * maxLengthSequence("@ABC") == 3
691 * maxLengthSequence(";;;;") == 4 (anything that repeats)
692 * maxLengthSequence(":;<=>") == 1 (ordered, but not composed of alphas or digits)
693 *
694 * @param string the pass
695 * @return the number of sequential letters or digits
696 */
697 public static int maxLengthSequence(String string) {
698 if (string.length() == 0) return 0;
699 char previousChar = string.charAt(0);
700 int category = categoryChar(previousChar); //current category of the sequence
701 int diff = 0; //difference between two consecutive characters
702 boolean hasDiff = false; //if we are currently targeting a sequence
703 int maxLength = 0; //maximum length of a sequence already found
704 int startSequence = 0; //where the current sequence started
705 for (int current = 1; current < string.length(); current++) {
706 char currentChar = string.charAt(current);
707 int categoryCurrent = categoryChar(currentChar);
708 int currentDiff = (int) currentChar - (int) previousChar;
709 if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
710 maxLength = Math.max(maxLength, current - startSequence);
711 startSequence = current;
712 hasDiff = false;
713 category = categoryCurrent;
714 }
715 else {
716 if(hasDiff && currentDiff != diff) {
717 maxLength = Math.max(maxLength, current - startSequence);
718 startSequence = current - 1;
719 }
720 diff = currentDiff;
721 hasDiff = true;
722 }
723 previousChar = currentChar;
724 }
725 maxLength = Math.max(maxLength, string.length() - startSequence);
726 return maxLength;
727 }
728
Jason parksf7b3cd42011-01-27 09:28:25 -0600729 /** Update the encryption password if it is enabled **/
Paul Lawrence3a5a0be2014-09-25 09:26:34 -0700730 private void updateEncryptionPassword(final int type, final String password) {
Amith Yamasanicd410ba2014-10-17 11:16:58 -0700731 if (!isDeviceEncryptionEnabled()) {
Jason parksf7b3cd42011-01-27 09:28:25 -0600732 return;
733 }
Paul Lawrence3a5a0be2014-09-25 09:26:34 -0700734 final IBinder service = ServiceManager.getService("mount");
Jason parksf7b3cd42011-01-27 09:28:25 -0600735 if (service == null) {
736 Log.e(TAG, "Could not find the mount service to update the encryption password");
737 return;
738 }
739
Paul Lawrence3a5a0be2014-09-25 09:26:34 -0700740 new AsyncTask<Void, Void, Void>() {
741 @Override
742 protected Void doInBackground(Void... dummy) {
743 IMountService mountService = IMountService.Stub.asInterface(service);
744 try {
745 mountService.changeEncryptionPassword(type, password);
746 } catch (RemoteException e) {
747 Log.e(TAG, "Error changing encryption password", e);
748 }
749 return null;
750 }
751 }.execute();
Jason parksf7b3cd42011-01-27 09:28:25 -0600752 }
753
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800754 /**
Jim Millercd709882010-03-25 18:24:02 -0700755 * Save a lock password. Does not ensure that the password is as good
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800756 * as the requested mode, but will adjust the mode to be as good as the
757 * pattern.
Jim Miller69aa4a92009-12-22 19:03:28 -0800758 * @param password The password to save
Jim Millercd709882010-03-25 18:24:02 -0700759 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
Jim Miller69aa4a92009-12-22 19:03:28 -0800760 */
Jim Millercd709882010-03-25 18:24:02 -0700761 public void saveLockPassword(String password, int quality) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700762 this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId());
Jim Miller6edf2632011-09-05 16:03:14 -0700763 }
764
765 /**
766 * Save a lock password. Does not ensure that the password is as good
767 * as the requested mode, but will adjust the mode to be as good as the
768 * pattern.
769 * @param password The password to save
770 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
771 * @param isFallback Specifies if this is a fallback to biometric weak
772 */
773 public void saveLockPassword(String password, int quality, boolean isFallback) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700774 saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId());
775 }
776
777 /**
778 * Save a lock password. Does not ensure that the password is as good
779 * as the requested mode, but will adjust the mode to be as good as the
780 * pattern.
781 * @param password The password to save
782 * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
783 * @param isFallback Specifies if this is a fallback to biometric weak
784 * @param userHandle The userId of the user to change the password for
785 */
786 public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800787 try {
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800788 DevicePolicyManager dpm = getDevicePolicyManager();
Paul Lawrenceba45bcb2014-07-02 15:38:35 -0700789 if (!TextUtils.isEmpty(password)) {
Adrian Roosab7dae52014-09-25 18:07:13 +0200790 getLockSettings().setLockPassword(password, userHandle);
Paul Lawrence8e397362014-01-27 15:22:30 -0800791 int computedQuality = computePasswordQuality(password);
792
Jim Miller6848dc82014-10-13 18:51:53 -0700793 // Update the device encryption password.
794 if (userHandle == UserHandle.USER_OWNER
795 && LockPatternUtils.isDeviceEncryptionEnabled()) {
796 final ContentResolver cr = mContext.getContentResolver();
797 final boolean required = Settings.Global.getInt(cr,
798 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, 1) == 1 ? true : false;
799 if (!required) {
800 clearEncryptionPassword();
801 } else {
802 boolean numeric = computedQuality
803 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
804 boolean numericComplex = computedQuality
805 == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
806 int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
807 : StorageManager.CRYPT_TYPE_PASSWORD;
808 updateEncryptionPassword(type, password);
809 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700810 }
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700811
Jim Miller6edf2632011-09-05 16:03:14 -0700812 if (!isFallback) {
Steven Ross329979c2011-09-28 11:42:56 -0400813 deleteGallery();
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700814 setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500815 if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
816 int letters = 0;
817 int uppercase = 0;
818 int lowercase = 0;
819 int numbers = 0;
820 int symbols = 0;
821 int nonletter = 0;
822 for (int i = 0; i < password.length(); i++) {
823 char c = password.charAt(i);
824 if (c >= 'A' && c <= 'Z') {
825 letters++;
826 uppercase++;
827 } else if (c >= 'a' && c <= 'z') {
828 letters++;
829 lowercase++;
830 } else if (c >= '0' && c <= '9') {
831 numbers++;
832 nonletter++;
833 } else {
834 symbols++;
835 nonletter++;
836 }
837 }
838 dpm.setActivePasswordState(Math.max(quality, computedQuality),
839 password.length(), letters, uppercase, lowercase,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700840 numbers, symbols, nonletter, userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500841 } else {
842 // The password is not anything.
843 dpm.setActivePasswordState(
844 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700845 0, 0, 0, 0, 0, 0, 0, userHandle);
Danielle Millett2364a222011-12-21 17:02:32 -0500846 }
Jim Miller6edf2632011-09-05 16:03:14 -0700847 } else {
Danielle Millett2364a222011-12-21 17:02:32 -0500848 // Case where it's a fallback for biometric weak
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700849 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
850 userHandle);
851 setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality),
852 userHandle);
Danielle Millett044a0a72011-11-07 15:42:12 -0500853 finishBiometricWeak();
Danielle Millett2364a222011-12-21 17:02:32 -0500854 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700855 0, 0, 0, 0, 0, 0, 0, userHandle);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700856 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700857 // Add the password to the password history. We assume all
Paul Lawrence8e397362014-01-27 15:22:30 -0800858 // password hashes have the same length for simplicity of implementation.
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700859 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -0700860 if (passwordHistory == null) {
861 passwordHistory = new String();
862 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700863 int passwordHistoryLength = getRequestedPasswordHistoryLength();
864 if (passwordHistoryLength == 0) {
865 passwordHistory = "";
866 } else {
Geoffrey Borggaard987672d22014-07-18 16:47:18 -0400867 byte[] hash = passwordToHash(password, userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700868 passwordHistory = new String(hash) + "," + passwordHistory;
869 // Cut it to contain passwordHistoryLength hashes
870 // and passwordHistoryLength -1 commas.
871 passwordHistory = passwordHistory.substring(0, Math.min(hash.length
872 * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
873 .length()));
874 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700875 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800876 } else {
Paul Lawrenceba45bcb2014-07-02 15:38:35 -0700877 // Empty password
Adrian Roosab7dae52014-09-25 18:07:13 +0200878 getLockSettings().setLockPassword(null, userHandle);
Paul Lawrence8e397362014-01-27 15:22:30 -0800879 if (userHandle == UserHandle.USER_OWNER) {
Paul Lawrenceba45bcb2014-07-02 15:38:35 -0700880 // Set the encryption password to default.
881 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
Paul Lawrence8e397362014-01-27 15:22:30 -0800882 }
883
Dianne Hackborn2509d3c2010-03-08 12:54:25 -0800884 dpm.setActivePasswordState(
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700885 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
886 userHandle);
Jim Miller31f90b62010-01-20 13:35:20 -0800887 }
Adrian Roos4b9e3242014-08-20 23:36:25 +0200888 onAfterChangingPassword();
Amith Yamasani52c489c2012-03-28 11:42:42 -0700889 } catch (RemoteException re) {
Jim Miller69aa4a92009-12-22 19:03:28 -0800890 // Cant do much
Amith Yamasani52c489c2012-03-28 11:42:42 -0700891 Log.e(TAG, "Unable to save lock password " + re);
Jim Miller69aa4a92009-12-22 19:03:28 -0800892 }
893 }
894
Jim Millercd709882010-03-25 18:24:02 -0700895 /**
Svetoslav16e4a1a2014-09-29 18:16:20 -0700896 * Gets whether the device is encrypted.
897 *
898 * @return Whether the device is encrypted.
899 */
900 public static boolean isDeviceEncrypted() {
901 IMountService mountService = IMountService.Stub.asInterface(
902 ServiceManager.getService("mount"));
903 try {
904 return mountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE
905 && mountService.getPasswordType() != StorageManager.CRYPT_TYPE_DEFAULT;
906 } catch (RemoteException re) {
907 Log.e(TAG, "Error getting encryption state", re);
908 }
909 return true;
910 }
911
912 /**
Jim Miller6848dc82014-10-13 18:51:53 -0700913 * Determine if the device supports encryption, even if it's set to default. This
914 * differs from isDeviceEncrypted() in that it returns true even if the device is
915 * encrypted with the default password.
916 * @return true if device encryption is enabled
917 */
918 public static boolean isDeviceEncryptionEnabled() {
919 final String status = SystemProperties.get("ro.crypto.state", "unsupported");
920 return "encrypted".equalsIgnoreCase(status);
921 }
922
923 /**
Svetoslav16e4a1a2014-09-29 18:16:20 -0700924 * Clears the encryption password.
925 */
926 public void clearEncryptionPassword() {
927 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
928 }
929
930 /**
Jim Millercd709882010-03-25 18:24:02 -0700931 * Retrieves the quality mode we're in.
932 * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
933 *
934 * @return stored password quality
935 */
936 public int getKeyguardStoredPasswordQuality() {
Adrian Roos1572ee32014-09-01 16:24:32 +0200937 return getKeyguardStoredPasswordQuality(getCurrentOrCallingUserId());
938 }
939
940 /**
941 * Retrieves the quality mode for {@param userHandle}.
942 * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
943 *
944 * @return stored password quality
945 */
946 public int getKeyguardStoredPasswordQuality(int userHandle) {
947 int quality = (int) getLong(PASSWORD_TYPE_KEY,
948 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
Jim Miller6edf2632011-09-05 16:03:14 -0700949 // If the user has chosen to use weak biometric sensor, then return the backup locking
950 // method and treat biometric as a special case.
951 if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
Adrian Roos1572ee32014-09-01 16:24:32 +0200952 quality = (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
953 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
Jim Miller6edf2632011-09-05 16:03:14 -0700954 }
955 return quality;
956 }
957
Danielle Millett58396982011-09-30 13:55:07 -0400958 /**
959 * @return true if the lockscreen method is set to biometric weak
960 */
Jim Miller6edf2632011-09-05 16:03:14 -0700961 public boolean usingBiometricWeak() {
962 int quality =
Jim Miller43120732014-04-14 16:56:08 -0700963 (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
Jim Miller6edf2632011-09-05 16:03:14 -0700964 return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
Jim Miller69aa4a92009-12-22 19:03:28 -0800965 }
966
967 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 * Deserialize a pattern.
969 * @param string The pattern serialized with {@link #patternToString}
970 * @return The pattern.
971 */
972 public static List<LockPatternView.Cell> stringToPattern(String string) {
973 List<LockPatternView.Cell> result = Lists.newArrayList();
974
975 final byte[] bytes = string.getBytes();
976 for (int i = 0; i < bytes.length; i++) {
977 byte b = bytes[i];
978 result.add(LockPatternView.Cell.of(b / 3, b % 3));
979 }
980 return result;
981 }
982
983 /**
984 * Serialize a pattern.
985 * @param pattern The pattern.
986 * @return The pattern in string form.
987 */
988 public static String patternToString(List<LockPatternView.Cell> pattern) {
989 if (pattern == null) {
990 return "";
991 }
992 final int patternSize = pattern.size();
993
994 byte[] res = new byte[patternSize];
995 for (int i = 0; i < patternSize; i++) {
996 LockPatternView.Cell cell = pattern.get(i);
997 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
998 }
999 return new String(res);
1000 }
Jim Miller69aa4a92009-12-22 19:03:28 -08001001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 /*
1003 * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
1004 * at least a second level of protection. First level is that the file
1005 * is in a location only readable by the system process.
1006 * @param pattern the gesture pattern.
1007 * @return the hash of the pattern in a byte array.
1008 */
Jim Millerde1af082013-09-11 14:58:26 -07001009 public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 if (pattern == null) {
1011 return null;
1012 }
Jim Miller69aa4a92009-12-22 19:03:28 -08001013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 final int patternSize = pattern.size();
1015 byte[] res = new byte[patternSize];
1016 for (int i = 0; i < patternSize; i++) {
1017 LockPatternView.Cell cell = pattern.get(i);
1018 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
1019 }
1020 try {
1021 MessageDigest md = MessageDigest.getInstance("SHA-1");
1022 byte[] hash = md.digest(res);
1023 return hash;
1024 } catch (NoSuchAlgorithmException nsa) {
1025 return res;
1026 }
1027 }
1028
Geoffrey Borggaard987672d22014-07-18 16:47:18 -04001029 private String getSalt(int userId) {
1030 long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
Jim Miller11b019d2010-01-20 16:34:45 -08001031 if (salt == 0) {
1032 try {
1033 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
Geoffrey Borggaard987672d22014-07-18 16:47:18 -04001034 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1035 Log.v(TAG, "Initialized lock password salt for user: " + userId);
Jim Miller11b019d2010-01-20 16:34:45 -08001036 } catch (NoSuchAlgorithmException e) {
1037 // Throw an exception rather than storing a password we'll never be able to recover
1038 throw new IllegalStateException("Couldn't get SecureRandom number", e);
1039 }
1040 }
1041 return Long.toHexString(salt);
1042 }
1043
Jim Miller69aa4a92009-12-22 19:03:28 -08001044 /*
1045 * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1046 * Not the most secure, but it is at least a second level of protection. First level is that
1047 * the file is in a location only readable by the system process.
1048 * @param password the gesture pattern.
1049 * @return the hash of the pattern in a byte array.
1050 */
Geoffrey Borggaard987672d22014-07-18 16:47:18 -04001051 public byte[] passwordToHash(String password, int userId) {
Jim Miller69aa4a92009-12-22 19:03:28 -08001052 if (password == null) {
1053 return null;
1054 }
1055 String algo = null;
1056 byte[] hashed = null;
1057 try {
Geoffrey Borggaard987672d22014-07-18 16:47:18 -04001058 byte[] saltedPassword = (password + getSalt(userId)).getBytes();
Jim Miller69aa4a92009-12-22 19:03:28 -08001059 byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
1060 byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
1061 hashed = (toHex(sha1) + toHex(md5)).getBytes();
1062 } catch (NoSuchAlgorithmException e) {
1063 Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo);
1064 }
1065 return hashed;
1066 }
1067
1068 private static String toHex(byte[] ary) {
1069 final String hex = "0123456789ABCDEF";
1070 String ret = "";
1071 for (int i = 0; i < ary.length; i++) {
1072 ret += hex.charAt((ary[i] >> 4) & 0xf);
1073 ret += hex.charAt(ary[i] & 0xf);
1074 }
1075 return ret;
1076 }
1077
1078 /**
Danielle Millett73da5fe2011-09-13 16:20:05 -04001079 * @return Whether the lock password is enabled, or if it is set as a backup for biometric weak
Jim Miller69aa4a92009-12-22 19:03:28 -08001080 */
1081 public boolean isLockPasswordEnabled() {
1082 long mode = getLong(PASSWORD_TYPE_KEY, 0);
Danielle Millett73da5fe2011-09-13 16:20:05 -04001083 long backupMode = getLong(PASSWORD_TYPE_ALTERNATE_KEY, 0);
1084 final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1085 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
Jim Miller85516d02014-01-31 17:08:37 -08001086 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
Danielle Millett73da5fe2011-09-13 16:20:05 -04001087 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1088 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
1089 final boolean backupEnabled = backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1090 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
Jim Miller85516d02014-01-31 17:08:37 -08001091 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
Danielle Millett73da5fe2011-09-13 16:20:05 -04001092 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1093 || backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
1094
1095 return savedPasswordExists() && (passwordEnabled ||
Danielle Millett58396982011-09-30 13:55:07 -04001096 (usingBiometricWeak() && backupEnabled));
Jim Miller69aa4a92009-12-22 19:03:28 -08001097 }
1098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 /**
Danielle Millett73da5fe2011-09-13 16:20:05 -04001100 * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 */
1102 public boolean isLockPatternEnabled() {
Danielle Millett73da5fe2011-09-13 16:20:05 -04001103 final boolean backupEnabled =
Jim Miller43120732014-04-14 16:56:08 -07001104 getLong(PASSWORD_TYPE_ALTERNATE_KEY,
1105 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
1106 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
Danielle Millett73da5fe2011-09-13 16:20:05 -04001107
Jim Millera4edd152012-01-06 18:24:04 -08001108 return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
Jim Miller43120732014-04-14 16:56:08 -07001109 && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
Danielle Millett73da5fe2011-09-13 16:20:05 -04001110 == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
Danielle Millett58396982011-09-30 13:55:07 -04001111 (usingBiometricWeak() && backupEnabled));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 }
1113
1114 /**
Danielle Millett58396982011-09-30 13:55:07 -04001115 * @return Whether biometric weak lock is installed and that the front facing camera exists
Jim Miller6edf2632011-09-05 16:03:14 -07001116 */
Danielle Millett58396982011-09-30 13:55:07 -04001117 public boolean isBiometricWeakInstalled() {
Danielle Millett58396982011-09-30 13:55:07 -04001118 // Check that it's installed
1119 PackageManager pm = mContext.getPackageManager();
1120 try {
1121 pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES);
1122 } catch (PackageManager.NameNotFoundException e) {
1123 return false;
1124 }
1125
1126 // Check that the camera is enabled
1127 if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
1128 return false;
1129 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001130 if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) {
Danielle Millett58396982011-09-30 13:55:07 -04001131 return false;
1132 }
1133
Brian Colonnaa0ee0042014-07-16 13:50:47 -04001134 // TODO: If we decide not to proceed with Face Unlock as a trustlet, this must be changed
1135 // back to returning true. If we become certain that Face Unlock will be a trustlet, this
1136 // entire function and a lot of other code can be removed.
1137 if (DEBUG) Log.d(TAG, "Forcing isBiometricWeakInstalled() to return false to disable it");
1138 return false;
Jim Miller6edf2632011-09-05 16:03:14 -07001139 }
1140
1141 /**
Danielle Millett925a7d82012-03-19 18:02:20 -04001142 * Set whether biometric weak liveliness is enabled.
1143 */
1144 public void setBiometricWeakLivelinessEnabled(boolean enabled) {
1145 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
1146 long newFlag;
1147 if (enabled) {
1148 newFlag = currentFlag | FLAG_BIOMETRIC_WEAK_LIVELINESS;
1149 } else {
1150 newFlag = currentFlag & ~FLAG_BIOMETRIC_WEAK_LIVELINESS;
1151 }
1152 setLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, newFlag);
1153 }
1154
1155 /**
1156 * @return Whether the biometric weak liveliness is enabled.
1157 */
1158 public boolean isBiometricWeakLivelinessEnabled() {
1159 long currentFlag = getLong(Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 0L);
1160 return ((currentFlag & FLAG_BIOMETRIC_WEAK_LIVELINESS) != 0);
1161 }
1162
1163 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 * Set whether the lock pattern is enabled.
1165 */
1166 public void setLockPatternEnabled(boolean enabled) {
Amith Yamasani156c4352010-03-05 17:10:03 -08001167 setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 }
1169
1170 /**
1171 * @return Whether the visible pattern is enabled.
1172 */
1173 public boolean isVisiblePatternEnabled() {
Jim Millera4edd152012-01-06 18:24:04 -08001174 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
1176
1177 /**
1178 * Set whether the visible pattern is enabled.
1179 */
1180 public void setVisiblePatternEnabled(boolean enabled) {
Amith Yamasani156c4352010-03-05 17:10:03 -08001181 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled);
Paul Lawrence878ba0a2014-08-20 13:08:01 -07001182
1183 // Update for crypto if owner
1184 int userId = getCurrentOrCallingUserId();
1185 if (userId != UserHandle.USER_OWNER) {
1186 return;
1187 }
1188
1189 IBinder service = ServiceManager.getService("mount");
1190 if (service == null) {
1191 Log.e(TAG, "Could not find the mount service to update the user info");
1192 return;
1193 }
1194
1195 IMountService mountService = IMountService.Stub.asInterface(service);
1196 try {
Elliott Hughesf839b4f2014-09-26 12:30:47 -07001197 mountService.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
Paul Lawrence878ba0a2014-08-20 13:08:01 -07001198 } catch (RemoteException e) {
1199 Log.e(TAG, "Error changing pattern visible state", e);
1200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 }
1202
1203 /**
1204 * @return Whether tactile feedback for the pattern is enabled.
1205 */
1206 public boolean isTactileFeedbackEnabled() {
Jeff Sharkey5ed9d682012-10-10 14:28:27 -07001207 return Settings.System.getIntForUser(mContentResolver,
1208 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 }
1210
1211 /**
1212 * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1213 * pattern until the deadline has passed.
1214 * @return the chosen deadline.
1215 */
1216 public long setLockoutAttemptDeadline() {
1217 final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
1218 setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
1219 return deadline;
1220 }
1221
1222 /**
1223 * @return The elapsed time in millis in the future when the user is allowed to
1224 * attempt to enter his/her lock pattern, or 0 if the user is welcome to
1225 * enter a pattern.
1226 */
1227 public long getLockoutAttemptDeadline() {
1228 final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
1229 final long now = SystemClock.elapsedRealtime();
1230 if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
1231 return 0L;
1232 }
1233 return deadline;
1234 }
1235
1236 /**
1237 * @return Whether the user is permanently locked out until they verify their
1238 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
1239 * attempts.
1240 */
1241 public boolean isPermanentlyLocked() {
Jim Millera4edd152012-01-06 18:24:04 -08001242 return getBoolean(LOCKOUT_PERMANENT_KEY, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 }
1244
1245 /**
1246 * Set the state of whether the device is permanently locked, meaning the user
Karl Rosaen678771b2009-08-21 14:00:26 -07001247 * must authenticate via other means.
1248 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 * @param locked Whether the user is permanently locked out until they verify their
1250 * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
1251 * attempts.
1252 */
1253 public void setPermanentlyLocked(boolean locked) {
1254 setBoolean(LOCKOUT_PERMANENT_KEY, locked);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 }
1256
John Wang0f7b3f82011-05-31 11:20:55 -07001257 public boolean isEmergencyCallCapable() {
1258 return mContext.getResources().getBoolean(
1259 com.android.internal.R.bool.config_voice_capable);
1260 }
1261
1262 public boolean isPukUnlockScreenEnable() {
1263 return mContext.getResources().getBoolean(
1264 com.android.internal.R.bool.config_enable_puk_unlock_screen);
1265 }
1266
Jim Miller1f56edc2011-11-07 19:00:48 -08001267 public boolean isEmergencyCallEnabledWhileSimLocked() {
1268 return mContext.getResources().getBoolean(
1269 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
1270 }
1271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272 /**
1273 * @return A formatted string of the next alarm (for showing on the lock screen),
1274 * or null if there is no next alarm.
1275 */
Jose Lima235510e2014-08-13 12:50:01 -07001276 public AlarmManager.AlarmClockInfo getNextAlarm() {
Adrian Roosedad7b22014-07-13 14:38:22 +02001277 AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
1278 return alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 }
1280
Jim Millerf45bb402013-08-20 18:58:32 -07001281 private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001282 try {
Jim Millerf45bb402013-08-20 18:58:32 -07001283 return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001284 } catch (RemoteException re) {
1285 return defaultValue;
1286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 }
1288
Jim Millerf45bb402013-08-20 18:58:32 -07001289 private boolean getBoolean(String secureSettingKey, boolean defaultValue) {
1290 return getBoolean(secureSettingKey, defaultValue, getCurrentOrCallingUserId());
1291 }
1292
1293 private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001294 try {
Jim Millerf45bb402013-08-20 18:58:32 -07001295 getLockSettings().setBoolean(secureSettingKey, enabled, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001296 } catch (RemoteException re) {
1297 // What can we do?
1298 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 }
1301
Jim Millerf45bb402013-08-20 18:58:32 -07001302 private void setBoolean(String secureSettingKey, boolean enabled) {
1303 setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId());
1304 }
1305
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001306 public int[] getAppWidgets() {
Jim Millerf45bb402013-08-20 18:58:32 -07001307 return getAppWidgets(UserHandle.USER_CURRENT);
1308 }
1309
1310 private int[] getAppWidgets(int userId) {
Amith Yamasani8fd96ec2012-09-21 17:48:49 -07001311 String appWidgetIdString = Settings.Secure.getStringForUser(
Jim Millerf45bb402013-08-20 18:58:32 -07001312 mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, userId);
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001313 String delims = ",";
Michael Jurka1254f2f2012-10-25 11:44:31 -07001314 if (appWidgetIdString != null && appWidgetIdString.length() > 0) {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001315 String[] appWidgetStringIds = appWidgetIdString.split(delims);
1316 int[] appWidgetIds = new int[appWidgetStringIds.length];
1317 for (int i = 0; i < appWidgetStringIds.length; i++) {
1318 String appWidget = appWidgetStringIds[i];
1319 try {
1320 appWidgetIds[i] = Integer.decode(appWidget);
1321 } catch (NumberFormatException e) {
Michael Jurka1254f2f2012-10-25 11:44:31 -07001322 Log.d(TAG, "Error when parsing widget id " + appWidget);
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001323 return null;
1324 }
1325 }
1326 return appWidgetIds;
Jim Millerf229e4d2012-09-12 20:32:50 -07001327 }
Michael Jurka67a871d2012-11-01 18:26:01 -07001328 return new int[0];
Jim Millerf229e4d2012-09-12 20:32:50 -07001329 }
1330
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001331 private static String combineStrings(int[] list, String separator) {
1332 int listLength = list.length;
1333
1334 switch (listLength) {
1335 case 0: {
1336 return "";
1337 }
1338 case 1: {
1339 return Integer.toString(list[0]);
1340 }
Michael Jurka20c41d52012-09-20 19:01:06 -07001341 }
1342
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001343 int strLength = 0;
1344 int separatorLength = separator.length();
1345
1346 String[] stringList = new String[list.length];
1347 for (int i = 0; i < listLength; i++) {
1348 stringList[i] = Integer.toString(list[i]);
1349 strLength += stringList[i].length();
1350 if (i < listLength - 1) {
1351 strLength += separatorLength;
1352 }
1353 }
1354
1355 StringBuilder sb = new StringBuilder(strLength);
1356
1357 for (int i = 0; i < listLength; i++) {
1358 sb.append(list[i]);
1359 if (i < listLength - 1) {
1360 sb.append(separator);
1361 }
1362 }
1363
1364 return sb.toString();
1365 }
1366
Jim Miller51117262012-11-04 17:58:09 -08001367 // appwidget used when appwidgets are disabled (we make an exception for
1368 // default clock widget)
1369 public void writeFallbackAppWidgetId(int appWidgetId) {
1370 Settings.Secure.putIntForUser(mContentResolver,
1371 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
1372 appWidgetId,
1373 UserHandle.USER_CURRENT);
1374 }
1375
1376 // appwidget used when appwidgets are disabled (we make an exception for
1377 // default clock widget)
1378 public int getFallbackAppWidgetId() {
1379 return Settings.Secure.getIntForUser(
1380 mContentResolver,
1381 Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID,
1382 AppWidgetManager.INVALID_APPWIDGET_ID,
1383 UserHandle.USER_CURRENT);
1384 }
1385
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001386 private void writeAppWidgets(int[] appWidgetIds) {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001387 Settings.Secure.putStringForUser(mContentResolver,
1388 Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS,
1389 combineStrings(appWidgetIds, ","),
1390 UserHandle.USER_CURRENT);
1391 }
1392
Michael Jurka1254f2f2012-10-25 11:44:31 -07001393 // TODO: log an error if this returns false
1394 public boolean addAppWidget(int widgetId, int index) {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001395 int[] widgets = getAppWidgets();
Michael Jurka1254f2f2012-10-25 11:44:31 -07001396 if (widgets == null) {
1397 return false;
1398 }
Michael Jurka229dd8b2012-10-26 16:06:12 -07001399 if (index < 0 || index > widgets.length) {
Michael Jurka1254f2f2012-10-25 11:44:31 -07001400 return false;
1401 }
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001402 int[] newWidgets = new int[widgets.length + 1];
1403 for (int i = 0, j = 0; i < newWidgets.length; i++) {
1404 if (index == i) {
1405 newWidgets[i] = widgetId;
1406 i++;
1407 }
1408 if (i < newWidgets.length) {
1409 newWidgets[i] = widgets[j];
1410 j++;
1411 }
1412 }
1413 writeAppWidgets(newWidgets);
Michael Jurka1254f2f2012-10-25 11:44:31 -07001414 return true;
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001415 }
1416
Michael Jurka1254f2f2012-10-25 11:44:31 -07001417 public boolean removeAppWidget(int widgetId) {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001418 int[] widgets = getAppWidgets();
Michael Jurka1254f2f2012-10-25 11:44:31 -07001419
Jim Millera9768602012-11-06 22:17:25 -08001420 if (widgets.length == 0) {
1421 return false;
1422 }
1423
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001424 int[] newWidgets = new int[widgets.length - 1];
1425 for (int i = 0, j = 0; i < widgets.length; i++) {
Michael Jurka1254f2f2012-10-25 11:44:31 -07001426 if (widgets[i] == widgetId) {
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001427 // continue...
Michael Jurka1254f2f2012-10-25 11:44:31 -07001428 } else if (j >= newWidgets.length) {
1429 // we couldn't find the widget
1430 return false;
Michael Jurkaaa2859a2012-10-24 12:46:49 -07001431 } else {
1432 newWidgets[j] = widgets[i];
1433 j++;
1434 }
1435 }
1436 writeAppWidgets(newWidgets);
1437 return true;
Michael Jurka20c41d52012-09-20 19:01:06 -07001438 }
1439
Geoffrey Borggaard987672d22014-07-18 16:47:18 -04001440 private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1441 try {
1442 return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1443 } catch (RemoteException re) {
1444 return defaultValue;
1445 }
1446 }
1447
Amith Yamasani52c489c2012-03-28 11:42:42 -07001448 private long getLong(String secureSettingKey, long defaultValue) {
1449 try {
1450 return getLockSettings().getLong(secureSettingKey, defaultValue,
1451 getCurrentOrCallingUserId());
1452 } catch (RemoteException re) {
1453 return defaultValue;
1454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 }
1456
Amith Yamasani156c4352010-03-05 17:10:03 -08001457 private void setLong(String secureSettingKey, long value) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001458 setLong(secureSettingKey, value, getCurrentOrCallingUserId());
1459 }
1460
1461 private void setLong(String secureSettingKey, long value, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001462 try {
Kenny Guy0cf13702013-11-29 16:33:05 +00001463 getLockSettings().setLong(secureSettingKey, value, userHandle);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001464 } catch (RemoteException re) {
1465 // What can we do?
1466 Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 }
1469
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001470 private String getString(String secureSettingKey) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001471 return getString(secureSettingKey, getCurrentOrCallingUserId());
1472 }
1473
1474 private String getString(String secureSettingKey, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001475 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001476 return getLockSettings().getString(secureSettingKey, null, userHandle);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001477 } catch (RemoteException re) {
1478 return null;
1479 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001480 }
1481
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001482 private void setString(String secureSettingKey, String value, int userHandle) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001483 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001484 getLockSettings().setString(secureSettingKey, value, userHandle);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001485 } catch (RemoteException re) {
1486 // What can we do?
1487 Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1488 }
Konstantin Lopyrev863f22d2010-05-12 17:16:58 -07001489 }
1490
Jim Miller69aa4a92009-12-22 19:03:28 -08001491 public boolean isSecure() {
Jim Millercd709882010-03-25 18:24:02 -07001492 long mode = getKeyguardStoredPasswordQuality();
1493 final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
1494 final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
Jim Miller85516d02014-01-31 17:08:37 -08001495 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
Jim Millercd709882010-03-25 18:24:02 -07001496 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001497 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1498 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
Jim Millercd709882010-03-25 18:24:02 -07001499 final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
Danielle Millett73da5fe2011-09-13 16:20:05 -04001500 || isPassword && savedPasswordExists();
Jim Miller69aa4a92009-12-22 19:03:28 -08001501 return secure;
1502 }
Jim Miller69ac9882010-02-24 15:35:05 -08001503
1504 /**
John Wang0f7b3f82011-05-31 11:20:55 -07001505 * Sets the emergency button visibility based on isEmergencyCallCapable().
1506 *
1507 * If the emergency button is visible, sets the text on the emergency button
1508 * to indicate what action will be taken.
1509 *
Jim Miller69ac9882010-02-24 15:35:05 -08001510 * If there's currently a call in progress, the button will take them to the call
Santos Cordon0bae09f2014-07-07 14:53:10 -07001511 * @param button The button to update
1512 * @param shown Indicates whether the given screen wants the emergency button to show at all
1513 * @param showIcon Indicates whether to show a phone icon for the button.
Jim Miller69ac9882010-02-24 15:35:05 -08001514 */
Santos Cordon0bae09f2014-07-07 14:53:10 -07001515 public void updateEmergencyCallButtonState(Button button, boolean shown, boolean showIcon) {
Jim Miller1f56edc2011-11-07 19:00:48 -08001516 if (isEmergencyCallCapable() && shown) {
John Wang0f7b3f82011-05-31 11:20:55 -07001517 button.setVisibility(View.VISIBLE);
1518 } else {
1519 button.setVisibility(View.GONE);
1520 return;
1521 }
1522
Jim Miller69ac9882010-02-24 15:35:05 -08001523 int textId;
Yorke Leecc5179f2014-09-03 15:01:18 -07001524 if (isInCall()) {
Jim Miller69ac9882010-02-24 15:35:05 -08001525 // show "return to call" text and show phone icon
1526 textId = R.string.lockscreen_return_to_call;
Jim Miller109f1fd2012-09-19 20:44:16 -07001527 int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
Jim Miller69ac9882010-02-24 15:35:05 -08001528 button.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
1529 } else {
1530 textId = R.string.lockscreen_emergency_call;
Jim Miller109f1fd2012-09-19 20:44:16 -07001531 int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0;
Jim Miller69ac9882010-02-24 15:35:05 -08001532 button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
1533 }
Jim Millere38c8e22013-09-24 15:54:04 -07001534 button.setText(textId);
Jim Miller69ac9882010-02-24 15:35:05 -08001535 }
1536
1537 /**
1538 * Resumes a call in progress. Typically launched from the EmergencyCall button
1539 * on various lockscreens.
Jim Miller69ac9882010-02-24 15:35:05 -08001540 */
Santos Cordon3534ede2014-05-29 13:07:10 -07001541 public void resumeCall() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07001542 getTelecommManager().showInCallScreen(false);
Santos Cordon0bae09f2014-07-07 14:53:10 -07001543 }
1544
Yorke Leecc5179f2014-09-03 15:01:18 -07001545 /**
1546 * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
1547 */
1548 public boolean isInCall() {
1549 return getTelecommManager().isInCall();
1550 }
1551
Tyler Gunnef9f6f92014-09-12 22:16:17 -07001552 private TelecomManager getTelecommManager() {
1553 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Jim Miller69ac9882010-02-24 15:35:05 -08001554 }
Danielle Millett044a0a72011-11-07 15:42:12 -05001555
1556 private void finishBiometricWeak() {
1557 setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
1558
1559 // Launch intent to show final screen, this also
1560 // moves the temporary gallery to the actual gallery
1561 Intent intent = new Intent();
1562 intent.setClassName("com.android.facelock",
1563 "com.android.facelock.SetupEndScreen");
1564 mContext.startActivity(intent);
1565 }
1566
Jim Millera4edd152012-01-06 18:24:04 -08001567 public void setPowerButtonInstantlyLocks(boolean enabled) {
1568 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled);
1569 }
1570
1571 public boolean getPowerButtonInstantlyLocks() {
1572 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true);
1573 }
Jim Millera9768602012-11-06 22:17:25 -08001574
Jim Miller51117262012-11-04 17:58:09 -08001575 public static boolean isSafeModeEnabled() {
1576 try {
1577 return IWindowManager.Stub.asInterface(
1578 ServiceManager.getService("window")).isSafeModeEnabled();
1579 } catch (RemoteException e) {
1580 // Shouldn't happen!
1581 }
1582 return false;
1583 }
Jim Millera4edd152012-01-06 18:24:04 -08001584
Jim Millerf45bb402013-08-20 18:58:32 -07001585 /**
1586 * Determine whether the user has selected any non-system widgets in keyguard
1587 *
1588 * @return true if widgets have been selected
1589 */
1590 public boolean hasWidgetsEnabledInKeyguard(int userid) {
1591 int widgets[] = getAppWidgets(userid);
1592 for (int i = 0; i < widgets.length; i++) {
1593 if (widgets[i] > 0) {
1594 return true;
1595 }
1596 }
1597 return false;
1598 }
1599
1600 public boolean getWidgetsEnabled() {
1601 return getWidgetsEnabled(getCurrentOrCallingUserId());
1602 }
1603
1604 public boolean getWidgetsEnabled(int userId) {
1605 return getBoolean(LOCKSCREEN_WIDGETS_ENABLED, false, userId);
1606 }
1607
1608 public void setWidgetsEnabled(boolean enabled) {
1609 setWidgetsEnabled(enabled, getCurrentOrCallingUserId());
1610 }
1611
1612 public void setWidgetsEnabled(boolean enabled, int userId) {
1613 setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId);
1614 }
1615
Adrian Roos82142c22014-03-27 14:56:59 +01001616 public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents) {
1617 setEnabledTrustAgents(activeTrustAgents, getCurrentOrCallingUserId());
1618 }
1619
1620 public List<ComponentName> getEnabledTrustAgents() {
1621 return getEnabledTrustAgents(getCurrentOrCallingUserId());
1622 }
1623
1624 public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1625 StringBuilder sb = new StringBuilder();
1626 for (ComponentName cn : activeTrustAgents) {
1627 if (sb.length() > 0) {
1628 sb.append(',');
1629 }
1630 sb.append(cn.flattenToShortString());
1631 }
1632 setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1633 getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
1634 }
1635
1636 public List<ComponentName> getEnabledTrustAgents(int userId) {
1637 String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1638 if (TextUtils.isEmpty(serialized)) {
1639 return null;
1640 }
1641 String[] split = serialized.split(",");
1642 ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1643 for (String s : split) {
1644 if (!TextUtils.isEmpty(s)) {
1645 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1646 }
1647 }
1648 return activeTrustAgents;
1649 }
Adrian Roos2c12cfa2014-06-25 23:28:53 +02001650
1651 /**
1652 * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
1653 */
1654 public void requireCredentialEntry(int userId) {
1655 getTrustManager().reportRequireCredentialEntry(userId);
1656 }
Adrian Roos4b9e3242014-08-20 23:36:25 +02001657
1658 private void onAfterChangingPassword() {
1659 getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
1660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661}