• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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