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