OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / core / java / com / android / internal / widget / LockPatternUtils.java
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      */
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
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
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;
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          */
197         public int getTimeoutMs() {
198             return mTimeoutMs;
199         }
200
201     }
202
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
215     private UserManager getUserManager() {
216         if (mUserManager == null) {
217             mUserManager = UserManager.get(mContext);
218         }
219         return mUserManager;
220     }
221
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
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
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
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      */
256     public int getRequestedPasswordQuality(int userId) {
257         return getDevicePolicyManager().getPasswordQuality(null, userId);
258     }
259
260     private int getRequestedPasswordHistoryLength(int userId) {
261         return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
262     }
263
264     public int getRequestedPasswordMinimumLetters(int userId) {
265         return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
266     }
267
268     public int getRequestedPasswordMinimumUpperCase(int userId) {
269         return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
270     }
271
272     public int getRequestedPasswordMinimumLowerCase(int userId) {
273         return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
274     }
275
276     public int getRequestedPasswordMinimumNumeric(int userId) {
277         return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
278     }
279
280     public int getRequestedPasswordMinimumSymbols(int userId) {
281         return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
282     }
283
284     public int getRequestedPasswordMinimumNonLetter(int userId) {
285         return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
286     }
287
288     public void reportFailedPasswordAttempt(int userId) {
289         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
290         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
291     }
292
293     public void reportSuccessfulPasswordAttempt(int userId) {
294         getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
295         getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
296     }
297
298     public int getCurrentFailedPasswordAttempts(int userId) {
299         return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId);
300     }
301
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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         onAfterChangingPassword(userHandle);
597     }
598
599     /**
600      * Disable showing lock screen at all for a given user.
601      * This is only meaningful if pattern, pin or password are not set.
602      *
603      * @param disable Disables lock screen when true
604      * @param userId User ID of the user this has effect on
605      */
606     public void setLockScreenDisabled(boolean disable, int userId) {
607         setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
608     }
609
610     /**
611      * Determine if LockScreen is disabled for the current user. This is used to decide whether
612      * LockScreen is shown after reboot or after screen timeout / short press on power.
613      *
614      * @return true if lock screen is disabled
615      */
616     public boolean isLockScreenDisabled(int userId) {
617         return !isSecure(userId) &&
618                 getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId);
619     }
620
621     /**
622      * Save a lock pattern.
623      * @param pattern The new pattern to save.
624      * @param userId the user whose pattern is to be saved.
625      */
626     public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
627         this.saveLockPattern(pattern, null, userId);
628     }
629     /**
630      * Save a lock pattern.
631      * @param pattern The new pattern to save.
632      * @param savedPattern The previously saved pattern, converted to String format
633      * @param userId the user whose pattern is to be saved.
634      */
635     public void saveLockPattern(List<LockPatternView.Cell> pattern, String savedPattern, int userId) {
636         try {
637             if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
638                 throw new IllegalArgumentException("pattern must not be null and at least "
639                         + MIN_LOCK_PATTERN_SIZE + " dots long.");
640             }
641
642             setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
643             getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
644             DevicePolicyManager dpm = getDevicePolicyManager();
645
646             // Update the device encryption password.
647             if (userId == UserHandle.USER_SYSTEM
648                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
649                 if (!shouldEncryptWithCredentials(true)) {
650                     clearEncryptionPassword();
651                 } else {
652                     String stringPattern = patternToString(pattern);
653                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
654                 }
655             }
656
657             setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
658
659             onAfterChangingPassword(userId);
660         } catch (RemoteException re) {
661             Log.e(TAG, "Couldn't save lock pattern " + re);
662         }
663     }
664
665     private void updateCryptoUserInfo(int userId) {
666         if (userId != UserHandle.USER_SYSTEM) {
667             return;
668         }
669
670         final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : "";
671
672         IBinder service = ServiceManager.getService("mount");
673         if (service == null) {
674             Log.e(TAG, "Could not find the mount service to update the user info");
675             return;
676         }
677
678         IMountService mountService = IMountService.Stub.asInterface(service);
679         try {
680             Log.d(TAG, "Setting owner info");
681             mountService.setField(StorageManager.OWNER_INFO_KEY, ownerInfo);
682         } catch (RemoteException e) {
683             Log.e(TAG, "Error changing user info", e);
684         }
685     }
686
687     public void setOwnerInfo(String info, int userId) {
688         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
689         updateCryptoUserInfo(userId);
690     }
691
692     public void setOwnerInfoEnabled(boolean enabled, int userId) {
693         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
694         updateCryptoUserInfo(userId);
695     }
696
697     public String getOwnerInfo(int userId) {
698         return getString(LOCK_SCREEN_OWNER_INFO, userId);
699     }
700
701     public boolean isOwnerInfoEnabled(int userId) {
702         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
703     }
704
705     /**
706      * Sets the device owner information. If the information is {@code null} or empty then the
707      * device owner info is cleared.
708      *
709      * @param info Device owner information which will be displayed instead of the user
710      * owner info.
711      */
712     public void setDeviceOwnerInfo(String info) {
713         if (info != null && info.isEmpty()) {
714             info = null;
715         }
716
717         setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM);
718     }
719
720     public String getDeviceOwnerInfo() {
721         return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM);
722     }
723
724     public boolean isDeviceOwnerInfoEnabled() {
725         return getDeviceOwnerInfo() != null;
726     }
727
728     /**
729      * Compute the password quality from the given password string.
730      */
731     static public int computePasswordQuality(String password) {
732         boolean hasDigit = false;
733         boolean hasNonDigit = false;
734         final int len = password.length();
735         for (int i = 0; i < len; i++) {
736             if (Character.isDigit(password.charAt(i))) {
737                 hasDigit = true;
738             } else {
739                 hasNonDigit = true;
740             }
741         }
742
743         if (hasNonDigit && hasDigit) {
744             return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
745         }
746         if (hasNonDigit) {
747             return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
748         }
749         if (hasDigit) {
750             return maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
751                     ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
752                     : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
753         }
754         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
755     }
756
757     private static int categoryChar(char c) {
758         if ('a' <= c && c <= 'z') return 0;
759         if ('A' <= c && c <= 'Z') return 1;
760         if ('0' <= c && c <= '9') return 2;
761         return 3;
762     }
763
764     private static int maxDiffCategory(int category) {
765         if (category == 0 || category == 1) return 1;
766         else if (category == 2) return 10;
767         return 0;
768     }
769
770     /*
771      * Returns the maximum length of a sequential characters.  A sequence is defined as
772      * monotonically increasing characters with a constant interval or the same character repeated.
773      *
774      * For example:
775      * maxLengthSequence("1234") == 4
776      * maxLengthSequence("1234abc") == 4
777      * maxLengthSequence("aabc") == 3
778      * maxLengthSequence("qwertyuio") == 1
779      * maxLengthSequence("@ABC") == 3
780      * maxLengthSequence(";;;;") == 4 (anything that repeats)
781      * maxLengthSequence(":;<=>") == 1  (ordered, but not composed of alphas or digits)
782      *
783      * @param string the pass
784      * @return the number of sequential letters or digits
785      */
786     public static int maxLengthSequence(String string) {
787         if (string.length() == 0) return 0;
788         char previousChar = string.charAt(0);
789         int category = categoryChar(previousChar); //current category of the sequence
790         int diff = 0; //difference between two consecutive characters
791         boolean hasDiff = false; //if we are currently targeting a sequence
792         int maxLength = 0; //maximum length of a sequence already found
793         int startSequence = 0; //where the current sequence started
794         for (int current = 1; current < string.length(); current++) {
795             char currentChar = string.charAt(current);
796             int categoryCurrent = categoryChar(currentChar);
797             int currentDiff = (int) currentChar - (int) previousChar;
798             if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
799                 maxLength = Math.max(maxLength, current - startSequence);
800                 startSequence = current;
801                 hasDiff = false;
802                 category = categoryCurrent;
803             }
804             else {
805                 if(hasDiff && currentDiff != diff) {
806                     maxLength = Math.max(maxLength, current - startSequence);
807                     startSequence = current - 1;
808                 }
809                 diff = currentDiff;
810                 hasDiff = true;
811             }
812             previousChar = currentChar;
813         }
814         maxLength = Math.max(maxLength, string.length() - startSequence);
815         return maxLength;
816     }
817
818     /** Update the encryption password if it is enabled **/
819     private void updateEncryptionPassword(final int type, final String password) {
820         if (!isDeviceEncryptionEnabled()) {
821             return;
822         }
823         final IBinder service = ServiceManager.getService("mount");
824         if (service == null) {
825             Log.e(TAG, "Could not find the mount service to update the encryption password");
826             return;
827         }
828
829         new AsyncTask<Void, Void, Void>() {
830             @Override
831             protected Void doInBackground(Void... dummy) {
832                 IMountService mountService = IMountService.Stub.asInterface(service);
833                 try {
834                     mountService.changeEncryptionPassword(type, password);
835                 } catch (RemoteException e) {
836                     Log.e(TAG, "Error changing encryption password", e);
837                 }
838                 return null;
839             }
840         }.execute();
841     }
842
843     /**
844      * Save a lock password.  Does not ensure that the password is as good
845      * as the requested mode, but will adjust the mode to be as good as the
846      * password.
847      * @param password The password to save
848      * @param savedPassword The previously saved lock password, or null if none
849      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
850      * @param userHandle The userId of the user to change the password for
851      */
852     public void saveLockPassword(String password, String savedPassword, int quality,
853             int userHandle) {
854         try {
855             DevicePolicyManager dpm = getDevicePolicyManager();
856             if (password == null || password.length() < MIN_LOCK_PASSWORD_SIZE) {
857                 throw new IllegalArgumentException("password must not be null and at least "
858                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
859             }
860
861             final int computedQuality = computePasswordQuality(password);
862             setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
863             getLockSettings().setLockPassword(password, savedPassword, userHandle);
864
865             // Update the device encryption password.
866             if (userHandle == UserHandle.USER_SYSTEM
867                     && LockPatternUtils.isDeviceEncryptionEnabled()) {
868                 if (!shouldEncryptWithCredentials(true)) {
869                     clearEncryptionPassword();
870                 } else {
871                     boolean numeric = computedQuality
872                             == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
873                     boolean numericComplex = computedQuality
874                             == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
875                     int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
876                             : StorageManager.CRYPT_TYPE_PASSWORD;
877                     updateEncryptionPassword(type, password);
878                 }
879             }
880
881             // Add the password to the password history. We assume all
882             // password hashes have the same length for simplicity of implementation.
883             String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
884             if (passwordHistory == null) {
885                 passwordHistory = "";
886             }
887             int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle);
888             if (passwordHistoryLength == 0) {
889                 passwordHistory = "";
890             } else {
891                 byte[] hash = passwordToHash(password, userHandle);
892                 passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory;
893                 // Cut it to contain passwordHistoryLength hashes
894                 // and passwordHistoryLength -1 commas.
895                 passwordHistory = passwordHistory.substring(0, Math.min(hash.length
896                         * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory
897                         .length()));
898             }
899             setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
900             onAfterChangingPassword(userHandle);
901         } catch (RemoteException re) {
902             // Cant do much
903             Log.e(TAG, "Unable to save lock password " + re);
904         }
905     }
906
907     /**
908      * Determine if the device supports encryption, even if it's set to default. This
909      * differs from isDeviceEncrypted() in that it returns true even if the device is
910      * encrypted with the default password.
911      * @return true if device encryption is enabled
912      */
913     public static boolean isDeviceEncryptionEnabled() {
914         return StorageManager.isEncrypted();
915     }
916
917     /**
918      * Determine if the device is file encrypted
919      * @return true if device is file encrypted
920      */
921     public static boolean isFileEncryptionEnabled() {
922         return StorageManager.isFileEncryptedNativeOrEmulated();
923     }
924
925     /**
926      * Clears the encryption password.
927      */
928     public void clearEncryptionPassword() {
929         updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
930     }
931
932     /**
933      * Retrieves the quality mode for {@param userHandle}.
934      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
935      *
936      * @return stored password quality
937      */
938     public int getKeyguardStoredPasswordQuality(int userHandle) {
939         return (int) getLong(PASSWORD_TYPE_KEY,
940                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
941     }
942
943     /**
944      * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
945      * for user handles that do not belong to a managed profile.
946      *
947      * @param userHandle Managed profile user id
948      * @param enabled True if separate challenge is enabled
949      * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
950      *            true
951      */
952     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
953             String managedUserPassword) {
954         UserInfo info = getUserManager().getUserInfo(userHandle);
955         if (info.isManagedProfile()) {
956             try {
957                 getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
958                         managedUserPassword);
959                 onAfterChangingPassword(userHandle);
960             } catch (RemoteException e) {
961                 Log.e(TAG, "Couldn't update work profile challenge enabled");
962             }
963         }
964     }
965
966     /**
967      * Retrieves whether the Separate Profile Challenge is enabled for this {@param userHandle}.
968      */
969     public boolean isSeparateProfileChallengeEnabled(int userHandle) {
970         UserInfo info = getUserManager().getUserInfo(userHandle);
971         if (info == null || !info.isManagedProfile()) {
972             return false;
973         }
974         try {
975             return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
976         } catch (RemoteException e) {
977             Log.e(TAG, "Couldn't get separate profile challenge enabled");
978             // Default value is false
979             return false;
980         }
981     }
982
983     /**
984      * Retrieves whether the current DPM allows use of the Profile Challenge.
985      */
986     public boolean isSeparateProfileChallengeAllowed(int userHandle) {
987         UserInfo info = getUserManager().getUserInfo(userHandle);
988         if (info == null || !info.isManagedProfile()) {
989             return false;
990         }
991         return getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle);
992     }
993
994     /**
995      * Retrieves whether the current profile and device locks can be unified.
996      */
997     public boolean isSeparateProfileChallengeAllowedToUnify(int userHandle) {
998         return getDevicePolicyManager().isProfileActivePasswordSufficientForParent(userHandle);
999     }
1000
1001     /**
1002      * Deserialize a pattern.
1003      * @param string The pattern serialized with {@link #patternToString}
1004      * @return The pattern.
1005      */
1006     public static List<LockPatternView.Cell> stringToPattern(String string) {
1007         if (string == null) {
1008             return null;
1009         }
1010
1011         List<LockPatternView.Cell> result = Lists.newArrayList();
1012
1013         final byte[] bytes = string.getBytes();
1014         for (int i = 0; i < bytes.length; i++) {
1015             byte b = (byte) (bytes[i] - '1');
1016             result.add(LockPatternView.Cell.of(b / 3, b % 3));
1017         }
1018         return result;
1019     }
1020
1021     /**
1022      * Serialize a pattern.
1023      * @param pattern The pattern.
1024      * @return The pattern in string form.
1025      */
1026     public static String patternToString(List<LockPatternView.Cell> pattern) {
1027         if (pattern == null) {
1028             return "";
1029         }
1030         final int patternSize = pattern.size();
1031
1032         byte[] res = new byte[patternSize];
1033         for (int i = 0; i < patternSize; i++) {
1034             LockPatternView.Cell cell = pattern.get(i);
1035             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1');
1036         }
1037         return new String(res);
1038     }
1039
1040     public static String patternStringToBaseZero(String pattern) {
1041         if (pattern == null) {
1042             return "";
1043         }
1044         final int patternSize = pattern.length();
1045
1046         byte[] res = new byte[patternSize];
1047         final byte[] bytes = pattern.getBytes();
1048         for (int i = 0; i < patternSize; i++) {
1049             res[i] = (byte) (bytes[i] - '1');
1050         }
1051         return new String(res);
1052     }
1053
1054     /*
1055      * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
1056      * at least a second level of protection. First level is that the file
1057      * is in a location only readable by the system process.
1058      * @param pattern the gesture pattern.
1059      * @return the hash of the pattern in a byte array.
1060      */
1061     public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
1062         if (pattern == null) {
1063             return null;
1064         }
1065
1066         final int patternSize = pattern.size();
1067         byte[] res = new byte[patternSize];
1068         for (int i = 0; i < patternSize; i++) {
1069             LockPatternView.Cell cell = pattern.get(i);
1070             res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
1071         }
1072         try {
1073             MessageDigest md = MessageDigest.getInstance("SHA-1");
1074             byte[] hash = md.digest(res);
1075             return hash;
1076         } catch (NoSuchAlgorithmException nsa) {
1077             return res;
1078         }
1079     }
1080
1081     private String getSalt(int userId) {
1082         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
1083         if (salt == 0) {
1084             try {
1085                 salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
1086                 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId);
1087                 Log.v(TAG, "Initialized lock password salt for user: " + userId);
1088             } catch (NoSuchAlgorithmException e) {
1089                 // Throw an exception rather than storing a password we'll never be able to recover
1090                 throw new IllegalStateException("Couldn't get SecureRandom number", e);
1091             }
1092         }
1093         return Long.toHexString(salt);
1094     }
1095
1096     /*
1097      * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
1098      * Not the most secure, but it is at least a second level of protection. First level is that
1099      * the file is in a location only readable by the system process.
1100      *
1101      * @param password the gesture pattern.
1102      *
1103      * @return the hash of the pattern in a byte array.
1104      */
1105     public byte[] passwordToHash(String password, int userId) {
1106         if (password == null) {
1107             return null;
1108         }
1109
1110         try {
1111             byte[] saltedPassword = (password + getSalt(userId)).getBytes();
1112             byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword);
1113             byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword);
1114
1115             byte[] combined = new byte[sha1.length + md5.length];
1116             System.arraycopy(sha1, 0, combined, 0, sha1.length);
1117             System.arraycopy(md5, 0, combined, sha1.length, md5.length);
1118
1119             final char[] hexEncoded = HexEncoding.encode(combined);
1120             return new String(hexEncoded).getBytes(StandardCharsets.UTF_8);
1121         } catch (NoSuchAlgorithmException e) {
1122             throw new AssertionError("Missing digest algorithm: ", e);
1123         }
1124     }
1125
1126     /**
1127      * @param userId the user for which to report the value
1128      * @return Whether the lock screen is secured.
1129      */
1130     public boolean isSecure(int userId) {
1131         int mode = getKeyguardStoredPasswordQuality(userId);
1132         return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
1133     }
1134
1135     public boolean isLockPasswordEnabled(int userId) {
1136         return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1137     }
1138
1139     private boolean isLockPasswordEnabled(int mode, int userId) {
1140         final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
1141                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1142                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
1143                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
1144                 || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
1145                 || mode == DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
1146         return passwordEnabled && savedPasswordExists(userId);
1147     }
1148
1149     /**
1150      * @return Whether the lock pattern is enabled
1151      */
1152     public boolean isLockPatternEnabled(int userId) {
1153         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
1154     }
1155
1156     @Deprecated
1157     public boolean isLegacyLockPatternEnabled(int userId) {
1158         // Note: this value should default to {@code true} to avoid any reset that might result.
1159         // We must use a special key to read this value, since it will by default return the value
1160         // based on the new logic.
1161         return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
1162     }
1163
1164     @Deprecated
1165     public void setLegacyLockPatternEnabled(int userId) {
1166         setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
1167     }
1168
1169     private boolean isLockPatternEnabled(int mode, int userId) {
1170         return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
1171                 && savedPatternExists(userId);
1172     }
1173
1174     /**
1175      * @return Whether the visible pattern is enabled.
1176      */
1177     public boolean isVisiblePatternEnabled(int userId) {
1178         return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
1179     }
1180
1181     /**
1182      * Set whether the visible pattern is enabled.
1183      */
1184     public void setVisiblePatternEnabled(boolean enabled, int userId) {
1185         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
1186
1187         // Update for crypto if owner
1188         if (userId != UserHandle.USER_SYSTEM) {
1189             return;
1190         }
1191
1192         IBinder service = ServiceManager.getService("mount");
1193         if (service == null) {
1194             Log.e(TAG, "Could not find the mount service to update the user info");
1195             return;
1196         }
1197
1198         IMountService mountService = IMountService.Stub.asInterface(service);
1199         try {
1200             mountService.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0");
1201         } catch (RemoteException e) {
1202             Log.e(TAG, "Error changing pattern visible state", e);
1203         }
1204     }
1205
1206     /**
1207      * Set whether the visible password is enabled for cryptkeeper screen.
1208      */
1209     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
1210         // Update for crypto if owner
1211         if (userId != UserHandle.USER_SYSTEM) {
1212             return;
1213         }
1214
1215         IBinder service = ServiceManager.getService("mount");
1216         if (service == null) {
1217             Log.e(TAG, "Could not find the mount service to update the user info");
1218             return;
1219         }
1220
1221         IMountService mountService = IMountService.Stub.asInterface(service);
1222         try {
1223             mountService.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0");
1224         } catch (RemoteException e) {
1225             Log.e(TAG, "Error changing password visible state", e);
1226         }
1227     }
1228
1229     /**
1230      * @return Whether tactile feedback for the pattern is enabled.
1231      */
1232     public boolean isTactileFeedbackEnabled() {
1233         return Settings.System.getIntForUser(mContentResolver,
1234                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
1235     }
1236
1237     /**
1238      * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
1239      * pattern until the deadline has passed.
1240      * @return the chosen deadline.
1241      */
1242     public long setLockoutAttemptDeadline(int userId, int timeoutMs) {
1243         final long deadline = SystemClock.elapsedRealtime() + timeoutMs;
1244         setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1245         setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, timeoutMs, userId);
1246         return deadline;
1247     }
1248
1249     /**
1250      * @return The elapsed time in millis in the future when the user is allowed to
1251      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
1252      *   enter a pattern.
1253      */
1254     public long getLockoutAttemptDeadline(int userId) {
1255         long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
1256         final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId);
1257         final long now = SystemClock.elapsedRealtime();
1258         if (deadline < now && deadline != 0) {
1259             // timeout expired
1260             setLong(LOCKOUT_ATTEMPT_DEADLINE, 0, userId);
1261             setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0, userId);
1262             return 0L;
1263         }
1264
1265         if (deadline > (now + timeoutMs)) {
1266             // device was rebooted, set new deadline
1267             deadline = now + timeoutMs;
1268             setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
1269         }
1270
1271         return deadline;
1272     }
1273
1274     private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) {
1275         try {
1276             return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId);
1277         } catch (RemoteException re) {
1278             return defaultValue;
1279         }
1280     }
1281
1282     private void setBoolean(String secureSettingKey, boolean enabled, int userId) {
1283         try {
1284             getLockSettings().setBoolean(secureSettingKey, enabled, userId);
1285         } catch (RemoteException re) {
1286             // What can we do?
1287             Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
1288         }
1289     }
1290
1291     private long getLong(String secureSettingKey, long defaultValue, int userHandle) {
1292         try {
1293             return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle);
1294         } catch (RemoteException re) {
1295             return defaultValue;
1296         }
1297     }
1298
1299     private void setLong(String secureSettingKey, long value, int userHandle) {
1300         try {
1301             getLockSettings().setLong(secureSettingKey, value, userHandle);
1302         } catch (RemoteException re) {
1303             // What can we do?
1304             Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
1305         }
1306     }
1307
1308     private String getString(String secureSettingKey, int userHandle) {
1309         try {
1310             return getLockSettings().getString(secureSettingKey, null, userHandle);
1311         } catch (RemoteException re) {
1312             return null;
1313         }
1314     }
1315
1316     private void setString(String secureSettingKey, String value, int userHandle) {
1317         try {
1318             getLockSettings().setString(secureSettingKey, value, userHandle);
1319         } catch (RemoteException re) {
1320             // What can we do?
1321             Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
1322         }
1323     }
1324
1325     public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
1326         setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
1327     }
1328
1329     public boolean getPowerButtonInstantlyLocks(int userId) {
1330         return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
1331     }
1332
1333     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
1334         StringBuilder sb = new StringBuilder();
1335         for (ComponentName cn : activeTrustAgents) {
1336             if (sb.length() > 0) {
1337                 sb.append(',');
1338             }
1339             sb.append(cn.flattenToShortString());
1340         }
1341         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
1342         getTrustManager().reportEnabledTrustAgentsChanged(userId);
1343     }
1344
1345     public List<ComponentName> getEnabledTrustAgents(int userId) {
1346         String serialized = getString(ENABLED_TRUST_AGENTS, userId);
1347         if (TextUtils.isEmpty(serialized)) {
1348             return null;
1349         }
1350         String[] split = serialized.split(",");
1351         ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
1352         for (String s : split) {
1353             if (!TextUtils.isEmpty(s)) {
1354                 activeTrustAgents.add(ComponentName.unflattenFromString(s));
1355             }
1356         }
1357         return activeTrustAgents;
1358     }
1359
1360     /**
1361      * Disable trust until credentials have been entered for user {@param userId}.
1362      *
1363      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1364      *
1365      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1366      */
1367     public void requireCredentialEntry(int userId) {
1368         requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
1369     }
1370
1371     /**
1372      * Requests strong authentication for user {@param userId}.
1373      *
1374      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
1375      *
1376      * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
1377      *                         the reason for and the strength of the requested authentication.
1378      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
1379      */
1380     public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
1381             int userId) {
1382         try {
1383             getLockSettings().requireStrongAuth(strongAuthReason, userId);
1384         } catch (RemoteException e) {
1385             Log.e(TAG, "Error while requesting strong auth: " + e);
1386         }
1387     }
1388
1389     private void onAfterChangingPassword(int userHandle) {
1390         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
1391     }
1392
1393     public boolean isCredentialRequiredToDecrypt(boolean defaultValue) {
1394         final int value = Settings.Global.getInt(mContentResolver,
1395                 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1);
1396         return value == -1 ? defaultValue : (value != 0);
1397     }
1398
1399     public void setCredentialRequiredToDecrypt(boolean required) {
1400         if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
1401             throw new IllegalStateException(
1402                     "Only the system or primary user may call setCredentialRequiredForDecrypt()");
1403         }
1404
1405         if (isDeviceEncryptionEnabled()){
1406             Settings.Global.putInt(mContext.getContentResolver(),
1407                Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0);
1408         }
1409     }
1410
1411     private boolean isDoNotAskCredentialsOnBootSet() {
1412         return mDevicePolicyManager.getDoNotAskCredentialsOnBoot();
1413     }
1414
1415     private boolean shouldEncryptWithCredentials(boolean defaultValue) {
1416         return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
1417     }
1418
1419     private void throwIfCalledOnMainThread() {
1420         if (Looper.getMainLooper().isCurrentThread()) {
1421             throw new IllegalStateException("should not be called from the main thread.");
1422         }
1423     }
1424
1425     public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1426         try {
1427             getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
1428         } catch (RemoteException e) {
1429             throw new RuntimeException("Could not register StrongAuthTracker");
1430         }
1431     }
1432
1433     public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
1434         try {
1435             getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
1436         } catch (RemoteException e) {
1437             Log.e(TAG, "Could not unregister StrongAuthTracker", e);
1438         }
1439     }
1440
1441     /**
1442      * @see StrongAuthTracker#getStrongAuthForUser
1443      */
1444     public int getStrongAuthForUser(int userId) {
1445         try {
1446             return getLockSettings().getStrongAuthForUser(userId);
1447         } catch (RemoteException e) {
1448             Log.e(TAG, "Could not get StrongAuth", e);
1449             return StrongAuthTracker.getDefaultFlags(mContext);
1450         }
1451     }
1452
1453     /**
1454      * @see StrongAuthTracker#isTrustAllowedForUser
1455      */
1456     public boolean isTrustAllowedForUser(int userId) {
1457         return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
1458     }
1459
1460     /**
1461      * @see StrongAuthTracker#isFingerprintAllowedForUser
1462      */
1463     public boolean isFingerprintAllowedForUser(int userId) {
1464         return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0;
1465     }
1466
1467     private ICheckCredentialProgressCallback wrapCallback(
1468             final CheckCredentialProgressCallback callback) {
1469         if (callback == null) {
1470             return null;
1471         } else {
1472             if (mHandler == null) {
1473                 throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
1474                         + " to use progress callbacks.");
1475             }
1476             return new ICheckCredentialProgressCallback.Stub() {
1477
1478                 @Override
1479                 public void onCredentialVerified() throws RemoteException {
1480                     mHandler.post(callback::onEarlyMatched);
1481                 }
1482             };
1483         }
1484     }
1485
1486     /**
1487      * Callback to be notified about progress when checking credentials.
1488      */
1489     public interface CheckCredentialProgressCallback {
1490
1491         /**
1492          * Called as soon as possible when we know that the credentials match but the user hasn't
1493          * been fully unlocked.
1494          */
1495         void onEarlyMatched();
1496     }
1497
1498     /**
1499      * Tracks the global strong authentication state.
1500      */
1501     public static class StrongAuthTracker {
1502
1503         @IntDef(flag = true,
1504                 value = { STRONG_AUTH_NOT_REQUIRED,
1505                         STRONG_AUTH_REQUIRED_AFTER_BOOT,
1506                         STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
1507                         SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
1508                         STRONG_AUTH_REQUIRED_AFTER_LOCKOUT})
1509         @Retention(RetentionPolicy.SOURCE)
1510         public @interface StrongAuthFlags {}
1511
1512         /**
1513          * Strong authentication is not required.
1514          */
1515         public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
1516
1517         /**
1518          * Strong authentication is required because the user has not authenticated since boot.
1519          */
1520         public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
1521
1522         /**
1523          * Strong authentication is required because a device admin has requested it.
1524          */
1525         public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
1526
1527         /**
1528          * Some authentication is required because the user has temporarily disabled trust.
1529          */
1530         public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
1531
1532         /**
1533          * Strong authentication is required because the user has been locked out after too many
1534          * attempts.
1535          */
1536         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
1537
1538         /**
1539          * Strong auth flags that do not prevent fingerprint from being accepted as auth.
1540          *
1541          * If any other flags are set, fingerprint is disabled.
1542          */
1543         private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
1544                 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
1545
1546         private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
1547         private final H mHandler;
1548         private final int mDefaultStrongAuthFlags;
1549
1550         public StrongAuthTracker(Context context) {
1551             this(context, Looper.myLooper());
1552         }
1553
1554         /**
1555          * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
1556          *               will be scheduled.
1557          * @param context the current {@link Context}
1558          */
1559         public StrongAuthTracker(Context context, Looper looper) {
1560             mHandler = new H(looper);
1561             mDefaultStrongAuthFlags = getDefaultFlags(context);
1562         }
1563
1564         public static @StrongAuthFlags int getDefaultFlags(Context context) {
1565             boolean strongAuthRequired = context.getResources().getBoolean(
1566                     com.android.internal.R.bool.config_strongAuthRequiredOnBoot);
1567             return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED;
1568         }
1569
1570         /**
1571          * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
1572          * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
1573          * authentication is required.
1574          *
1575          * @param userId the user for whom the state is queried.
1576          */
1577         public @StrongAuthFlags int getStrongAuthForUser(int userId) {
1578             return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags);
1579         }
1580
1581         /**
1582          * @return true if unlocking with trust alone is allowed for {@param userId} by the current
1583          * strong authentication requirements.
1584          */
1585         public boolean isTrustAllowedForUser(int userId) {
1586             return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
1587         }
1588
1589         /**
1590          * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
1591          * current strong authentication requirements.
1592          */
1593         public boolean isFingerprintAllowedForUser(int userId) {
1594             return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
1595         }
1596
1597         /**
1598          * Called when the strong authentication requirements for {@param userId} changed.
1599          */
1600         public void onStrongAuthRequiredChanged(int userId) {
1601         }
1602
1603         protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1604                 int userId) {
1605             int oldValue = getStrongAuthForUser(userId);
1606             if (strongAuthFlags != oldValue) {
1607                 if (strongAuthFlags == mDefaultStrongAuthFlags) {
1608                     mStrongAuthRequiredForUser.delete(userId);
1609                 } else {
1610                     mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
1611                 }
1612                 onStrongAuthRequiredChanged(userId);
1613             }
1614         }
1615
1616
1617         protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
1618             @Override
1619             public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
1620                     int userId) {
1621                 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
1622                         strongAuthFlags, userId).sendToTarget();
1623             }
1624         };
1625
1626         private class H extends Handler {
1627             static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
1628
1629             public H(Looper looper) {
1630                 super(looper);
1631             }
1632
1633             @Override
1634             public void handleMessage(Message msg) {
1635                 switch (msg.what) {
1636                     case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
1637                         handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
1638                         break;
1639                 }
1640             }
1641         };
1642     }
1643 }