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