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.Manifest;
20 import android.app.ActivityManager;
21 import android.app.ActivityManagerNative;
22 import android.app.admin.DevicePolicyManager;
23 import android.app.trust.TrustManager;
24 import android.bluetooth.BluetoothClass;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.pm.PackageManager;
29 import android.os.AsyncTask;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 import android.os.SystemClock;
34 import android.os.SystemProperties;
35 import android.os.UserHandle;
36 import android.os.storage.IMountService;
37 import android.os.storage.StorageManager;
38 import android.provider.Settings;
39 import android.text.TextUtils;
40 import android.util.Log;
41 
42 import com.google.android.collect.Lists;
43 
44 import java.nio.charset.StandardCharsets;
45 import java.security.MessageDigest;
46 import java.security.NoSuchAlgorithmException;
47 import java.security.SecureRandom;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.List;
51 
52 import libcore.util.HexEncoding;
53 
54 /**
55  * Utilities for the lock pattern and its settings.
56  */
57 public class LockPatternUtils {
58 
59     private static final String TAG = "LockPatternUtils";
60     private static final boolean DEBUG = false;
61 
62     /**
63      * The number of incorrect attempts before which we fall back on an alternative
64      * method of verifying the user, and resetting their lock pattern.
65      */
66     public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
67 
68     /**
69      * The interval of the countdown for showing progress of the lockout.
70      */
71     public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
72 
73 
74     /**
75      * This dictates when we start telling the user that continued failed attempts will wipe
76      * their device.
77      */
78     public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5;
79 
80     /**
81      * The minimum number of dots in a valid pattern.
82      */
83     public static final int MIN_LOCK_PATTERN_SIZE = 4;
84 
85     /**
86      * The minimum size of a valid password.
87      */
88     public static final int MIN_LOCK_PASSWORD_SIZE = 4;
89 
90     /**
91      * The minimum number of dots the user must include in a wrong pattern
92      * attempt for it to be counted against the counts that affect
93      * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
94      */
95     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
96 
97     @Deprecated
98     public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
99     public final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
100     public final static String LOCKOUT_ATTEMPT_TIMEOUT_MS = "lockscreen.lockoutattempttimeoutmss";
101     public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
102     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
103     @Deprecated
104     public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
105     public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
106     public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
107     public final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
108     @Deprecated
109     public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
110             = "lockscreen.biometric_weak_fallback";
111     @Deprecated
112     public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
113             = "lockscreen.biometricweakeverchosen";
114     public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
115             = "lockscreen.power_button_instantly_locks";
116     @Deprecated
117     public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled";
118 
119     public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
120 
121     private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO;
122     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
123             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
124 
125     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
126 
127     // Maximum allowed number of repeated or ordered characters in a sequence before we'll
128     // consider it a complex PIN/password.
129     public static final int MAX_ALLOWED_SEQUENCE = 3;
130 
131     private final Context mContext;
132     private final ContentResolver mContentResolver;
133     private DevicePolicyManager mDevicePolicyManager;
134     private ILockSettings mLockSettingsService;
135 
136 
137     public static final class RequestThrottledException extends Exception {
138         private int mTimeoutMs;
RequestThrottledException(int timeoutMs)139         public RequestThrottledException(int timeoutMs) {
140             mTimeoutMs = timeoutMs;
141         }
142 
143         /**
144          * @return The amount of time in ms before another request may
145          * be executed
146          */
getTimeoutMs()147         public int getTimeoutMs() {
148             return mTimeoutMs;
149         }
150 
151     }
152 
getDevicePolicyManager()153     public DevicePolicyManager getDevicePolicyManager() {
154         if (mDevicePolicyManager == null) {
155             mDevicePolicyManager =
156                 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
157             if (mDevicePolicyManager == null) {
158                 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
159                         new IllegalStateException("Stack trace:"));
160             }
161         }
162         return mDevicePolicyManager;
163     }
164 
getTrustManager()165     private TrustManager getTrustManager() {
166         TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
167         if (trust == null) {
168             Log.e(TAG, "Can't get TrustManagerService: is it running?",
169                     new IllegalStateException("Stack trace:"));
170         }
171         return trust;
172     }
173 
LockPatternUtils(Context context)174     public LockPatternUtils(Context context) {
175         mContext = context;
176         mContentResolver = context.getContentResolver();
177     }
178 
getLockSettings()179     private ILockSettings getLockSettings() {
180         if (mLockSettingsService == null) {
181             ILockSettings service = ILockSettings.Stub.asInterface(
182                     ServiceManager.getService("lock_settings"));
183             mLockSettingsService = service;
184         }
185         return mLockSettingsService;
186     }
187 
getRequestedMinimumPasswordLength(int userId)188     public int getRequestedMinimumPasswordLength(int userId) {
189         return getDevicePolicyManager().getPasswordMinimumLength(null, userId);
190     }
191 
192     /**
193      * Gets the device policy password mode. If the mode is non-specific, returns
194      * MODE_PATTERN which allows the user to choose anything.
195      */
getRequestedPasswordQuality(int userId)196     public int getRequestedPasswordQuality(int userId) {
197         return getDevicePolicyManager().getPasswordQuality(null, userId);
198     }
199 
getRequestedPasswordHistoryLength(int userId)200     private int getRequestedPasswordHistoryLength(int userId) {
201         return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
202     }
203 
getRequestedPasswordMinimumLetters(int userId)204     public int getRequestedPasswordMinimumLetters(int userId) {
205         return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
206     }
207 
getRequestedPasswordMinimumUpperCase(int userId)208     public int getRequestedPasswordMinimumUpperCase(int userId) {
209         return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
210     }
211 
getRequestedPasswordMinimumLowerCase(int userId)212     public int getRequestedPasswordMinimumLowerCase(int userId) {
213         return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
214     }
215 
getRequestedPasswordMinimumNumeric(int userId)216     public int getRequestedPasswordMinimumNumeric(int userId) {
217         return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
218     }
219 
getRequestedPasswordMinimumSymbols(int userId)220     public int getRequestedPasswordMinimumSymbols(int userId) {
221         return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
222     }
223 
getRequestedPasswordMinimumNonLetter(int userId)224     public int getRequestedPasswordMinimumNonLetter(int userId) {
225         return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
226     }
227 
reportFailedPasswordAttempt(int userId)228     public void reportFailedPasswordAttempt(int userId) {
229         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
230         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
231         getTrustManager().reportRequireCredentialEntry(userId);
232     }
233 
reportSuccessfulPasswordAttempt(int userId)234     public void reportSuccessfulPasswordAttempt(int userId) {
235         getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
236         getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
237     }
238 
239     /**
240      * Check to see if a pattern matches the saved pattern.
241      * If pattern matches, return an opaque attestation that the challenge
242      * was verified.
243      *
244      * @param pattern The pattern to check.
245      * @param challenge The challenge to verify against the pattern
246      * @return the attestation that the challenge was verified, or null.
247      */
verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)248     public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
249             throws RequestThrottledException {
250         try {
251             VerifyCredentialResponse response =
252                 getLockSettings().verifyPattern(patternToString(pattern), challenge, userId);
253             if (response == null) {
254                 // Shouldn't happen
255                 return null;
256             }
257 
258             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
259                 return response.getPayload();
260             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
261                 throw new RequestThrottledException(response.getTimeout());
262             } else {
263                 return null;
264             }
265         } catch (RemoteException re) {
266             return null;
267         }
268     }
269 
270     /**
271      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
272      * always returns true.
273      * @param pattern The pattern to check.
274      * @return Whether the pattern matches the stored one.
275      */
checkPattern(List<LockPatternView.Cell> pattern, int userId)276     public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
277             throws RequestThrottledException {
278         try {
279             VerifyCredentialResponse response =
280                     getLockSettings().checkPattern(patternToString(pattern), userId);
281 
282             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
283                 return true;
284             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
285                 throw new RequestThrottledException(response.getTimeout());
286             } else {
287                 return false;
288             }
289         } catch (RemoteException re) {
290             return true;
291         }
292     }
293 
294     /**
295      * Check to see if a password matches the saved password.
296      * If password matches, return an opaque attestation that the challenge
297      * was verified.
298      *
299      * @param password The password to check.
300      * @param challenge The challenge to verify against the password
301      * @return the attestation that the challenge was verified, or null.
302      */
verifyPassword(String password, long challenge, int userId)303     public byte[] verifyPassword(String password, long challenge, int userId)
304             throws RequestThrottledException {
305         try {
306             VerifyCredentialResponse response =
307                     getLockSettings().verifyPassword(password, challenge, userId);
308 
309             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
310                 return response.getPayload();
311             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
312                 throw new RequestThrottledException(response.getTimeout());
313             } else {
314                 return null;
315             }
316         } catch (RemoteException re) {
317             return null;
318         }
319     }
320 
321     /**
322      * Check to see if a password matches the saved password.  If no password exists,
323      * always returns true.
324      * @param password The password to check.
325      * @return Whether the password matches the stored one.
326      */
checkPassword(String password, int userId)327     public boolean checkPassword(String password, int userId) throws RequestThrottledException {
328         try {
329             VerifyCredentialResponse response =
330                     getLockSettings().checkPassword(password, userId);
331             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
332                 return true;
333             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
334                 throw new RequestThrottledException(response.getTimeout());
335             } else {
336                 return false;
337             }
338         } catch (RemoteException re) {
339             return true;
340         }
341     }
342 
343     /**
344      * Check to see if vold already has the password.
345      * Note that this also clears vold's copy of the password.
346      * @return Whether the vold password matches or not.
347      */
checkVoldPassword(int userId)348     public boolean checkVoldPassword(int userId) {
349         try {
350             return getLockSettings().checkVoldPassword(userId);
351         } catch (RemoteException re) {
352             return false;
353         }
354     }
355 
356     /**
357      * Check to see if a password matches any of the passwords stored in the
358      * password history.
359      *
360      * @param password The password to check.
361      * @return Whether the password matches any in the history.
362      */
checkPasswordHistory(String password, int userId)363     public boolean checkPasswordHistory(String password, int userId) {
364         String passwordHashString = new String(
365                 passwordToHash(password, userId), StandardCharsets.UTF_8);
366         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
367         if (passwordHistory == null) {
368             return false;
369         }
370         // Password History may be too long...
371         int passwordHashLength = passwordHashString.length();
372         int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
373         if(passwordHistoryLength == 0) {
374             return false;
375         }
376         int neededPasswordHistoryLength = passwordHashLength * passwordHistoryLength
377                 + passwordHistoryLength - 1;
378         if (passwordHistory.length() > neededPasswordHistoryLength) {
379             passwordHistory = passwordHistory.substring(0, neededPasswordHistoryLength);
380         }
381         return passwordHistory.contains(passwordHashString);
382     }
383 
384     /**
385      * Check to see if the user has stored a lock pattern.
386      * @return Whether a saved pattern exists.
387      */
savedPatternExists(int userId)388     private boolean savedPatternExists(int userId) {
389         try {
390             return getLockSettings().havePattern(userId);
391         } catch (RemoteException re) {
392             return false;
393         }
394     }
395 
396     /**
397      * Check to see if the user has stored a lock pattern.
398      * @return Whether a saved pattern exists.
399      */
savedPasswordExists(int userId)400     private boolean savedPasswordExists(int userId) {
401         try {
402             return getLockSettings().havePassword(userId);
403         } catch (RemoteException re) {
404             return false;
405         }
406     }
407 
408     /**
409      * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
410      * currently cleared.
411      *
412      * @return True if the user has ever chosen a pattern.
413      */
isPatternEverChosen(int userId)414     public boolean isPatternEverChosen(int userId) {
415         return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
416     }
417 
418     /**
419      * Used by device policy manager to validate the current password
420      * information it has.
421      */
getActivePasswordQuality(int userId)422     public int getActivePasswordQuality(int userId) {
423         int quality = getKeyguardStoredPasswordQuality(userId);
424 
425         if (isLockPasswordEnabled(quality, userId)) {
426             // Quality is a password and a password exists. Return the quality.
427             return quality;
428         }
429 
430         if (isLockPatternEnabled(quality, userId)) {
431             // Quality is a pattern and a pattern exists. Return the quality.
432             return quality;
433         }
434 
435         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
436     }
437 
438     /**
439      * Clear any lock pattern or password.
440      */
clearLock(int userHandle)441     public void clearLock(int userHandle) {
442         setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
443 
444         try {
445             getLockSettings().setLockPassword(null, null, userHandle);
446             getLockSettings().setLockPattern(null, null, userHandle);
447         } catch (RemoteException e) {
448             // well, we tried...
449         }
450 
451         if (userHandle == UserHandle.USER_OWNER) {
452             // Set the encryption password to default.
453             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
454         }
455 
456         setCredentialRequiredToDecrypt(false);
457 
458         getDevicePolicyManager().setActivePasswordState(
459                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);
460 
461         onAfterChangingPassword(userHandle);
462     }
463 
464     /**
465      * Disable showing lock screen at all for a given user.
466      * This is only meaningful if pattern, pin or password are not set.
467      *
468      * @param disable Disables lock screen when true
469      * @param userId User ID of the user this has effect on
470      */
setLockScreenDisabled(boolean disable, int userId)471     public void setLockScreenDisabled(boolean disable, int userId) {
472         setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
473     }
474 
475     /**
476      * Determine if LockScreen is disabled for the current user. This is used to decide whether
477      * LockScreen is shown after reboot or after screen timeout / short press on power.
478      *
479      * @return true if lock screen is disabled
480      */
isLockScreenDisabled(int userId)481     public boolean isLockScreenDisabled(int userId) {
482         return !isSecure(userId) &&
483                 getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId);
484     }
485 
486     /**
487      * Save a lock pattern.
488      * @param pattern The new pattern to save.
489      * @param userId the user whose pattern is to be saved.
490      */
saveLockPattern(List<LockPatternView.Cell> pattern, int userId)491     public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
492         this.saveLockPattern(pattern, null, userId);
493     }
494     /**
495      * Save a lock pattern.
496      * @param pattern The new pattern to save.
497      * @param savedPattern The previously saved pattern, converted to String format
498      * @param userId the user whose pattern is to be saved.
499      */
saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId)500     public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId) {
501         try {
502             if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
503                 throw new IllegalArgumentException("pattern must not be null and at least "
504                         + MIN_LOCK_PATTERN_SIZE + " dots long.");
505             }
506 
507             getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
508             DevicePolicyManager dpm = getDevicePolicyManager();
509 
510             // Update the device encryption password.
511             if (userId == UserHandle.USER_OWNER
512                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
513                 if (!shouldEncryptWithCredentials(true)) {
514                     clearEncryptionPassword();
515                 } else {
516                     String stringPattern = patternToString(pattern);
517                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
518                 }
519             }
520 
521             setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
522 
523             setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
524             dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
525                     pattern.size(), 0, 0, 0, 0, 0, 0, userId);
526             onAfterChangingPassword(userId);
527         } catch (RemoteException re) {
528             Log.e(TAG, "Couldn't save lock pattern " + re);
529         }
530     }
531 
updateCryptoUserInfo(int userId)532     private void updateCryptoUserInfo(int userId) {
533         if (userId != UserHandle.USER_OWNER) {
534             return;
535         }
536 
537         final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : "";
538 
539         IBinder service = ServiceManager.getService("mount");
540         if (service == null) {
541             Log.e(TAG, "Could not find the mount service to update the user info");
542             return;
543         }
544 
545         IMountService mountService = IMountService.Stub.asInterface(service);
546         try {
547             Log.d(TAG, "Setting owner info");
548             mountService.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
549         } catch (RemoteException e) {
550             Log.e(TAG, "Error changing user info", e);
551         }
552     }
553 
setOwnerInfo(String info, int userId)554     public void setOwnerInfo(String info, int userId) {
555         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
556         updateCryptoUserInfo(userId);
557     }
558 
setOwnerInfoEnabled(boolean enabled, int userId)559     public void setOwnerInfoEnabled(boolean enabled, int userId) {
560         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
561         updateCryptoUserInfo(userId);
562     }
563 
getOwnerInfo(int userId)564     public String getOwnerInfo(int userId) {
565         return getString(LOCK_SCREEN_OWNER_INFO, userId);
566     }
567 
isOwnerInfoEnabled(int userId)568     public boolean isOwnerInfoEnabled(int userId) {
569         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
570     }
571 
572     /**
573      * Compute the password quality from the given password string.
574      */
computePasswordQuality(String password)575     static public int computePasswordQuality(String password) {
576         boolean hasDigit = false;
577         boolean hasNonDigit = false;
578         final int len = password.length();
579         for (int i = 0; i < len; i++) {
580             if (Character.isDigit(password.charAt(i))) {
581                 hasDigit = true;
582             } else {
583                 hasNonDigit = true;
584             }
585         }
586 
587         if (hasNonDigit && hasDigit) {
588             return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
589         }
590         if (hasNonDigit) {
591             return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
592         }
593         if (hasDigit) {
594             return maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
595                     ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
596                     : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
597         }
598         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
599     }
600 
categoryChar(char c)601     private static int categoryChar(char c) {
602         if ('a' <= c && c <= 'z') return 0;
603         if ('A' <= c && c <= 'Z') return 1;
604         if ('0' <= c && c <= '9') return 2;
605         return 3;
606     }
607 
maxDiffCategory(int category)608     private static int maxDiffCategory(int category) {
609         if (category == 0 || category == 1) return 1;
610         else if (category == 2) return 10;
611         return 0;
612     }
613 
614     /*
615      * Returns the maximum length of a sequential characters.  A sequence is defined as
616      * monotonically increasing characters with a constant interval or the same character repeated.
617      *
618      * For example:
619      * maxLengthSequence("1234") == 4
620      * maxLengthSequence("1234abc") == 4
621      * maxLengthSequence("aabc") == 3
622      * maxLengthSequence("qwertyuio") == 1
623      * maxLengthSequence("@ABC") == 3
624      * maxLengthSequence(";;;;") == 4 (anything that repeats)
625      * maxLengthSequence(":;<=>") == 1  (ordered, but not composed of alphas or digits)
626      *
627      * @param string the pass
628      * @return the number of sequential letters or digits
629      */
maxLengthSequence(String string)630     public static int maxLengthSequence(String string) {
631         if (string.length() == 0) return 0;
632         char previousChar = string.charAt(0);
633         int category = categoryChar(previousChar); //current category of the sequence
634         int diff = 0; //difference between two consecutive characters
635         boolean hasDiff = false; //if we are currently targeting a sequence
636         int maxLength = 0; //maximum length of a sequence already found
637         int startSequence = 0; //where the current sequence started
638         for (int current = 1; current < string.length(); current++) {
639             char currentChar = string.charAt(current);
640             int categoryCurrent = categoryChar(currentChar);
641             int currentDiff = (int) currentChar - (int) previousChar;
642             if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
643                 maxLength = Math.max(maxLength, current - startSequence);
644                 startSequence = current;
645                 hasDiff = false;
646                 category = categoryCurrent;
647             }
648             else {
649                 if(hasDiff && currentDiff != diff) {
650                     maxLength = Math.max(maxLength, current - startSequence);
651                     startSequence = current - 1;
652                 }
653                 diff = currentDiff;
654                 hasDiff = true;
655             }
656             previousChar = currentChar;
657         }
658         maxLength = Math.max(maxLength, string.length() - startSequence);
659         return maxLength;
660     }
661 
662     /** Update the encryption password if it is enabled **/
updateEncryptionPassword(final int type, final String password)663     private void updateEncryptionPassword(final int type, final String password) {
664         if (!isDeviceEncryptionEnabled()) {
665             return;
666         }
667         final IBinder service = ServiceManager.getService("mount");
668         if (service == null) {
669             Log.e(TAG, "Could not find the mount service to update the encryption password");
670             return;
671         }
672 
673         new AsyncTask<Void, Void, Void>() {
674             @Override
675             protected Void doInBackground(Void... dummy) {
676                 IMountService mountService = IMountService.Stub.asInterface(service);
677                 try {
678                     mountService.changeEncryptionPassword(type, password);
679                 } catch (RemoteException e) {
680                     Log.e(TAG, "Error changing encryption password", e);
681                 }
682                 return null;
683             }
684         }.execute();
685     }
686 
687     /**
688      * Save a lock password.  Does not ensure that the password is as good
689      * as the requested mode, but will adjust the mode to be as good as the
690      * password.
691      * @param password The password to save
692      * @param savedPassword The previously saved lock password, or null if none
693      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
694      * @param userHandle The userId of the user to change the password for
695      */
saveLockPassword(String password, String savedPassword, int quality, int userHandle)696     public void saveLockPassword(String password, String savedPassword, int quality,
697             int userHandle) {
698         try {
699             DevicePolicyManager dpm = getDevicePolicyManager();
700             if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
701                 throw new IllegalArgumentException("password must not be null and at least "
702                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
703             }
704 
705             getLockSettings().setLockPassword(password, savedPassword, userHandle);
706             int computedQuality = computePasswordQuality(password);
707 
708             // Update the device encryption password.
709             if (userHandle == UserHandle.USER_OWNER
710                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
711                 if (!shouldEncryptWithCredentials(true)) {
712                     clearEncryptionPassword();
713                 } else {
714                     boolean numeric = computedQuality
715                             == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
716                     boolean numericComplex = computedQuality
717                             == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
718                     int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
719                             : StorageManager.CRYPT_TYPE_PASSWORD;
720                     updateEncryptionPassword(type, password);
721                 }
722             }
723 
724             setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
725             if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
726                 int letters = 0;
727                 int uppercase = 0;
728                 int lowercase = 0;
729                 int numbers = 0;
730                 int symbols = 0;
731                 int nonletter = 0;
732                 for (int i = 0; i < password.length(); i++) {
733                     char c = password.charAt(i);
734                     if (c >= 'A' && c <= 'Z') {
735                         letters++;
736                         uppercase++;
737                     } else if (c >= 'a' && c <= 'z') {
738                         letters++;
739                         lowercase++;
740                     } else if (c >= '0' && c <= '9') {
741                         numbers++;
742                         nonletter++;
743                     } else {
744                         symbols++;
745                         nonletter++;
746                     }
747                 }
748                 dpm.setActivePasswordState(Math.max(quality, computedQuality),
749                         password.length(), letters, uppercase, lowercase,
750                         numbers, symbols, nonletter, userHandle);
751             } else {
752                 // The password is not anything.
753                 dpm.setActivePasswordState(
754                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
755                         0, 0, 0, 0, 0, 0, 0, userHandle);
756             }
757 
758             // Add the password to the password history. We assume all
759             // password hashes have the same length for simplicity of implementation.
760             String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
761             if (passwordHistory == null) {
762                 passwordHistory = "";
763             }
764             int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
765             if (passwordHistoryLength == 0) {
766                 passwordHistory = "";
767             } else {
768                 byte[] hash = passwordToHash(password, userHandle);
769                 passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
770                 // Cut it to contain passwordHistoryLength hashes
771                 // and passwordHistoryLength -1 commas.
772                 passwordHistory = passwordHistory.substring(0, Math.min(hash.length
773                         * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
774                         .length()));
775             }
776             setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
777             onAfterChangingPassword(userHandle);
778         } catch (RemoteException re) {
779             // Cant do much
780             Log.e(TAG, "Unable to save lock password " + re);
781         }
782     }
783 
784     /**
785      * Gets whether the device is encrypted.
786      *
787      * @return Whether the device is encrypted.
788      */
isDeviceEncrypted()789     public static boolean isDeviceEncrypted() {
790         IMountService mountService = IMountService.Stub.asInterface(
791                 ServiceManager.getService("mount"));
792         try {
793             return mountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE
794                     && mountService.getPasswordType() != StorageManager.CRYPT_TYPE_DEFAULT;
795         } catch (RemoteException re) {
796             Log.e(TAG, "Error getting encryption state", re);
797         }
798         return true;
799     }
800 
801     /**
802      * Determine if the device supports encryption, even if it's set to default. This
803      * differs from isDeviceEncrypted() in that it returns true even if the device is
804      * encrypted with the default password.
805      * @return true if device encryption is enabled
806      */
isDeviceEncryptionEnabled()807     public static boolean isDeviceEncryptionEnabled() {
808         final String status = SystemProperties.get("ro.crypto.state", "unsupported");
809         return "encrypted".equalsIgnoreCase(status);
810     }
811 
812     /**
813      * Clears the encryption password.
814      */
clearEncryptionPassword()815     public void clearEncryptionPassword() {
816         updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
817     }
818 
819     /**
820      * Retrieves the quality mode for {@param userHandle}.
821      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
822      *
823      * @return stored password quality
824      */
getKeyguardStoredPasswordQuality(int userHandle)825     public int getKeyguardStoredPasswordQuality(int userHandle) {
826         return (int) getLong(PASSWORD_TYPE_KEY,
827                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
828     }
829 
830     /**
831      * Deserialize a pattern.
832      * @param string The pattern serialized with {@link #patternToString}
833      * @return The pattern.
834      */
stringToPattern(String string)835     public static List<LockPatternView.Cell> stringToPattern(String string) {
836         if (string == null) {
837             return null;
838         }
839 
840         List<LockPatternView.Cell> result = Lists.newArrayList();
841 
842         final byte[] bytes = string.getBytes();
843         for (int i = 0; i < bytes.length; i++) {
844             byte b = (byte) (bytes[i] - '1');
845             result.add(LockPatternView.Cell.of(b / 3, b % 3));
846         }
847         return result;
848     }
849 
850     /**
851      * Serialize a pattern.
852      * @param pattern The pattern.
853      * @return The pattern in string form.
854      */
patternToString(List<LockPatternView.Cell> pattern)855     public static String patternToString(List<LockPatternView.Cell> pattern) {
856         if (pattern == null) {
857             return "";
858         }
859         final int patternSize = pattern.size();
860 
861         byte[] res = new byte[patternSize];
862         for (int i = 0; i < patternSize; i++) {
863             LockPatternView.Cell cell = pattern.get(i);
864             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
865         }
866         return new String(res);
867     }
868 
patternStringToBaseZero(String pattern)869     public static String patternStringToBaseZero(String pattern) {
870         if (pattern == null) {
871             return "";
872         }
873         final int patternSize = pattern.length();
874 
875         byte[] res = new byte[patternSize];
876         final byte[] bytes = pattern.getBytes();
877         for (int i = 0; i < patternSize; i++) {
878             res[i] = (byte) (bytes[i] - '1');
879         }
880         return new String(res);
881     }
882 
883     /*
884      * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
885      * at least a second level of protection. First level is that the file
886      * is in a location only readable by the system process.
887      * @param pattern the gesture pattern.
888      * @return the hash of the pattern in a byte array.
889      */
patternToHash(List<LockPatternView.Cell> pattern)890     public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
891         if (pattern == null) {
892             return null;
893         }
894 
895         final int patternSize = pattern.size();
896         byte[] res = new byte[patternSize];
897         for (int i = 0; i < patternSize; i++) {
898             LockPatternView.Cell cell = pattern.get(i);
899             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
900         }
901         try {
902             MessageDigest md = MessageDigest.getInstance("SHA-1");
903             byte[] hash = md.digest(res);
904             return hash;
905         } catch (NoSuchAlgorithmException nsa) {
906             return res;
907         }
908     }
909 
getSalt(int userId)910     private String getSalt(int userId) {
911         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
912         if (salt == 0) {
913             try {
914                 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
915                 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
916                 Log.v(TAG, "Initialized lock password salt for user: " + userId);
917             } catch (NoSuchAlgorithmException e) {
918                 // Throw an exception rather than storing a password we'll never be able to recover
919                 throw new IllegalStateException("Couldn't get SecureRandom number", e);
920             }
921         }
922         return Long.toHexString(salt);
923     }
924 
925     /*
926      * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
927      * Not the most secure, but it is at least a second level of protection. First level is that
928      * the file is in a location only readable by the system process.
929      *
930      * @param password the gesture pattern.
931      *
932      * @return the hash of the pattern in a byte array.
933      */
passwordToHash(String password, int userId)934     public byte[] passwordToHash(String password, int userId) {
935         if (password == null) {
936             return null;
937         }
938 
939         try {
940             byte[] saltedPassword = (password + getSalt(userId)).getBytes();
941             byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
942             byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
943 
944             byte[] combined = new byte[sha1.length + md5.length];
945             System.arraycopy(sha1, 0, combined, 0, sha1.length);
946             System.arraycopy(md5, 0, combined, sha1.length, md5.length);
947 
948             final char[] hexEncoded = HexEncoding.encode(combined);
949             return new String(hexEncoded).getBytes(StandardCharsets.UTF_8);
950         } catch (NoSuchAlgorithmException e) {
951             throw new AssertionError("Missing digest algorithm: ", e);
952         }
953     }
954 
955     /**
956      * @param userId the user for which to report the value
957      * @return Whether the lock screen is secured.
958      */
isSecure(int userId)959     public boolean isSecure(int userId) {
960         int mode = getKeyguardStoredPasswordQuality(userId);
961         return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
962     }
963 
isLockPasswordEnabled(int userId)964     public boolean isLockPasswordEnabled(int userId) {
965         return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
966     }
967 
isLockPasswordEnabled(int mode, int userId)968     private boolean isLockPasswordEnabled(int mode, int userId) {
969         final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
970                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
971                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
972                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
973                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
974         return passwordEnabled && savedPasswordExists(userId);
975     }
976 
977     /**
978      * @return Whether the lock pattern is enabled
979      */
isLockPatternEnabled(int userId)980     public boolean isLockPatternEnabled(int userId) {
981         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
982     }
983 
isLockPatternEnabled(int mode, int userId)984     private boolean isLockPatternEnabled(int mode, int userId) {
985         return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
986                 && savedPatternExists(userId);
987     }
988 
989     /**
990      * @return Whether the visible pattern is enabled.
991      */
isVisiblePatternEnabled(int userId)992     public boolean isVisiblePatternEnabled(int userId) {
993         return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
994     }
995 
996     /**
997      * Set whether the visible pattern is enabled.
998      */
setVisiblePatternEnabled(boolean enabled, int userId)999     public void setVisiblePatternEnabled(boolean enabled, int userId) {
1000         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
1001 
1002         // Update for crypto if owner
1003         if (userId != UserHandle.USER_OWNER) {
1004             return;
1005         }
1006 
1007         IBinder service = ServiceManager.getService("mount");
1008         if (service == null) {
1009             Log.e(TAG, "Could not find the mount service to update the user info");
1010             return;
1011         }
1012 
1013         IMountService mountService = IMountService.Stub.asInterface(service);
1014         try {
1015             mountService.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1016         } catch (RemoteException e) {
1017             Log.e(TAG, "Error changing pattern visible state", e);
1018         }
1019     }
1020 
1021     /**
1022      * Set whether the visible password is enabled for cryptkeeper screen.
1023      */
setVisiblePasswordEnabled(boolean enabled, int userId)1024     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
1025         // Update for crypto if owner
1026         if (userId != UserHandle.USER_OWNER) {
1027             return;
1028         }
1029 
1030         IBinder service = ServiceManager.getService("mount");
1031         if (service == null) {
1032             Log.e(TAG, "Could not find the mount service to update the user info");
1033             return;
1034         }
1035 
1036         IMountService mountService = IMountService.Stub.asInterface(service);
1037         try {
1038             mountService.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0");
1039         } catch (RemoteException e) {
1040             Log.e(TAG, "Error changing password visible state", e);
1041         }
1042     }
1043 
1044     /**
1045      * @return Whether tactile feedback for the pattern is enabled.
1046      */
isTactileFeedbackEnabled()1047     public boolean isTactileFeedbackEnabled() {
1048         return Settings.System.getIntForUser(mContentResolver,
1049                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1050     }
1051 
1052     /**
1053      * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1054      * pattern until the deadline has passed.
1055      * @return the chosen deadline.
1056      */
setLockoutAttemptDeadline(int userId, int timeoutMs)1057     public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
1058         final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
1059         setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1060         setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, timeoutMs, userId);
1061         return deadline;
1062     }
1063 
1064     /**
1065      * @return The elapsed time in millis in the future when the user is allowed to
1066      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1067      *   enter a pattern.
1068      */
getLockoutAttemptDeadline(int userId)1069     public long getLockoutAttemptDeadline(int userId) {
1070         final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
1071         final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId);
1072         final long now = SystemClock.elapsedRealtime();
1073         if (deadline < now || deadline > (now + timeoutMs)) {
1074             return 0L;
1075         }
1076         return deadline;
1077     }
1078 
getBoolean(String secureSettingKey, boolean defaultValue, int userId)1079     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1080         try {
1081             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1082         } catch (RemoteException re) {
1083             return defaultValue;
1084         }
1085     }
1086 
setBoolean(String secureSettingKey, boolean enabled, int userId)1087     private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1088         try {
1089             getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1090         } catch (RemoteException re) {
1091             // What can we do?
1092             Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1093         }
1094     }
1095 
getLong(String secureSettingKey, long defaultValue, int userHandle)1096     private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1097         try {
1098             return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1099         } catch (RemoteException re) {
1100             return defaultValue;
1101         }
1102     }
1103 
setLong(String secureSettingKey, long value, int userHandle)1104     private void setLong(String secureSettingKey, long value, int userHandle) {
1105         try {
1106             getLockSettings().setLong(secureSettingKey, value, userHandle);
1107         } catch (RemoteException re) {
1108             // What can we do?
1109             Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1110         }
1111     }
1112 
getString(String secureSettingKey, int userHandle)1113     private String getString(String secureSettingKey, int userHandle) {
1114         try {
1115             return getLockSettings().getString(secureSettingKey, null, userHandle);
1116         } catch (RemoteException re) {
1117             return null;
1118         }
1119     }
1120 
setString(String secureSettingKey, String value, int userHandle)1121     private void setString(String secureSettingKey, String value, int userHandle) {
1122         try {
1123             getLockSettings().setString(secureSettingKey, value, userHandle);
1124         } catch (RemoteException re) {
1125             // What can we do?
1126             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1127         }
1128     }
1129 
setPowerButtonInstantlyLocks(boolean enabled, int userId)1130     public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
1131         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
1132     }
1133 
getPowerButtonInstantlyLocks(int userId)1134     public boolean getPowerButtonInstantlyLocks(int userId) {
1135         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
1136     }
1137 
setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1138     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1139         StringBuilder sb = new StringBuilder();
1140         for (ComponentName cn : activeTrustAgents) {
1141             if (sb.length() > 0) {
1142                 sb.append(',');
1143             }
1144             sb.append(cn.flattenToShortString());
1145         }
1146         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1147         getTrustManager().reportEnabledTrustAgentsChanged(userId);
1148     }
1149 
getEnabledTrustAgents(int userId)1150     public List<ComponentName> getEnabledTrustAgents(int userId) {
1151         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1152         if (TextUtils.isEmpty(serialized)) {
1153             return null;
1154         }
1155         String[] split = serialized.split(",");
1156         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1157         for (String s : split) {
1158             if (!TextUtils.isEmpty(s)) {
1159                 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1160             }
1161         }
1162         return activeTrustAgents;
1163     }
1164 
1165     /**
1166      * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
1167      */
requireCredentialEntry(int userId)1168     public void requireCredentialEntry(int userId) {
1169         getTrustManager().reportRequireCredentialEntry(userId);
1170     }
1171 
onAfterChangingPassword(int userHandle)1172     private void onAfterChangingPassword(int userHandle) {
1173         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1174     }
1175 
isCredentialRequiredToDecrypt(boolean defaultValue)1176     public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1177         final int value = Settings.Global.getInt(mContentResolver,
1178                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1179         return value == -1 ? defaultValue : (value != 0);
1180     }
1181 
setCredentialRequiredToDecrypt(boolean required)1182     public void setCredentialRequiredToDecrypt(boolean required) {
1183         if (ActivityManager.getCurrentUser() != UserHandle.USER_OWNER) {
1184             Log.w(TAG, "Only device owner may call setCredentialRequiredForDecrypt()");
1185             return;
1186         }
1187 
1188         if (isDeviceEncryptionEnabled()){
1189             Settings.Global.putInt(mContext.getContentResolver(),
1190                Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1191         }
1192     }
1193 
isDoNotAskCredentialsOnBootSet()1194     private boolean isDoNotAskCredentialsOnBootSet() {
1195         return mDevicePolicyManager.getDoNotAskCredentialsOnBoot();
1196     }
1197 
shouldEncryptWithCredentials(boolean defaultValue)1198     private boolean shouldEncryptWithCredentials(boolean defaultValue) {
1199         return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
1200     }
1201 }
1202