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