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