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.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.RequiresFeature; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.annotation.SystemService; 28 import android.annotation.TestApi; 29 import android.app.admin.DevicePolicyManager; 30 import android.app.admin.DevicePolicyManager.PasswordComplexity; 31 import android.app.admin.PasswordMetrics; 32 import android.app.trust.ITrustManager; 33 import android.compat.annotation.UnsupportedAppUsage; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.pm.PackageManager; 37 import android.content.pm.ResolveInfo; 38 import android.os.Binder; 39 import android.os.Build; 40 import android.os.IBinder; 41 import android.os.RemoteException; 42 import android.os.ServiceManager; 43 import android.os.ServiceManager.ServiceNotFoundException; 44 import android.os.UserHandle; 45 import android.provider.Settings; 46 import android.service.persistentdata.IPersistentDataBlockService; 47 import android.util.ArrayMap; 48 import android.util.Log; 49 import android.view.IOnKeyguardExitResult; 50 import android.view.IWindowManager; 51 import android.view.WindowManager.LayoutParams; 52 import android.view.WindowManagerGlobal; 53 54 import com.android.internal.policy.IKeyguardDismissCallback; 55 import com.android.internal.policy.IKeyguardLockedStateListener; 56 import com.android.internal.util.Preconditions; 57 import com.android.internal.widget.IWeakEscrowTokenActivatedListener; 58 import com.android.internal.widget.IWeakEscrowTokenRemovedListener; 59 import com.android.internal.widget.LockPatternUtils; 60 import com.android.internal.widget.LockPatternView; 61 import com.android.internal.widget.LockscreenCredential; 62 import com.android.internal.widget.VerifyCredentialResponse; 63 64 import java.nio.charset.Charset; 65 import java.util.Arrays; 66 import java.util.List; 67 import java.util.Objects; 68 import java.util.concurrent.Executor; 69 70 /** 71 * Class that can be used to lock and unlock the keyguard. The 72 * actual class to control the keyguard locking is 73 * {@link android.app.KeyguardManager.KeyguardLock}. 74 */ 75 @SystemService(Context.KEYGUARD_SERVICE) 76 public class KeyguardManager { 77 78 private static final String TAG = "KeyguardManager"; 79 80 private final Context mContext; 81 private final LockPatternUtils mLockPatternUtils; 82 private final IWindowManager mWM; 83 private final IActivityManager mAm; 84 private final ITrustManager mTrustManager; 85 private final INotificationManager mNotificationManager; 86 private final ArrayMap<WeakEscrowTokenRemovedListener, IWeakEscrowTokenRemovedListener> 87 mListeners = new ArrayMap<>(); 88 89 /** 90 * Intent used to prompt user for device credentials. 91 * @hide 92 */ 93 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL = 94 "android.app.action.CONFIRM_DEVICE_CREDENTIAL"; 95 96 /** 97 * Intent used to prompt user for device credentials. 98 * @hide 99 */ 100 public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER = 101 "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER"; 102 103 /** 104 * Intent used to prompt user for factory reset credentials. 105 * @hide 106 */ 107 public static final String ACTION_CONFIRM_FRP_CREDENTIAL = 108 "android.app.action.CONFIRM_FRP_CREDENTIAL"; 109 110 /** 111 * A CharSequence dialog title to show to the user when used with a 112 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 113 * @hide 114 */ 115 public static final String EXTRA_TITLE = "android.app.extra.TITLE"; 116 117 /** 118 * A CharSequence description to show to the user when used with 119 * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}. 120 * @hide 121 */ 122 public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION"; 123 124 /** 125 * A CharSequence description to show to the user on the alternate button when used with 126 * {@link #ACTION_CONFIRM_FRP_CREDENTIAL}. 127 * @hide 128 */ 129 public static final String EXTRA_ALTERNATE_BUTTON_LABEL = 130 "android.app.extra.ALTERNATE_BUTTON_LABEL"; 131 132 /** 133 * Result code returned by the activity started by 134 * {@link #createConfirmFactoryResetCredentialIntent} indicating that the user clicked the 135 * alternate button. 136 * 137 * @hide 138 */ 139 public static final int RESULT_ALTERNATE = 1; 140 141 /** 142 * 143 * If this is set, check device policy for allowed biometrics when the user is authenticating. 144 * This should only be used in the context of managed profiles. 145 * 146 * @hide 147 */ 148 public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm"; 149 150 /** 151 * 152 * Password lock type, see {@link #setLock} 153 * 154 * @hide 155 */ 156 @SystemApi 157 public static final int PASSWORD = 0; 158 159 /** 160 * 161 * Pin lock type, see {@link #setLock} 162 * 163 * @hide 164 */ 165 @SystemApi 166 public static final int PIN = 1; 167 168 /** 169 * 170 * Pattern lock type, see {@link #setLock} 171 * 172 * @hide 173 */ 174 @SystemApi 175 public static final int PATTERN = 2; 176 177 /** 178 * Available lock types 179 */ 180 @IntDef({ 181 PASSWORD, 182 PIN, 183 PATTERN 184 }) 185 @interface LockTypes {} 186 187 private final IKeyguardLockedStateListener mIKeyguardLockedStateListener = 188 new IKeyguardLockedStateListener.Stub() { 189 @Override 190 public void onKeyguardLockedStateChanged(boolean isKeyguardLocked) { 191 mKeyguardLockedStateListeners.forEach((listener, executor) -> { 192 executor.execute( 193 () -> listener.onKeyguardLockedStateChanged(isKeyguardLocked)); 194 }); 195 } 196 }; 197 private final ArrayMap<KeyguardLockedStateListener, Executor> 198 mKeyguardLockedStateListeners = new ArrayMap<>(); 199 200 /** 201 * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics 202 * if enrolled) for the current user of the device. The caller is expected to launch this 203 * activity using {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 204 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 205 * 206 * @return the intent for launching the activity or null if no password is required. 207 * @deprecated see BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean) 208 */ 209 @Deprecated 210 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description)211 public Intent createConfirmDeviceCredentialIntent(CharSequence title, 212 CharSequence description) { 213 if (!isDeviceSecure()) return null; 214 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL); 215 intent.putExtra(EXTRA_TITLE, title); 216 intent.putExtra(EXTRA_DESCRIPTION, description); 217 218 // explicitly set the package for security 219 intent.setPackage(getSettingsPackageForIntent(intent)); 220 return intent; 221 } 222 223 /** 224 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 225 * for the given user. The caller is expected to launch this activity using 226 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 227 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 228 * 229 * @return the intent for launching the activity or null if no password is required. 230 * 231 * @hide 232 */ createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId)233 public Intent createConfirmDeviceCredentialIntent( 234 CharSequence title, CharSequence description, int userId) { 235 if (!isDeviceSecure(userId)) return null; 236 Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER); 237 intent.putExtra(EXTRA_TITLE, title); 238 intent.putExtra(EXTRA_DESCRIPTION, description); 239 intent.putExtra(Intent.EXTRA_USER_ID, userId); 240 241 // explicitly set the package for security 242 intent.setPackage(getSettingsPackageForIntent(intent)); 243 244 return intent; 245 } 246 247 /** 248 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 249 * for the given user. The caller is expected to launch this activity using 250 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 251 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 252 * 253 * @param disallowBiometricsIfPolicyExists If true check if the Device Policy Manager has 254 * disabled biometrics on the device. If biometrics are disabled, fall back to PIN/pattern/pass. 255 * 256 * @return the intent for launching the activity or null if no password is required. 257 * 258 * @hide 259 */ createConfirmDeviceCredentialIntent( CharSequence title, CharSequence description, int userId, boolean disallowBiometricsIfPolicyExists)260 public Intent createConfirmDeviceCredentialIntent( 261 CharSequence title, CharSequence description, int userId, 262 boolean disallowBiometricsIfPolicyExists) { 263 Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId); 264 if (intent != null) { 265 intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, 266 disallowBiometricsIfPolicyExists); 267 } 268 return intent; 269 } 270 271 /** 272 * Get an intent to prompt the user to confirm credentials (pin, pattern or password) 273 * for the previous owner of the device. The caller is expected to launch this activity using 274 * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for 275 * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge. 276 * 277 * @param alternateButtonLabel if not empty, a button is provided with the given label. Upon 278 * clicking this button, the activity returns 279 * {@link #RESULT_ALTERNATE} 280 * 281 * @return the intent for launching the activity or null if the previous owner of the device 282 * did not set a credential. 283 * @throws UnsupportedOperationException if the device does not support factory reset 284 * credentials 285 * @throws IllegalStateException if the device has already been provisioned 286 * @hide 287 */ 288 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 289 @SystemApi createConfirmFactoryResetCredentialIntent( CharSequence title, CharSequence description, CharSequence alternateButtonLabel)290 public Intent createConfirmFactoryResetCredentialIntent( 291 CharSequence title, CharSequence description, CharSequence alternateButtonLabel) { 292 if (!LockPatternUtils.frpCredentialEnabled(mContext)) { 293 Log.w(TAG, "Factory reset credentials not supported."); 294 throw new UnsupportedOperationException("not supported on this device"); 295 } 296 297 // Cannot verify credential if the device is provisioned 298 if (Settings.Global.getInt(mContext.getContentResolver(), 299 Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 300 Log.e(TAG, "Factory reset credential cannot be verified after provisioning."); 301 throw new IllegalStateException("must not be provisioned yet"); 302 } 303 304 // Make sure we have a credential 305 try { 306 IPersistentDataBlockService pdb = IPersistentDataBlockService.Stub.asInterface( 307 ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE)); 308 if (pdb == null) { 309 Log.e(TAG, "No persistent data block service"); 310 throw new UnsupportedOperationException("not supported on this device"); 311 } 312 // The following will throw an UnsupportedOperationException if the device does not 313 // support factory reset credentials (or something went wrong retrieving it). 314 if (!pdb.hasFrpCredentialHandle()) { 315 Log.i(TAG, "The persistent data block does not have a factory reset credential."); 316 return null; 317 } 318 } catch (RemoteException e) { 319 throw e.rethrowFromSystemServer(); 320 } 321 322 Intent intent = new Intent(ACTION_CONFIRM_FRP_CREDENTIAL); 323 intent.putExtra(EXTRA_TITLE, title); 324 intent.putExtra(EXTRA_DESCRIPTION, description); 325 intent.putExtra(EXTRA_ALTERNATE_BUTTON_LABEL, alternateButtonLabel); 326 327 // explicitly set the package for security 328 intent.setPackage(getSettingsPackageForIntent(intent)); 329 330 return intent; 331 } 332 333 /** 334 * Controls whether notifications can be shown atop a securely locked screen in their full 335 * private form (same as when the device is unlocked). 336 * 337 * <p>Other sources like the DevicePolicyManger and Settings app can modify this configuration. 338 * The result is that private notifications are only shown if all sources allow it. 339 * 340 * @param allow secure notifications can be shown if {@code true}, 341 * secure notifications cannot be shown if {@code false} 342 * @hide 343 */ 344 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 345 @RequiresPermission(Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) 346 @SystemApi setPrivateNotificationsAllowed(boolean allow)347 public void setPrivateNotificationsAllowed(boolean allow) { 348 try { 349 mNotificationManager.setPrivateNotificationsAllowed(allow); 350 } catch (RemoteException e) { 351 throw e.rethrowFromSystemServer(); 352 } 353 } 354 355 /** 356 * Returns whether notifications can be shown atop a securely locked screen in their full 357 * private form (same as when the device is unlocked). 358 * 359 * @return {@code true} if secure notifications can be shown, {@code false} otherwise. 360 * By default, private notifications are allowed. 361 * @hide 362 */ 363 @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) 364 @RequiresPermission(Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) 365 @SystemApi getPrivateNotificationsAllowed()366 public boolean getPrivateNotificationsAllowed() { 367 try { 368 return mNotificationManager.getPrivateNotificationsAllowed(); 369 } catch (RemoteException e) { 370 throw e.rethrowFromSystemServer(); 371 } 372 } 373 getSettingsPackageForIntent(Intent intent)374 private String getSettingsPackageForIntent(Intent intent) { 375 List<ResolveInfo> resolveInfos = mContext.getPackageManager() 376 .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); 377 for (int i = 0; i < resolveInfos.size(); i++) { 378 return resolveInfos.get(i).activityInfo.packageName; 379 } 380 381 return "com.android.settings"; 382 } 383 384 /** 385 * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows 386 * you to disable / reenable the keyguard. 387 * 388 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 389 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 390 * instead; this allows you to seamlessly hide the keyguard as your application 391 * moves in and out of the foreground and does not require that any special 392 * permissions be requested. 393 */ 394 @Deprecated 395 public class KeyguardLock { 396 private final IBinder mToken = new Binder(); 397 private final String mTag; 398 KeyguardLock(String tag)399 KeyguardLock(String tag) { 400 mTag = tag; 401 } 402 403 /** 404 * Disable the keyguard from showing. If the keyguard is currently 405 * showing, hide it. The keyguard will be prevented from showing again 406 * until {@link #reenableKeyguard()} is called. 407 * 408 * A good place to call this is from {@link android.app.Activity#onResume()} 409 * 410 * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} 411 * is enabled that requires a password. 412 * 413 * @see #reenableKeyguard() 414 */ 415 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) disableKeyguard()416 public void disableKeyguard() { 417 try { 418 mWM.disableKeyguard(mToken, mTag, mContext.getUserId()); 419 } catch (RemoteException ex) { 420 } 421 } 422 423 /** 424 * Reenable the keyguard. The keyguard will reappear if the previous 425 * call to {@link #disableKeyguard()} caused it to be hidden. 426 * 427 * A good place to call this is from {@link android.app.Activity#onPause()} 428 * 429 * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} 430 * is enabled that requires a password. 431 * 432 * @see #disableKeyguard() 433 */ 434 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) reenableKeyguard()435 public void reenableKeyguard() { 436 try { 437 mWM.reenableKeyguard(mToken, mContext.getUserId()); 438 } catch (RemoteException ex) { 439 } 440 } 441 } 442 443 /** 444 * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify 445 * caller of result. 446 * 447 * @deprecated Use {@link KeyguardDismissCallback} 448 */ 449 @Deprecated 450 public interface OnKeyguardExitResult { 451 452 /** 453 * @param success True if the user was able to authenticate, false if 454 * not. 455 */ onKeyguardExitResult(boolean success)456 void onKeyguardExitResult(boolean success); 457 } 458 459 /** 460 * Callback passed to 461 * {@link KeyguardManager#requestDismissKeyguard(Activity, KeyguardDismissCallback)} 462 * to notify caller of result. 463 */ 464 public static abstract class KeyguardDismissCallback { 465 466 /** 467 * Called when dismissing Keyguard is currently not feasible, i.e. when Keyguard is not 468 * available, not showing or when the activity requesting the Keyguard dismissal isn't 469 * showing or isn't showing behind Keyguard. 470 */ onDismissError()471 public void onDismissError() { } 472 473 /** 474 * Called when dismissing Keyguard has succeeded and the device is now unlocked. 475 */ onDismissSucceeded()476 public void onDismissSucceeded() { } 477 478 /** 479 * Called when dismissing Keyguard has been cancelled, i.e. when the user cancelled the 480 * operation or the bouncer was hidden for some other reason. 481 */ onDismissCancelled()482 public void onDismissCancelled() { } 483 } 484 485 /** 486 * Callback passed to 487 * {@link KeyguardManager#addWeakEscrowToken} 488 * to notify caller of state change. 489 * @hide 490 */ 491 @SystemApi 492 public interface WeakEscrowTokenActivatedListener { 493 /** 494 * The method to be called when the token is activated. 495 * @param handle 64 bit handle corresponding to the escrow token 496 * @param user user for whom the weak escrow token has been added 497 */ onWeakEscrowTokenActivated(long handle, @NonNull UserHandle user)498 void onWeakEscrowTokenActivated(long handle, @NonNull UserHandle user); 499 } 500 501 /** 502 * Listener passed to 503 * {@link KeyguardManager#registerWeakEscrowTokenRemovedListener} and 504 * {@link KeyguardManager#unregisterWeakEscrowTokenRemovedListener} 505 * to notify caller of an weak escrow token has been removed. 506 * @hide 507 */ 508 @SystemApi 509 public interface WeakEscrowTokenRemovedListener { 510 /** 511 * The method to be called when the token is removed. 512 * @param handle 64 bit handle corresponding to the escrow token 513 * @param user user for whom the escrow token has been added 514 */ onWeakEscrowTokenRemoved(long handle, @NonNull UserHandle user)515 void onWeakEscrowTokenRemoved(long handle, @NonNull UserHandle user); 516 } 517 KeyguardManager(Context context)518 KeyguardManager(Context context) throws ServiceNotFoundException { 519 mContext = context; 520 mLockPatternUtils = new LockPatternUtils(context); 521 mWM = WindowManagerGlobal.getWindowManagerService(); 522 mAm = ActivityManager.getService(); 523 mTrustManager = ITrustManager.Stub.asInterface( 524 ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE)); 525 mNotificationManager = INotificationManager.Stub.asInterface( 526 ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE)); 527 } 528 529 /** 530 * Enables you to lock or unlock the keyguard. Get an instance of this class by 531 * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. 532 * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}. 533 * @param tag A tag that informally identifies who you are (for debugging who 534 * is disabling the keyguard). 535 * 536 * @return A {@link KeyguardLock} handle to use to disable and reenable the 537 * keyguard. 538 * 539 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 540 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 541 * instead; this allows you to seamlessly hide the keyguard as your application 542 * moves in and out of the foreground and does not require that any special 543 * permissions be requested. 544 */ 545 @Deprecated newKeyguardLock(String tag)546 public KeyguardLock newKeyguardLock(String tag) { 547 return new KeyguardLock(tag); 548 } 549 550 /** 551 * Return whether the keyguard is currently locked. 552 * 553 * @return {@code true} if the keyguard is locked. 554 */ isKeyguardLocked()555 public boolean isKeyguardLocked() { 556 try { 557 return mWM.isKeyguardLocked(); 558 } catch (RemoteException ex) { 559 return false; 560 } 561 } 562 563 /** 564 * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card 565 * is currently locked. 566 * 567 * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states. 568 * 569 * @return {@code true} if a PIN, pattern or password is set or a SIM card is locked. 570 */ isKeyguardSecure()571 public boolean isKeyguardSecure() { 572 try { 573 return mWM.isKeyguardSecure(mContext.getUserId()); 574 } catch (RemoteException ex) { 575 return false; 576 } 577 } 578 579 /** 580 * If keyguard screen is showing or in restricted key input mode (i.e. in 581 * keyguard password emergency screen). When in such mode, certain keys, 582 * such as the Home key and the right soft keys, don't work. 583 * 584 * @return {@code true} if in keyguard restricted input mode. 585 * @deprecated Use {@link #isKeyguardLocked()} instead. 586 */ inKeyguardRestrictedInputMode()587 public boolean inKeyguardRestrictedInputMode() { 588 return isKeyguardLocked(); 589 } 590 591 /** 592 * Returns whether the device is currently locked and requires a PIN, pattern or 593 * password to unlock. 594 * 595 * @return {@code true} if unlocking the device currently requires a PIN, pattern or 596 * password. 597 */ isDeviceLocked()598 public boolean isDeviceLocked() { 599 return isDeviceLocked(mContext.getUserId()); 600 } 601 602 /** 603 * Per-user version of {@link #isDeviceLocked()}. 604 * 605 * @hide 606 */ 607 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) isDeviceLocked(int userId)608 public boolean isDeviceLocked(int userId) { 609 try { 610 return mTrustManager.isDeviceLocked(userId, mContext.getAssociatedDisplayId()); 611 } catch (RemoteException e) { 612 return false; 613 } 614 } 615 616 /** 617 * Returns whether the device is secured with a PIN, pattern or 618 * password. 619 * 620 * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure. 621 * 622 * @return {@code true} if a PIN, pattern or password was set. 623 */ isDeviceSecure()624 public boolean isDeviceSecure() { 625 return isDeviceSecure(mContext.getUserId()); 626 } 627 628 /** 629 * Per-user version of {@link #isDeviceSecure()}. 630 * 631 * @hide 632 */ 633 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isDeviceSecure(int userId)634 public boolean isDeviceSecure(int userId) { 635 try { 636 return mTrustManager.isDeviceSecure(userId, mContext.getAssociatedDisplayId()); 637 } catch (RemoteException e) { 638 return false; 639 } 640 } 641 642 /** 643 * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to 644 * be dismissed. 645 * <p> 646 * If the Keyguard is not secure or the device is currently in a trusted state, calling this 647 * method will immediately dismiss the Keyguard without any user interaction. 648 * <p> 649 * If the Keyguard is secure and the device is not in a trusted state, this will bring up the 650 * UI so the user can enter their credentials. 651 * <p> 652 * If the value set for the {@link Activity} attr {@link android.R.attr#turnScreenOn} is true, 653 * the screen will turn on when the keyguard is dismissed. 654 * 655 * @param activity The activity requesting the dismissal. The activity must be either visible 656 * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in 657 * which it would be visible if Keyguard would not be hiding it. If that's not 658 * the case, the request will fail immediately and 659 * {@link KeyguardDismissCallback#onDismissError} will be invoked. 660 * @param callback The callback to be called if the request to dismiss Keyguard was successful 661 * or {@code null} if the caller isn't interested in knowing the result. The 662 * callback will not be invoked if the activity was destroyed before the 663 * callback was received. 664 */ requestDismissKeyguard(@onNull Activity activity, @Nullable KeyguardDismissCallback callback)665 public void requestDismissKeyguard(@NonNull Activity activity, 666 @Nullable KeyguardDismissCallback callback) { 667 requestDismissKeyguard(activity, null /* message */, callback); 668 } 669 670 /** 671 * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to 672 * be dismissed. 673 * <p> 674 * If the Keyguard is not secure or the device is currently in a trusted state, calling this 675 * method will immediately dismiss the Keyguard without any user interaction. 676 * <p> 677 * If the Keyguard is secure and the device is not in a trusted state, this will bring up the 678 * UI so the user can enter their credentials. 679 * <p> 680 * If the value set for the {@link Activity} attr {@link android.R.attr#turnScreenOn} is true, 681 * the screen will turn on when the keyguard is dismissed. 682 * 683 * @param activity The activity requesting the dismissal. The activity must be either visible 684 * by using {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} or must be in a state in 685 * which it would be visible if Keyguard would not be hiding it. If that's not 686 * the case, the request will fail immediately and 687 * {@link KeyguardDismissCallback#onDismissError} will be invoked. 688 * @param message A message that will be shown in the keyguard explaining why the user 689 * would want to dismiss it. 690 * @param callback The callback to be called if the request to dismiss Keyguard was successful 691 * or {@code null} if the caller isn't interested in knowing the result. The 692 * callback will not be invoked if the activity was destroyed before the 693 * callback was received. 694 * @hide 695 */ 696 @RequiresPermission(Manifest.permission.SHOW_KEYGUARD_MESSAGE) 697 @SystemApi requestDismissKeyguard(@onNull Activity activity, @Nullable CharSequence message, @Nullable KeyguardDismissCallback callback)698 public void requestDismissKeyguard(@NonNull Activity activity, @Nullable CharSequence message, 699 @Nullable KeyguardDismissCallback callback) { 700 ActivityClient.getInstance().dismissKeyguard( 701 activity.getActivityToken(), new IKeyguardDismissCallback.Stub() { 702 @Override 703 public void onDismissError() throws RemoteException { 704 if (callback != null && !activity.isDestroyed()) { 705 activity.mHandler.post(callback::onDismissError); 706 } 707 } 708 709 @Override 710 public void onDismissSucceeded() throws RemoteException { 711 if (callback != null && !activity.isDestroyed()) { 712 activity.mHandler.post(callback::onDismissSucceeded); 713 } 714 } 715 716 @Override 717 public void onDismissCancelled() throws RemoteException { 718 if (callback != null && !activity.isDestroyed()) { 719 activity.mHandler.post(callback::onDismissCancelled); 720 } 721 } 722 }, message); 723 } 724 725 /** 726 * Exit the keyguard securely. The use case for this api is that, after 727 * disabling the keyguard, your app, which was granted permission to 728 * disable the keyguard and show a limited amount of information deemed 729 * safe without the user getting past the keyguard, needs to navigate to 730 * something that is not safe to view without getting past the keyguard. 731 * 732 * This will, if the keyguard is secure, bring up the unlock screen of 733 * the keyguard. 734 * 735 * @param callback Lets you know whether the operation was successful and 736 * it is safe to launch anything that would normally be considered safe 737 * once the user has gotten past the keyguard. 738 739 * @deprecated Use {@link LayoutParams#FLAG_DISMISS_KEYGUARD} 740 * and/or {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} 741 * instead; this allows you to seamlessly hide the keyguard as your application 742 * moves in and out of the foreground and does not require that any special 743 * permissions be requested. 744 */ 745 @Deprecated 746 @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) exitKeyguardSecurely(final OnKeyguardExitResult callback)747 public void exitKeyguardSecurely(final OnKeyguardExitResult callback) { 748 try { 749 mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() { 750 public void onKeyguardExitResult(boolean success) throws RemoteException { 751 if (callback != null) { 752 callback.onKeyguardExitResult(success); 753 } 754 } 755 }); 756 } catch (RemoteException e) { 757 758 } 759 } 760 checkInitialLockMethodUsage()761 private boolean checkInitialLockMethodUsage() { 762 if (!hasPermission(Manifest.permission.SET_INITIAL_LOCK)) { 763 throw new SecurityException("Requires SET_INITIAL_LOCK permission."); 764 } 765 return true; 766 } 767 hasPermission(String permission)768 private boolean hasPermission(String permission) { 769 return PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( 770 permission); 771 } 772 773 /** 774 * Determine if a given password is valid based off its lock type and expected complexity level. 775 * 776 * @param lockType - type of lock as specified in {@link LockTypes} 777 * @param password - password to validate; this has the same encoding 778 * as the output of String#getBytes 779 * @param complexity - complexity level imposed by the requester 780 * as defined in {@code DevicePolicyManager.PasswordComplexity} 781 * @return {@code true} if the password is valid, false otherwise 782 * @hide 783 */ 784 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 785 @SystemApi isValidLockPasswordComplexity(@ockTypes int lockType, @NonNull byte[] password, @PasswordComplexity int complexity)786 public boolean isValidLockPasswordComplexity(@LockTypes int lockType, @NonNull byte[] password, 787 @PasswordComplexity int complexity) { 788 if (!checkInitialLockMethodUsage()) { 789 return false; 790 } 791 complexity = PasswordMetrics.sanitizeComplexityLevel(complexity); 792 // TODO: b/131755827 add devicePolicyManager support for Auto 793 DevicePolicyManager devicePolicyManager = 794 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 795 PasswordMetrics adminMetrics = 796 devicePolicyManager.getPasswordMinimumMetrics(mContext.getUserId()); 797 // Check if the password fits the mold of a pin or pattern. 798 boolean isPinOrPattern = lockType != PASSWORD; 799 800 return PasswordMetrics.validatePassword( 801 adminMetrics, complexity, isPinOrPattern, password).size() == 0; 802 } 803 804 /** 805 * Determine the minimum allowable length for a lock type for a given complexity level. 806 * 807 * @param isPin - whether this is a PIN-type password (only digits) 808 * @param complexity - complexity level imposed by the requester 809 * as defined in {@code DevicePolicyManager.PasswordComplexity} 810 * @return minimum allowable password length 811 * @hide 812 */ 813 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 814 @SystemApi getMinLockLength(boolean isPin, @PasswordComplexity int complexity)815 public int getMinLockLength(boolean isPin, @PasswordComplexity int complexity) { 816 if (!checkInitialLockMethodUsage()) { 817 return -1; 818 } 819 complexity = PasswordMetrics.sanitizeComplexityLevel(complexity); 820 // TODO: b/131755827 add devicePolicyManager support for Auto 821 DevicePolicyManager devicePolicyManager = 822 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 823 PasswordMetrics adminMetrics = 824 devicePolicyManager.getPasswordMinimumMetrics(mContext.getUserId()); 825 PasswordMetrics minMetrics = 826 PasswordMetrics.applyComplexity(adminMetrics, isPin, complexity); 827 return minMetrics.length; 828 } 829 830 /** 831 * Set the lockscreen password after validating against its expected complexity level. 832 * 833 * Below {@link android.os.Build.VERSION_CODES#S_V2}, this API will only work 834 * when {@link PackageManager.FEATURE_AUTOMOTIVE} is present. 835 * @param lockType - type of lock as specified in {@link LockTypes} 836 * @param password - password to validate; this has the same encoding 837 * as the output of String#getBytes 838 * @param complexity - complexity level imposed by the requester 839 * as defined in {@code DevicePolicyManager.PasswordComplexity} 840 * @return {@code true} if the lock is successfully set, false otherwise 841 * @hide 842 */ 843 @RequiresPermission(Manifest.permission.SET_INITIAL_LOCK) 844 @SystemApi setLock(@ockTypes int lockType, @NonNull byte[] password, @PasswordComplexity int complexity)845 public boolean setLock(@LockTypes int lockType, @NonNull byte[] password, 846 @PasswordComplexity int complexity) { 847 if (!checkInitialLockMethodUsage()) { 848 return false; 849 } 850 851 int userId = mContext.getUserId(); 852 if (isDeviceSecure(userId)) { 853 Log.e(TAG, "Password already set, rejecting call to setLock"); 854 return false; 855 } 856 if (!isValidLockPasswordComplexity(lockType, password, complexity)) { 857 Log.e(TAG, "Password is not valid, rejecting call to setLock"); 858 return false; 859 } 860 boolean success; 861 try { 862 LockscreenCredential credential = createLockscreenCredential( 863 lockType, password); 864 success = mLockPatternUtils.setLockCredential( 865 credential, 866 /* savedPassword= */ LockscreenCredential.createNone(), 867 userId); 868 } catch (Exception e) { 869 Log.e(TAG, "Save lock exception", e); 870 success = false; 871 } finally { 872 Arrays.fill(password, (byte) 0); 873 } 874 return success; 875 } 876 877 /** 878 * Create a weak escrow token for the current user, which can later be used to unlock FBE 879 * or change user password. 880 * 881 * After adding, if the user currently has a secure lockscreen, they will need to perform a 882 * confirm credential operation in order to activate the token for future use. If the user 883 * has no secure lockscreen, then the token is activated immediately. 884 * 885 * If the user changes or removes the lockscreen password, any activated weak escrow token will 886 * be removed. 887 * 888 * @return a unique 64-bit token handle which is needed to refer to this token later. 889 * @hide 890 */ 891 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 892 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 893 @SystemApi addWeakEscrowToken(@onNull byte[] token, @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor, @NonNull WeakEscrowTokenActivatedListener listener)894 public long addWeakEscrowToken(@NonNull byte[] token, @NonNull UserHandle user, 895 @NonNull @CallbackExecutor Executor executor, 896 @NonNull WeakEscrowTokenActivatedListener listener) { 897 Objects.requireNonNull(token, "Token cannot be null."); 898 Objects.requireNonNull(user, "User cannot be null."); 899 Objects.requireNonNull(executor, "Executor cannot be null."); 900 Objects.requireNonNull(listener, "Listener cannot be null."); 901 int userId = user.getIdentifier(); 902 IWeakEscrowTokenActivatedListener internalListener = 903 new IWeakEscrowTokenActivatedListener.Stub() { 904 @Override 905 public void onWeakEscrowTokenActivated(long handle, int userId) { 906 UserHandle user = UserHandle.of(userId); 907 final long restoreToken = Binder.clearCallingIdentity(); 908 try { 909 executor.execute(() -> listener.onWeakEscrowTokenActivated(handle, user)); 910 } finally { 911 Binder.restoreCallingIdentity(restoreToken); 912 } 913 Log.i(TAG, "Weak escrow token activated."); 914 } 915 }; 916 return mLockPatternUtils.addWeakEscrowToken(token, userId, internalListener); 917 } 918 919 /** 920 * Remove a weak escrow token. 921 * 922 * @return {@code true} if the given handle refers to a valid weak token previously returned 923 * from {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise. 924 * @hide 925 */ 926 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 927 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 928 @SystemApi removeWeakEscrowToken(long handle, @NonNull UserHandle user)929 public boolean removeWeakEscrowToken(long handle, @NonNull UserHandle user) { 930 Objects.requireNonNull(user, "User cannot be null."); 931 return mLockPatternUtils.removeWeakEscrowToken(handle, user.getIdentifier()); 932 } 933 934 /** 935 * Check if the given weak escrow token is active or not. 936 * @hide 937 */ 938 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 939 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 940 @SystemApi isWeakEscrowTokenActive(long handle, @NonNull UserHandle user)941 public boolean isWeakEscrowTokenActive(long handle, @NonNull UserHandle user) { 942 Objects.requireNonNull(user, "User cannot be null."); 943 return mLockPatternUtils.isWeakEscrowTokenActive(handle, user.getIdentifier()); 944 } 945 946 /** 947 * Check if the given weak escrow token is validate. 948 * @hide 949 */ 950 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 951 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 952 @SystemApi isWeakEscrowTokenValid(long handle, @NonNull byte[] token, @NonNull UserHandle user)953 public boolean isWeakEscrowTokenValid(long handle, @NonNull byte[] token, 954 @NonNull UserHandle user) { 955 Objects.requireNonNull(token, "Token cannot be null."); 956 Objects.requireNonNull(user, "User cannot be null."); 957 return mLockPatternUtils.isWeakEscrowTokenValid(handle, token, user.getIdentifier()); 958 } 959 960 /** 961 * Register the given WeakEscrowTokenRemovedListener. 962 * 963 * @return {@code true} if the listener is registered successfully, return false otherwise. 964 * @hide 965 */ 966 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 967 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 968 @SystemApi registerWeakEscrowTokenRemovedListener( @onNull @allbackExecutor Executor executor, @NonNull WeakEscrowTokenRemovedListener listener)969 public boolean registerWeakEscrowTokenRemovedListener( 970 @NonNull @CallbackExecutor Executor executor, 971 @NonNull WeakEscrowTokenRemovedListener listener) { 972 Objects.requireNonNull(listener, "Listener cannot be null."); 973 Objects.requireNonNull(executor, "Executor cannot be null."); 974 Preconditions.checkArgument(!mListeners.containsKey(listener), 975 "Listener already registered: %s", listener); 976 IWeakEscrowTokenRemovedListener internalListener = 977 new IWeakEscrowTokenRemovedListener.Stub() { 978 @Override 979 public void onWeakEscrowTokenRemoved(long handle, int userId) { 980 UserHandle user = UserHandle.of(userId); 981 final long token = Binder.clearCallingIdentity(); 982 try { 983 executor.execute(() -> listener.onWeakEscrowTokenRemoved(handle, user)); 984 } finally { 985 Binder.restoreCallingIdentity(token); 986 } 987 } 988 }; 989 if (mLockPatternUtils.registerWeakEscrowTokenRemovedListener(internalListener)) { 990 mListeners.put(listener, internalListener); 991 return true; 992 } else { 993 Log.e(TAG, "Listener failed to register"); 994 return false; 995 } 996 } 997 998 /** 999 * Unregister the given WeakEscrowTokenRemovedListener. 1000 * 1001 * @return {@code true} if the listener is unregistered successfully, return false otherwise. 1002 * @hide 1003 */ 1004 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) 1005 @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) 1006 @SystemApi unregisterWeakEscrowTokenRemovedListener( @onNull WeakEscrowTokenRemovedListener listener)1007 public boolean unregisterWeakEscrowTokenRemovedListener( 1008 @NonNull WeakEscrowTokenRemovedListener listener) { 1009 Objects.requireNonNull(listener, "Listener cannot be null."); 1010 IWeakEscrowTokenRemovedListener internalListener = mListeners.get(listener); 1011 Preconditions.checkArgument(internalListener != null, "Listener was not registered"); 1012 if (mLockPatternUtils.unregisterWeakEscrowTokenRemovedListener(internalListener)) { 1013 mListeners.remove(listener); 1014 return true; 1015 } else { 1016 Log.e(TAG, "Listener failed to unregister."); 1017 return false; 1018 } 1019 } 1020 1021 /** 1022 * Set the lockscreen password to {@code newPassword} after validating the current password 1023 * against {@code currentPassword}. 1024 * <p>If no password is currently set, {@code currentPassword} should be set to {@code null}. 1025 * <p>To clear the current password, {@code newPassword} should be set to {@code null}. 1026 * 1027 * @return {@code true} if password successfully set. 1028 * 1029 * @throws IllegalArgumentException if {@code newLockType} or {@code currentLockType} 1030 * is invalid. 1031 * 1032 * @hide 1033 */ 1034 @TestApi 1035 @RequiresPermission(anyOf = { 1036 Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, 1037 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE 1038 }) setLock(@ockTypes int newLockType, @Nullable byte[] newPassword, @LockTypes int currentLockType, @Nullable byte[] currentPassword)1039 public boolean setLock(@LockTypes int newLockType, @Nullable byte[] newPassword, 1040 @LockTypes int currentLockType, @Nullable byte[] currentPassword) { 1041 final int userId = mContext.getUserId(); 1042 LockscreenCredential currentCredential = createLockscreenCredential( 1043 currentLockType, currentPassword); 1044 LockscreenCredential newCredential = createLockscreenCredential( 1045 newLockType, newPassword); 1046 return mLockPatternUtils.setLockCredential(newCredential, currentCredential, userId); 1047 } 1048 1049 /** 1050 * Verifies the current lock credentials against {@code password}. 1051 * <p>To check if no password is set, {@code password} should be set to {@code null}. 1052 * 1053 * @return {@code true} if credentials match 1054 * 1055 * @throws IllegalArgumentException if {@code lockType} is invalid. 1056 * 1057 * @hide 1058 */ 1059 @TestApi 1060 @RequiresPermission(anyOf = { 1061 Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, 1062 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE 1063 }) checkLock(@ockTypes int lockType, @Nullable byte[] password)1064 public boolean checkLock(@LockTypes int lockType, @Nullable byte[] password) { 1065 final LockscreenCredential credential = createLockscreenCredential( 1066 lockType, password); 1067 final VerifyCredentialResponse response = mLockPatternUtils.verifyCredential( 1068 credential, mContext.getUserId(), /* flags= */ 0); 1069 if (response == null) { 1070 return false; 1071 } 1072 return response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK; 1073 } 1074 createLockscreenCredential( @ockTypes int lockType, @Nullable byte[] password)1075 private LockscreenCredential createLockscreenCredential( 1076 @LockTypes int lockType, @Nullable byte[] password) { 1077 if (password == null) { 1078 return LockscreenCredential.createNone(); 1079 } 1080 switch (lockType) { 1081 case PASSWORD: 1082 CharSequence passwordStr = new String(password, Charset.forName("UTF-8")); 1083 return LockscreenCredential.createPassword(passwordStr); 1084 case PIN: 1085 CharSequence pinStr = new String(password); 1086 return LockscreenCredential.createPin(pinStr); 1087 case PATTERN: 1088 List<LockPatternView.Cell> pattern = 1089 LockPatternUtils.byteArrayToPattern(password); 1090 return LockscreenCredential.createPattern(pattern); 1091 default: 1092 throw new IllegalArgumentException("Unknown lock type " + lockType); 1093 } 1094 } 1095 1096 /** 1097 * Listener for keyguard locked state changes. 1098 */ 1099 @FunctionalInterface 1100 public interface KeyguardLockedStateListener { 1101 /** 1102 * Callback function that executes when the keyguard locked state changes. 1103 */ onKeyguardLockedStateChanged(boolean isKeyguardLocked)1104 void onKeyguardLockedStateChanged(boolean isKeyguardLocked); 1105 } 1106 1107 /** 1108 * Registers a listener to execute when the keyguard locked state changes. 1109 * 1110 * @param listener The listener to add to receive keyguard locked state changes. 1111 * 1112 * @see #isKeyguardLocked() 1113 * @see #removeKeyguardLockedStateListener(KeyguardLockedStateListener) 1114 */ 1115 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) addKeyguardLockedStateListener(@onNull @allbackExecutor Executor executor, @NonNull KeyguardLockedStateListener listener)1116 public void addKeyguardLockedStateListener(@NonNull @CallbackExecutor Executor executor, 1117 @NonNull KeyguardLockedStateListener listener) { 1118 synchronized (mKeyguardLockedStateListeners) { 1119 mKeyguardLockedStateListeners.put(listener, executor); 1120 if (mKeyguardLockedStateListeners.size() > 1) { 1121 return; 1122 } 1123 try { 1124 mWM.addKeyguardLockedStateListener(mIKeyguardLockedStateListener); 1125 } catch (RemoteException e) { 1126 throw e.rethrowFromSystemServer(); 1127 } 1128 } 1129 } 1130 1131 /** 1132 * Unregisters a listener that executes when the keyguard locked state changes. 1133 * 1134 * @param listener The listener to remove. 1135 * 1136 * @see #isKeyguardLocked() 1137 * @see #addKeyguardLockedStateListener(Executor, KeyguardLockedStateListener) 1138 */ 1139 @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) removeKeyguardLockedStateListener(@onNull KeyguardLockedStateListener listener)1140 public void removeKeyguardLockedStateListener(@NonNull KeyguardLockedStateListener listener) { 1141 synchronized (mKeyguardLockedStateListeners) { 1142 mKeyguardLockedStateListeners.remove(listener); 1143 if (!mKeyguardLockedStateListeners.isEmpty()) { 1144 return; 1145 } 1146 try { 1147 mWM.removeKeyguardLockedStateListener(mIKeyguardLockedStateListener); 1148 } catch (RemoteException e) { 1149 throw e.rethrowFromSystemServer(); 1150 } 1151 } 1152 } 1153 } 1154