1 /* <lambda>null2 * Copyright (C) 2023 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.android.settings.biometrics2.ui.view 17 18 import android.content.Context 19 import android.content.Intent 20 import android.content.pm.PackageManager.FEATURE_FINGERPRINT 21 import android.hardware.fingerprint.FingerprintManager 22 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal 23 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback 24 import android.os.UserHandle 25 import android.util.Log 26 import androidx.test.ext.junit.runners.AndroidJUnit4 27 import androidx.test.platform.app.InstrumentationRegistry 28 import androidx.test.uiautomator.By 29 import androidx.test.uiautomator.UiDevice 30 import androidx.test.uiautomator.UiObject2 31 import androidx.test.uiautomator.Until 32 import com.android.internal.widget.LockPatternChecker 33 import com.android.internal.widget.LockPatternUtils 34 import com.android.internal.widget.LockscreenCredential 35 import com.android.internal.widget.VerifyCredentialResponse 36 import com.android.settings.biometrics2.utils.LockScreenUtil 37 import com.google.common.truth.Truth.assertThat 38 import org.junit.After 39 import org.junit.Assume 40 import org.junit.Before 41 import org.junit.Ignore 42 import org.junit.Test 43 import org.junit.runner.RunWith 44 import java.io.IOException 45 46 @Ignore 47 @RunWith(AndroidJUnit4::class) 48 class FingerprintEnrollmentActivityTest { 49 50 private val context: Context by lazy { 51 InstrumentationRegistry.getInstrumentation().context 52 } 53 54 private val fingerprintManager: FingerprintManager by lazy { 55 context.getSystemService(FingerprintManager::class.java)!! 56 } 57 58 private var fingerprintPropCallbackLaunched = false 59 private var canAssumeUdfps = false 60 private var canAssumeSfps = false 61 private var enrollingPageTitle: String = "" 62 private var runAsLandscape = false 63 64 private val device: UiDevice by lazy { 65 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) 66 } 67 68 @Before 69 @Throws(InterruptedException::class) 70 fun setUp() { 71 // Stop every test if it is not a fingerprint device 72 Assume.assumeTrue(context.packageManager.hasSystemFeature(FEATURE_FINGERPRINT)) 73 74 fingerprintPropCallbackLaunched = false 75 fingerprintManager.addAuthenticatorsRegisteredCallback( 76 object : IFingerprintAuthenticatorsRegisteredCallback.Stub() { 77 override fun onAllAuthenticatorsRegistered( 78 list: List<FingerprintSensorPropertiesInternal> 79 ) { 80 fingerprintPropCallbackLaunched = true 81 assertThat(list).isNotNull() 82 assertThat(list).isNotEmpty() 83 val prop = list[0] 84 canAssumeUdfps = prop.isAnyUdfpsType 85 canAssumeSfps = prop.isAnySidefpsType 86 enrollingPageTitle = if (canAssumeUdfps) { 87 UDFPS_ENROLLING_TITLE 88 } else if (canAssumeSfps) { 89 SFPS_ENROLLING_TITLE 90 } else { 91 RFPS_ENROLLING_TITLE 92 } 93 } 94 }) 95 var i: Long = 0 96 while (i < IDLE_TIMEOUT && !fingerprintPropCallbackLaunched) { 97 Thread.sleep(100L) 98 i += 100L 99 } 100 assertThat(fingerprintPropCallbackLaunched).isTrue() 101 device.pressHome() 102 103 // Stop settings before performing test 104 try { 105 device.executeShellCommand("am force-stop $SETTINGS_PACKAGE_NAME") 106 } catch (e: IOException) { 107 Log.e(TAG, "Fail to stop settings app", e) 108 } 109 } 110 111 @After 112 @Throws(Exception::class) 113 fun tearDown() { 114 runAsLandscape = false 115 setDeviceOrientation() 116 117 LockScreenUtil.resetLockscreen(TEST_PIN) 118 device.pressHome() 119 } 120 121 @Test 122 fun testIntroChooseLock() { 123 setDeviceOrientation() 124 val intent = newActivityIntent(false) 125 context.startActivity(intent) 126 assertThat( 127 device.wait( 128 Until.hasObject(By.text("Choose your backup screen lock method")), 129 IDLE_TIMEOUT 130 ) 131 ).isTrue() 132 } 133 134 @Test 135 fun testIntroChooseLock_runAslandscape() { 136 runAsLandscape = true 137 testIntroChooseLock() 138 } 139 140 private fun verifyIntroPage() { 141 device.waitForIdle() 142 run { 143 var i: Long = 0 144 while (i < IDLE_TIMEOUT) { 145 if (device.wait(Until.hasObject(By.text("More")), 50L)) { 146 break 147 } else if (device.wait(Until.hasObject(By.text("I agree")), 50L)) { 148 break 149 } 150 i += 100L 151 } 152 } 153 154 // Click more btn at most twice and the introduction should stay in the last page 155 var moreBtn: UiObject2? = null 156 var i = 0 157 val more = if (runAsLandscape) 5 else 2 158 while (i < more && device.findObject(By.text("More")).also { moreBtn = it } != null) { 159 moreBtn!!.click() 160 device.waitForIdle() 161 device.wait(Until.hasObject(By.text("More")), IDLE_TIMEOUT) 162 ++i 163 } 164 assertThat(device.wait(Until.hasObject(By.text("No thanks")), IDLE_TIMEOUT)).isTrue() 165 assertThat(device.wait(Until.hasObject(By.text("I agree")), IDLE_TIMEOUT)).isTrue() 166 } 167 168 @Test 169 fun testIntroWithGkPwHandle_withUdfps_clickStart() { 170 Assume.assumeTrue(canAssumeUdfps) 171 172 setDeviceOrientation() 173 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 174 launchIntroWithGkPwHandle(false) 175 176 // Intro page 177 verifyIntroPage() 178 val agreeBtn = device.findObject(By.text("I agree")) 179 assertThat(agreeBtn).isNotNull() 180 agreeBtn.click() 181 182 // FindUdfps page 183 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 184 val lottie = device.findObject( 185 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 186 ) 187 assertThat(lottie).isNotNull() 188 assertThat(lottie.isClickable).isTrue() 189 val startBtn = device.findObject(By.text("Start")) 190 assertThat(startBtn.isClickable).isTrue() 191 startBtn.click() 192 193 // Enrolling page 194 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 195 } 196 197 @Test 198 fun testIntroWithGkPwHandle_withUdfps_clickStart_runAslandscape() { 199 runAsLandscape = true 200 testIntroWithGkPwHandle_withUdfps_clickStart() 201 } 202 203 @Test 204 fun testIntroWithGkPwHandle_withUdfps_clickLottie() { 205 Assume.assumeTrue(canAssumeUdfps) 206 207 setDeviceOrientation() 208 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 209 launchIntroWithGkPwHandle(false) 210 211 // Intro page 212 verifyIntroPage() 213 val agreeBtn = device.findObject(By.text("I agree")) 214 assertThat(agreeBtn).isNotNull() 215 agreeBtn.click() 216 217 // FindUdfps page 218 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 219 val lottie = device.findObject(By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")) 220 assertThat(lottie).isNotNull() 221 assertThat(lottie.isClickable).isTrue() 222 val startBtn = device.findObject(By.text("Start")) 223 assertThat(startBtn.isClickable).isTrue() 224 lottie.click() 225 226 // Enrolling page 227 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 228 } 229 230 @Test 231 fun testIntroWithGkPwHandle_withUdfps_clickLottie_runAslandscape() { 232 runAsLandscape = true 233 testIntroWithGkPwHandle_withUdfps_clickLottie() 234 } 235 236 @Test 237 fun testIntroWithGkPwHandle_withSfps() { 238 Assume.assumeTrue(canAssumeSfps) 239 240 setDeviceOrientation() 241 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 242 launchIntroWithGkPwHandle(false) 243 244 // Intro page 245 verifyIntroPage() 246 val agreeBtn = device.findObject(By.text("I agree")) 247 assertThat(agreeBtn).isNotNull() 248 agreeBtn.click() 249 250 // FindSfps page 251 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 252 val lottie = device.findObject( 253 By.res(SETTINGS_PACKAGE_NAME,"illustration_lottie") 254 ) 255 assertThat(lottie).isNotNull() 256 257 // We don't have view which can be clicked to run to next page, stop at here. 258 } 259 260 @Test 261 fun testIntroWithGkPwHandle_withSfps_runAslandscape() { 262 runAsLandscape = true 263 testIntroWithGkPwHandle_withSfps() 264 } 265 266 @Test 267 fun testIntroWithGkPwHandle_withRfps() { 268 Assume.assumeFalse(canAssumeUdfps || canAssumeSfps) 269 270 setDeviceOrientation() 271 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 272 launchIntroWithGkPwHandle(false) 273 274 // Intro page 275 verifyIntroPage() 276 val agreeBtn = device.findObject(By.text("I agree")) 277 assertThat(agreeBtn).isNotNull() 278 agreeBtn.click() 279 280 // FindRfps page 281 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 282 val lottie = device.findObject( 283 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 284 ) 285 if (lottie == null) { 286 // FindSfps page shall have an animation view if no lottie view 287 assertThat( 288 device.findObject( 289 By.res(SETTINGS_PACKAGE_NAME, "fingerprint_sensor_location_animation") 290 ) 291 ).isNotNull() 292 } 293 } 294 295 @Test 296 fun testIntroWithGkPwHandle_withRfps_runAslandscape() { 297 runAsLandscape = true 298 testIntroWithGkPwHandle_withRfps() 299 } 300 301 @Test 302 fun testIntroWithGkPwHandle_clickNoThanksInIntroPage() { 303 setDeviceOrientation() 304 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 305 launchIntroWithGkPwHandle(false) 306 307 // Intro page 308 verifyIntroPage() 309 val noThanksBtn = device.findObject(By.text("No thanks")) 310 assertThat(noThanksBtn).isNotNull() 311 noThanksBtn.click() 312 313 // Back to home 314 device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT) 315 assertThat(device.findObject(By.text("No thanks"))).isNull() 316 } 317 318 @Test 319 fun testIntroWithGkPwHandle_clickNoThanksInIntroPage_runAslandscape() { 320 runAsLandscape = true 321 testIntroWithGkPwHandle_clickNoThanksInIntroPage() 322 } 323 324 @Test 325 fun testIntroWithGkPwHandle_clickSkipInFindSensor() { 326 setDeviceOrientation() 327 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 328 launchIntroWithGkPwHandle(false) 329 330 // Intro page 331 verifyIntroPage() 332 val agreeBtn = device.findObject(By.text("I agree")) 333 assertThat(agreeBtn).isNotNull() 334 agreeBtn.click() 335 336 // FindSensor page 337 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 338 val doItLaterBtn = device.findObject(By.text(DO_IT_LATER)) 339 assertThat(doItLaterBtn).isNotNull() 340 assertThat(doItLaterBtn.isClickable).isTrue() 341 doItLaterBtn.click() 342 343 // Back to home 344 device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT) 345 assertThat(device.findObject(By.text(DO_IT_LATER))).isNull() 346 } 347 348 @Test 349 fun testIntroWithGkPwHandle_clickSkipInFindSensor_runAslandscape() { 350 runAsLandscape = true 351 testIntroWithGkPwHandle_clickSkipInFindSensor() 352 } 353 354 @Test 355 fun testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw() { 356 setDeviceOrientation() 357 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 358 launchIntroWithGkPwHandle(true) 359 360 // Intro page 361 verifyIntroPage() 362 val agreeBtn = device.findObject(By.text("I agree")) 363 assertThat(agreeBtn).isNotNull() 364 agreeBtn.click() 365 366 // FindSensor page 367 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 368 val doItLaterBtn = device.findObject(By.text(DO_IT_LATER)) 369 assertThat(doItLaterBtn).isNotNull() 370 assertThat(doItLaterBtn.isClickable).isTrue() 371 doItLaterBtn.click() 372 373 // SkipSetupFindFpsDialog 374 assertThat(device.wait(Until.hasObject(By.text("Skip fingerprint?")), IDLE_TIMEOUT)).isTrue() 375 val skipAnywayBtn = device.findObject(By.text("Skip anyway")) 376 assertThat(skipAnywayBtn).isNotNull() 377 assertThat(skipAnywayBtn.isClickable).isTrue() 378 skipAnywayBtn.click() 379 380 // Back to home 381 device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT) 382 assertThat(device.findObject(By.text("Skip anyway"))).isNull() 383 assertThat(device.findObject(By.text(DO_IT_LATER))).isNull() 384 } 385 386 @Test 387 fun testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw_runAslandscape() { 388 runAsLandscape = true 389 testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw() 390 } 391 392 @Test 393 fun testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw() { 394 setDeviceOrientation() 395 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 396 launchIntroWithGkPwHandle(true) 397 398 // Intro page 399 verifyIntroPage() 400 val agreeBtn = device.findObject(By.text("I agree")) 401 assertThat(agreeBtn).isNotNull() 402 agreeBtn.click() 403 404 // FindSensor page 405 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 406 val doItLaterBtn = device.findObject(By.text(DO_IT_LATER)) 407 assertThat(doItLaterBtn).isNotNull() 408 assertThat(doItLaterBtn.isClickable).isTrue() 409 doItLaterBtn.click() 410 411 // SkipSetupFindFpsDialog 412 assertThat(device.wait(Until.hasObject(By.text("Skip fingerprint?")), IDLE_TIMEOUT)).isTrue() 413 val goBackBtn = device.findObject(By.text("Go back")) 414 assertThat(goBackBtn).isNotNull() 415 assertThat(goBackBtn.isClickable).isTrue() 416 goBackBtn.click() 417 418 // FindSensor page again 419 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 420 } 421 422 @Test 423 fun testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw_runAslandscape() { 424 runAsLandscape = true 425 testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw() 426 } 427 428 @Test 429 fun testIntroCheckPin() { 430 setDeviceOrientation() 431 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 432 val intent = newActivityIntent(false) 433 context.startActivity(intent) 434 assertThat( 435 device.wait( 436 Until.hasObject(By.text("Enter your device PIN to continue")), 437 IDLE_TIMEOUT 438 ) 439 ).isTrue() 440 } 441 442 @Test 443 fun testEnrollingWithGkPwHandle() { 444 setDeviceOrientation() 445 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 446 launchEnrollingWithGkPwHandle() 447 448 // Enrolling screen 449 device.waitForIdle() 450 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 451 } 452 453 @Test 454 fun testEnrollingWithGkPwHandle_runAslandscape() { 455 runAsLandscape = true 456 testEnrollingWithGkPwHandle() 457 } 458 459 @Test 460 fun testEnrollingIconTouchDialog_withSfps() { 461 Assume.assumeTrue(canAssumeSfps) 462 463 setDeviceOrientation() 464 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 465 launchEnrollingWithGkPwHandle() 466 467 // Enrolling screen 468 device.waitForIdle() 469 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 470 val lottie = device.findObject( 471 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 472 ) 473 assertThat(lottie).isNotNull() 474 lottie.click() 475 lottie.click() 476 lottie.click() 477 478 // IconTouchDialog 479 device.waitForIdle() 480 assertThat( 481 device.wait( 482 Until.hasObject(By.text("Touch the sensor instead")), 483 IDLE_TIMEOUT 484 ) 485 ) 486 .isTrue() 487 val okButton = device.findObject(By.text("OK")) 488 assertThat(okButton).isNotNull() 489 okButton.click() 490 491 // Enrolling screen again 492 device.waitForIdle() 493 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 494 } 495 496 @Test 497 fun testEnrollingIconTouchDialog_withSfps_runAslandscape() { 498 runAsLandscape = true 499 testEnrollingIconTouchDialog_withSfps() 500 } 501 502 @Test 503 fun testEnrollingIconTouchDialog_withRfps() { 504 Assume.assumeFalse(canAssumeUdfps || canAssumeSfps) 505 506 setDeviceOrientation() 507 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 508 launchEnrollingWithGkPwHandle() 509 510 // Enrolling screen 511 device.waitForIdle() 512 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 513 val lottie = device.findObject( 514 By.res(SETTINGS_PACKAGE_NAME, "fingerprint_progress_bar") 515 ) 516 assertThat(lottie).isNotNull() 517 lottie.click() 518 lottie.click() 519 lottie.click() 520 521 // IconTouchDialog 522 device.waitForIdle() 523 assertThat( 524 device.wait( 525 Until.hasObject(By.text("Whoops, that\u2019s not the sensor")), 526 IDLE_TIMEOUT 527 ) 528 ).isTrue() 529 val okButton = device.findObject(By.text("OK")) 530 assertThat(okButton).isNotNull() 531 okButton.click() 532 533 // Enrolling screen again 534 device.waitForIdle() 535 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 536 } 537 538 @Test 539 fun testEnrollingIconTouchDialog_withRfps_runAslandscape() { 540 runAsLandscape = true 541 testEnrollingIconTouchDialog_withRfps() 542 } 543 544 @Test 545 fun testFindUdfpsWithGkPwHandle_clickStart() { 546 Assume.assumeTrue(canAssumeUdfps) 547 548 setDeviceOrientation() 549 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 550 launchFindSensorWithGkPwHandle() 551 552 // FindUdfps page 553 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 554 val lottie = device.findObject( 555 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 556 ) 557 assertThat(lottie).isNotNull() 558 assertThat(lottie.isClickable).isTrue() 559 val startBtn = device.findObject(By.text("Start")) 560 assertThat(startBtn.isClickable).isTrue() 561 startBtn.click() 562 563 // Enrolling page 564 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 565 } 566 567 @Test 568 fun testFindUdfpsWithGkPwHandle_clickStart_runAslandscape() { 569 runAsLandscape = true 570 testFindUdfpsWithGkPwHandle_clickStart() 571 } 572 573 @Test 574 fun testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack() { 575 Assume.assumeTrue(canAssumeUdfps) 576 577 setDeviceOrientation() 578 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 579 launchFindSensorWithGkPwHandle() 580 581 // FindUdfps page (portrait) 582 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 583 584 // rotate device 585 if (runAsLandscape) { 586 device.setOrientationPortrait() 587 } else { 588 device.setOrientationLandscape() 589 } 590 device.waitForIdle() 591 592 // FindUdfps page (landscape) 593 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 594 val lottie = device.findObject( 595 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 596 ) 597 assertThat(lottie).isNotNull() 598 assertThat(lottie.isClickable).isTrue() 599 val startBtn = device.findObject(By.text("Start")) 600 assertThat(startBtn.isClickable).isTrue() 601 startBtn.click() 602 603 // Enrolling page 604 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 605 606 // Press back 607 device.pressBack() 608 device.waitForIdle() 609 610 // FindUdfps page (landscape-again) 611 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 612 } 613 614 @Test 615 fun testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack_runAslandscape() { 616 runAsLandscape = true 617 testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack() 618 } 619 620 @Test 621 fun testFindUdfpsWithGkPwHandle_clickLottie() { 622 Assume.assumeTrue(canAssumeUdfps) 623 624 setDeviceOrientation() 625 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 626 launchFindSensorWithGkPwHandle() 627 628 // FindUdfps page 629 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 630 val lottie = device.findObject( 631 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 632 ) 633 assertThat(lottie).isNotNull() 634 assertThat(lottie.isClickable).isTrue() 635 val startBtn = device.findObject(By.text("Start")) 636 assertThat(startBtn.isClickable).isTrue() 637 lottie.click() 638 639 // Enrolling page 640 assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue() 641 } 642 643 @Test 644 fun testFindUdfpsWithGkPwHandle_clickLottie_runAslandscape() { 645 runAsLandscape = true 646 testFindUdfpsWithGkPwHandle_clickLottie() 647 } 648 649 @Test 650 fun testFindSfpsWithGkPwHandle() { 651 Assume.assumeTrue(canAssumeSfps) 652 653 setDeviceOrientation() 654 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 655 launchFindSensorWithGkPwHandle() 656 657 // FindSfps page 658 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 659 val lottie = device.findObject( 660 By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie") 661 ) 662 assertThat(lottie).isNotNull() 663 664 // We don't have view which can be clicked to run to next page, stop at here. 665 } 666 667 @Test 668 fun testFindSfpsWithGkPwHandle_runAslandscape() { 669 runAsLandscape = true 670 testFindSfpsWithGkPwHandle() 671 } 672 673 @Test 674 fun testFindRfpsWithGkPwHandle() { 675 Assume.assumeFalse(canAssumeUdfps || canAssumeSfps) 676 677 setDeviceOrientation() 678 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 679 launchFindSensorWithGkPwHandle() 680 681 // FindRfps page 682 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 683 val lottie = device.findObject( 684 By.res( 685 SETTINGS_PACKAGE_NAME, 686 "illustration_lottie" 687 ) 688 ) 689 if (lottie == null) { 690 // FindSfps page shall have an animation view if no lottie view 691 assertThat( 692 device.findObject( 693 By.res( 694 SETTINGS_PACKAGE_NAME, 695 "fingerprint_sensor_location_animation" 696 ) 697 ) 698 ).isNotNull() 699 } 700 } 701 702 @Test 703 fun testFindRfpsWithGkPwHandle_runAslandscape() { 704 runAsLandscape = true 705 testFindRfpsWithGkPwHandle() 706 } 707 708 @Test 709 fun testFindSensorWithGkPwHandle_clickSkipInFindSensor() { 710 setDeviceOrientation() 711 LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true) 712 launchFindSensorWithGkPwHandle() 713 714 // FindSensor page 715 assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 716 val doItLaterBtn = device.findObject(By.text(DO_IT_LATER)) 717 assertThat(doItLaterBtn).isNotNull() 718 assertThat(doItLaterBtn.isClickable).isTrue() 719 doItLaterBtn.click() 720 721 // Back to home 722 device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT) 723 assertThat(device.wait(Until.gone(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue() 724 } 725 726 @Test 727 fun testFindSensorWithGkPwHandle_clickSkipInFindSensor_runAslandscape() { 728 runAsLandscape = true 729 testFindSensorWithGkPwHandle_clickSkipInFindSensor() 730 } 731 732 private fun launchIntroWithGkPwHandle(isSuw: Boolean) { 733 val lockPatternUtils = LockPatternUtils(context) 734 val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN) 735 val userId = UserHandle.myUserId() 736 val onVerifyCallback = 737 LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int -> 738 val intent = newActivityIntent(isSuw) 739 intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle) 740 context.startActivity(intent) 741 } 742 LockPatternChecker.verifyCredential( 743 lockPatternUtils, lockscreenCredential, 744 userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback 745 ) 746 } 747 748 private fun launchFindSensorWithGkPwHandle() { 749 val lockPatternUtils = LockPatternUtils(context) 750 val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN) 751 val userId = UserHandle.myUserId() 752 val onVerifyCallback = 753 LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int -> 754 val intent = newActivityIntent(false) 755 intent.putExtra(EXTRA_SKIP_INTRO, true) 756 intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle) 757 context.startActivity(intent) 758 } 759 LockPatternChecker.verifyCredential( 760 lockPatternUtils, lockscreenCredential, 761 userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback 762 ) 763 } 764 765 private fun launchEnrollingWithGkPwHandle() { 766 val lockPatternUtils = LockPatternUtils(context) 767 val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN) 768 val userId = UserHandle.myUserId() 769 val onVerifyCallback = 770 LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int -> 771 val intent = newActivityIntent(false) 772 intent.putExtra(EXTRA_SKIP_FIND_SENSOR, true) 773 intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle) 774 context.startActivity(intent) 775 } 776 LockPatternChecker.verifyCredential( 777 lockPatternUtils, lockscreenCredential, 778 userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback 779 ) 780 } 781 782 private fun newActivityIntent(isSuw: Boolean): Intent { 783 val intent = Intent() 784 intent.setClassName( 785 SETTINGS_PACKAGE_NAME, 786 if (isSuw) SUW_ACTIVITY_CLASS_NAME else ACTIVITY_CLASS_NAME 787 ) 788 if (isSuw) { 789 intent.putExtra(EXTRA_IS_SETUP_FLOW, true) 790 } 791 intent.putExtra(EXTRA_PAGE_TRANSITION_TYPE, 1) 792 intent.putExtra(Intent.EXTRA_USER_ID, context.userId) 793 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) 794 return intent 795 } 796 797 private fun setDeviceOrientation() { 798 if (runAsLandscape) { 799 device.setOrientationLandscape() 800 } else { 801 device.setOrientationPortrait() 802 } 803 device.waitForIdle() 804 } 805 806 companion object { 807 private const val TAG = "FingerprintEnrollmentActivityTest" 808 const val SETTINGS_PACKAGE_NAME = "com.android.settings" 809 private const val ACTIVITY_CLASS_NAME = 810 "com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity" 811 private const val SUW_ACTIVITY_CLASS_NAME = "$ACTIVITY_CLASS_NAME\$SetupActivity" 812 private const val EXTRA_IS_SETUP_FLOW = "isSetupFlow" 813 private const val EXTRA_SKIP_INTRO = "skip_intro" 814 private const val EXTRA_SKIP_FIND_SENSOR = "skip_find_sensor" 815 private const val EXTRA_PAGE_TRANSITION_TYPE = "page_transition_type" 816 private const val EXTRA_KEY_GK_PW_HANDLE = "gk_pw_handle" 817 private const val TEST_PIN = "1234" 818 private const val DO_IT_LATER = "Do it later" 819 private const val UDFPS_ENROLLING_TITLE = "Touch & hold the fingerprint sensor" 820 private const val SFPS_ENROLLING_TITLE = 821 "Lift, then touch. Move your finger slightly each time." 822 private const val RFPS_ENROLLING_TITLE = "Lift, then touch again" 823 private const val IDLE_TIMEOUT = 10000L 824 } 825 } 826