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 android.app; 18 19 import android.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresFeature; 26 import android.annotation.RequiresPermission; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.annotation.TestApi; 30 import android.annotation.UserIdInt; 31 import android.app.admin.DevicePolicyManager; 32 import android.app.admin.DevicePolicyManager.PasswordComplexity; 33 import android.app.admin.PasswordMetrics; 34 import android.app.trust.ITrustManager; 35 import android.compat.annotation.UnsupportedAppUsage; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.pm.PackageManager; 40 import android.content.pm.ResolveInfo; 41 import android.os.Binder; 42 import android.os.Build; 43 import android.os.IBinder; 44 import android.os.RemoteException; 45 import android.os.ServiceManager; 46 import android.os.ServiceManager.ServiceNotFoundException; 47 import android.os.UserHandle; 48 import android.provider.Settings; 49 import android.service.persistentdata.IPersistentDataBlockService; 50 import android.util.ArrayMap; 51 import android.util.Log; 52 import android.view.IOnKeyguardExitResult; 53 import android.view.IWindowManager; 54 import android.view.WindowManagerGlobal; 55 56 import com.android.internal.annotations.GuardedBy; 57 import com.android.internal.annotations.VisibleForTesting; 58 import com.android.internal.policy.IDeviceLockedStateListener; 59 import com.android.internal.policy.IKeyguardDismissCallback; 60 import com.android.internal.policy.IKeyguardLockedStateListener; 61 import com.android.internal.util.Preconditions; 62 import com.android.internal.widget.IWeakEscrowTokenActivatedListener; 63 import com.android.internal.widget.IWeakEscrowTokenRemovedListener; 64 import com.android.internal.widget.LockPatternUtils; 65 import com.android.internal.widget.LockPatternView; 66 import com.android.internal.widget.LockscreenCredential; 67 import com.android.internal.widget.PasswordValidationError; 68 import com.android.internal.widget.VerifyCredentialResponse; 69 70 import java.lang.annotation.Retention; 71 import java.lang.annotation.RetentionPolicy; 72 import java.nio.charset.Charset; 73 import java.util.List; 74 import java.util.Objects; 75 import java.util.concurrent.Executor; 76 77 /** 78 * Class to manage and query the state of the lock screen (also known as Keyguard). 79 */ 80 @SystemService(Context.KEYGUARD_SERVICE) 81 public class KeyguardManager { 82 83 private static final String TAG = "KeyguardManager"; 84 85 private final Context mContext; 86 private final LockPatternUtils mLockPatternUtils; 87 private final IWindowManager mWM; 88 private final IActivityManager mAm; 89 private final ITrustManager mTrustManager; 90 private final INotificationManager mNotificationManager; 91 private final ArrayMap<WeakEscrowTokenRemovedListener, IWeakEscrowTokenRemovedListener> 92 mListeners = new ArrayMap<>(); 93 94 /** 95 * Intent used to prompt user for device credentials. 96 * @hide 97 */ 98 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL = 99 "android.app.action.CONFIRM_DEVICE_CREDENTIAL"; 100 101 /** 102 * Intent used to prompt user for device credentials. 103 * @hide 104 */ 105 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER = 106 "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER"; 107 108 /** 109 * Intent used to prompt user for factory reset credentials. 110 * @hide 111 */ 112 public static final String ACTION_CONFIRM_FRP_CREDENTIAL = 113 "android.app.action.CONFIRM_FRP_CREDENTIAL"; 114 115 /** 116 * Intent used to prompt user to to validate the credentials of a remote device. 117 * @hide 118 */ 119 public static final String ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL = 120 "android.app.action.CONFIRM_REMOTE_DEVICE_CREDENTIAL"; 121 122 /** 123 * Intent used to prompt user for device credential for entering repair 124 * mode. If the credential is verified successfully, then the information 125 * needed to verify the credential again will be written to a location that 126 * is available to repair mode. This makes it possible for repair mode to 127 * require that the same credential be provided to exit repair mode. 128 * @hide 129 */ 130 public static final String ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL = 131 "android.app.action.PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL"; 132 133 /** 134 * Intent used to prompt user for device credential that is written by 135 * {@link #ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL} for exiting 136 * repair mode. 137 * @hide 138 */ 139 public static final String ACTION_CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL = 140 "android.app.action.CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL"; 141 142 /** 143 * A CharSequence dialog title to show to the user when used with a 144 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 145 * @hide 146 */ 147 public static final String EXTRA_TITLE = "android.app.extra.TITLE"; 148 149 /** 150 * A CharSequence description to show to the user when used with 151 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 152 * @hide 153 */ 154 public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION"; 155 156 /** 157 * A CharSequence description to show to the user on the alternate button when used with 158 * {@link #ACTION_CONFIRM_FRP_CREDENTIAL}. 159 * @hide 160 */ 161 public static final String EXTRA_ALTERNATE_BUTTON_LABEL = 162 "android.app.extra.ALTERNATE_BUTTON_LABEL"; 163 164 /** 165 * A CharSequence label for the checkbox when used with 166 * {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} 167 * @hide 168 */ 169 public static final String EXTRA_CHECKBOX_LABEL = "android.app.extra.CHECKBOX_LABEL"; 170 171 /** 172 * A {@link RemoteLockscreenValidationSession} extra to be sent along with 173 * {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for 174 * a remote device's lock screen. 175 * @hide 176 */ 177 public static final String EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION = 178 "android.app.extra.REMOTE_LOCKSCREEN_VALIDATION_SESSION"; 179 180 /** 181 * A boolean indicating that credential confirmation activity should be a task overlay. 182 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER}. 183 * @hide 184 */ 185 public static final String EXTRA_FORCE_TASK_OVERLAY = 186 "android.app.KeyguardManager.FORCE_TASK_OVERLAY"; 187 188 /** 189 * Result code returned by the activity started by 190 * {@link #createConfirmFactoryResetCredentialIntent} or 191 * {@link #createConfirmDeviceCredentialForRemoteValidationIntent} 192 * indicating that the user clicked the alternate button. 193 * 194 * @hide 195 */ 196 public static final int RESULT_ALTERNATE = 1; 197 198 /** 199 * 200 * If this is set, check device policy for allowed biometrics when the user is authenticating. 201 * This should only be used in the context of managed profiles. 202 * 203 * @hide 204 */ 205 public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; 206 207 /** 208 * When switching to a secure user, system server will expect a callback when the UI has 209 * completed the switch. 210 * 211 * @hide 212 */ 213 public static final String LOCK_ON_USER_SWITCH_CALLBACK = "onSwitchCallback"; 214 215 216 /** 217 * 218 * Password lock type, see {@link #setLock} 219 * 220 * @hide 221 */ 222 @SystemApi 223 public static final int PASSWORD = 0; 224 225 /** 226 * 227 * Pin lock type, see {@link #setLock} 228 * 229 * @hide 230 */ 231 @SystemApi 232 public static final int PIN = 1; 233 234 /** 235 * 236 * Pattern lock type, see {@link #setLock} 237 * 238 * @hide 239 */ 240 @SystemApi 241 public static final int PATTERN = 2; 242 243 /** 244 * Available lock types 245 */ 246 @IntDef({ 247 PASSWORD, 248 PIN, 249 PATTERN 250 }) 251 @Retention(RetentionPolicy.SOURCE) 252 @interface LockTypes {} 253 254 private final IKeyguardLockedStateListener mIKeyguardLockedStateListener = 255 new IKeyguardLockedStateListener.Stub() { 256 @Override 257 public void onKeyguardLockedStateChanged(boolean isKeyguardLocked) { 258 mKeyguardLockedStateListeners.forEach((listener, executor) -> { 259 executor.execute( 260 () -> listener.onKeyguardLockedStateChanged(isKeyguardLocked)); 261 }); 262 } 263 }; 264 private final ArrayMap<KeyguardLockedStateListener, Executor> 265 mKeyguardLockedStateListeners = new ArrayMap<>(); 266 267 private final IDeviceLockedStateListener mIDeviceLockedStateListener = 268 new IDeviceLockedStateListener.Stub() { 269 @Override 270 public void onDeviceLockedStateChanged(boolean isDeviceLocked) { 271 if (!Flags.deviceUnlockListener()) { 272 return; 273 } 274 synchronized (mDeviceLockedStateListeners) { 275 mDeviceLockedStateListeners.forEach((listener, executor) -> { 276 executor.execute( 277 () -> listener.onDeviceLockedStateChanged(isDeviceLocked)); 278 }); 279 } 280 } 281 }; 282 283 @GuardedBy("mDeviceLockedStateListeners") 284 private final ArrayMap<DeviceLockedStateListener, Executor> 285 mDeviceLockedStateListeners = new ArrayMap<>(); 286 287 /** 288 * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics 289 * if enrolled) for the current user of the device. The caller is expected to launch this 290 * activity using {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 291 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 292 * 293 * @return the intent for launching the activity or null if no password is required. 294 * 295 * @deprecated see {@link 296 * android.hardware.biometrics.BiometricPrompt.Builder#setAllowedAuthenticators(int)} 297 */ 298 @Deprecated 299 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description)300 public Intent createConfirmDeviceCredentialIntent(CharSequence title, 301 CharSequence description) { 302 if (!isDeviceSecure()) return null; 303 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL); 304 intent.putExtra(EXTRA_TITLE, title); 305 intent.putExtra(EXTRA_DESCRIPTION, description); 306 307 // explicitly set the package for security 308 intent.setPackage(getSettingsPackageForIntent(intent)); 309 return intent; 310 } 311 312 /** 313 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 314 * for the given user. The caller is expected to launch this activity using 315 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 316 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 317 * 318 * @return the intent for launching the activity or null if no password is required. 319 * 320 * @hide 321 */ createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId)322 public Intent createConfirmDeviceCredentialIntent( 323 CharSequence title, CharSequence description, int userId) { 324 if (!isDeviceSecure(userId)) return null; 325 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER); 326 intent.putExtra(EXTRA_TITLE, title); 327 intent.putExtra(EXTRA_DESCRIPTION, description); 328 intent.putExtra(Intent.EXTRA_USER_ID, userId); 329 330 // explicitly set the package for security 331 intent.setPackage(getSettingsPackageForIntent(intent)); 332 333 return intent; 334 } 335 336 /** 337 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 338 * for the given user. The caller is expected to launch this activity using 339 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 340 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 341 * 342 * @param disallowBiometricsIfPolicyExists If true check if the Device Policy Manager has 343 * disabled biometrics on the device. If biometrics are disabled, fall back to PIN/pattern/pass. 344 * 345 * @return the intent for launching the activity or null if no password is required. 346 * 347 * @hide 348 */ createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId, boolean disallowBiometricsIfPolicyExists)349 public Intent createConfirmDeviceCredentialIntent( 350 CharSequence title, CharSequence description, int userId, 351 boolean disallowBiometricsIfPolicyExists) { 352 Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId); 353 if (intent != null) { 354 intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, 355 disallowBiometricsIfPolicyExists); 356 } 357 return intent; 358 } 359 360 /** 361 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 362 * for the previous owner of the device. The caller is expected to launch this activity using 363 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 364 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 365 * 366 * @param alternateButtonLabel if not empty, a button is provided with the given label. Upon 367 * clicking this button, the activity returns 368 * {@link #RESULT_ALTERNATE} 369 * 370 * @return the intent for launching the activity or null if the previous owner of the device 371 * did not set a credential. 372 * @throws UnsupportedOperationException if the device does not support factory reset 373 * credentials 374 * @throws IllegalStateException if the device has already been provisioned 375 * @hide 376 */ 377 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 378 @SystemApi createConfirmFactoryResetCredentialIntent( CharSequence title, CharSequence description, CharSequence alternateButtonLabel)379 public Intent createConfirmFactoryResetCredentialIntent( 380 CharSequence title, CharSequence description, CharSequence alternateButtonLabel) { 381 if (!LockPatternUtils.frpCredentialEnabled(mContext)) { 382 Log.w(TAG, "Factory reset credentials not supported."); 383 throw new UnsupportedOperationException("not supported on this device"); 384 } 385 386 // Cannot verify credential if the device is provisioned 387 if (Settings.Global.getInt(mContext.getContentResolver(), 388 Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 389 Log.e(TAG, "Factory reset credential cannot be verified after provisioning."); 390 throw new IllegalStateException("must not be provisioned yet"); 391 } 392 393 // Make sure we have a credential 394 try { 395 IPersistentDataBlockService pdb = IPersistentDataBlockService.Stub.asInterface( 396 ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE)); 397 if (pdb == null) { 398 Log.e(TAG, "No persistent data block service"); 399 throw new UnsupportedOperationException("not supported on this device"); 400 } 401 // The following will throw an UnsupportedOperationException if the device does not 402 // support factory reset credentials (or something went wrong retrieving it). 403 if (!pdb.hasFrpCredentialHandle()) { 404 Log.i(TAG, "The persistent data block does not have a factory reset credential."); 405 return null; 406 } 407 } catch (RemoteException e) { 408 throw e.rethrowFromSystemServer(); 409 } 410 411 Intent intent = new Intent(ACTION_CONFIRM_FRP_CREDENTIAL); 412 intent.putExtra(EXTRA_TITLE, title); 413 intent.putExtra(EXTRA_DESCRIPTION, description); 414 intent.putExtra(EXTRA_ALTERNATE_BUTTON_LABEL, alternateButtonLabel); 415 416 // explicitly set the package for security 417 intent.setPackage(getSettingsPackageForIntent(intent)); 418 419 return intent; 420 } 421 422 /** 423 * Get an Intent to launch an activity to prompt the user to confirm the 424 * credentials (pin, pattern or password) of a remote device. 425 * @param session contains information necessary to start remote device credential validation. 426 * @param remoteLockscreenValidationServiceComponent 427 * the {@link ComponentName} of the implementation of 428 * {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService} 429 * @param checkboxLabel if not empty, a checkbox is provided with the given label. When checked, 430 * the validated remote device credential will be set as the device lock of 431 * the current device. 432 * @param alternateButtonLabel if not empty, a button is provided with the given label. Upon 433 * clicking this button, the activity returns 434 * {@link #RESULT_ALTERNATE}. 435 * @hide 436 */ 437 @SystemApi 438 @RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN) 439 @NonNull createConfirmDeviceCredentialForRemoteValidationIntent( @onNull RemoteLockscreenValidationSession session, @NonNull ComponentName remoteLockscreenValidationServiceComponent, @Nullable CharSequence title, @Nullable CharSequence description, @Nullable CharSequence checkboxLabel, @Nullable CharSequence alternateButtonLabel)440 public Intent createConfirmDeviceCredentialForRemoteValidationIntent( 441 @NonNull RemoteLockscreenValidationSession session, 442 @NonNull ComponentName remoteLockscreenValidationServiceComponent, 443 @Nullable CharSequence title, 444 @Nullable CharSequence description, 445 @Nullable CharSequence checkboxLabel, 446 @Nullable CharSequence alternateButtonLabel) { 447 Intent intent = new Intent(ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL) 448 .putExtra(EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION, session) 449 .putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent) 450 .putExtra(EXTRA_TITLE, title) 451 .putExtra(EXTRA_DESCRIPTION, description) 452 .putExtra(EXTRA_CHECKBOX_LABEL, checkboxLabel) 453 .putExtra(EXTRA_ALTERNATE_BUTTON_LABEL, alternateButtonLabel); 454 455 // explicitly set the package for security 456 intent.setPackage(getSettingsPackageForIntent(intent)); 457 458 return intent; 459 } 460 461 /** 462 * Controls whether notifications can be shown atop a securely locked screen in their full 463 * private form (same as when the device is unlocked). 464 * 465 * <p>Other sources like the DevicePolicyManger and Settings app can modify this configuration. 466 * The result is that private notifications are only shown if all sources allow it. 467 * 468 * @param allow secure notifications can be shown if {@code true}, 469 * secure notifications cannot be shown if {@code false} 470 * @hide 471 */ 472 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 473 @RequiresPermission(Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) 474 @SystemApi setPrivateNotificationsAllowed(boolean allow)475 public void setPrivateNotificationsAllowed(boolean allow) { 476 try { 477 mNotificationManager.setPrivateNotificationsAllowed(allow); 478 } catch (RemoteException e) { 479 throw e.rethrowFromSystemServer(); 480 } 481 } 482 483 /** 484 * Returns whether notifications can be shown atop a securely locked screen in their full 485 * private form (same as when the device is unlocked). 486 * 487 * @return {@code true} if secure notifications can be shown, {@code false} otherwise. 488 * By default, private notifications are allowed. 489 * @hide 490 */ 491 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 492 @RequiresPermission(Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) 493 @SystemApi getPrivateNotificationsAllowed()494 public boolean getPrivateNotificationsAllowed() { 495 try { 496 return mNotificationManager.getPrivateNotificationsAllowed(); 497 } catch (RemoteException e) { 498 throw e.rethrowFromSystemServer(); 499 } 500 } 501 getSettingsPackageForIntent(Intent intent)502 private String getSettingsPackageForIntent(Intent intent) { 503 List<ResolveInfo> resolveInfos = mContext.getPackageManager() 504 .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); 505 for (int i = 0; i < resolveInfos.size(); i++) { 506 return resolveInfos.get(i).activityInfo.packageName; 507 } 508 509 return "com.android.settings"; 510 } 511 512 /** 513 * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows 514 * you to temporarily disable / reenable the keyguard (lock screen). 515 * 516 * @deprecated Use {@link android.R.attr#showWhenLocked} or {@link 517 * android.app.Activity#setShowWhenLocked(boolean)} instead. This allows you to seamlessly 518 * occlude and unocclude the keyguard as your application moves in and out of the foreground 519 * and does not require that any special permissions be requested. 520 */ 521 @Deprecated 522 public class KeyguardLock { 523 private final IBinder mToken = new Binder(); 524 private final String mTag; 525 KeyguardLock(String tag)526 KeyguardLock(String tag) { 527 mTag = tag; 528 } 529 530 /** 531 * Disable the keyguard from showing. If the keyguard is currently 532 * showing, hide it. The keyguard will be prevented from showing again 533 * until {@link #reenableKeyguard()} is called. 534 * <p> 535 * This only works if the keyguard is not secure. 536 * <p> 537 * A good place to call this is from {@link android.app.Activity#onResume()} 538 * 539 * @see KeyguardManager#isKeyguardSecure() 540 * @see #reenableKeyguard() 541 */ 542 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) disableKeyguard()543 public void disableKeyguard() { 544 try { 545 mWM.disableKeyguard(mToken, mTag, mContext.getUserId()); 546 } catch (RemoteException ex) { 547 } 548 } 549 550 /** 551 * Reenable the keyguard. The keyguard will reappear if the previous 552 * call to {@link #disableKeyguard()} caused it to be hidden. 553 * 554 * A good place to call this is from {@link android.app.Activity#onPause()} 555 * 556 * @see #disableKeyguard() 557 */ 558 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) reenableKeyguard()559 public void reenableKeyguard() { 560 try { 561 mWM.reenableKeyguard(mToken, mContext.getUserId()); 562 } catch (RemoteException ex) { 563 } 564 } 565 } 566 567 /** 568 * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify 569 * caller of result. 570 * 571 * @deprecated Use {@link KeyguardDismissCallback} 572 */ 573 @Deprecated 574 public interface OnKeyguardExitResult { 575 576 /** 577 * @param success True if the user was able to authenticate, false if 578 * not. 579 */ onKeyguardExitResult(boolean success)580 void onKeyguardExitResult(boolean success); 581 } 582 583 /** 584 * Callback passed to 585 * {@link KeyguardManager#requestDismissKeyguard(Activity, KeyguardDismissCallback)} 586 * to notify caller of result. 587 */ 588 public static abstract class KeyguardDismissCallback { 589 590 /** 591 * Called when dismissing Keyguard is currently not feasible, i.e. when Keyguard is not 592 * available, not showing or when the activity requesting the Keyguard dismissal isn't 593 * showing or isn't showing behind Keyguard. 594 */ onDismissError()595 public void onDismissError() { } 596 597 /** 598 * Called when dismissing Keyguard has succeeded and the device is now unlocked. 599 */ onDismissSucceeded()600 public void onDismissSucceeded() { } 601 602 /** 603 * Called when dismissing Keyguard has been cancelled, i.e. when the user cancelled the 604 * operation or the bouncer was hidden for some other reason. 605 */ onDismissCancelled()606 public void onDismissCancelled() { } 607 } 608 609 /** 610 * Callback passed to 611 * {@link KeyguardManager#addWeakEscrowToken} 612 * to notify caller of state change. 613 * @hide 614 */ 615 @SystemApi 616 public interface WeakEscrowTokenActivatedListener { 617 /** 618 * The method to be called when the token is activated. 619 * @param handle 64 bit handle corresponding to the escrow token 620 * @param user user for whom the weak escrow token has been added 621 */ onWeakEscrowTokenActivated(long handle, @NonNull UserHandle user)622 void onWeakEscrowTokenActivated(long handle, @NonNull UserHandle user); 623 } 624 625 /** 626 * Listener passed to 627 * {@link KeyguardManager#registerWeakEscrowTokenRemovedListener} and 628 * {@link KeyguardManager#unregisterWeakEscrowTokenRemovedListener} 629 * to notify caller of an weak escrow token has been removed. 630 * @hide 631 */ 632 @SystemApi 633 public interface WeakEscrowTokenRemovedListener { 634 /** 635 * The method to be called when the token is removed. 636 * @param handle 64 bit handle corresponding to the escrow token 637 * @param user user for whom the escrow token has been added 638 */ onWeakEscrowTokenRemoved(long handle, @NonNull UserHandle user)639 void onWeakEscrowTokenRemoved(long handle, @NonNull UserHandle user); 640 } 641 KeyguardManager(Context context)642 KeyguardManager(Context context) throws ServiceNotFoundException { 643 mContext = context; 644 mLockPatternUtils = new LockPatternUtils(context); 645 mWM = WindowManagerGlobal.getWindowManagerService(); 646 mAm = ActivityManager.getService(); 647 mTrustManager = ITrustManager.Stub.asInterface( 648 ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE)); 649 mNotificationManager = INotificationManager.Stub.asInterface( 650 ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE)); 651 } 652 653 /** 654 * Enables you to temporarily disable / reenable the keyguard (lock screen). 655 * 656 * @param tag A tag that informally identifies who you are (for debugging who 657 * is disabling the keyguard). 658 * 659 * @return A {@link KeyguardLock} handle to use to disable and reenable the 660 * keyguard. 661 * 662 * @deprecated Use {@link android.R.attr#showWhenLocked} or {@link 663 * android.app.Activity#setShowWhenLocked(boolean)} instead. This allows you to seamlessly 664 * occlude and unocclude the keyguard as your application moves in and out of the foreground 665 * and does not require that any special permissions be requested. 666 */ 667 @Deprecated newKeyguardLock(String tag)668 public KeyguardLock newKeyguardLock(String tag) { 669 return new KeyguardLock(tag); 670 } 671 672 /** 673 * Returns whether the lock screen (also known as Keyguard) is showing. 674 * <p> 675 * Specifically, this returns {@code true} in the following cases: 676 * <ul> 677 * <li>The lock screen is showing in the foreground.</li> 678 * <li>The lock screen is showing, but it is occluded by an activity that is showing on top of 679 * it. A common example is the phone app receiving a call or making an emergency call.</li> 680 * <li>The lock screen was showing but is temporarily disabled as a result of <a 681 * href="https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode">lock task 682 * mode</a> or an app using the deprecated {@link KeyguardLock} API.</li> 683 * </ul> 684 * <p> 685 * "Showing" refers to a logical state of the UI, regardless of whether the screen happens to be 686 * on. When the power button is pressed on an unlocked device, the lock screen starts "showing" 687 * immediately when the screen turns off. 688 * <p> 689 * This method does not distinguish a lock screen that is requiring authentication (e.g. with 690 * PIN, pattern, password, or biometric) from a lock screen that is trivially dismissible (e.g. 691 * with swipe). It also does not distinguish a lock screen requesting a SIM card PIN from a 692 * normal device lock screen. Finally, it always returns the global lock screen state and does 693 * not consider the {@link Context}'s user specifically. 694 * <p> 695 * Note that {@code isKeyguardLocked()} is confusingly named and probably should be called 696 * {@code isKeyguardShowing()}. On many devices, the lock screen displays an <i>unlocked</i> 697 * padlock icon when it is trivially dismissible. As mentioned above, {@code isKeyguardLocked()} 698 * actually returns {@code true} in this case, not {@code false} as might be expected. {@link 699 * #isDeviceLocked()} is an alternative API that has slightly different semantics. 700 * 701 * @return {@code true} if the lock screen is showing 702 * @see #isDeviceLocked() 703 */ isKeyguardLocked()704 public boolean isKeyguardLocked() { 705 try { 706 return mWM.isKeyguardLocked(); 707 } catch (RemoteException ex) { 708 return false; 709 } 710 } 711 712 /** 713 * Returns whether the user has a secure lock screen or there is a locked SIM card. 714 * <p> 715 * Specifically, this returns {@code true} if at least one of the following is true: 716 * <ul> 717 * <li>The {@link Context}'s user has a secure lock screen. A full user or a profile that uses 718 * a separate challenge has a secure lock screen if its lock screen is set to PIN, pattern, or 719 * password, as opposed to swipe or none. A profile that uses a unified challenge is 720 * considered to have a secure lock screen if and only if its parent user has a secure lock 721 * screen.</li> 722 * <li>At least one SIM card is currently locked and requires a PIN.</li> 723 * </ul> 724 * <p> 725 * This method does not consider whether the lock screen is currently showing or not. 726 * <p> 727 * See also {@link #isDeviceSecure()} which excludes locked SIM cards. 728 * 729 * @return {@code true} if the user has a secure lock screen or there is a locked SIM card 730 * @see #isDeviceSecure() 731 */ isKeyguardSecure()732 public boolean isKeyguardSecure() { 733 try { 734 return mWM.isKeyguardSecure(mContext.getUserId()); 735 } catch (RemoteException ex) { 736 return false; 737 } 738 } 739 740 /** 741 * Returns whether the lock screen is showing. 742 * <p> 743 * This is exactly the same as {@link #isKeyguardLocked()}. 744 * 745 * @return the value of {@link #isKeyguardLocked()} 746 * @deprecated Use {@link #isKeyguardLocked()} instead. 747 */ inKeyguardRestrictedInputMode()748 public boolean inKeyguardRestrictedInputMode() { 749 return isKeyguardLocked(); 750 } 751 752 /** 753 * Returns whether the device is currently locked for the user. 754 * <p> 755 * This method returns the device locked state for the {@link Context}'s user. The device is 756 * considered to be locked for a user when the user's apps are currently inaccessible and some 757 * form of lock screen authentication is required to regain access to them. The lock screen 758 * authentication typically uses PIN, pattern, password, or biometric. Some devices may support 759 * additional methods, such as unlock using a paired smartwatch. "Swipe" does not count as 760 * authentication; if the lock screen is dismissible with swipe, for example due to the lock 761 * screen being set to Swipe or due to the device being kept unlocked by being near a trusted 762 * bluetooth device or in a trusted location, the device is considered unlocked. 763 * <div class="note"> 764 * <p> 765 * <b>Note:</b> In the case of multiple full users, each user can have their own lock screen 766 * authentication configured. The device-locked state may differ between different users. For 767 * example, the device may be unlocked for the current user, but locked for a non-current user 768 * if lock screen authentication would be required to access that user's apps after switching to 769 * that user. 770 * <p> 771 * In the case of a profile, when the device goes to the main lock screen, up to two layers of 772 * authentication may be required to regain access to the profile's apps: one to unlock the main 773 * lock screen, and one to unlock the profile (when a separate profile challenge is required). 774 * For a profile, the device is considered to be locked as long as any challenge remains, either 775 * the parent user's challenge (when applicable) or the profile's challenge (when applicable). 776 * </div> 777 * 778 * @return {@code true} if the device is currently locked for the user 779 * @see #isKeyguardLocked() 780 */ isDeviceLocked()781 public boolean isDeviceLocked() { 782 return isDeviceLocked(mContext.getUserId(), mContext.getDeviceId()); 783 } 784 785 /** 786 * Per-user version of {@link #isDeviceLocked()}. 787 * 788 * @hide 789 */ 790 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) isDeviceLocked(int userId)791 public boolean isDeviceLocked(int userId) { 792 return isDeviceLocked(userId, mContext.getDeviceId()); 793 } 794 795 /** 796 * Per-user per-device version of {@link #isDeviceLocked()}. 797 * 798 * @hide 799 */ isDeviceLocked(@serIdInt int userId, int deviceId)800 public boolean isDeviceLocked(@UserIdInt int userId, int deviceId) { 801 try { 802 return mTrustManager.isDeviceLocked(userId, deviceId); 803 } catch (RemoteException e) { 804 return false; 805 } 806 } 807 808 /** 809 * Returns whether the user has a secure lock screen. 810 * <p> 811 * This returns {@code true} if the {@link Context}'s user has a secure lock screen. A full user 812 * or a profile that uses a separate challenge has a secure lock screen if its lock screen is 813 * set to PIN, pattern, or password, as opposed to swipe or none. A profile that uses a unified 814 * challenge is considered to have a secure lock screen if and only if its parent user has a 815 * secure lock screen. 816 * <p> 817 * This method does not consider whether the lock screen is currently showing or not. 818 * <p> 819 * See also {@link #isKeyguardSecure()} which includes locked SIM cards. 820 * 821 * @return {@code true} if the user has a secure lock screen 822 * @see #isKeyguardSecure() 823 */ isDeviceSecure()824 public boolean isDeviceSecure() { 825 return isDeviceSecure(mContext.getUserId(), mContext.getDeviceId()); 826 } 827 828 /** 829 * Per-user version of {@link #isDeviceSecure()}. 830 * 831 * @hide 832 */ 833 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isDeviceSecure(int userId)834 public boolean isDeviceSecure(int userId) { 835 return isDeviceSecure(userId, mContext.getDeviceId()); 836 } 837 838 /** 839 * Per-user per-device version of {@link #isDeviceSecure()}. 840 * 841 * @hide 842 */ isDeviceSecure(@serIdInt int userId, int deviceId)843 public boolean isDeviceSecure(@UserIdInt int userId, int deviceId) { 844 try { 845 return mTrustManager.isDeviceSecure(userId, deviceId); 846 } catch (RemoteException e) { 847 return false; 848 } 849 } 850 851 /** 852 * Requests that the Keyguard (lock screen) be dismissed if it is currently showing. 853 * <p> 854 * If the Keyguard is not secure or the device is currently in a trusted state, calling this 855 * method will immediately dismiss the Keyguard without any user interaction. 856 * <p> 857 * If the Keyguard is secure and the device is not in a trusted state, this will bring up the 858 * UI so the user can enter their credentials. 859 * <p> 860 * If the value set for the {@link Activity} attr {@link android.R.attr#turnScreenOn} is true, 861 * the screen will turn on when the keyguard is dismissed. 862 * 863 * @param activity The activity requesting the dismissal. The activity must either be visible 864 * by using {@link android.R.attr#showWhenLocked} or {@link 865 * android.app.Activity#setShowWhenLocked(boolean)}, or must be in a state in 866 * which it would be visible if Keyguard would not be hiding it. If that's not 867 * the case, the request will fail immediately and 868 * {@link KeyguardDismissCallback#onDismissError} will be invoked. 869 * @param callback The callback to be called if the request to dismiss Keyguard was successful 870 * or {@code null} if the caller isn't interested in knowing the result. The 871 * callback will not be invoked if the activity was destroyed before the 872 * callback was received. 873 */ requestDismissKeyguard(@onNull Activity activity, @Nullable KeyguardDismissCallback callback)874 public void requestDismissKeyguard(@NonNull Activity activity, 875 @Nullable KeyguardDismissCallback callback) { 876 requestDismissKeyguard(activity, null /* message */, callback); 877 } 878 879 /** 880 * Requests that the Keyguard (lock screen) be dismissed if it is currently showing. 881 * <p> 882 * If the Keyguard is not secure or the device is currently in a trusted state, calling this 883 * method will immediately dismiss the Keyguard without any user interaction. 884 * <p> 885 * If the Keyguard is secure and the device is not in a trusted state, this will bring up the 886 * UI so the user can enter their credentials. 887 * <p> 888 * If the value set for the {@link Activity} attr {@link android.R.attr#turnScreenOn} is true, 889 * the screen will turn on when the keyguard is dismissed. 890 * 891 * @param activity The activity requesting the dismissal. The activity must either be visible 892 * by using {@link android.R.attr#showWhenLocked} or {@link 893 * android.app.Activity#setShowWhenLocked(boolean)}, or must be in a state in 894 * which it would be visible if Keyguard would not be hiding it. If that's not 895 * the case, the request will fail immediately and 896 * {@link KeyguardDismissCallback#onDismissError} will be invoked. 897 * @param message A message that will be shown in the keyguard explaining why the user 898 * would want to dismiss it. 899 * @param callback The callback to be called if the request to dismiss Keyguard was successful 900 * or {@code null} if the caller isn't interested in knowing the result. The 901 * callback will not be invoked if the activity was destroyed before the 902 * callback was received. 903 * @hide 904 */ 905 @RequiresPermission(Manifest.permission.SHOW_KEYGUARD_MESSAGE) 906 @SystemApi requestDismissKeyguard(@onNull Activity activity, @Nullable CharSequence message, @Nullable KeyguardDismissCallback callback)907 public void requestDismissKeyguard(@NonNull Activity activity, @Nullable CharSequence message, 908 @Nullable KeyguardDismissCallback callback) { 909 ActivityClient.getInstance().dismissKeyguard( 910 activity.getActivityToken(), new IKeyguardDismissCallback.Stub() { 911 @Override 912 public void onDismissError() throws RemoteException { 913 if (callback != null && !activity.isDestroyed()) { 914 activity.mHandler.post(callback::onDismissError); 915 } 916 } 917 918 @Override 919 public void onDismissSucceeded() throws RemoteException { 920 if (callback != null && !activity.isDestroyed()) { 921 activity.mHandler.post(callback::onDismissSucceeded); 922 } 923 } 924 925 @Override 926 public void onDismissCancelled() throws RemoteException { 927 if (callback != null && !activity.isDestroyed()) { 928 activity.mHandler.post(callback::onDismissCancelled); 929 } 930 } 931 }, message); 932 } 933 934 /** 935 * Exit the keyguard securely. The use case for this api is that, after 936 * disabling the keyguard, your app, which was granted permission to 937 * disable the keyguard and show a limited amount of information deemed 938 * safe without the user getting past the keyguard, needs to navigate to 939 * something that is not safe to view without getting past the keyguard. 940 * 941 * This will, if the keyguard is secure, bring up the unlock screen of 942 * the keyguard. 943 * 944 * @param callback Lets you know whether the operation was successful and 945 * it is safe to launch anything that would normally be considered safe 946 * once the user has gotten past the keyguard. 947 * 948 * @deprecated Use {@link android.R.attr#showWhenLocked} or {@link 949 * android.app.Activity#setShowWhenLocked(boolean)} to seamlessly occlude and unocclude the 950 * keyguard as your application moves in and out of the foreground, without requiring any 951 * special permissions. Use {@link #requestDismissKeyguard(android.app.Activity, 952 * KeyguardDismissCallback)} to request dismissal of the keyguard. 953 */ 954 @Deprecated 955 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) exitKeyguardSecurely(final OnKeyguardExitResult callback)956 public void exitKeyguardSecurely(final OnKeyguardExitResult callback) { 957 try { 958 mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() { 959 public void onKeyguardExitResult(boolean success) throws RemoteException { 960 if (callback != null) { 961 callback.onKeyguardExitResult(success); 962 } 963 } 964 }); 965 } catch (RemoteException e) { 966 967 } 968 } 969 970 /** @hide */ 971 @VisibleForTesting checkInitialLockMethodUsage()972 public boolean checkInitialLockMethodUsage() { 973 if (!hasPermission(Manifest.permission.SET_INITIAL_LOCK)) { 974 throw new SecurityException("Requires SET_INITIAL_LOCK permission."); 975 } 976 return true; 977 } 978 hasPermission(String permission)979 private boolean hasPermission(String permission) { 980 return PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( 981 permission); 982 } 983 984 /** 985 * Determine if a given password is valid based off its lock type and expected complexity level. 986 * 987 * @param lockType - type of lock as specified in {@link LockTypes} 988 * @param password - password to validate; this has the same encoding 989 * as the output of String#getBytes 990 * @param complexity - complexity level imposed by the requester 991 * as defined in {@code DevicePolicyManager.PasswordComplexity} 992 * @return {@code true} if the password is valid, false otherwise 993 * @hide 994 */ 995 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 996 @SystemApi isValidLockPasswordComplexity(@ockTypes int lockType, @NonNull byte[] password, @PasswordComplexity int complexity)997 public boolean isValidLockPasswordComplexity(@LockTypes int lockType, @NonNull byte[] password, 998 @PasswordComplexity int complexity) { 999 if (!checkInitialLockMethodUsage()) { 1000 return false; 1001 } 1002 Objects.requireNonNull(password, "Password cannot be null."); 1003 complexity = PasswordMetrics.sanitizeComplexityLevel(complexity); 1004 PasswordMetrics adminMetrics = 1005 mLockPatternUtils.getRequestedPasswordMetrics(mContext.getUserId()); 1006 try (LockscreenCredential credential = createLockscreenCredential(lockType, password)) { 1007 return PasswordMetrics.validateCredential(adminMetrics, complexity, 1008 credential).size() == 0; 1009 } 1010 } 1011 1012 /** 1013 * Determine the minimum allowable length for a lock type for a given complexity level. 1014 * 1015 * @param isPin - whether this is a PIN-type password (only digits) 1016 * @param complexity - complexity level imposed by the requester 1017 * as defined in {@code DevicePolicyManager.PasswordComplexity} 1018 * @return minimum allowable password length 1019 * @hide 1020 */ 1021 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 1022 @SystemApi getMinLockLength(boolean isPin, @PasswordComplexity int complexity)1023 public int getMinLockLength(boolean isPin, @PasswordComplexity int complexity) { 1024 if (!checkInitialLockMethodUsage()) { 1025 return -1; 1026 } 1027 complexity = PasswordMetrics.sanitizeComplexityLevel(complexity); 1028 PasswordMetrics adminMetrics = 1029 mLockPatternUtils.getRequestedPasswordMetrics(mContext.getUserId()); 1030 PasswordMetrics minMetrics = 1031 PasswordMetrics.applyComplexity(adminMetrics, isPin, complexity); 1032 return minMetrics.length; 1033 } 1034 1035 /** 1036 * Set the lockscreen password after validating against its expected complexity level. 1037 * 1038 * Below {@link android.os.Build.VERSION_CODES#S_V2}, this API will only work 1039 * when {@link PackageManager.FEATURE_AUTOMOTIVE} is present. 1040 * @param lockType - type of lock as specified in {@link LockTypes} 1041 * @param password - password to validate; this has the same encoding 1042 * as the output of String#getBytes 1043 * @param complexity - complexity level imposed by the requester 1044 * as defined in {@code DevicePolicyManager.PasswordComplexity} 1045 * @return {@code true} if the lock is successfully set, false otherwise 1046 * @hide 1047 */ 1048 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 1049 @SystemApi setLock(@ockTypes int lockType, @NonNull byte[] password, @PasswordComplexity int complexity)1050 public boolean setLock(@LockTypes int lockType, @NonNull byte[] password, 1051 @PasswordComplexity int complexity) { 1052 if (!checkInitialLockMethodUsage()) { 1053 return false; 1054 } 1055 1056 int userId = mContext.getUserId(); 1057 if (isDeviceSecure(userId)) { 1058 Log.e(TAG, "Password already set, rejecting call to setLock"); 1059 return false; 1060 } 1061 if (!isValidLockPasswordComplexity(lockType, password, complexity)) { 1062 Log.e(TAG, "Password is not valid, rejecting call to setLock"); 1063 return false; 1064 } 1065 boolean success; 1066 try (LockscreenCredential credential = createLockscreenCredential(lockType, password)) { 1067 success = mLockPatternUtils.setLockCredential( 1068 credential, 1069 /* savedPassword= */ LockscreenCredential.createNone(), 1070 userId); 1071 } catch (Exception e) { 1072 Log.e(TAG, "Save lock exception", e); 1073 success = false; 1074 } finally { 1075 LockPatternUtils.zeroize(password); 1076 } 1077 return success; 1078 } 1079 1080 /** 1081 * Create a weak escrow token for the current user, which can later be used to unlock FBE 1082 * or change user password. 1083 * 1084 * After adding, if the user currently has a secure lockscreen, they will need to perform a 1085 * confirm credential operation in order to activate the token for future use. If the user 1086 * has no secure lockscreen, then the token is activated immediately. 1087 * 1088 * If the user changes or removes the lockscreen password, any activated weak escrow token will 1089 * be removed. 1090 * 1091 * @return a unique 64-bit token handle which is needed to refer to this token later. 1092 * @hide 1093 */ 1094 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1095 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1096 @SystemApi addWeakEscrowToken(@onNull byte[] token, @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor, @NonNull WeakEscrowTokenActivatedListener listener)1097 public long addWeakEscrowToken(@NonNull byte[] token, @NonNull UserHandle user, 1098 @NonNull @CallbackExecutor Executor executor, 1099 @NonNull WeakEscrowTokenActivatedListener listener) { 1100 Objects.requireNonNull(token, "Token cannot be null."); 1101 Objects.requireNonNull(user, "User cannot be null."); 1102 Objects.requireNonNull(executor, "Executor cannot be null."); 1103 Objects.requireNonNull(listener, "Listener cannot be null."); 1104 int userId = user.getIdentifier(); 1105 IWeakEscrowTokenActivatedListener internalListener = 1106 new IWeakEscrowTokenActivatedListener.Stub() { 1107 @Override 1108 public void onWeakEscrowTokenActivated(long handle, int userId) { 1109 UserHandle user = UserHandle.of(userId); 1110 final long restoreToken = Binder.clearCallingIdentity(); 1111 try { 1112 executor.execute(() -> listener.onWeakEscrowTokenActivated(handle, user)); 1113 } finally { 1114 Binder.restoreCallingIdentity(restoreToken); 1115 } 1116 Log.i(TAG, "Weak escrow token activated."); 1117 } 1118 }; 1119 return mLockPatternUtils.addWeakEscrowToken(token, userId, internalListener); 1120 } 1121 1122 /** 1123 * Remove a weak escrow token. 1124 * 1125 * @return {@code true} if the given handle refers to a valid weak token previously returned 1126 * from {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise. 1127 * @hide 1128 */ 1129 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1130 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1131 @SystemApi removeWeakEscrowToken(long handle, @NonNull UserHandle user)1132 public boolean removeWeakEscrowToken(long handle, @NonNull UserHandle user) { 1133 Objects.requireNonNull(user, "User cannot be null."); 1134 return mLockPatternUtils.removeWeakEscrowToken(handle, user.getIdentifier()); 1135 } 1136 1137 /** 1138 * Check if the given weak escrow token is active or not. 1139 * @hide 1140 */ 1141 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1142 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1143 @SystemApi isWeakEscrowTokenActive(long handle, @NonNull UserHandle user)1144 public boolean isWeakEscrowTokenActive(long handle, @NonNull UserHandle user) { 1145 Objects.requireNonNull(user, "User cannot be null."); 1146 return mLockPatternUtils.isWeakEscrowTokenActive(handle, user.getIdentifier()); 1147 } 1148 1149 /** 1150 * Check if the given weak escrow token is validate. 1151 * @hide 1152 */ 1153 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1154 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1155 @SystemApi isWeakEscrowTokenValid(long handle, @NonNull byte[] token, @NonNull UserHandle user)1156 public boolean isWeakEscrowTokenValid(long handle, @NonNull byte[] token, 1157 @NonNull UserHandle user) { 1158 Objects.requireNonNull(token, "Token cannot be null."); 1159 Objects.requireNonNull(user, "User cannot be null."); 1160 return mLockPatternUtils.isWeakEscrowTokenValid(handle, token, user.getIdentifier()); 1161 } 1162 1163 /** 1164 * Register the given WeakEscrowTokenRemovedListener. 1165 * 1166 * @return {@code true} if the listener is registered successfully, return false otherwise. 1167 * @hide 1168 */ 1169 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1170 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1171 @SystemApi registerWeakEscrowTokenRemovedListener( @onNull @allbackExecutor Executor executor, @NonNull WeakEscrowTokenRemovedListener listener)1172 public boolean registerWeakEscrowTokenRemovedListener( 1173 @NonNull @CallbackExecutor Executor executor, 1174 @NonNull WeakEscrowTokenRemovedListener listener) { 1175 Objects.requireNonNull(listener, "Listener cannot be null."); 1176 Objects.requireNonNull(executor, "Executor cannot be null."); 1177 Preconditions.checkArgument(!mListeners.containsKey(listener), 1178 "Listener already registered: %s", listener); 1179 IWeakEscrowTokenRemovedListener internalListener = 1180 new IWeakEscrowTokenRemovedListener.Stub() { 1181 @Override 1182 public void onWeakEscrowTokenRemoved(long handle, int userId) { 1183 UserHandle user = UserHandle.of(userId); 1184 final long token = Binder.clearCallingIdentity(); 1185 try { 1186 executor.execute(() -> listener.onWeakEscrowTokenRemoved(handle, user)); 1187 } finally { 1188 Binder.restoreCallingIdentity(token); 1189 } 1190 } 1191 }; 1192 if (mLockPatternUtils.registerWeakEscrowTokenRemovedListener(internalListener)) { 1193 mListeners.put(listener, internalListener); 1194 return true; 1195 } else { 1196 Log.e(TAG, "Listener failed to register"); 1197 return false; 1198 } 1199 } 1200 1201 /** 1202 * Unregister the given WeakEscrowTokenRemovedListener. 1203 * 1204 * @return {@code true} if the listener is unregistered successfully, return false otherwise. 1205 * @hide 1206 */ 1207 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1208 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1209 @SystemApi unregisterWeakEscrowTokenRemovedListener( @onNull WeakEscrowTokenRemovedListener listener)1210 public boolean unregisterWeakEscrowTokenRemovedListener( 1211 @NonNull WeakEscrowTokenRemovedListener listener) { 1212 Objects.requireNonNull(listener, "Listener cannot be null."); 1213 IWeakEscrowTokenRemovedListener internalListener = mListeners.get(listener); 1214 Preconditions.checkArgument(internalListener != null, "Listener was not registered"); 1215 if (mLockPatternUtils.unregisterWeakEscrowTokenRemovedListener(internalListener)) { 1216 mListeners.remove(listener); 1217 return true; 1218 } else { 1219 Log.e(TAG, "Listener failed to unregister."); 1220 return false; 1221 } 1222 } 1223 1224 /** 1225 * Set the lockscreen password to {@code newPassword} after validating the current password 1226 * against {@code currentPassword}. 1227 * <p>If no password is currently set, {@code currentPassword} should be set to {@code null}. 1228 * <p>To clear the current password, {@code newPassword} should be set to {@code null}. 1229 * 1230 * @return {@code true} if password successfully set. 1231 * 1232 * @throws IllegalArgumentException if {@code newLockType} or {@code currentLockType} 1233 * is invalid. 1234 * 1235 * @hide 1236 */ 1237 @TestApi 1238 @RequiresPermission(anyOf = { 1239 Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, 1240 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE 1241 }) setLock(@ockTypes int newLockType, @Nullable byte[] newPassword, @LockTypes int currentLockType, @Nullable byte[] currentPassword)1242 public boolean setLock(@LockTypes int newLockType, @Nullable byte[] newPassword, 1243 @LockTypes int currentLockType, @Nullable byte[] currentPassword) { 1244 final int userId = mContext.getUserId(); 1245 try (LockscreenCredential currentCredential = createLockscreenCredential( 1246 currentLockType, currentPassword); 1247 LockscreenCredential newCredential = createLockscreenCredential( 1248 newLockType, newPassword)) { 1249 PasswordMetrics adminMetrics = 1250 mLockPatternUtils.getRequestedPasswordMetrics(mContext.getUserId()); 1251 List<PasswordValidationError> errors = PasswordMetrics.validateCredential(adminMetrics, 1252 DevicePolicyManager.PASSWORD_COMPLEXITY_NONE, newCredential); 1253 if (!errors.isEmpty()) { 1254 Log.e(TAG, "New credential is not valid: " + errors.get(0)); 1255 return false; 1256 } 1257 return mLockPatternUtils.setLockCredential(newCredential, currentCredential, userId); 1258 } 1259 } 1260 1261 /** 1262 * Verifies the current lock credentials against {@code password}. 1263 * <p>To check if no password is set, {@code password} should be set to {@code null}. 1264 * 1265 * @return {@code true} if credentials match 1266 * 1267 * @throws IllegalArgumentException if {@code lockType} is invalid. 1268 * 1269 * @hide 1270 */ 1271 @TestApi 1272 @RequiresPermission(anyOf = { 1273 Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, 1274 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE 1275 }) checkLock(@ockTypes int lockType, @Nullable byte[] password)1276 public boolean checkLock(@LockTypes int lockType, @Nullable byte[] password) { 1277 try (LockscreenCredential credential = createLockscreenCredential(lockType, password)) { 1278 final VerifyCredentialResponse response = mLockPatternUtils.verifyCredential( 1279 credential, mContext.getUserId(), /* flags= */ 0); 1280 if (response == null) { 1281 return false; 1282 } 1283 return response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK; 1284 } 1285 } 1286 1287 /** Starts a session to verify lockscreen credentials provided by a remote device. 1288 * 1289 * The session and corresponding public key will be removed when 1290 * {@code validateRemoteLockScreen} provides a correct guess or after 10 minutes of inactivity. 1291 * 1292 * @return information necessary to perform remote lock screen credentials check, including 1293 1294 * short lived public key used to send encrypted guess and lock screen type. 1295 * 1296 * @throws IllegalStateException if lock screen is not set 1297 * 1298 * @hide 1299 */ 1300 @SystemApi 1301 @RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN) 1302 @NonNull startRemoteLockscreenValidation()1303 public RemoteLockscreenValidationSession startRemoteLockscreenValidation() { 1304 return mLockPatternUtils.startRemoteLockscreenValidation(); 1305 } 1306 1307 /** 1308 * Verifies credentials guess from a remote device. 1309 * 1310 * <p>Secret must be encrypted using {@code SecureBox} library 1311 * with public key from {@code RemoteLockscreenValidationSession} 1312 * and header set to {@code "encrypted_remote_credentials"} in UTF-8 encoding. 1313 * 1314 * @throws IllegalStateException if there was a decryption error. 1315 * 1316 * @hide 1317 */ 1318 @SystemApi 1319 @RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN) 1320 @NonNull validateRemoteLockscreen( @onNull byte[] encryptedCredential)1321 public RemoteLockscreenValidationResult validateRemoteLockscreen( 1322 @NonNull byte[] encryptedCredential) { 1323 return mLockPatternUtils.validateRemoteLockscreen(encryptedCredential); 1324 } 1325 createLockscreenCredential( @ockTypes int lockType, @Nullable byte[] password)1326 private LockscreenCredential createLockscreenCredential( 1327 @LockTypes int lockType, @Nullable byte[] password) { 1328 if (password == null) { 1329 return LockscreenCredential.createNone(); 1330 } 1331 switch (lockType) { 1332 case PASSWORD: 1333 CharSequence passwordStr = new String(password, Charset.forName("UTF-8")); 1334 return LockscreenCredential.createPassword(passwordStr); 1335 case PIN: 1336 CharSequence pinStr = new String(password); 1337 return LockscreenCredential.createPin(pinStr); 1338 case PATTERN: 1339 List<LockPatternView.Cell> pattern = 1340 LockPatternUtils.byteArrayToPattern(password); 1341 return LockscreenCredential.createPattern(pattern); 1342 default: 1343 throw new IllegalArgumentException("Unknown lock type " + lockType); 1344 } 1345 } 1346 1347 /** 1348 * Listener for keyguard locked state changes. 1349 */ 1350 @FunctionalInterface 1351 public interface KeyguardLockedStateListener { 1352 /** 1353 * Callback function that executes when the keyguard locked state changes. 1354 */ onKeyguardLockedStateChanged(boolean isKeyguardLocked)1355 void onKeyguardLockedStateChanged(boolean isKeyguardLocked); 1356 } 1357 1358 /** 1359 * Registers a listener to execute when the keyguard locked state changes. 1360 * 1361 * @param listener The listener to add to receive keyguard locked state changes. 1362 * 1363 * @see #isKeyguardLocked() 1364 * @see #removeKeyguardLockedStateListener(KeyguardLockedStateListener) 1365 */ 1366 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) addKeyguardLockedStateListener(@onNull @allbackExecutor Executor executor, @NonNull KeyguardLockedStateListener listener)1367 public void addKeyguardLockedStateListener(@NonNull @CallbackExecutor Executor executor, 1368 @NonNull KeyguardLockedStateListener listener) { 1369 synchronized (mKeyguardLockedStateListeners) { 1370 mKeyguardLockedStateListeners.put(listener, executor); 1371 if (mKeyguardLockedStateListeners.size() > 1) { 1372 return; 1373 } 1374 try { 1375 mWM.addKeyguardLockedStateListener(mIKeyguardLockedStateListener); 1376 } catch (RemoteException e) { 1377 throw e.rethrowFromSystemServer(); 1378 } 1379 } 1380 } 1381 1382 /** 1383 * Unregisters a listener that executes when the keyguard locked state changes. 1384 * 1385 * @param listener The listener to remove. 1386 * 1387 * @see #isKeyguardLocked() 1388 * @see #addKeyguardLockedStateListener(Executor, KeyguardLockedStateListener) 1389 */ 1390 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) removeKeyguardLockedStateListener(@onNull KeyguardLockedStateListener listener)1391 public void removeKeyguardLockedStateListener(@NonNull KeyguardLockedStateListener listener) { 1392 synchronized (mKeyguardLockedStateListeners) { 1393 mKeyguardLockedStateListeners.remove(listener); 1394 if (!mKeyguardLockedStateListeners.isEmpty()) { 1395 return; 1396 } 1397 try { 1398 mWM.removeKeyguardLockedStateListener(mIKeyguardLockedStateListener); 1399 } catch (RemoteException e) { 1400 throw e.rethrowFromSystemServer(); 1401 } 1402 } 1403 } 1404 1405 1406 /** 1407 * Listener for device locked state changes. 1408 */ 1409 @FunctionalInterface 1410 @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) 1411 public interface DeviceLockedStateListener { 1412 /** 1413 * Callback function that executes when the device locked state changes. 1414 */ onDeviceLockedStateChanged(boolean isDeviceLocked)1415 void onDeviceLockedStateChanged(boolean isDeviceLocked); 1416 } 1417 1418 1419 /** 1420 * Registers a listener to execute when the device locked state changes. 1421 * 1422 * @param executor The {@link Executor} where the {@code listener} will be invoked 1423 * @param listener The listener to add to receive device locked state changes. 1424 * 1425 * @see #isDeviceLocked() 1426 * @see #removeDeviceLockedStateListener(DeviceLockedStateListener) 1427 */ 1428 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) 1429 @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) addDeviceLockedStateListener(@onNull @allbackExecutor Executor executor, @NonNull DeviceLockedStateListener listener)1430 public void addDeviceLockedStateListener(@NonNull @CallbackExecutor Executor executor, 1431 @NonNull DeviceLockedStateListener listener) { 1432 if (!Flags.deviceUnlockListener()) { 1433 return; 1434 } 1435 1436 synchronized (mDeviceLockedStateListeners) { 1437 mDeviceLockedStateListeners.put(listener, executor); 1438 if (mDeviceLockedStateListeners.size() > 1) { 1439 return; 1440 } 1441 try { 1442 mTrustManager.registerDeviceLockedStateListener(mIDeviceLockedStateListener, 1443 mContext.getDeviceId()); 1444 } catch (RemoteException re) { 1445 Log.d(TAG, "TrustManager service died", re); 1446 } 1447 } 1448 } 1449 1450 /** 1451 * Unregisters a listener that executes when the device locked state changes. 1452 * 1453 * @param listener The listener to remove. 1454 * 1455 * @see #isDeviceLocked() 1456 * @see #addDeviceLockedStateListener(Executor, DeviceLockedStateListener) 1457 */ 1458 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) 1459 @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) removeDeviceLockedStateListener(@onNull DeviceLockedStateListener listener)1460 public void removeDeviceLockedStateListener(@NonNull DeviceLockedStateListener listener) { 1461 if (!Flags.deviceUnlockListener()) { 1462 return; 1463 } 1464 1465 synchronized (mDeviceLockedStateListeners) { 1466 mDeviceLockedStateListeners.remove(listener); 1467 if (!mDeviceLockedStateListeners.isEmpty()) { 1468 return; 1469 } 1470 try { 1471 mTrustManager.unregisterDeviceLockedStateListener(mIDeviceLockedStateListener); 1472 } catch (RemoteException re) { 1473 Log.d(TAG, "TrustManager service died", re); 1474 } 1475 } 1476 } 1477 } 1478