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