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