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