1 package com.android.internal.widget;
2 
3 import android.os.AsyncTask;
4 
5 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
6 
7 /**
8  * Helper class to check/verify PIN/Password/Pattern asynchronously.
9  */
10 public final class LockPatternChecker {
11     /**
12      * Interface for a callback to be invoked after security check.
13      */
14     public interface OnCheckCallback {
15 
16         /**
17          * Invoked as soon as possible we know that the credentials match. This will be called
18          * earlier than {@link #onChecked} but only if the credentials match.
19          */
onEarlyMatched()20         default void onEarlyMatched() {}
21 
22         /**
23          * Invoked when a security check is finished.
24          *
25          * @param matched Whether the PIN/Password/Pattern matches the stored one.
26          * @param throttleTimeoutMs The amount of time in ms to wait before reattempting
27          * the call. Only non-0 if matched is false.
28          */
onChecked(boolean matched, int throttleTimeoutMs)29         void onChecked(boolean matched, int throttleTimeoutMs);
30 
31         /**
32          * Called when the underlying AsyncTask was cancelled.
33          */
onCancelled()34         default void onCancelled() {}
35     }
36 
37     /**
38      * Interface for a callback to be invoked after security verification.
39      */
40     public interface OnVerifyCallback {
41         /**
42          * Invoked when a security verification is finished.
43          *
44          * @param attestation The attestation that the challenge was verified, or null.
45          * @param throttleTimeoutMs The amount of time in ms to wait before reattempting
46          * the call. Only non-0 if attestation is null.
47          */
onVerified(byte[] attestation, int throttleTimeoutMs)48         void onVerified(byte[] attestation, int throttleTimeoutMs);
49     }
50 
51     /**
52      * Verify a lockscreen credential asynchronously.
53      *
54      * @param utils The LockPatternUtils instance to use.
55      * @param credential The credential to check.
56      * @param challenge The challenge to verify against the credential.
57      * @param userId The user to check against the credential.
58      * @param callback The callback to be invoked with the verification result.
59      */
verifyCredential(final LockPatternUtils utils, final LockscreenCredential credential, final long challenge, final int userId, final OnVerifyCallback callback)60     public static AsyncTask<?, ?, ?> verifyCredential(final LockPatternUtils utils,
61             final LockscreenCredential credential,
62             final long challenge,
63             final int userId,
64             final OnVerifyCallback callback) {
65         // Create a copy of the credential since checking credential is asynchrounous.
66         final LockscreenCredential credentialCopy = credential.duplicate();
67         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
68             private int mThrottleTimeout;
69 
70             @Override
71             protected byte[] doInBackground(Void... args) {
72                 try {
73                     return utils.verifyCredential(credentialCopy, challenge, userId);
74                 } catch (RequestThrottledException ex) {
75                     mThrottleTimeout = ex.getTimeoutMs();
76                     return null;
77                 }
78             }
79 
80             @Override
81             protected void onPostExecute(byte[] result) {
82                 callback.onVerified(result, mThrottleTimeout);
83                 credentialCopy.zeroize();
84             }
85 
86             @Override
87             protected void onCancelled() {
88                 credentialCopy.zeroize();
89             }
90         };
91         task.execute();
92         return task;
93     }
94 
95     /**
96      * Checks a lockscreen credential asynchronously.
97      *
98      * @param utils The LockPatternUtils instance to use.
99      * @param credential The credential to check.
100      * @param userId The user to check against the credential.
101      * @param callback The callback to be invoked with the check result.
102      */
checkCredential(final LockPatternUtils utils, final LockscreenCredential credential, final int userId, final OnCheckCallback callback)103     public static AsyncTask<?, ?, ?> checkCredential(final LockPatternUtils utils,
104             final LockscreenCredential credential,
105             final int userId,
106             final OnCheckCallback callback) {
107         // Create a copy of the credential since checking credential is asynchrounous.
108         final LockscreenCredential credentialCopy = credential.duplicate();
109         AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
110             private int mThrottleTimeout;
111 
112             @Override
113             protected Boolean doInBackground(Void... args) {
114                 try {
115                     return utils.checkCredential(credentialCopy, userId, callback::onEarlyMatched);
116                 } catch (RequestThrottledException ex) {
117                     mThrottleTimeout = ex.getTimeoutMs();
118                     return false;
119                 }
120             }
121 
122             @Override
123             protected void onPostExecute(Boolean result) {
124                 callback.onChecked(result, mThrottleTimeout);
125                 credentialCopy.zeroize();
126             }
127 
128             @Override
129             protected void onCancelled() {
130                 callback.onCancelled();
131                 credentialCopy.zeroize();
132             }
133         };
134         task.execute();
135         return task;
136     }
137 
138     /**
139      * Perform a lockscreen credential verification explicitly on a managed profile with unified
140      * challenge, using the parent user's credential.
141      *
142      * @param utils The LockPatternUtils instance to use.
143      * @param credential The credential to check.
144      * @param challenge The challenge to verify against the credential.
145      * @param userId The user to check against the credential.
146      * @param callback The callback to be invoked with the verification result.
147      */
verifyTiedProfileChallenge(final LockPatternUtils utils, final LockscreenCredential credential, final long challenge, final int userId, final OnVerifyCallback callback)148     public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
149             final LockscreenCredential credential,
150             final long challenge,
151             final int userId,
152             final OnVerifyCallback callback) {
153         // Create a copy of the credential since checking credential is asynchrounous.
154         final LockscreenCredential credentialCopy = credential.duplicate();
155         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
156             private int mThrottleTimeout;
157 
158             @Override
159             protected byte[] doInBackground(Void... args) {
160                 try {
161                     return utils.verifyTiedProfileChallenge(credentialCopy, challenge, userId);
162                 } catch (RequestThrottledException ex) {
163                     mThrottleTimeout = ex.getTimeoutMs();
164                     return null;
165                 }
166             }
167 
168             @Override
169             protected void onPostExecute(byte[] result) {
170                 callback.onVerified(result, mThrottleTimeout);
171                 credentialCopy.zeroize();
172             }
173 
174             @Override
175             protected void onCancelled() {
176                 credentialCopy.zeroize();
177             }
178         };
179         task.execute();
180         return task;
181     }
182 }
183