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