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