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