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