1 /*
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 
17 package com.android.internal.widget;
18 
19 import android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.app.admin.DevicePolicyManager;
22 import android.app.admin.PasswordMetrics;
23 import android.app.trust.IStrongAuthTracker;
24 import android.app.trust.TrustManager;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.pm.UserInfo;
29 import android.os.AsyncTask;
30 import android.os.Handler;
31 import android.os.IBinder;
32 import android.os.Looper;
33 import android.os.Message;
34 import android.os.RemoteException;
35 import android.os.ServiceManager;
36 import android.os.SystemClock;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.os.storage.IStorageManager;
40 import android.os.storage.StorageManager;
41 import android.provider.Settings;
42 import android.text.TextUtils;
43 import android.util.Log;
44 import android.util.SparseIntArray;
45 
46 import com.android.internal.annotations.VisibleForTesting;
47 import com.google.android.collect.Lists;
48 
49 import libcore.util.HexEncoding;
50 
51 import java.lang.annotation.Retention;
52 import java.lang.annotation.RetentionPolicy;
53 import java.nio.charset.StandardCharsets;
54 import java.security.MessageDigest;
55 import java.security.NoSuchAlgorithmException;
56 import java.security.SecureRandom;
57 import java.util.ArrayList;
58 import java.util.Collection;
59 import java.util.List;
60 
61 /**
62  * Utilities for the lock pattern and its settings.
63  */
64 public class LockPatternUtils {
65 
66     private static final String TAG = "LockPatternUtils";
67     private static final boolean DEBUG = false;
68 
69     /**
70      * The key to identify when the lock pattern enabled flag is being accessed for legacy reasons.
71      */
72     public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled";
73 
74     /**
75      * The number of incorrect attempts before which we fall back on an alternative
76      * method of verifying the user, and resetting their lock pattern.
77      */
78     public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
79 
80     /**
81      * The interval of the countdown for showing progress of the lockout.
82      */
83     public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
84 
85 
86     /**
87      * This dictates when we start telling the user that continued failed attempts will wipe
88      * their device.
89      */
90     public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
91 
92     /**
93      * The minimum number of dots in a valid pattern.
94      */
95     public static final int MIN_LOCK_PATTERN_SIZE = 4;
96 
97     /**
98      * The minimum size of a valid password.
99      */
100     public static final int MIN_LOCK_PASSWORD_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      */
107     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
108 
109     public static final int CREDENTIAL_TYPE_NONE = -1;
110 
111     public static final int CREDENTIAL_TYPE_PATTERN = 1;
112 
113     public static final int CREDENTIAL_TYPE_PASSWORD = 2;
114 
115     @Deprecated
116     public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
117     public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
118     public final static String LOCKOUT_ATTEMPT_TIMEOUT_MS = "lockscreen.lockoutattempttimeoutmss";
119     public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
120     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
121     @Deprecated
122     public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
123     public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
124     public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
125     public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
126     @Deprecated
127     public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
128             = "lockscreen.biometric_weak_fallback";
129     @Deprecated
130     public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
131             = "lockscreen.biometricweakeverchosen";
132     public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
133             = "lockscreen.power_button_instantly_locks";
134     @Deprecated
135     public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
136 
137     public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
138 
139     private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
140     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
141             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
142 
143     private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
144 
145     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
146     private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
147 
148     public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
149     public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
150     public static final String SYNTHETIC_PASSWORD_KEY_PREFIX = "synthetic_password_";
151 
152     public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle";
153     public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp";
154 
155     private final Context mContext;
156     private final ContentResolver mContentResolver;
157     private DevicePolicyManager mDevicePolicyManager;
158     private ILockSettings mLockSettingsService;
159     private UserManager mUserManager;
160     private final Handler mHandler;
161 
162     /**
163      * Use {@link TrustManager#isTrustUsuallyManaged(int)}.
164      *
165      * This returns the lazily-peristed value and should only be used by TrustManagerService.
166      */
isTrustUsuallyManaged(int userId)167     public boolean isTrustUsuallyManaged(int userId) {
168         if (!(mLockSettingsService instanceof ILockSettings.Stub)) {
169             throw new IllegalStateException("May only be called by TrustManagerService. "
170                     + "Use TrustManager.isTrustUsuallyManaged()");
171         }
172         try {
173             return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId);
174         } catch (RemoteException e) {
175             return false;
176         }
177     }
178 
setTrustUsuallyManaged(boolean managed, int userId)179     public void setTrustUsuallyManaged(boolean managed, int userId) {
180         try {
181             getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId);
182         } catch (RemoteException e) {
183             // System dead.
184         }
185     }
186 
userPresent(int userId)187     public void userPresent(int userId) {
188         try {
189             getLockSettings().userPresent(userId);
190         } catch (RemoteException e) {
191             throw e.rethrowFromSystemServer();
192         }
193     }
194 
195     public static final class RequestThrottledException extends Exception {
196         private int mTimeoutMs;
RequestThrottledException(int timeoutMs)197         public RequestThrottledException(int timeoutMs) {
198             mTimeoutMs = timeoutMs;
199         }
200 
201         /**
202          * @return The amount of time in ms before another request may
203          * be executed
204          */
getTimeoutMs()205         public int getTimeoutMs() {
206             return mTimeoutMs;
207         }
208 
209     }
210 
getDevicePolicyManager()211     public DevicePolicyManager getDevicePolicyManager() {
212         if (mDevicePolicyManager == null) {
213             mDevicePolicyManager =
214                 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
215             if (mDevicePolicyManager == null) {
216                 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
217                         new IllegalStateException("Stack trace:"));
218             }
219         }
220         return mDevicePolicyManager;
221     }
222 
getUserManager()223     private UserManager getUserManager() {
224         if (mUserManager == null) {
225             mUserManager = UserManager.get(mContext);
226         }
227         return mUserManager;
228     }
229 
getTrustManager()230     private TrustManager getTrustManager() {
231         TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
232         if (trust == null) {
233             Log.e(TAG, "Can't get TrustManagerService: is it running?",
234                     new IllegalStateException("Stack trace:"));
235         }
236         return trust;
237     }
238 
LockPatternUtils(Context context)239     public LockPatternUtils(Context context) {
240         mContext = context;
241         mContentResolver = context.getContentResolver();
242 
243         Looper looper = Looper.myLooper();
244         mHandler = looper != null ? new Handler(looper) : null;
245     }
246 
247     @VisibleForTesting
getLockSettings()248     public ILockSettings getLockSettings() {
249         if (mLockSettingsService == null) {
250             ILockSettings service = ILockSettings.Stub.asInterface(
251                     ServiceManager.getService("lock_settings"));
252             mLockSettingsService = service;
253         }
254         return mLockSettingsService;
255     }
256 
getRequestedMinimumPasswordLength(int userId)257     public int getRequestedMinimumPasswordLength(int userId) {
258         return getDevicePolicyManager().getPasswordMinimumLength(null, userId);
259     }
260 
261     /**
262      * Gets the device policy password mode. If the mode is non-specific, returns
263      * MODE_PATTERN which allows the user to choose anything.
264      */
getRequestedPasswordQuality(int userId)265     public int getRequestedPasswordQuality(int userId) {
266         return getDevicePolicyManager().getPasswordQuality(null, userId);
267     }
268 
getRequestedPasswordHistoryLength(int userId)269     private int getRequestedPasswordHistoryLength(int userId) {
270         return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
271     }
272 
getRequestedPasswordMinimumLetters(int userId)273     public int getRequestedPasswordMinimumLetters(int userId) {
274         return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
275     }
276 
getRequestedPasswordMinimumUpperCase(int userId)277     public int getRequestedPasswordMinimumUpperCase(int userId) {
278         return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
279     }
280 
getRequestedPasswordMinimumLowerCase(int userId)281     public int getRequestedPasswordMinimumLowerCase(int userId) {
282         return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
283     }
284 
getRequestedPasswordMinimumNumeric(int userId)285     public int getRequestedPasswordMinimumNumeric(int userId) {
286         return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
287     }
288 
getRequestedPasswordMinimumSymbols(int userId)289     public int getRequestedPasswordMinimumSymbols(int userId) {
290         return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
291     }
292 
getRequestedPasswordMinimumNonLetter(int userId)293     public int getRequestedPasswordMinimumNonLetter(int userId) {
294         return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
295     }
296 
reportFailedPasswordAttempt(int userId)297     public void reportFailedPasswordAttempt(int userId) {
298         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
299         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
300     }
301 
reportSuccessfulPasswordAttempt(int userId)302     public void reportSuccessfulPasswordAttempt(int userId) {
303         getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
304         getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
305     }
306 
reportPasswordLockout(int timeoutMs, int userId)307     public void reportPasswordLockout(int timeoutMs, int userId) {
308         getTrustManager().reportUnlockLockout(timeoutMs, userId);
309     }
310 
getCurrentFailedPasswordAttempts(int userId)311     public int getCurrentFailedPasswordAttempts(int userId) {
312         return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId);
313     }
314 
getMaximumFailedPasswordsForWipe(int userId)315     public int getMaximumFailedPasswordsForWipe(int userId) {
316         return getDevicePolicyManager().getMaximumFailedPasswordsForWipe(
317                 null /* componentName */, userId);
318     }
319 
verifyCredential(String credential, int type, long challenge, int userId)320     private byte[] verifyCredential(String credential, int type, long challenge, int userId)
321             throws RequestThrottledException {
322         try {
323             VerifyCredentialResponse response = getLockSettings().verifyCredential(credential,
324                     type, challenge, userId);
325             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
326                 return response.getPayload();
327             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
328                 throw new RequestThrottledException(response.getTimeout());
329             } else {
330                 return null;
331             }
332         } catch (RemoteException re) {
333             return null;
334         }
335     }
336 
checkCredential(String credential, int type, int userId, @Nullable CheckCredentialProgressCallback progressCallback)337     private boolean checkCredential(String credential, int type, int userId,
338             @Nullable CheckCredentialProgressCallback progressCallback)
339             throws RequestThrottledException {
340         try {
341             VerifyCredentialResponse response = getLockSettings().checkCredential(credential, type,
342                     userId, wrapCallback(progressCallback));
343 
344             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
345                 return true;
346             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
347                 throw new RequestThrottledException(response.getTimeout());
348             } else {
349                 return false;
350             }
351         } catch (RemoteException re) {
352             return false;
353         }
354     }
355 
356     /**
357      * Check to see if a pattern matches the saved pattern.
358      * If pattern matches, return an opaque attestation that the challenge
359      * was verified.
360      *
361      * @param pattern The pattern to check.
362      * @param challenge The challenge to verify against the pattern
363      * @return the attestation that the challenge was verified, or null.
364      */
verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)365     public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
366             throws RequestThrottledException {
367         throwIfCalledOnMainThread();
368         return verifyCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
369                 userId);
370     }
371 
372     /**
373      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
374      * always returns true.
375      * @param pattern The pattern to check.
376      * @return Whether the pattern matches the stored one.
377      */
checkPattern(List<LockPatternView.Cell> pattern, int userId)378     public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
379             throws RequestThrottledException {
380         return checkPattern(pattern, userId, null /* progressCallback */);
381     }
382 
383     /**
384      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
385      * always returns true.
386      * @param pattern The pattern to check.
387      * @return Whether the pattern matches the stored one.
388      */
checkPattern(List<LockPatternView.Cell> pattern, int userId, @Nullable CheckCredentialProgressCallback progressCallback)389     public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
390             @Nullable CheckCredentialProgressCallback progressCallback)
391             throws RequestThrottledException {
392         throwIfCalledOnMainThread();
393         return checkCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN, userId,
394                 progressCallback);
395     }
396 
397     /**
398      * Check to see if a password matches the saved password.
399      * If password matches, return an opaque attestation that the challenge
400      * was verified.
401      *
402      * @param password The password to check.
403      * @param challenge The challenge to verify against the password
404      * @return the attestation that the challenge was verified, or null.
405      */
verifyPassword(String password, long challenge, int userId)406     public byte[] verifyPassword(String password, long challenge, int userId)
407             throws RequestThrottledException {
408         throwIfCalledOnMainThread();
409         return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId);
410     }
411 
412 
413     /**
414      * Check to see if a password matches the saved password.
415      * If password matches, return an opaque attestation that the challenge
416      * was verified.
417      *
418      * @param password The password to check.
419      * @param challenge The challenge to verify against the password
420      * @return the attestation that the challenge was verified, or null.
421      */
verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId)422     public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
423             int userId) throws RequestThrottledException {
424         throwIfCalledOnMainThread();
425         try {
426             VerifyCredentialResponse response =
427                     getLockSettings().verifyTiedProfileChallenge(password,
428                             isPattern ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_PASSWORD, challenge,
429                             userId);
430 
431             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
432                 return response.getPayload();
433             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
434                 throw new RequestThrottledException(response.getTimeout());
435             } else {
436                 return null;
437             }
438         } catch (RemoteException re) {
439             return null;
440         }
441     }
442 
443     /**
444      * Check to see if a password matches the saved password.  If no password exists,
445      * always returns true.
446      * @param password The password to check.
447      * @return Whether the password matches the stored one.
448      */
checkPassword(String password, int userId)449     public boolean checkPassword(String password, int userId) throws RequestThrottledException {
450         return checkPassword(password, userId, null /* progressCallback */);
451     }
452 
453     /**
454      * Check to see if a password matches the saved password.  If no password exists,
455      * always returns true.
456      * @param password The password to check.
457      * @return Whether the password matches the stored one.
458      */
checkPassword(String password, int userId, @Nullable CheckCredentialProgressCallback progressCallback)459     public boolean checkPassword(String password, int userId,
460             @Nullable CheckCredentialProgressCallback progressCallback)
461             throws RequestThrottledException {
462         throwIfCalledOnMainThread();
463         return checkCredential(password, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
464     }
465 
466     /**
467      * Check to see if vold already has the password.
468      * Note that this also clears vold's copy of the password.
469      * @return Whether the vold password matches or not.
470      */
checkVoldPassword(int userId)471     public boolean checkVoldPassword(int userId) {
472         try {
473             return getLockSettings().checkVoldPassword(userId);
474         } catch (RemoteException re) {
475             return false;
476         }
477     }
478 
479     /**
480      * Check to see if a password matches any of the passwords stored in the
481      * password history.
482      *
483      * @param password The password to check.
484      * @return Whether the password matches any in the history.
485      */
checkPasswordHistory(String password, int userId)486     public boolean checkPasswordHistory(String password, int userId) {
487         String passwordHashString = new String(
488                 passwordToHash(password, userId), StandardCharsets.UTF_8);
489         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
490         if (passwordHistory == null) {
491             return false;
492         }
493         // Password History may be too long...
494         int passwordHashLength = passwordHashString.length();
495         int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
496         if(passwordHistoryLength == 0) {
497             return false;
498         }
499         int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
500                 + passwordHistoryLength - 1;
501         if (passwordHistory.length() > neededPasswordHistoryLength) {
502             passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
503         }
504         return passwordHistory.contains(passwordHashString);
505     }
506 
507     /**
508      * Check to see if the user has stored a lock pattern.
509      * @return Whether a saved pattern exists.
510      */
savedPatternExists(int userId)511     private boolean savedPatternExists(int userId) {
512         try {
513             return getLockSettings().havePattern(userId);
514         } catch (RemoteException re) {
515             return false;
516         }
517     }
518 
519     /**
520      * Check to see if the user has stored a lock pattern.
521      * @return Whether a saved pattern exists.
522      */
savedPasswordExists(int userId)523     private boolean savedPasswordExists(int userId) {
524         try {
525             return getLockSettings().havePassword(userId);
526         } catch (RemoteException re) {
527             return false;
528         }
529     }
530 
531     /**
532      * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
533      * currently cleared.
534      *
535      * @return True if the user has ever chosen a pattern.
536      */
isPatternEverChosen(int userId)537     public boolean isPatternEverChosen(int userId) {
538         return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
539     }
540 
541     /**
542      * Used by device policy manager to validate the current password
543      * information it has.
544      */
getActivePasswordQuality(int userId)545     public int getActivePasswordQuality(int userId) {
546         int quality = getKeyguardStoredPasswordQuality(userId);
547 
548         if (isLockPasswordEnabled(quality, userId)) {
549             // Quality is a password and a password exists. Return the quality.
550             return quality;
551         }
552 
553         if (isLockPatternEnabled(quality, userId)) {
554             // Quality is a pattern and a pattern exists. Return the quality.
555             return quality;
556         }
557 
558         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
559     }
560 
561     /**
562      * Use it to reset keystore without wiping work profile
563      */
resetKeyStore(int userId)564     public void resetKeyStore(int userId) {
565         try {
566             getLockSettings().resetKeyStore(userId);
567         } catch (RemoteException e) {
568             // It should not happen
569             Log.e(TAG, "Couldn't reset keystore " + e);
570         }
571     }
572 
573     /**
574      * Clear any lock pattern or password.
575      */
clearLock(String savedCredential, int userHandle)576     public void clearLock(String savedCredential, int userHandle) {
577         setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
578 
579         try{
580             getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, savedCredential,
581                     userHandle);
582         } catch (RemoteException e) {
583             // well, we tried...
584         }
585 
586         if (userHandle == UserHandle.USER_SYSTEM) {
587             // Set the encryption password to default.
588             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
589             setCredentialRequiredToDecrypt(false);
590         }
591 
592         onAfterChangingPassword(userHandle);
593     }
594 
595     /**
596      * Disable showing lock screen at all for a given user.
597      * This is only meaningful if pattern, pin or password are not set.
598      *
599      * @param disable Disables lock screen when true
600      * @param userId User ID of the user this has effect on
601      */
setLockScreenDisabled(boolean disable, int userId)602     public void setLockScreenDisabled(boolean disable, int userId) {
603         setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
604     }
605 
606     /**
607      * Determine if LockScreen is disabled for the current user. This is used to decide whether
608      * LockScreen is shown after reboot or after screen timeout / short press on power.
609      *
610      * @return true if lock screen is disabled
611      */
isLockScreenDisabled(int userId)612     public boolean isLockScreenDisabled(int userId) {
613         if (isSecure(userId)) {
614             return false;
615         }
616         boolean disabledByDefault = mContext.getResources().getBoolean(
617                 com.android.internal.R.bool.config_disableLockscreenByDefault);
618         boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
619         return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
620                 || (disabledByDefault && !isSystemUser);
621     }
622 
623     /**
624      * Save a lock pattern.
625      * @param pattern The new pattern to save.
626      * @param userId the user whose pattern is to be saved.
627      */
saveLockPattern(List<LockPatternView.Cell> pattern, int userId)628     public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
629         this.saveLockPattern(pattern, null, userId);
630     }
631     /**
632      * Save a lock pattern.
633      * @param pattern The new pattern to save.
634      * @param savedPattern The previously saved pattern, converted to String format
635      * @param userId the user whose pattern is to be saved.
636      */
saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId)637     public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId) {
638         try {
639             if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
640                 throw new IllegalArgumentException("pattern must not be null and at least "
641                         + MIN_LOCK_PATTERN_SIZE + " dots long.");
642             }
643 
644             setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
645             getLockSettings().setLockCredential(patternToString(pattern), CREDENTIAL_TYPE_PATTERN,
646                     savedPattern, userId);
647 
648             // Update the device encryption password.
649             if (userId == UserHandle.USER_SYSTEM
650                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
651                 if (!shouldEncryptWithCredentials(true)) {
652                     clearEncryptionPassword();
653                 } else {
654                     String stringPattern = patternToString(pattern);
655                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
656                 }
657             }
658 
659             setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
660             onAfterChangingPassword(userId);
661         } catch (RemoteException re) {
662             Log.e(TAG, "Couldn't save lock pattern " + re);
663         }
664     }
665 
updateCryptoUserInfo(int userId)666     private void updateCryptoUserInfo(int userId) {
667         if (userId != UserHandle.USER_SYSTEM) {
668             return;
669         }
670 
671         final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : "";
672 
673         IBinder service = ServiceManager.getService("mount");
674         if (service == null) {
675             Log.e(TAG, "Could not find the mount service to update the user info");
676             return;
677         }
678 
679         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
680         try {
681             Log.d(TAG, "Setting owner info");
682             storageManager.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
683         } catch (RemoteException e) {
684             Log.e(TAG, "Error changing user info", e);
685         }
686     }
687 
setOwnerInfo(String info, int userId)688     public void setOwnerInfo(String info, int userId) {
689         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
690         updateCryptoUserInfo(userId);
691     }
692 
setOwnerInfoEnabled(boolean enabled, int userId)693     public void setOwnerInfoEnabled(boolean enabled, int userId) {
694         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
695         updateCryptoUserInfo(userId);
696     }
697 
getOwnerInfo(int userId)698     public String getOwnerInfo(int userId) {
699         return getString(LOCK_SCREEN_OWNER_INFO, userId);
700     }
701 
isOwnerInfoEnabled(int userId)702     public boolean isOwnerInfoEnabled(int userId) {
703         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
704     }
705 
706     /**
707      * Sets the device owner information. If the information is {@code null} or empty then the
708      * device owner info is cleared.
709      *
710      * @param info Device owner information which will be displayed instead of the user
711      * owner info.
712      */
setDeviceOwnerInfo(String info)713     public void setDeviceOwnerInfo(String info) {
714         if (info != null && info.isEmpty()) {
715             info = null;
716         }
717 
718         setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM);
719     }
720 
getDeviceOwnerInfo()721     public String getDeviceOwnerInfo() {
722         return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM);
723     }
724 
isDeviceOwnerInfoEnabled()725     public boolean isDeviceOwnerInfoEnabled() {
726         return getDeviceOwnerInfo() != null;
727     }
728 
729     /** Update the encryption password if it is enabled **/
updateEncryptionPassword(final int type, final String password)730     private void updateEncryptionPassword(final int type, final String password) {
731         if (!isDeviceEncryptionEnabled()) {
732             return;
733         }
734         final IBinder service = ServiceManager.getService("mount");
735         if (service == null) {
736             Log.e(TAG, "Could not find the mount service to update the encryption password");
737             return;
738         }
739 
740         new AsyncTask<Void, Void, Void>() {
741             @Override
742             protected Void doInBackground(Void... dummy) {
743                 IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
744                 try {
745                     storageManager.changeEncryptionPassword(type, password);
746                 } catch (RemoteException e) {
747                     Log.e(TAG, "Error changing encryption password", e);
748                 }
749                 return null;
750             }
751         }.execute();
752     }
753 
754     /**
755      * Save a lock password.  Does not ensure that the password is as good
756      * as the requested mode, but will adjust the mode to be as good as the
757      * password.
758      * @param password The password to save
759      * @param savedPassword The previously saved lock password, or null if none
760      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
761      * @param userHandle The userId of the user to change the password for
762      */
saveLockPassword(String password, String savedPassword, int quality, int userHandle)763     public void saveLockPassword(String password, String savedPassword, int quality,
764             int userHandle) {
765         try {
766             if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
767                 throw new IllegalArgumentException("password must not be null and at least "
768                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
769             }
770 
771             final int computedQuality = PasswordMetrics.computeForPassword(password).quality;
772             setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
773             getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
774                     userHandle);
775 
776             updateEncryptionPasswordIfNeeded(password, computedQuality, userHandle);
777             updatePasswordHistory(password, userHandle);
778         } catch (RemoteException re) {
779             // Cant do much
780             Log.e(TAG, "Unable to save lock password " + re);
781         }
782     }
783 
784     /**
785      * Update device encryption password if calling user is USER_SYSTEM and device supports
786      * encryption.
787      */
updateEncryptionPasswordIfNeeded(String password, int quality, int userHandle)788     private void updateEncryptionPasswordIfNeeded(String password, int quality, int userHandle) {
789         // Update the device encryption password.
790         if (userHandle == UserHandle.USER_SYSTEM
791                 && LockPatternUtils.isDeviceEncryptionEnabled()) {
792             if (!shouldEncryptWithCredentials(true)) {
793                 clearEncryptionPassword();
794             } else {
795                 boolean numeric = quality == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
796                 boolean numericComplex = quality
797                         == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
798                 int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
799                         : StorageManager.CRYPT_TYPE_PASSWORD;
800                 updateEncryptionPassword(type, password);
801             }
802         }
803     }
804 
updatePasswordHistory(String password, int userHandle)805     private void updatePasswordHistory(String password, int userHandle) {
806 
807         // Add the password to the password history. We assume all
808         // password hashes have the same length for simplicity of implementation.
809         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
810         if (passwordHistory == null) {
811             passwordHistory = "";
812         }
813         int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
814         if (passwordHistoryLength == 0) {
815             passwordHistory = "";
816         } else {
817             byte[] hash = passwordToHash(password, userHandle);
818             passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
819             // Cut it to contain passwordHistoryLength hashes
820             // and passwordHistoryLength -1 commas.
821             passwordHistory = passwordHistory.substring(0, Math.min(hash.length
822                     * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
823                     .length()));
824         }
825         setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
826         onAfterChangingPassword(userHandle);
827     }
828 
829     /**
830      * Determine if the device supports encryption, even if it's set to default. This
831      * differs from isDeviceEncrypted() in that it returns true even if the device is
832      * encrypted with the default password.
833      * @return true if device encryption is enabled
834      */
isDeviceEncryptionEnabled()835     public static boolean isDeviceEncryptionEnabled() {
836         return StorageManager.isEncrypted();
837     }
838 
839     /**
840      * Determine if the device is file encrypted
841      * @return true if device is file encrypted
842      */
isFileEncryptionEnabled()843     public static boolean isFileEncryptionEnabled() {
844         return StorageManager.isFileEncryptedNativeOrEmulated();
845     }
846 
847     /**
848      * Clears the encryption password.
849      */
clearEncryptionPassword()850     public void clearEncryptionPassword() {
851         updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
852     }
853 
854     /**
855      * Retrieves the quality mode for {@param userHandle}.
856      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
857      *
858      * @return stored password quality
859      */
getKeyguardStoredPasswordQuality(int userHandle)860     public int getKeyguardStoredPasswordQuality(int userHandle) {
861         return (int) getLong(PASSWORD_TYPE_KEY,
862                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
863     }
864 
865     /**
866      * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
867      * for user handles that do not belong to a managed profile.
868      *
869      * @param userHandle Managed profile user id
870      * @param enabled True if separate challenge is enabled
871      * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
872      *            true
873      */
setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, String managedUserPassword)874     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
875             String managedUserPassword) {
876         UserInfo info = getUserManager().getUserInfo(userHandle);
877         if (info.isManagedProfile()) {
878             try {
879                 getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
880                         managedUserPassword);
881                 onAfterChangingPassword(userHandle);
882             } catch (RemoteException e) {
883                 Log.e(TAG, "Couldn't update work profile challenge enabled");
884             }
885         }
886     }
887 
888     /**
889      * Retrieves whether the Separate Profile Challenge is enabled for this {@param userHandle}.
890      */
isSeparateProfileChallengeEnabled(int userHandle)891     public boolean isSeparateProfileChallengeEnabled(int userHandle) {
892         UserInfo info = getUserManager().getUserInfo(userHandle);
893         if (info == null || !info.isManagedProfile()) {
894             return false;
895         }
896         try {
897             return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
898         } catch (RemoteException e) {
899             Log.e(TAG, "Couldn't get separate profile challenge enabled");
900             // Default value is false
901             return false;
902         }
903     }
904 
905     /**
906      * Retrieves whether the current DPM allows use of the Profile Challenge.
907      */
isSeparateProfileChallengeAllowed(int userHandle)908     public boolean isSeparateProfileChallengeAllowed(int userHandle) {
909         UserInfo info = getUserManager().getUserInfo(userHandle);
910         if (info == null || !info.isManagedProfile()) {
911             return false;
912         }
913         return getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle);
914     }
915 
916     /**
917      * Retrieves whether the current profile and device locks can be unified.
918      */
isSeparateProfileChallengeAllowedToUnify(int userHandle)919     public boolean isSeparateProfileChallengeAllowedToUnify(int userHandle) {
920         return getDevicePolicyManager().isProfileActivePasswordSufficientForParent(userHandle);
921     }
922 
923     /**
924      * Deserialize a pattern.
925      * @param string The pattern serialized with {@link #patternToString}
926      * @return The pattern.
927      */
stringToPattern(String string)928     public static List<LockPatternView.Cell> stringToPattern(String string) {
929         if (string == null) {
930             return null;
931         }
932 
933         List<LockPatternView.Cell> result = Lists.newArrayList();
934 
935         final byte[] bytes = string.getBytes();
936         for (int i = 0; i < bytes.length; i++) {
937             byte b = (byte) (bytes[i] - '1');
938             result.add(LockPatternView.Cell.of(b / 3, b % 3));
939         }
940         return result;
941     }
942 
943     /**
944      * Serialize a pattern.
945      * @param pattern The pattern.
946      * @return The pattern in string form.
947      */
patternToString(List<LockPatternView.Cell> pattern)948     public static String patternToString(List<LockPatternView.Cell> pattern) {
949         if (pattern == null) {
950             return "";
951         }
952         final int patternSize = pattern.size();
953 
954         byte[] res = new byte[patternSize];
955         for (int i = 0; i < patternSize; i++) {
956             LockPatternView.Cell cell = pattern.get(i);
957             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
958         }
959         return new String(res);
960     }
961 
patternStringToBaseZero(String pattern)962     public static String patternStringToBaseZero(String pattern) {
963         if (pattern == null) {
964             return "";
965         }
966         final int patternSize = pattern.length();
967 
968         byte[] res = new byte[patternSize];
969         final byte[] bytes = pattern.getBytes();
970         for (int i = 0; i < patternSize; i++) {
971             res[i] = (byte) (bytes[i] - '1');
972         }
973         return new String(res);
974     }
975 
976     /*
977      * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
978      * at least a second level of protection. First level is that the file
979      * is in a location only readable by the system process.
980      * @param pattern the gesture pattern.
981      * @return the hash of the pattern in a byte array.
982      */
patternToHash(List<LockPatternView.Cell> pattern)983     public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
984         if (pattern == null) {
985             return null;
986         }
987 
988         final int patternSize = pattern.size();
989         byte[] res = new byte[patternSize];
990         for (int i = 0; i < patternSize; i++) {
991             LockPatternView.Cell cell = pattern.get(i);
992             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
993         }
994         try {
995             MessageDigest md = MessageDigest.getInstance("SHA-1");
996             byte[] hash = md.digest(res);
997             return hash;
998         } catch (NoSuchAlgorithmException nsa) {
999             return res;
1000         }
1001     }
1002 
getSalt(int userId)1003     private String getSalt(int userId) {
1004         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
1005         if (salt == 0) {
1006             try {
1007                 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
1008                 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1009                 Log.v(TAG, "Initialized lock password salt for user: " + userId);
1010             } catch (NoSuchAlgorithmException e) {
1011                 // Throw an exception rather than storing a password we'll never be able to recover
1012                 throw new IllegalStateException("Couldn't get SecureRandom number", e);
1013             }
1014         }
1015         return Long.toHexString(salt);
1016     }
1017 
1018     /*
1019      * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1020      * Not the most secure, but it is at least a second level of protection. First level is that
1021      * the file is in a location only readable by the system process.
1022      *
1023      * @param password the gesture pattern.
1024      *
1025      * @return the hash of the pattern in a byte array.
1026      */
passwordToHash(String password, int userId)1027     public byte[] passwordToHash(String password, int userId) {
1028         if (password == null) {
1029             return null;
1030         }
1031 
1032         try {
1033             byte[] saltedPassword = (password + getSalt(userId)).getBytes();
1034             byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
1035             byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
1036 
1037             byte[] combined = new byte[sha1.length + md5.length];
1038             System.arraycopy(sha1, 0, combined, 0, sha1.length);
1039             System.arraycopy(md5, 0, combined, sha1.length, md5.length);
1040 
1041             final char[] hexEncoded = HexEncoding.encode(combined);
1042             return new String(hexEncoded).getBytes(StandardCharsets.UTF_8);
1043         } catch (NoSuchAlgorithmException e) {
1044             throw new AssertionError("Missing digest algorithm: ", e);
1045         }
1046     }
1047 
1048     /**
1049      * @param userId the user for which to report the value
1050      * @return Whether the lock screen is secured.
1051      */
isSecure(int userId)1052     public boolean isSecure(int userId) {
1053         int mode = getKeyguardStoredPasswordQuality(userId);
1054         return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
1055     }
1056 
isLockPasswordEnabled(int userId)1057     public boolean isLockPasswordEnabled(int userId) {
1058         return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1059     }
1060 
isLockPasswordEnabled(int mode, int userId)1061     private boolean isLockPasswordEnabled(int mode, int userId) {
1062         final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1063                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1064                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1065                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1066                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
1067                 || mode == DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
1068         return passwordEnabled && savedPasswordExists(userId);
1069     }
1070 
1071     /**
1072      * @return Whether the lock pattern is enabled
1073      */
isLockPatternEnabled(int userId)1074     public boolean isLockPatternEnabled(int userId) {
1075         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1076     }
1077 
1078     @Deprecated
isLegacyLockPatternEnabled(int userId)1079     public boolean isLegacyLockPatternEnabled(int userId) {
1080         // Note: this value should default to {@code true} to avoid any reset that might result.
1081         // We must use a special key to read this value, since it will by default return the value
1082         // based on the new logic.
1083         return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
1084     }
1085 
1086     @Deprecated
setLegacyLockPatternEnabled(int userId)1087     public void setLegacyLockPatternEnabled(int userId) {
1088         setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
1089     }
1090 
isLockPatternEnabled(int mode, int userId)1091     private boolean isLockPatternEnabled(int mode, int userId) {
1092         return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
1093                 && savedPatternExists(userId);
1094     }
1095 
1096     /**
1097      * @return Whether the visible pattern is enabled.
1098      */
isVisiblePatternEnabled(int userId)1099     public boolean isVisiblePatternEnabled(int userId) {
1100         return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
1101     }
1102 
1103     /**
1104      * Set whether the visible pattern is enabled.
1105      */
setVisiblePatternEnabled(boolean enabled, int userId)1106     public void setVisiblePatternEnabled(boolean enabled, int userId) {
1107         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
1108 
1109         // Update for crypto if owner
1110         if (userId != UserHandle.USER_SYSTEM) {
1111             return;
1112         }
1113 
1114         IBinder service = ServiceManager.getService("mount");
1115         if (service == null) {
1116             Log.e(TAG, "Could not find the mount service to update the user info");
1117             return;
1118         }
1119 
1120         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1121         try {
1122             storageManager.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1123         } catch (RemoteException e) {
1124             Log.e(TAG, "Error changing pattern visible state", e);
1125         }
1126     }
1127 
1128     /**
1129      * Set whether the visible password is enabled for cryptkeeper screen.
1130      */
setVisiblePasswordEnabled(boolean enabled, int userId)1131     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
1132         // Update for crypto if owner
1133         if (userId != UserHandle.USER_SYSTEM) {
1134             return;
1135         }
1136 
1137         IBinder service = ServiceManager.getService("mount");
1138         if (service == null) {
1139             Log.e(TAG, "Could not find the mount service to update the user info");
1140             return;
1141         }
1142 
1143         IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
1144         try {
1145             storageManager.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0");
1146         } catch (RemoteException e) {
1147             Log.e(TAG, "Error changing password visible state", e);
1148         }
1149     }
1150 
1151     /**
1152      * @return Whether tactile feedback for the pattern is enabled.
1153      */
isTactileFeedbackEnabled()1154     public boolean isTactileFeedbackEnabled() {
1155         return Settings.System.getIntForUser(mContentResolver,
1156                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1157     }
1158 
1159     /**
1160      * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1161      * pattern until the deadline has passed.
1162      * @return the chosen deadline.
1163      */
setLockoutAttemptDeadline(int userId, int timeoutMs)1164     public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
1165         final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
1166         setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1167         setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, timeoutMs, userId);
1168         return deadline;
1169     }
1170 
1171     /**
1172      * @return The elapsed time in millis in the future when the user is allowed to
1173      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1174      *   enter a pattern.
1175      */
getLockoutAttemptDeadline(int userId)1176     public long getLockoutAttemptDeadline(int userId) {
1177         long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
1178         final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId);
1179         final long now = SystemClock.elapsedRealtime();
1180         if (deadline < now && deadline != 0) {
1181             // timeout expired
1182             setLong(LOCKOUT_ATTEMPT_DEADLINE, 0, userId);
1183             setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0, userId);
1184             return 0L;
1185         }
1186 
1187         if (deadline > (now + timeoutMs)) {
1188             // device was rebooted, set new deadline
1189             deadline = now + timeoutMs;
1190             setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1191         }
1192 
1193         return deadline;
1194     }
1195 
getBoolean(String secureSettingKey, boolean defaultValue, int userId)1196     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1197         try {
1198             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1199         } catch (RemoteException re) {
1200             return defaultValue;
1201         }
1202     }
1203 
setBoolean(String secureSettingKey, boolean enabled, int userId)1204     private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1205         try {
1206             getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1207         } catch (RemoteException re) {
1208             // What can we do?
1209             Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1210         }
1211     }
1212 
getLong(String secureSettingKey, long defaultValue, int userHandle)1213     private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1214         try {
1215             return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1216         } catch (RemoteException re) {
1217             return defaultValue;
1218         }
1219     }
1220 
setLong(String secureSettingKey, long value, int userHandle)1221     private void setLong(String secureSettingKey, long value, int userHandle) {
1222         try {
1223             getLockSettings().setLong(secureSettingKey, value, userHandle);
1224         } catch (RemoteException re) {
1225             // What can we do?
1226             Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1227         }
1228     }
1229 
getString(String secureSettingKey, int userHandle)1230     private String getString(String secureSettingKey, int userHandle) {
1231         try {
1232             return getLockSettings().getString(secureSettingKey, null, userHandle);
1233         } catch (RemoteException re) {
1234             return null;
1235         }
1236     }
1237 
setString(String secureSettingKey, String value, int userHandle)1238     private void setString(String secureSettingKey, String value, int userHandle) {
1239         try {
1240             getLockSettings().setString(secureSettingKey, value, userHandle);
1241         } catch (RemoteException re) {
1242             // What can we do?
1243             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1244         }
1245     }
1246 
setPowerButtonInstantlyLocks(boolean enabled, int userId)1247     public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
1248         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
1249     }
1250 
getPowerButtonInstantlyLocks(int userId)1251     public boolean getPowerButtonInstantlyLocks(int userId) {
1252         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
1253     }
1254 
setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1255     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1256         StringBuilder sb = new StringBuilder();
1257         for (ComponentName cn : activeTrustAgents) {
1258             if (sb.length() > 0) {
1259                 sb.append(',');
1260             }
1261             sb.append(cn.flattenToShortString());
1262         }
1263         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1264         getTrustManager().reportEnabledTrustAgentsChanged(userId);
1265     }
1266 
getEnabledTrustAgents(int userId)1267     public List<ComponentName> getEnabledTrustAgents(int userId) {
1268         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1269         if (TextUtils.isEmpty(serialized)) {
1270             return null;
1271         }
1272         String[] split = serialized.split(",");
1273         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1274         for (String s : split) {
1275             if (!TextUtils.isEmpty(s)) {
1276                 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1277             }
1278         }
1279         return activeTrustAgents;
1280     }
1281 
1282     /**
1283      * Disable trust until credentials have been entered for user {@param userId}.
1284      *
1285      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1286      *
1287      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1288      */
requireCredentialEntry(int userId)1289     public void requireCredentialEntry(int userId) {
1290         requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
1291     }
1292 
1293     /**
1294      * Requests strong authentication for user {@param userId}.
1295      *
1296      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1297      *
1298      * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
1299      *                         the reason for and the strength of the requested authentication.
1300      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1301      */
requireStrongAuth(@trongAuthTracker.StrongAuthFlags int strongAuthReason, int userId)1302     public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
1303             int userId) {
1304         try {
1305             getLockSettings().requireStrongAuth(strongAuthReason, userId);
1306         } catch (RemoteException e) {
1307             Log.e(TAG, "Error while requesting strong auth: " + e);
1308         }
1309     }
1310 
onAfterChangingPassword(int userHandle)1311     private void onAfterChangingPassword(int userHandle) {
1312         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1313     }
1314 
isCredentialRequiredToDecrypt(boolean defaultValue)1315     public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1316         final int value = Settings.Global.getInt(mContentResolver,
1317                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1318         return value == -1 ? defaultValue : (value != 0);
1319     }
1320 
setCredentialRequiredToDecrypt(boolean required)1321     public void setCredentialRequiredToDecrypt(boolean required) {
1322         if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
1323             throw new IllegalStateException(
1324                     "Only the system or primary user may call setCredentialRequiredForDecrypt()");
1325         }
1326 
1327         if (isDeviceEncryptionEnabled()){
1328             Settings.Global.putInt(mContext.getContentResolver(),
1329                Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1330         }
1331     }
1332 
isDoNotAskCredentialsOnBootSet()1333     private boolean isDoNotAskCredentialsOnBootSet() {
1334         return getDevicePolicyManager().getDoNotAskCredentialsOnBoot();
1335     }
1336 
shouldEncryptWithCredentials(boolean defaultValue)1337     private boolean shouldEncryptWithCredentials(boolean defaultValue) {
1338         return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
1339     }
1340 
throwIfCalledOnMainThread()1341     private void throwIfCalledOnMainThread() {
1342         if (Looper.getMainLooper().isCurrentThread()) {
1343             throw new IllegalStateException("should not be called from the main thread.");
1344         }
1345     }
1346 
registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1347     public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1348         try {
1349             getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
1350         } catch (RemoteException e) {
1351             throw new RuntimeException("Could not register StrongAuthTracker");
1352         }
1353     }
1354 
unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1355     public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1356         try {
1357             getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
1358         } catch (RemoteException e) {
1359             Log.e(TAG, "Could not unregister StrongAuthTracker", e);
1360         }
1361     }
1362 
1363     /**
1364      * @see StrongAuthTracker#getStrongAuthForUser
1365      */
getStrongAuthForUser(int userId)1366     public int getStrongAuthForUser(int userId) {
1367         try {
1368             return getLockSettings().getStrongAuthForUser(userId);
1369         } catch (RemoteException e) {
1370             Log.e(TAG, "Could not get StrongAuth", e);
1371             return StrongAuthTracker.getDefaultFlags(mContext);
1372         }
1373     }
1374 
1375     /**
1376      * @see StrongAuthTracker#isTrustAllowedForUser
1377      */
isTrustAllowedForUser(int userId)1378     public boolean isTrustAllowedForUser(int userId) {
1379         return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
1380     }
1381 
1382     /**
1383      * @see StrongAuthTracker#isFingerprintAllowedForUser
1384      */
isFingerprintAllowedForUser(int userId)1385     public boolean isFingerprintAllowedForUser(int userId) {
1386         return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0;
1387     }
1388 
wrapCallback( final CheckCredentialProgressCallback callback)1389     private ICheckCredentialProgressCallback wrapCallback(
1390             final CheckCredentialProgressCallback callback) {
1391         if (callback == null) {
1392             return null;
1393         } else {
1394             if (mHandler == null) {
1395                 throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
1396                         + " to use progress callbacks.");
1397             }
1398             return new ICheckCredentialProgressCallback.Stub() {
1399 
1400                 @Override
1401                 public void onCredentialVerified() throws RemoteException {
1402                     mHandler.post(callback::onEarlyMatched);
1403                 }
1404             };
1405         }
1406     }
1407 
1408     /**
1409      * Create an escrow token for the current user, which can later be used to unlock FBE
1410      * or change user password.
1411      *
1412      * After adding, if the user currently has lockscreen password, he will need to perform a
1413      * confirm credential operation in order to activate the token for future use. If the user
1414      * has no secure lockscreen, then the token is activated immediately.
1415      *
1416      * @return a unique 64-bit token handle which is needed to refer to this token later.
1417      */
1418     public long addEscrowToken(byte[] token, int userId) {
1419         try {
1420             return getLockSettings().addEscrowToken(token, userId);
1421         } catch (RemoteException re) {
1422             return 0L;
1423         }
1424     }
1425 
1426     /**
1427      * Remove an escrow token.
1428      * @return true if the given handle refers to a valid token previously returned from
1429      * {@link #addEscrowToken}, whether it's active or not. return false otherwise.
1430      */
1431     public boolean removeEscrowToken(long handle, int userId) {
1432         try {
1433             return getLockSettings().removeEscrowToken(handle, userId);
1434         } catch (RemoteException re) {
1435             return false;
1436         }
1437     }
1438 
1439     /**
1440      * Check if the given escrow token is active or not. Only active token can be used to call
1441      * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken}
1442      */
1443     public boolean isEscrowTokenActive(long handle, int userId) {
1444         try {
1445             return getLockSettings().isEscrowTokenActive(handle, userId);
1446         } catch (RemoteException re) {
1447             return false;
1448         }
1449     }
1450 
1451     public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
1452             byte[] token, int userId) {
1453         try {
1454             if (type != CREDENTIAL_TYPE_NONE) {
1455                 if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
1456                     throw new IllegalArgumentException("password must not be null and at least "
1457                             + "of length " + MIN_LOCK_PASSWORD_SIZE);
1458                 }
1459 
1460                 final int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
1461                 if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
1462                         token, userId)) {
1463                     return false;
1464                 }
1465                 setLong(PASSWORD_TYPE_KEY, Math.max(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
1466                         computedQuality), userId);
1467 
1468                 updateEncryptionPasswordIfNeeded(credential, computedQuality, userId);
1469                 updatePasswordHistory(credential, userId);
1470             } else {
1471                 if (!TextUtils.isEmpty(credential)) {
1472                     throw new IllegalArgumentException("password must be emtpy for NONE type");
1473                 }
1474                 if (!getLockSettings().setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE,
1475                         tokenHandle, token, userId)) {
1476                     return false;
1477                 }
1478                 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
1479                         userId);
1480 
1481                 if (userId == UserHandle.USER_SYSTEM) {
1482                     // Set the encryption password to default.
1483                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
1484                     setCredentialRequiredToDecrypt(false);
1485                 }
1486             }
1487             onAfterChangingPassword(userId);
1488             return true;
1489         } catch (RemoteException re) {
1490             Log.e(TAG, "Unable to save lock password ", re);
1491             re.rethrowFromSystemServer();
1492         }
1493         return false;
1494     }
1495 
1496     public void unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
1497         try {
1498             getLockSettings().unlockUserWithToken(tokenHandle, token, userId);
1499         } catch (RemoteException re) {
1500             Log.e(TAG, "Unable to unlock user with token", re);
1501             re.rethrowFromSystemServer();
1502         }
1503     }
1504 
1505 
1506     /**
1507      * Callback to be notified about progress when checking credentials.
1508      */
1509     public interface CheckCredentialProgressCallback {
1510 
1511         /**
1512          * Called as soon as possible when we know that the credentials match but the user hasn't
1513          * been fully unlocked.
1514          */
1515         void onEarlyMatched();
1516     }
1517 
1518     /**
1519      * Tracks the global strong authentication state.
1520      */
1521     public static class StrongAuthTracker {
1522 
1523         @IntDef(flag = true,
1524                 value = { STRONG_AUTH_NOT_REQUIRED,
1525                         STRONG_AUTH_REQUIRED_AFTER_BOOT,
1526                         STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
1527                         SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
1528                         STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
1529                         STRONG_AUTH_REQUIRED_AFTER_TIMEOUT})
1530         @Retention(RetentionPolicy.SOURCE)
1531         public @interface StrongAuthFlags {}
1532 
1533         /**
1534          * Strong authentication is not required.
1535          */
1536         public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
1537 
1538         /**
1539          * Strong authentication is required because the user has not authenticated since boot.
1540          */
1541         public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
1542 
1543         /**
1544          * Strong authentication is required because a device admin has requested it.
1545          */
1546         public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
1547 
1548         /**
1549          * Some authentication is required because the user has temporarily disabled trust.
1550          */
1551         public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
1552 
1553         /**
1554          * Strong authentication is required because the user has been locked out after too many
1555          * attempts.
1556          */
1557         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
1558 
1559         /**
1560          * Strong authentication is required because it hasn't been used for a time required by
1561          * a device admin.
1562          */
1563         public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10;
1564 
1565         /**
1566          * Strong auth flags that do not prevent fingerprint from being accepted as auth.
1567          *
1568          * If any other flags are set, fingerprint is disabled.
1569          */
1570         private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
1571                 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
1572 
1573         private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
1574         private final H mHandler;
1575         private final int mDefaultStrongAuthFlags;
1576 
1577         public StrongAuthTracker(Context context) {
1578             this(context, Looper.myLooper());
1579         }
1580 
1581         /**
1582          * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
1583          *               will be scheduled.
1584          * @param context the current {@link Context}
1585          */
1586         public StrongAuthTracker(Context context, Looper looper) {
1587             mHandler = new H(looper);
1588             mDefaultStrongAuthFlags = getDefaultFlags(context);
1589         }
1590 
1591         public static @StrongAuthFlags int getDefaultFlags(Context context) {
1592             boolean strongAuthRequired = context.getResources().getBoolean(
1593                     com.android.internal.R.bool.config_strongAuthRequiredOnBoot);
1594             return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED;
1595         }
1596 
1597         /**
1598          * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
1599          * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
1600          * authentication is required.
1601          *
1602          * @param userId the user for whom the state is queried.
1603          */
1604         public @StrongAuthFlags int getStrongAuthForUser(int userId) {
1605             return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags);
1606         }
1607 
1608         /**
1609          * @return true if unlocking with trust alone is allowed for {@param userId} by the current
1610          * strong authentication requirements.
1611          */
1612         public boolean isTrustAllowedForUser(int userId) {
1613             return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
1614         }
1615 
1616         /**
1617          * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
1618          * current strong authentication requirements.
1619          */
1620         public boolean isFingerprintAllowedForUser(int userId) {
1621             return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
1622         }
1623 
1624         /**
1625          * Called when the strong authentication requirements for {@param userId} changed.
1626          */
1627         public void onStrongAuthRequiredChanged(int userId) {
1628         }
1629 
1630         protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1631                 int userId) {
1632             int oldValue = getStrongAuthForUser(userId);
1633             if (strongAuthFlags != oldValue) {
1634                 if (strongAuthFlags == mDefaultStrongAuthFlags) {
1635                     mStrongAuthRequiredForUser.delete(userId);
1636                 } else {
1637                     mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
1638                 }
1639                 onStrongAuthRequiredChanged(userId);
1640             }
1641         }
1642 
1643 
1644         protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
1645             @Override
1646             public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1647                     int userId) {
1648                 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
1649                         strongAuthFlags, userId).sendToTarget();
1650             }
1651         };
1652 
1653         private class H extends Handler {
1654             static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
1655 
1656             public H(Looper looper) {
1657                 super(looper);
1658             }
1659 
1660             @Override
1661             public void handleMessage(Message msg) {
1662                 switch (msg.what) {
1663                     case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
1664                         handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
1665                         break;
1666                 }
1667             }
1668         }
1669     }
1670 
1671     public void enableSyntheticPassword() {
1672         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1L, UserHandle.USER_SYSTEM);
1673     }
1674 
1675     public boolean isSyntheticPasswordEnabled() {
1676         return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0;
1677     }
1678 }
1679