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