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