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