1 package com.android.internal.widget; 2 3 import android.compat.annotation.UnsupportedAppUsage; 4 import android.os.AsyncTask; 5 6 import com.android.internal.widget.LockPatternUtils.RequestThrottledException; 7 8 import java.util.ArrayList; 9 import java.util.List; 10 11 /** 12 * Helper class to check/verify PIN/Password/Pattern asynchronously. 13 */ 14 public final class LockPatternChecker { 15 /** 16 * Interface for a callback to be invoked after security check. 17 */ 18 public interface OnCheckCallback { 19 20 /** 21 * Invoked as soon as possible we know that the credentials match. This will be called 22 * earlier than {@link #onChecked} but only if the credentials match. 23 */ onEarlyMatched()24 default void onEarlyMatched() {} 25 26 /** 27 * Invoked when a security check is finished. 28 * 29 * @param matched Whether the PIN/Password/Pattern matches the stored one. 30 * @param throttleTimeoutMs The amount of time in ms to wait before reattempting 31 * the call. Only non-0 if matched is false. 32 */ onChecked(boolean matched, int throttleTimeoutMs)33 void onChecked(boolean matched, int throttleTimeoutMs); 34 35 /** 36 * Called when the underlying AsyncTask was cancelled. 37 */ onCancelled()38 default void onCancelled() {} 39 } 40 41 /** 42 * Interface for a callback to be invoked after security verification. 43 */ 44 public interface OnVerifyCallback { 45 /** 46 * Invoked when a security verification is finished. 47 * 48 * @param attestation The attestation that the challenge was verified, or null. 49 * @param throttleTimeoutMs The amount of time in ms to wait before reattempting 50 * the call. Only non-0 if attestation is null. 51 */ onVerified(byte[] attestation, int throttleTimeoutMs)52 void onVerified(byte[] attestation, int throttleTimeoutMs); 53 } 54 55 /** 56 * Verify a pattern asynchronously. 57 * 58 * @param utils The LockPatternUtils instance to use. 59 * @param pattern The pattern to check. 60 * @param challenge The challenge to verify against the pattern. 61 * @param userId The user to check against the pattern. 62 * @param callback The callback to be invoked with the verification result. 63 */ verifyPattern(final LockPatternUtils utils, final List<LockPatternView.Cell> pattern, final long challenge, final int userId, final OnVerifyCallback callback)64 public static AsyncTask<?, ?, ?> verifyPattern(final LockPatternUtils utils, 65 final List<LockPatternView.Cell> pattern, 66 final long challenge, 67 final int userId, 68 final OnVerifyCallback callback) { 69 AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() { 70 private int mThrottleTimeout; 71 private List<LockPatternView.Cell> patternCopy; 72 73 @Override 74 protected void onPreExecute() { 75 // Make a copy of the pattern to prevent race conditions. 76 // No need to clone the individual cells because they are immutable. 77 patternCopy = new ArrayList(pattern); 78 } 79 80 @Override 81 protected byte[] doInBackground(Void... args) { 82 try { 83 return utils.verifyPattern(patternCopy, challenge, userId); 84 } catch (RequestThrottledException ex) { 85 mThrottleTimeout = ex.getTimeoutMs(); 86 return null; 87 } 88 } 89 90 @Override 91 protected void onPostExecute(byte[] result) { 92 callback.onVerified(result, mThrottleTimeout); 93 } 94 }; 95 task.execute(); 96 return task; 97 } 98 99 /** 100 * Checks a pattern asynchronously. 101 * 102 * @param utils The LockPatternUtils instance to use. 103 * @param pattern The pattern to check. 104 * @param userId The user to check against the pattern. 105 * @param callback The callback to be invoked with the check result. 106 */ checkPattern(final LockPatternUtils utils, final List<LockPatternView.Cell> pattern, final int userId, final OnCheckCallback callback)107 public static AsyncTask<?, ?, ?> checkPattern(final LockPatternUtils utils, 108 final List<LockPatternView.Cell> pattern, 109 final int userId, 110 final OnCheckCallback callback) { 111 AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() { 112 private int mThrottleTimeout; 113 private List<LockPatternView.Cell> patternCopy; 114 115 @Override 116 protected void onPreExecute() { 117 // Make a copy of the pattern to prevent race conditions. 118 // No need to clone the individual cells because they are immutable. 119 patternCopy = new ArrayList(pattern); 120 } 121 122 @Override 123 protected Boolean doInBackground(Void... args) { 124 try { 125 return utils.checkPattern(patternCopy, userId, callback::onEarlyMatched); 126 } catch (RequestThrottledException ex) { 127 mThrottleTimeout = ex.getTimeoutMs(); 128 return false; 129 } 130 } 131 132 @Override 133 protected void onPostExecute(Boolean result) { 134 callback.onChecked(result, mThrottleTimeout); 135 } 136 137 @Override 138 protected void onCancelled() { 139 callback.onCancelled(); 140 } 141 }; 142 task.execute(); 143 return task; 144 } 145 146 /** 147 * Verify a password asynchronously. 148 * 149 * @param utils The LockPatternUtils instance to use. 150 * @param password The password to check. 151 * @param challenge The challenge to verify against the pattern. 152 * @param userId The user to check against the pattern. 153 * @param callback The callback to be invoked with the verification result. 154 * 155 * @deprecated Pass the password as a byte array. 156 */ 157 @Deprecated verifyPassword(final LockPatternUtils utils, final String password, final long challenge, final int userId, final OnVerifyCallback callback)158 public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils, 159 final String password, 160 final long challenge, 161 final int userId, 162 final OnVerifyCallback callback) { 163 byte[] passwordBytes = password != null ? password.getBytes() : null; 164 return verifyPassword(utils, passwordBytes, challenge, userId, callback); 165 } 166 167 /** 168 * Verify a password asynchronously. 169 * 170 * @param utils The LockPatternUtils instance to use. 171 * @param password The password to check. 172 * @param challenge The challenge to verify against the pattern. 173 * @param userId The user to check against the pattern. 174 * @param callback The callback to be invoked with the verification result. 175 */ verifyPassword(final LockPatternUtils utils, final byte[] password, final long challenge, final int userId, final OnVerifyCallback callback)176 public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils, 177 final byte[] password, 178 final long challenge, 179 final int userId, 180 final OnVerifyCallback callback) { 181 AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() { 182 private int mThrottleTimeout; 183 184 @Override 185 protected byte[] doInBackground(Void... args) { 186 try { 187 return utils.verifyPassword(password, challenge, userId); 188 } catch (RequestThrottledException ex) { 189 mThrottleTimeout = ex.getTimeoutMs(); 190 return null; 191 } 192 } 193 194 @Override 195 protected void onPostExecute(byte[] result) { 196 callback.onVerified(result, mThrottleTimeout); 197 } 198 }; 199 task.execute(); 200 return task; 201 } 202 203 /** 204 * Verify a password asynchronously. 205 * 206 * @param utils The LockPatternUtils instance to use. 207 * @param password The password to check. 208 * @param challenge The challenge to verify against the pattern. 209 * @param userId The user to check against the pattern. 210 * @param callback The callback to be invoked with the verification result. 211 */ verifyTiedProfileChallenge(final LockPatternUtils utils, final byte[] password, final boolean isPattern, final long challenge, final int userId, final OnVerifyCallback callback)212 public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils, 213 final byte[] password, 214 final boolean isPattern, 215 final long challenge, 216 final int userId, 217 final OnVerifyCallback callback) { 218 AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() { 219 private int mThrottleTimeout; 220 221 @Override 222 protected byte[] doInBackground(Void... args) { 223 try { 224 return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId); 225 } catch (RequestThrottledException ex) { 226 mThrottleTimeout = ex.getTimeoutMs(); 227 return null; 228 } 229 } 230 231 @Override 232 protected void onPostExecute(byte[] result) { 233 callback.onVerified(result, mThrottleTimeout); 234 } 235 }; 236 task.execute(); 237 return task; 238 } 239 240 /** 241 * Checks a password asynchronously. 242 * 243 * @param utils The LockPatternUtils instance to use. 244 * @param password The password to check. 245 * @param userId The user to check against the pattern. 246 * @param callback The callback to be invoked with the check result. 247 * @deprecated Pass passwords as byte[] 248 */ 249 @UnsupportedAppUsage 250 @Deprecated checkPassword(final LockPatternUtils utils, final String password, final int userId, final OnCheckCallback callback)251 public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils, 252 final String password, 253 final int userId, 254 final OnCheckCallback callback) { 255 byte[] passwordBytes = password != null ? password.getBytes() : null; 256 return checkPassword(utils, passwordBytes, userId, callback); 257 } 258 259 /** 260 * Checks a password asynchronously. 261 * 262 * @param utils The LockPatternUtils instance to use. 263 * @param passwordBytes The password to check. 264 * @param userId The user to check against the pattern. 265 * @param callback The callback to be invoked with the check result. 266 */ checkPassword(final LockPatternUtils utils, final byte[] passwordBytes, final int userId, final OnCheckCallback callback)267 public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils, 268 final byte[] passwordBytes, 269 final int userId, 270 final OnCheckCallback callback) { 271 AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() { 272 private int mThrottleTimeout; 273 274 @Override 275 protected Boolean doInBackground(Void... args) { 276 try { 277 return utils.checkPassword(passwordBytes, userId, callback::onEarlyMatched); 278 } catch (RequestThrottledException ex) { 279 mThrottleTimeout = ex.getTimeoutMs(); 280 return false; 281 } 282 } 283 284 @Override 285 protected void onPostExecute(Boolean result) { 286 callback.onChecked(result, mThrottleTimeout); 287 } 288 289 @Override 290 protected void onCancelled() { 291 callback.onCancelled(); 292 } 293 }; 294 task.execute(); 295 return task; 296 } 297 } 298