1 /* 2 * Copyright (C) 2017 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 package com.example.android.autofill.service; 17 18 import android.service.autofill.SaveInfo; 19 import android.util.Log; 20 import android.view.View; 21 22 import com.example.android.autofill.service.model.FilledAutofillField; 23 import com.example.android.autofill.service.model.FilledAutofillFieldCollection; 24 import com.google.common.collect.ImmutableMap; 25 26 import java.util.Calendar; 27 28 import static com.example.android.autofill.service.CommonUtil.TAG; 29 30 public final class AutofillHints { 31 public static final int PARTITION_OTHER = 0; 32 public static final int PARTITION_ADDRESS = 1; 33 public static final int PARTITION_EMAIL = 2; 34 public static final int PARTITION_CREDIT_CARD = 3; 35 public static final int[] PARTITIONS = { 36 PARTITION_OTHER, PARTITION_ADDRESS, PARTITION_EMAIL, PARTITION_CREDIT_CARD 37 }; 38 /* TODO: finish building fake data for all hints. */ 39 private static final ImmutableMap<String, AutofillHintProperties> sValidHints = 40 new ImmutableMap.Builder<String, AutofillHintProperties>() 41 .put(View.AUTOFILL_HINT_EMAIL_ADDRESS, new AutofillHintProperties( 42 View.AUTOFILL_HINT_EMAIL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS, 43 PARTITION_EMAIL, 44 (seed) -> { 45 FilledAutofillField filledAutofillField = 46 new FilledAutofillField(View.AUTOFILL_HINT_EMAIL_ADDRESS); 47 filledAutofillField.setTextValue("email" + seed); 48 return filledAutofillField; 49 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 50 .put(View.AUTOFILL_HINT_NAME, new AutofillHintProperties( 51 View.AUTOFILL_HINT_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC, 52 PARTITION_OTHER, 53 (seed) -> { 54 FilledAutofillField filledAutofillField = 55 new FilledAutofillField(View.AUTOFILL_HINT_NAME); 56 filledAutofillField.setTextValue("name" + seed); 57 return filledAutofillField; 58 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 59 .put(View.AUTOFILL_HINT_USERNAME, new AutofillHintProperties( 60 View.AUTOFILL_HINT_USERNAME, SaveInfo.SAVE_DATA_TYPE_USERNAME, 61 PARTITION_OTHER, 62 (seed) -> { 63 FilledAutofillField filledAutofillField = 64 new FilledAutofillField(View.AUTOFILL_HINT_USERNAME); 65 filledAutofillField.setTextValue("login" + seed); 66 return filledAutofillField; 67 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 68 .put(View.AUTOFILL_HINT_PASSWORD, new AutofillHintProperties( 69 View.AUTOFILL_HINT_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD, 70 PARTITION_OTHER, 71 (seed) -> { 72 FilledAutofillField filledAutofillField = 73 new FilledAutofillField(View.AUTOFILL_HINT_PASSWORD); 74 filledAutofillField.setTextValue("login" + seed); 75 return filledAutofillField; 76 }, View.AUTOFILL_TYPE_TEXT)) 77 .put(View.AUTOFILL_HINT_PHONE, new AutofillHintProperties( 78 View.AUTOFILL_HINT_PHONE, SaveInfo.SAVE_DATA_TYPE_GENERIC, 79 PARTITION_OTHER, 80 (seed) -> { 81 FilledAutofillField filledAutofillField = 82 new FilledAutofillField(View.AUTOFILL_HINT_PHONE); 83 filledAutofillField.setTextValue("" + seed + "2345678910"); 84 return filledAutofillField; 85 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 86 .put(View.AUTOFILL_HINT_POSTAL_ADDRESS, new AutofillHintProperties( 87 View.AUTOFILL_HINT_POSTAL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 88 PARTITION_ADDRESS, 89 (seed) -> { 90 FilledAutofillField filledAutofillField = 91 new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_ADDRESS); 92 filledAutofillField.setTextValue( 93 "" + seed + " Fake Ln, Fake, FA, FAA 10001"); 94 return filledAutofillField; 95 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 96 .put(View.AUTOFILL_HINT_POSTAL_CODE, new AutofillHintProperties( 97 View.AUTOFILL_HINT_POSTAL_CODE, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 98 PARTITION_ADDRESS, 99 (seed) -> { 100 FilledAutofillField filledAutofillField = 101 new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_CODE); 102 filledAutofillField.setTextValue("1000" + seed); 103 return filledAutofillField; 104 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 105 .put(View.AUTOFILL_HINT_CREDIT_CARD_NUMBER, new AutofillHintProperties( 106 View.AUTOFILL_HINT_CREDIT_CARD_NUMBER, 107 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, 108 PARTITION_CREDIT_CARD, 109 (seed) -> { 110 FilledAutofillField filledAutofillField = new FilledAutofillField( 111 View.AUTOFILL_HINT_CREDIT_CARD_NUMBER); 112 filledAutofillField.setTextValue("" + seed + "234567"); 113 return filledAutofillField; 114 }, View.AUTOFILL_TYPE_TEXT)) 115 .put(View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, new AutofillHintProperties( 116 View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, 117 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, 118 PARTITION_CREDIT_CARD, 119 (seed) -> { 120 FilledAutofillField filledAutofillField = new FilledAutofillField( 121 View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE); 122 filledAutofillField.setTextValue("" + seed + seed + seed); 123 return filledAutofillField; 124 }, View.AUTOFILL_TYPE_TEXT)) 125 .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE, 126 new AutofillHintProperties( 127 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE, 128 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 129 (seed) -> { 130 FilledAutofillField filledAutofillField = new FilledAutofillField( 131 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE); 132 Calendar calendar = Calendar.getInstance(); 133 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed); 134 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 135 return filledAutofillField; 136 }, View.AUTOFILL_TYPE_DATE)) 137 .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH, 138 new AutofillHintProperties( 139 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH, 140 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 141 (seed) -> { 142 CharSequence[] months = monthRange(); 143 int month = seed % months.length; 144 Calendar calendar = Calendar.getInstance(); 145 calendar.set(Calendar.MONTH, month); 146 FilledAutofillField filledAutofillField = 147 new FilledAutofillField( 148 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH); 149 filledAutofillField.setListValue(months, month); 150 filledAutofillField.setTextValue(Integer.toString(month)); 151 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 152 return filledAutofillField; 153 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST, 154 View.AUTOFILL_TYPE_DATE)) 155 .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR, new AutofillHintProperties( 156 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR, 157 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 158 (seed) -> { 159 FilledAutofillField filledAutofillField = new FilledAutofillField( 160 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR); 161 Calendar calendar = Calendar.getInstance(); 162 int expYear = calendar.get(Calendar.YEAR) + seed; 163 calendar.set(Calendar.YEAR, expYear); 164 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 165 filledAutofillField.setTextValue(Integer.toString(expYear)); 166 return filledAutofillField; 167 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST, 168 View.AUTOFILL_TYPE_DATE)) 169 .put(View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY, new AutofillHintProperties( 170 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY, 171 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 172 (seed) -> { 173 CharSequence[] days = dayRange(); 174 int day = seed % days.length; 175 FilledAutofillField filledAutofillField = new FilledAutofillField( 176 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY); 177 Calendar calendar = Calendar.getInstance(); 178 calendar.set(Calendar.DATE, day); 179 filledAutofillField.setListValue(days, day); 180 filledAutofillField.setTextValue(Integer.toString(day)); 181 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 182 return filledAutofillField; 183 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST, 184 View.AUTOFILL_TYPE_DATE)) 185 .put(W3cHints.HONORIFIC_PREFIX, new AutofillHintProperties( 186 W3cHints.HONORIFIC_PREFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC, 187 PARTITION_OTHER, 188 (seed) -> { 189 FilledAutofillField filledAutofillField = new FilledAutofillField( 190 W3cHints.HONORIFIC_PREFIX); 191 CharSequence[] examplePrefixes = {"Miss", "Ms.", "Mr.", "Mx.", 192 "Sr.", "Dr.", "Lady", "Lord"}; 193 filledAutofillField.setListValue(examplePrefixes, 194 seed % examplePrefixes.length); 195 return filledAutofillField; 196 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 197 .put(W3cHints.GIVEN_NAME, new AutofillHintProperties(W3cHints.GIVEN_NAME, 198 SaveInfo.SAVE_DATA_TYPE_GENERIC, 199 PARTITION_OTHER, 200 (seed) -> { 201 FilledAutofillField filledAutofillField = 202 new FilledAutofillField(W3cHints.GIVEN_NAME); 203 filledAutofillField.setTextValue("name" + seed); 204 return filledAutofillField; 205 }, View.AUTOFILL_TYPE_TEXT)) 206 .put(W3cHints.ADDITIONAL_NAME, new AutofillHintProperties( 207 W3cHints.ADDITIONAL_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC, 208 PARTITION_OTHER, 209 (seed) -> { 210 FilledAutofillField filledAutofillField = 211 new FilledAutofillField(W3cHints.ADDITIONAL_NAME); 212 filledAutofillField.setTextValue("addtlname" + seed); 213 return filledAutofillField; 214 }, View.AUTOFILL_TYPE_TEXT)) 215 .put(W3cHints.FAMILY_NAME, new AutofillHintProperties( 216 W3cHints.FAMILY_NAME, SaveInfo.SAVE_DATA_TYPE_GENERIC, 217 PARTITION_OTHER, 218 (seed) -> { 219 FilledAutofillField filledAutofillField = 220 new FilledAutofillField(W3cHints.FAMILY_NAME); 221 filledAutofillField.setTextValue("famname" + seed); 222 return filledAutofillField; 223 }, View.AUTOFILL_TYPE_TEXT)) 224 .put(W3cHints.HONORIFIC_SUFFIX, new AutofillHintProperties( 225 W3cHints.HONORIFIC_SUFFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC, 226 PARTITION_OTHER, 227 (seed) -> { 228 FilledAutofillField filledAutofillField = 229 new FilledAutofillField(W3cHints.HONORIFIC_SUFFIX); 230 CharSequence[] exampleSuffixes = {"san", "kun", "chan", "sama"}; 231 filledAutofillField.setListValue(exampleSuffixes, 232 seed % exampleSuffixes.length); 233 return filledAutofillField; 234 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 235 .put(W3cHints.NEW_PASSWORD, new AutofillHintProperties( 236 W3cHints.NEW_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD, 237 PARTITION_OTHER, 238 (seed) -> { 239 FilledAutofillField filledAutofillField = 240 new FilledAutofillField(W3cHints.NEW_PASSWORD); 241 filledAutofillField.setTextValue("login" + seed); 242 return filledAutofillField; 243 }, View.AUTOFILL_TYPE_TEXT)) 244 .put(W3cHints.CURRENT_PASSWORD, new AutofillHintProperties( 245 View.AUTOFILL_HINT_PASSWORD, SaveInfo.SAVE_DATA_TYPE_PASSWORD, 246 PARTITION_OTHER, 247 (seed) -> { 248 FilledAutofillField filledAutofillField = 249 new FilledAutofillField(View.AUTOFILL_HINT_PASSWORD); 250 filledAutofillField.setTextValue("login" + seed); 251 return filledAutofillField; 252 }, View.AUTOFILL_TYPE_TEXT)) 253 .put(W3cHints.ORGANIZATION_TITLE, new AutofillHintProperties( 254 W3cHints.ORGANIZATION_TITLE, SaveInfo.SAVE_DATA_TYPE_GENERIC, 255 PARTITION_OTHER, 256 (seed) -> { 257 FilledAutofillField filledAutofillField = 258 new FilledAutofillField(W3cHints.ORGANIZATION_TITLE); 259 filledAutofillField.setTextValue("org" + seed); 260 return filledAutofillField; 261 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 262 .put(W3cHints.ORGANIZATION, new AutofillHintProperties(W3cHints.ORGANIZATION, 263 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 264 (seed) -> { 265 FilledAutofillField filledAutofillField = 266 new FilledAutofillField(W3cHints.ORGANIZATION); 267 filledAutofillField.setTextValue("org" + seed); 268 return filledAutofillField; 269 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 270 .put(W3cHints.STREET_ADDRESS, new AutofillHintProperties( 271 W3cHints.STREET_ADDRESS, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 272 PARTITION_ADDRESS, 273 (seed) -> { 274 FilledAutofillField filledAutofillField = 275 new FilledAutofillField(W3cHints.STREET_ADDRESS); 276 filledAutofillField.setTextValue( 277 "" + seed + " Fake Ln, Fake, FA, FAA 10001"); 278 return filledAutofillField; 279 }, View.AUTOFILL_TYPE_TEXT)) 280 .put(W3cHints.ADDRESS_LINE1, new AutofillHintProperties(W3cHints.ADDRESS_LINE1, 281 SaveInfo.SAVE_DATA_TYPE_ADDRESS, 282 PARTITION_ADDRESS, 283 (seed) -> { 284 FilledAutofillField filledAutofillField = 285 new FilledAutofillField(W3cHints.ADDRESS_LINE1); 286 filledAutofillField.setTextValue("" + seed + " Fake Ln"); 287 return filledAutofillField; 288 }, View.AUTOFILL_TYPE_TEXT)) 289 .put(W3cHints.ADDRESS_LINE2, new AutofillHintProperties(W3cHints.ADDRESS_LINE2, 290 SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS, 291 (seed) -> { 292 FilledAutofillField filledAutofillField = 293 new FilledAutofillField(W3cHints.ADDRESS_LINE2); 294 filledAutofillField.setTextValue("Apt. " + seed); 295 return filledAutofillField; 296 }, View.AUTOFILL_TYPE_TEXT)) 297 .put(W3cHints.ADDRESS_LINE3, new AutofillHintProperties(W3cHints.ADDRESS_LINE3, 298 SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS, 299 (seed) -> { 300 FilledAutofillField filledAutofillField = 301 new FilledAutofillField(W3cHints.ADDRESS_LINE3); 302 filledAutofillField.setTextValue("FA" + seed + ", FA, FAA"); 303 return filledAutofillField; 304 }, View.AUTOFILL_TYPE_TEXT)) 305 .put(W3cHints.ADDRESS_LEVEL4, new AutofillHintProperties( 306 W3cHints.ADDRESS_LEVEL4, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 307 PARTITION_ADDRESS, 308 (seed) -> { 309 FilledAutofillField filledAutofillField = 310 new FilledAutofillField(W3cHints.ADDRESS_LEVEL4); 311 return filledAutofillField; 312 }, View.AUTOFILL_TYPE_TEXT)) 313 .put(W3cHints.ADDRESS_LEVEL3, new AutofillHintProperties( 314 W3cHints.ADDRESS_LEVEL3, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 315 PARTITION_ADDRESS, 316 (seed) -> { 317 FilledAutofillField filledAutofillField = 318 new FilledAutofillField(W3cHints.ADDRESS_LEVEL3); 319 return filledAutofillField; 320 }, View.AUTOFILL_TYPE_TEXT)) 321 .put(W3cHints.ADDRESS_LEVEL2, new AutofillHintProperties( 322 W3cHints.ADDRESS_LEVEL2, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 323 PARTITION_ADDRESS, 324 (seed) -> { 325 FilledAutofillField filledAutofillField = 326 new FilledAutofillField(W3cHints.ADDRESS_LEVEL2); 327 return filledAutofillField; 328 }, View.AUTOFILL_TYPE_TEXT)) 329 .put(W3cHints.ADDRESS_LEVEL1, new AutofillHintProperties( 330 W3cHints.ADDRESS_LEVEL1, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 331 PARTITION_ADDRESS, 332 (seed) -> { 333 FilledAutofillField filledAutofillField = 334 new FilledAutofillField(W3cHints.ADDRESS_LEVEL1); 335 return filledAutofillField; 336 }, View.AUTOFILL_TYPE_TEXT)) 337 .put(W3cHints.COUNTRY, new AutofillHintProperties(W3cHints.COUNTRY, 338 SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS, 339 (seed) -> { 340 FilledAutofillField filledAutofillField = 341 new FilledAutofillField(W3cHints.COUNTRY); 342 return filledAutofillField; 343 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 344 .put(W3cHints.COUNTRY_NAME, new AutofillHintProperties(W3cHints.COUNTRY_NAME, 345 SaveInfo.SAVE_DATA_TYPE_ADDRESS, PARTITION_ADDRESS, 346 (seed) -> { 347 FilledAutofillField filledAutofillField = 348 new FilledAutofillField(W3cHints.COUNTRY_NAME); 349 CharSequence[] exampleCountries = {"USA", "Mexico", "Canada"}; 350 filledAutofillField.setListValue(exampleCountries, 351 seed % exampleCountries.length); 352 return filledAutofillField; 353 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 354 .put(W3cHints.POSTAL_CODE, new AutofillHintProperties( 355 View.AUTOFILL_HINT_POSTAL_CODE, SaveInfo.SAVE_DATA_TYPE_ADDRESS, 356 PARTITION_ADDRESS, 357 (seed) -> { 358 FilledAutofillField filledAutofillField = 359 new FilledAutofillField(View.AUTOFILL_HINT_POSTAL_CODE); 360 filledAutofillField.setTextValue("" + seed + seed + seed + seed + 361 seed); 362 return filledAutofillField; 363 }, View.AUTOFILL_TYPE_TEXT)) 364 .put(W3cHints.CC_NAME, new AutofillHintProperties(W3cHints.CC_NAME, 365 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, 366 PARTITION_CREDIT_CARD, 367 (seed) -> { 368 FilledAutofillField filledAutofillField = 369 new FilledAutofillField(W3cHints.CC_NAME); 370 filledAutofillField.setTextValue("firstname" + seed + "lastname" + 371 seed); 372 return filledAutofillField; 373 }, View.AUTOFILL_TYPE_TEXT)) 374 .put(W3cHints.CC_GIVEN_NAME, new AutofillHintProperties(W3cHints.CC_GIVEN_NAME, 375 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 376 (seed) -> { 377 FilledAutofillField filledAutofillField = 378 new FilledAutofillField(W3cHints.CC_GIVEN_NAME); 379 filledAutofillField.setTextValue("givenname" + seed); 380 return filledAutofillField; 381 }, View.AUTOFILL_TYPE_TEXT)) 382 .put(W3cHints.CC_ADDITIONAL_NAME, new AutofillHintProperties( 383 W3cHints.CC_ADDITIONAL_NAME, SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, 384 PARTITION_CREDIT_CARD, 385 (seed) -> { 386 FilledAutofillField filledAutofillField = 387 new FilledAutofillField(W3cHints.CC_ADDITIONAL_NAME); 388 filledAutofillField.setTextValue("addtlname" + seed); 389 return filledAutofillField; 390 }, View.AUTOFILL_TYPE_TEXT)) 391 .put(W3cHints.CC_FAMILY_NAME, new AutofillHintProperties( 392 W3cHints.CC_FAMILY_NAME, SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, 393 PARTITION_CREDIT_CARD, 394 (seed) -> { 395 FilledAutofillField filledAutofillField = 396 new FilledAutofillField(W3cHints.CC_FAMILY_NAME); 397 filledAutofillField.setTextValue("familyname" + seed); 398 return filledAutofillField; 399 }, View.AUTOFILL_TYPE_TEXT)) 400 .put(W3cHints.CC_NUMBER, new AutofillHintProperties( 401 View.AUTOFILL_HINT_CREDIT_CARD_NUMBER, 402 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 403 (seed) -> { 404 FilledAutofillField filledAutofillField = new FilledAutofillField( 405 View.AUTOFILL_HINT_CREDIT_CARD_NUMBER); 406 filledAutofillField.setTextValue("" + seed + "234567"); 407 return filledAutofillField; 408 }, View.AUTOFILL_TYPE_TEXT)) 409 .put(W3cHints.CC_EXPIRATION, new AutofillHintProperties( 410 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE, 411 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 412 (seed) -> { 413 FilledAutofillField filledAutofillField = new FilledAutofillField( 414 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE); 415 Calendar calendar = Calendar.getInstance(); 416 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + seed); 417 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 418 return filledAutofillField; 419 }, View.AUTOFILL_TYPE_DATE)) 420 .put(W3cHints.CC_EXPIRATION_MONTH, new AutofillHintProperties( 421 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH, 422 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 423 (seed) -> { 424 FilledAutofillField filledAutofillField = new FilledAutofillField( 425 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH); 426 CharSequence[] months = monthRange(); 427 filledAutofillField.setListValue(months, 428 seed % months.length); 429 return filledAutofillField; 430 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 431 .put(W3cHints.CC_EXPIRATION_YEAR, new AutofillHintProperties( 432 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR, 433 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 434 (seed) -> { 435 FilledAutofillField filledAutofillField = new FilledAutofillField( 436 View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR); 437 Calendar calendar = Calendar.getInstance(); 438 int expYear = calendar.get(Calendar.YEAR) + seed; 439 calendar.set(Calendar.YEAR, expYear); 440 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 441 filledAutofillField.setTextValue("" + expYear); 442 return filledAutofillField; 443 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 444 .put(W3cHints.CC_CSC, new AutofillHintProperties( 445 View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE, 446 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 447 (seed) -> { 448 FilledAutofillField filledAutofillField = new FilledAutofillField( 449 View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE); 450 filledAutofillField.setTextValue("" + seed + seed + seed); 451 return filledAutofillField; 452 }, View.AUTOFILL_TYPE_TEXT)) 453 .put(W3cHints.CC_TYPE, new AutofillHintProperties(W3cHints.CC_TYPE, 454 SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD, PARTITION_CREDIT_CARD, 455 (seed) -> { 456 FilledAutofillField filledAutofillField = 457 new FilledAutofillField(W3cHints.CC_TYPE); 458 filledAutofillField.setTextValue("type" + seed); 459 return filledAutofillField; 460 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 461 .put(W3cHints.TRANSACTION_CURRENCY, new AutofillHintProperties( 462 W3cHints.TRANSACTION_CURRENCY, SaveInfo.SAVE_DATA_TYPE_GENERIC, 463 PARTITION_OTHER, 464 (seed) -> { 465 FilledAutofillField filledAutofillField = 466 new FilledAutofillField(W3cHints.TRANSACTION_CURRENCY); 467 CharSequence[] exampleCurrencies = {"USD", "CAD", "KYD", "CRC"}; 468 filledAutofillField.setListValue(exampleCurrencies, 469 seed % exampleCurrencies.length); 470 return filledAutofillField; 471 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 472 .put(W3cHints.TRANSACTION_AMOUNT, new AutofillHintProperties( 473 W3cHints.TRANSACTION_AMOUNT, SaveInfo.SAVE_DATA_TYPE_GENERIC, 474 PARTITION_OTHER, 475 (seed) -> { 476 FilledAutofillField filledAutofillField = 477 new FilledAutofillField(W3cHints.TRANSACTION_AMOUNT); 478 filledAutofillField.setTextValue("" + seed * 100); 479 return filledAutofillField; 480 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 481 .put(W3cHints.LANGUAGE, new AutofillHintProperties(W3cHints.LANGUAGE, 482 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 483 (seed) -> { 484 FilledAutofillField filledAutofillField = 485 new FilledAutofillField(W3cHints.LANGUAGE); 486 CharSequence[] exampleLanguages = {"Bulgarian", "Croatian", "Czech", 487 "Danish", "Dutch", "English", "Estonian"}; 488 filledAutofillField.setListValue(exampleLanguages, 489 seed % exampleLanguages.length); 490 return filledAutofillField; 491 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 492 .put(W3cHints.BDAY, new AutofillHintProperties(W3cHints.BDAY, 493 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 494 (seed) -> { 495 FilledAutofillField filledAutofillField = 496 new FilledAutofillField(W3cHints.BDAY); 497 Calendar calendar = Calendar.getInstance(); 498 calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - seed * 10); 499 calendar.set(Calendar.MONTH, seed % 12); 500 calendar.set(Calendar.DATE, seed % 27); 501 filledAutofillField.setDateValue(calendar.getTimeInMillis()); 502 return filledAutofillField; 503 }, View.AUTOFILL_TYPE_DATE)) 504 .put(W3cHints.BDAY_DAY, new AutofillHintProperties(W3cHints.BDAY_DAY, 505 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 506 (seed) -> { 507 FilledAutofillField filledAutofillField = 508 new FilledAutofillField(W3cHints.BDAY_DAY); 509 filledAutofillField.setTextValue("" + seed % 27); 510 return filledAutofillField; 511 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 512 .put(W3cHints.BDAY_MONTH, new AutofillHintProperties(W3cHints.BDAY_MONTH, 513 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 514 (seed) -> { 515 FilledAutofillField filledAutofillField = 516 new FilledAutofillField(W3cHints.BDAY_MONTH); 517 filledAutofillField.setTextValue("" + seed % 12); 518 return filledAutofillField; 519 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 520 .put(W3cHints.BDAY_YEAR, new AutofillHintProperties(W3cHints.BDAY_YEAR, 521 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 522 (seed) -> { 523 FilledAutofillField filledAutofillField = 524 new FilledAutofillField(W3cHints.BDAY_YEAR); 525 int year = Calendar.getInstance().get(Calendar.YEAR) - seed * 10; 526 filledAutofillField.setTextValue("" + year); 527 return filledAutofillField; 528 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 529 .put(W3cHints.SEX, new AutofillHintProperties(W3cHints.SEX, 530 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 531 (seed) -> { 532 FilledAutofillField filledAutofillField = 533 new FilledAutofillField(W3cHints.SEX); 534 filledAutofillField.setTextValue("Other"); 535 return filledAutofillField; 536 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 537 .put(W3cHints.URL, new AutofillHintProperties(W3cHints.URL, 538 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 539 (seed) -> { 540 FilledAutofillField filledAutofillField = 541 new FilledAutofillField(W3cHints.URL); 542 filledAutofillField.setTextValue("http://google.com"); 543 return filledAutofillField; 544 }, View.AUTOFILL_TYPE_TEXT)) 545 .put(W3cHints.PHOTO, new AutofillHintProperties(W3cHints.PHOTO, 546 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 547 (seed) -> { 548 FilledAutofillField filledAutofillField = 549 new FilledAutofillField(W3cHints.PHOTO); 550 filledAutofillField.setTextValue("photo" + seed + ".jpg"); 551 return filledAutofillField; 552 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 553 .put(W3cHints.PREFIX_SECTION, new AutofillHintProperties( 554 W3cHints.PREFIX_SECTION, SaveInfo.SAVE_DATA_TYPE_GENERIC, 555 PARTITION_OTHER, 556 (seed) -> { 557 FilledAutofillField filledAutofillField = 558 new FilledAutofillField(W3cHints.PREFIX_SECTION); 559 return filledAutofillField; 560 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 561 .put(W3cHints.SHIPPING, new AutofillHintProperties(W3cHints.SHIPPING, 562 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_ADDRESS, 563 (seed) -> { 564 FilledAutofillField filledAutofillField = 565 new FilledAutofillField(W3cHints.SHIPPING); 566 return filledAutofillField; 567 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 568 .put(W3cHints.BILLING, new AutofillHintProperties(W3cHints.BILLING, 569 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_ADDRESS, 570 (seed) -> { 571 FilledAutofillField filledAutofillField = 572 new FilledAutofillField(W3cHints.BILLING); 573 return filledAutofillField; 574 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 575 .put(W3cHints.PREFIX_HOME, new AutofillHintProperties(W3cHints.PREFIX_HOME, 576 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 577 (seed) -> { 578 FilledAutofillField filledAutofillField = 579 new FilledAutofillField(W3cHints.PREFIX_HOME); 580 return filledAutofillField; 581 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 582 .put(W3cHints.PREFIX_WORK, new AutofillHintProperties(W3cHints.PREFIX_WORK, 583 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 584 (seed) -> { 585 FilledAutofillField filledAutofillField = 586 new FilledAutofillField(W3cHints.PREFIX_WORK); 587 return filledAutofillField; 588 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 589 .put(W3cHints.PREFIX_FAX, new AutofillHintProperties(W3cHints.PREFIX_FAX, 590 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 591 (seed) -> { 592 FilledAutofillField filledAutofillField = 593 new FilledAutofillField(W3cHints.PREFIX_FAX); 594 return filledAutofillField; 595 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 596 .put(W3cHints.PREFIX_PAGER, new AutofillHintProperties(W3cHints.PREFIX_PAGER, 597 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 598 (seed) -> { 599 FilledAutofillField filledAutofillField = 600 new FilledAutofillField(W3cHints.PREFIX_PAGER); 601 return filledAutofillField; 602 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 603 .put(W3cHints.TEL, new AutofillHintProperties(W3cHints.TEL, 604 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 605 (seed) -> { 606 FilledAutofillField filledAutofillField = 607 new FilledAutofillField(W3cHints.TEL); 608 return filledAutofillField; 609 }, View.AUTOFILL_TYPE_TEXT)) 610 .put(W3cHints.TEL_COUNTRY_CODE, new AutofillHintProperties( 611 W3cHints.TEL_COUNTRY_CODE, SaveInfo.SAVE_DATA_TYPE_GENERIC, 612 PARTITION_OTHER, 613 (seed) -> { 614 FilledAutofillField filledAutofillField = 615 new FilledAutofillField(W3cHints.TEL_COUNTRY_CODE); 616 return filledAutofillField; 617 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 618 .put(W3cHints.TEL_NATIONAL, new AutofillHintProperties(W3cHints.TEL_NATIONAL, 619 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 620 (seed) -> { 621 FilledAutofillField filledAutofillField = 622 new FilledAutofillField(W3cHints.TEL_NATIONAL); 623 return filledAutofillField; 624 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 625 .put(W3cHints.TEL_AREA_CODE, new AutofillHintProperties( 626 W3cHints.TEL_AREA_CODE, SaveInfo.SAVE_DATA_TYPE_GENERIC, 627 PARTITION_OTHER, 628 (seed) -> { 629 FilledAutofillField filledAutofillField = 630 new FilledAutofillField(W3cHints.TEL_AREA_CODE); 631 return filledAutofillField; 632 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 633 .put(W3cHints.TEL_LOCAL, new AutofillHintProperties( 634 W3cHints.TEL_LOCAL, SaveInfo.SAVE_DATA_TYPE_GENERIC, 635 PARTITION_OTHER, 636 (seed) -> { 637 FilledAutofillField filledAutofillField = 638 new FilledAutofillField(W3cHints.TEL_LOCAL); 639 return filledAutofillField; 640 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 641 .put(W3cHints.TEL_LOCAL_PREFIX, new AutofillHintProperties( 642 W3cHints.TEL_LOCAL_PREFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC, 643 PARTITION_OTHER, 644 (seed) -> { 645 FilledAutofillField filledAutofillField = 646 new FilledAutofillField(W3cHints.TEL_LOCAL_PREFIX); 647 return filledAutofillField; 648 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 649 .put(W3cHints.TEL_LOCAL_SUFFIX, new AutofillHintProperties( 650 W3cHints.TEL_LOCAL_SUFFIX, SaveInfo.SAVE_DATA_TYPE_GENERIC, 651 PARTITION_OTHER, 652 (seed) -> { 653 FilledAutofillField filledAutofillField = 654 new FilledAutofillField(W3cHints.TEL_LOCAL_SUFFIX); 655 return filledAutofillField; 656 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 657 .put(W3cHints.TEL_EXTENSION, new AutofillHintProperties(W3cHints.TEL_EXTENSION, 658 SaveInfo.SAVE_DATA_TYPE_GENERIC, PARTITION_OTHER, 659 (seed) -> { 660 FilledAutofillField filledAutofillField = 661 new FilledAutofillField(W3cHints.TEL_EXTENSION); 662 return filledAutofillField; 663 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 664 .put(W3cHints.EMAIL, new AutofillHintProperties( 665 View.AUTOFILL_HINT_EMAIL_ADDRESS, SaveInfo.SAVE_DATA_TYPE_GENERIC, 666 PARTITION_EMAIL, 667 (seed) -> { 668 FilledAutofillField filledAutofillField = 669 new FilledAutofillField(View.AUTOFILL_HINT_EMAIL_ADDRESS); 670 filledAutofillField.setTextValue("email" + seed); 671 return filledAutofillField; 672 }, View.AUTOFILL_TYPE_TEXT)) 673 .put(W3cHints.IMPP, new AutofillHintProperties(W3cHints.IMPP, 674 SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS, PARTITION_EMAIL, 675 (seed) -> { 676 FilledAutofillField filledAutofillField = 677 new FilledAutofillField(W3cHints.IMPP); 678 return filledAutofillField; 679 }, View.AUTOFILL_TYPE_TEXT, View.AUTOFILL_TYPE_LIST)) 680 .build(); 681 682 private AutofillHints() { 683 } 684 685 public static boolean isValidTypeForHints(String[] hints, int type) { 686 if (hints != null) { 687 for (String hint : hints) { 688 if (hint != null && sValidHints.containsKey(hint)) { 689 boolean valid = sValidHints.get(hint).isValidType(type); 690 if (valid) { 691 return true; 692 } 693 } 694 } 695 } 696 return false; 697 } 698 699 public static boolean isValidHint(String hint) { 700 return sValidHints.containsKey(hint); 701 } 702 703 public static int getSaveTypeForHints(String[] hints) { 704 int saveType = 0; 705 if (hints != null) { 706 for (String hint : hints) { 707 if (hint != null && sValidHints.containsKey(hint)) { 708 saveType |= sValidHints.get(hint).getSaveType(); 709 } 710 } 711 } 712 return saveType; 713 } 714 715 public static FilledAutofillField getFakeField(String hint, int seed) { 716 return sValidHints.get(hint).generateFakeField(seed); 717 } 718 719 public static FilledAutofillFieldCollection getFakeFieldCollection(int partition, int seed) { 720 FilledAutofillFieldCollection filledAutofillFieldCollection = 721 new FilledAutofillFieldCollection(); 722 for (String hint : sValidHints.keySet()) { 723 if (hint != null && sValidHints.get(hint).getPartition() == partition) { 724 FilledAutofillField fakeField = getFakeField(hint, seed); 725 filledAutofillFieldCollection.add(fakeField); 726 } 727 } 728 return filledAutofillFieldCollection; 729 } 730 731 private static String getStoredHintName(String hint) { 732 return sValidHints.get(hint).getAutofillHint(); 733 } 734 735 public static void convertToStoredHintNames(String[] hints) { 736 for (int i = 0; i < hints.length; i++) { 737 hints[i] = getStoredHintName(hints[i]); 738 } 739 } 740 741 private static CharSequence[] dayRange() { 742 CharSequence[] days = new CharSequence[27]; 743 for (int i = 0; i < days.length; i++) { 744 days[i] = Integer.toString(i); 745 } 746 return days; 747 } 748 749 private static CharSequence[] monthRange() { 750 CharSequence[] months = new CharSequence[12]; 751 for (int i = 0; i < months.length; i++) { 752 months[i] = Integer.toString(i); 753 } 754 return months; 755 } 756 757 public static String[] filterForSupportedHints(String[] hints) { 758 String[] filteredHints = new String[hints.length]; 759 int i = 0; 760 for (String hint : hints) { 761 if (AutofillHints.isValidHint(hint)) { 762 filteredHints[i++] = hint; 763 } else { 764 Log.w(TAG, "Invalid autofill hint: " + hint); 765 } 766 } 767 if (i == 0) { 768 return null; 769 } 770 String[] finalFilteredHints = new String[i]; 771 System.arraycopy(filteredHints, 0, finalFilteredHints, 0, i); 772 return finalFilteredHints; 773 } 774 } 775