1 /* 2 * 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 17 package com.android.systemui.keyguard.ui.viewmodel 18 19 import androidx.test.ext.junit.runners.AndroidJUnit4 20 import androidx.test.filters.SmallTest 21 import com.android.settingslib.Utils 22 import com.android.systemui.SysuiTestCase 23 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository 24 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository 25 import com.android.systemui.coroutines.collectLastValue 26 import com.android.systemui.flags.FakeFeatureFlags 27 import com.android.systemui.flags.Flags 28 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository 29 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository 30 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor 31 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor 32 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory 33 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory 34 import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor 35 import com.android.systemui.keyguard.shared.model.KeyguardState 36 import com.android.systemui.keyguard.shared.model.StatusBarState 37 import com.android.systemui.keyguard.shared.model.TransitionState 38 import com.android.systemui.keyguard.shared.model.TransitionStep 39 import com.android.systemui.shade.data.repository.FakeShadeRepository 40 import com.android.systemui.statusbar.phone.SystemUIDialogManager 41 import com.android.systemui.util.mockito.argumentCaptor 42 import com.android.systemui.util.mockito.mock 43 import com.android.wm.shell.animation.Interpolators 44 import com.google.common.collect.Range 45 import com.google.common.truth.Truth.assertThat 46 import kotlinx.coroutines.ExperimentalCoroutinesApi 47 import kotlinx.coroutines.test.TestScope 48 import kotlinx.coroutines.test.runCurrent 49 import kotlinx.coroutines.test.runTest 50 import org.junit.Before 51 import org.junit.Test 52 import org.junit.runner.RunWith 53 import org.mockito.Mock 54 import org.mockito.Mockito 55 import org.mockito.MockitoAnnotations 56 57 /** Tests UDFPS lockscreen view model transitions. */ 58 @ExperimentalCoroutinesApi 59 @SmallTest 60 @RunWith(AndroidJUnit4::class) 61 class UdfpsLockscreenViewModelTest : SysuiTestCase() { 62 private val lockscreenColorResId = android.R.attr.textColorPrimary 63 private val alternateBouncerResId = com.android.internal.R.attr.materialColorOnPrimaryFixed 64 private val lockscreenColor = Utils.getColorAttrDefaultColor(context, lockscreenColorResId) 65 private val alternateBouncerColor = 66 Utils.getColorAttrDefaultColor(context, alternateBouncerResId) 67 68 @Mock private lateinit var dialogManager: SystemUIDialogManager 69 70 private lateinit var underTest: UdfpsLockscreenViewModel 71 private lateinit var testScope: TestScope 72 private lateinit var transitionRepository: FakeKeyguardTransitionRepository 73 private lateinit var configRepository: FakeConfigurationRepository 74 private lateinit var keyguardRepository: FakeKeyguardRepository 75 private lateinit var keyguardInteractor: KeyguardInteractor 76 private lateinit var bouncerRepository: FakeKeyguardBouncerRepository 77 private lateinit var shadeRepository: FakeShadeRepository 78 private lateinit var featureFlags: FakeFeatureFlags 79 80 @Before 81 fun setUp() { 82 MockitoAnnotations.initMocks(this) 83 testScope = TestScope() 84 transitionRepository = FakeKeyguardTransitionRepository() 85 shadeRepository = FakeShadeRepository() 86 featureFlags = 87 FakeFeatureFlags().apply { 88 set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true) 89 set(Flags.FACE_AUTH_REFACTOR, false) 90 } 91 KeyguardInteractorFactory.create( 92 featureFlags = featureFlags, 93 ) 94 .also { 95 keyguardInteractor = it.keyguardInteractor 96 keyguardRepository = it.repository 97 configRepository = it.configurationRepository 98 bouncerRepository = it.bouncerRepository 99 } 100 101 val transitionInteractor = 102 KeyguardTransitionInteractorFactory.create( 103 scope = testScope.backgroundScope, 104 repository = transitionRepository, 105 keyguardInteractor = keyguardInteractor, 106 ) 107 .keyguardTransitionInteractor 108 109 underTest = 110 UdfpsLockscreenViewModel( 111 context, 112 lockscreenColorResId, 113 alternateBouncerResId, 114 transitionInteractor, 115 UdfpsKeyguardInteractor( 116 configRepository, 117 BurnInInteractor( 118 context, 119 burnInHelperWrapper = mock(), 120 testScope.backgroundScope, 121 configRepository, 122 keyguardInteractor, 123 ), 124 keyguardInteractor, 125 shadeRepository, 126 dialogManager, 127 ), 128 keyguardInteractor, 129 ) 130 } 131 132 @Test 133 fun goneToAodTransition() = 134 testScope.runTest { 135 val transition by collectLastValue(underTest.transition) 136 val visible by collectLastValue(underTest.visible) 137 138 // TransitionState.STARTED: gone -> AOD 139 transitionRepository.sendTransitionStep( 140 TransitionStep( 141 from = KeyguardState.GONE, 142 to = KeyguardState.AOD, 143 value = 0f, 144 transitionState = TransitionState.STARTED, 145 ownerName = "goneToAodTransition", 146 ) 147 ) 148 runCurrent() 149 assertThat(transition?.alpha).isEqualTo(0f) 150 assertThat(visible).isFalse() 151 152 // TransitionState.RUNNING: gone -> AOD 153 transitionRepository.sendTransitionStep( 154 TransitionStep( 155 from = KeyguardState.GONE, 156 to = KeyguardState.AOD, 157 value = .6f, 158 transitionState = TransitionState.RUNNING, 159 ownerName = "goneToAodTransition", 160 ) 161 ) 162 runCurrent() 163 assertThat(transition?.alpha).isEqualTo(0f) 164 assertThat(visible).isFalse() 165 166 // TransitionState.FINISHED: gone -> AOD 167 transitionRepository.sendTransitionStep( 168 TransitionStep( 169 from = KeyguardState.GONE, 170 to = KeyguardState.AOD, 171 value = 1f, 172 transitionState = TransitionState.FINISHED, 173 ownerName = "goneToAodTransition", 174 ) 175 ) 176 runCurrent() 177 assertThat(transition?.alpha).isEqualTo(0f) 178 assertThat(visible).isFalse() 179 } 180 181 @Test 182 fun lockscreenToAod() = 183 testScope.runTest { 184 val transition by collectLastValue(underTest.transition) 185 val visible by collectLastValue(underTest.visible) 186 keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) 187 188 // TransitionState.STARTED: lockscreen -> AOD 189 transitionRepository.sendTransitionStep( 190 TransitionStep( 191 from = KeyguardState.LOCKSCREEN, 192 to = KeyguardState.AOD, 193 value = 0f, 194 transitionState = TransitionState.STARTED, 195 ownerName = "lockscreenToAod", 196 ) 197 ) 198 runCurrent() 199 assertThat(transition?.alpha).isEqualTo(1f) 200 assertThat(transition?.scale).isEqualTo(1f) 201 assertThat(transition?.color).isEqualTo(lockscreenColor) 202 assertThat(visible).isTrue() 203 204 // TransitionState.RUNNING: lockscreen -> AOD 205 transitionRepository.sendTransitionStep( 206 TransitionStep( 207 from = KeyguardState.LOCKSCREEN, 208 to = KeyguardState.AOD, 209 value = .6f, 210 transitionState = TransitionState.RUNNING, 211 ownerName = "lockscreenToAod", 212 ) 213 ) 214 runCurrent() 215 assertThat(transition?.alpha).isIn(Range.closed(.39f, .41f)) 216 assertThat(transition?.scale).isEqualTo(1f) 217 assertThat(transition?.color).isEqualTo(lockscreenColor) 218 assertThat(visible).isTrue() 219 220 // TransitionState.FINISHED: lockscreen -> AOD 221 transitionRepository.sendTransitionStep( 222 TransitionStep( 223 from = KeyguardState.LOCKSCREEN, 224 to = KeyguardState.AOD, 225 value = 1f, 226 transitionState = TransitionState.FINISHED, 227 ownerName = "lockscreenToAod", 228 ) 229 ) 230 runCurrent() 231 assertThat(transition?.alpha).isEqualTo(0f) 232 assertThat(transition?.scale).isEqualTo(1f) 233 assertThat(transition?.color).isEqualTo(lockscreenColor) 234 assertThat(visible).isFalse() 235 } 236 237 @Test 238 fun lockscreenShadeLockedToAod() = 239 testScope.runTest { 240 val transition by collectLastValue(underTest.transition) 241 val visible by collectLastValue(underTest.visible) 242 keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) 243 244 // TransitionState.STARTED: lockscreen -> AOD 245 transitionRepository.sendTransitionStep( 246 TransitionStep( 247 from = KeyguardState.LOCKSCREEN, 248 to = KeyguardState.AOD, 249 value = 0f, 250 transitionState = TransitionState.STARTED, 251 ownerName = "lockscreenToAod", 252 ) 253 ) 254 runCurrent() 255 assertThat(transition?.alpha).isEqualTo(0f) 256 assertThat(visible).isFalse() 257 258 // TransitionState.RUNNING: lockscreen -> AOD 259 transitionRepository.sendTransitionStep( 260 TransitionStep( 261 from = KeyguardState.LOCKSCREEN, 262 to = KeyguardState.AOD, 263 value = .6f, 264 transitionState = TransitionState.RUNNING, 265 ownerName = "lockscreenToAod", 266 ) 267 ) 268 runCurrent() 269 assertThat(transition?.alpha).isEqualTo(0f) 270 assertThat(visible).isFalse() 271 272 // TransitionState.FINISHED: lockscreen -> AOD 273 transitionRepository.sendTransitionStep( 274 TransitionStep( 275 from = KeyguardState.LOCKSCREEN, 276 to = KeyguardState.AOD, 277 value = 1f, 278 transitionState = TransitionState.FINISHED, 279 ownerName = "lockscreenToAod", 280 ) 281 ) 282 runCurrent() 283 assertThat(transition?.alpha).isEqualTo(0f) 284 assertThat(visible).isFalse() 285 } 286 287 @Test 288 fun aodToLockscreen() = 289 testScope.runTest { 290 val transition by collectLastValue(underTest.transition) 291 val visible by collectLastValue(underTest.visible) 292 293 // TransitionState.STARTED: AOD -> lockscreen 294 transitionRepository.sendTransitionStep( 295 TransitionStep( 296 from = KeyguardState.AOD, 297 to = KeyguardState.LOCKSCREEN, 298 value = 0f, 299 transitionState = TransitionState.STARTED, 300 ownerName = "aodToLockscreen", 301 ) 302 ) 303 runCurrent() 304 assertThat(transition?.alpha).isEqualTo(0f) 305 assertThat(transition?.scale).isEqualTo(1f) 306 assertThat(transition?.color).isEqualTo(lockscreenColor) 307 assertThat(visible).isFalse() 308 309 // TransitionState.RUNNING: AOD -> lockscreen 310 transitionRepository.sendTransitionStep( 311 TransitionStep( 312 from = KeyguardState.AOD, 313 to = KeyguardState.LOCKSCREEN, 314 value = .6f, 315 transitionState = TransitionState.RUNNING, 316 ownerName = "aodToLockscreen", 317 ) 318 ) 319 runCurrent() 320 assertThat(transition?.alpha).isIn(Range.closed(.59f, .61f)) 321 assertThat(transition?.scale).isEqualTo(1f) 322 assertThat(transition?.color).isEqualTo(lockscreenColor) 323 assertThat(visible).isTrue() 324 325 // TransitionState.FINISHED: AOD -> lockscreen 326 transitionRepository.sendTransitionStep( 327 TransitionStep( 328 from = KeyguardState.AOD, 329 to = KeyguardState.LOCKSCREEN, 330 value = 1f, 331 transitionState = TransitionState.FINISHED, 332 ownerName = "aodToLockscreen", 333 ) 334 ) 335 runCurrent() 336 assertThat(transition?.alpha).isEqualTo(1f) 337 assertThat(transition?.scale).isEqualTo(1f) 338 assertThat(transition?.color).isEqualTo(lockscreenColor) 339 assertThat(visible).isTrue() 340 } 341 342 @Test 343 fun lockscreenToAlternateBouncer() = 344 testScope.runTest { 345 val transition by collectLastValue(underTest.transition) 346 val visible by collectLastValue(underTest.visible) 347 keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) 348 349 // TransitionState.STARTED: lockscreen -> alternate bouncer 350 transitionRepository.sendTransitionStep( 351 TransitionStep( 352 from = KeyguardState.LOCKSCREEN, 353 to = KeyguardState.ALTERNATE_BOUNCER, 354 value = 0f, 355 transitionState = TransitionState.STARTED, 356 ownerName = "lockscreenToAlternateBouncer", 357 ) 358 ) 359 runCurrent() 360 assertThat(transition?.alpha).isEqualTo(1f) 361 assertThat(transition?.scale).isEqualTo(1f) 362 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 363 assertThat(visible).isTrue() 364 365 // TransitionState.RUNNING: lockscreen -> alternate bouncer 366 transitionRepository.sendTransitionStep( 367 TransitionStep( 368 from = KeyguardState.LOCKSCREEN, 369 to = KeyguardState.ALTERNATE_BOUNCER, 370 value = .6f, 371 transitionState = TransitionState.RUNNING, 372 ownerName = "lockscreenToAlternateBouncer", 373 ) 374 ) 375 runCurrent() 376 assertThat(transition?.alpha).isEqualTo(1f) 377 assertThat(transition?.scale).isEqualTo(1f) 378 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 379 assertThat(visible).isTrue() 380 381 // TransitionState.FINISHED: lockscreen -> alternate bouncer 382 transitionRepository.sendTransitionStep( 383 TransitionStep( 384 from = KeyguardState.LOCKSCREEN, 385 to = KeyguardState.ALTERNATE_BOUNCER, 386 value = 1f, 387 transitionState = TransitionState.FINISHED, 388 ownerName = "lockscreenToAlternateBouncer", 389 ) 390 ) 391 runCurrent() 392 assertThat(transition?.alpha).isEqualTo(1f) 393 assertThat(transition?.scale).isEqualTo(1f) 394 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 395 assertThat(visible).isTrue() 396 } 397 398 fun alternateBouncerToPrimaryBouncer() = 399 testScope.runTest { 400 val transition by collectLastValue(underTest.transition) 401 val visible by collectLastValue(underTest.visible) 402 403 // TransitionState.STARTED: alternate bouncer -> primary bouncer 404 transitionRepository.sendTransitionStep( 405 TransitionStep( 406 from = KeyguardState.ALTERNATE_BOUNCER, 407 to = KeyguardState.PRIMARY_BOUNCER, 408 value = 0f, 409 transitionState = TransitionState.STARTED, 410 ownerName = "alternateBouncerToPrimaryBouncer", 411 ) 412 ) 413 runCurrent() 414 assertThat(transition?.alpha).isEqualTo(1f) 415 assertThat(transition?.scale).isEqualTo(1f) 416 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 417 assertThat(visible).isTrue() 418 419 // TransitionState.RUNNING: alternate bouncer -> primary bouncer 420 transitionRepository.sendTransitionStep( 421 TransitionStep( 422 from = KeyguardState.ALTERNATE_BOUNCER, 423 to = KeyguardState.PRIMARY_BOUNCER, 424 value = .6f, 425 transitionState = TransitionState.RUNNING, 426 ownerName = "alternateBouncerToPrimaryBouncer", 427 ) 428 ) 429 runCurrent() 430 assertThat(transition?.alpha).isIn(Range.closed(.59f, .61f)) 431 assertThat(transition?.scale).isEqualTo(1f) 432 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 433 assertThat(visible).isTrue() 434 435 // TransitionState.FINISHED: alternate bouncer -> primary bouncer 436 transitionRepository.sendTransitionStep( 437 TransitionStep( 438 from = KeyguardState.ALTERNATE_BOUNCER, 439 to = KeyguardState.PRIMARY_BOUNCER, 440 value = 1f, 441 transitionState = TransitionState.FINISHED, 442 ownerName = "alternateBouncerToPrimaryBouncer", 443 ) 444 ) 445 runCurrent() 446 assertThat(transition?.alpha).isEqualTo(0f) 447 assertThat(transition?.scale).isEqualTo(1f) 448 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 449 assertThat(visible).isFalse() 450 } 451 452 fun alternateBouncerToAod() = 453 testScope.runTest { 454 val transition by collectLastValue(underTest.transition) 455 val visible by collectLastValue(underTest.visible) 456 457 // TransitionState.STARTED: alternate bouncer -> aod 458 transitionRepository.sendTransitionStep( 459 TransitionStep( 460 from = KeyguardState.ALTERNATE_BOUNCER, 461 to = KeyguardState.AOD, 462 value = 0f, 463 transitionState = TransitionState.STARTED, 464 ownerName = "alternateBouncerToAod", 465 ) 466 ) 467 runCurrent() 468 assertThat(transition?.alpha).isEqualTo(1f) 469 assertThat(transition?.scale).isEqualTo(1f) 470 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 471 assertThat(visible).isTrue() 472 473 // TransitionState.RUNNING: alternate bouncer -> aod 474 transitionRepository.sendTransitionStep( 475 TransitionStep( 476 from = KeyguardState.ALTERNATE_BOUNCER, 477 to = KeyguardState.AOD, 478 value = .6f, 479 transitionState = TransitionState.RUNNING, 480 ownerName = "alternateBouncerToAod", 481 ) 482 ) 483 runCurrent() 484 assertThat(transition?.alpha).isIn(Range.closed(.39f, .41f)) 485 assertThat(transition?.scale).isEqualTo(1f) 486 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 487 assertThat(visible).isTrue() 488 489 // TransitionState.FINISHED: alternate bouncer -> aod 490 transitionRepository.sendTransitionStep( 491 TransitionStep( 492 from = KeyguardState.ALTERNATE_BOUNCER, 493 to = KeyguardState.AOD, 494 value = 1f, 495 transitionState = TransitionState.FINISHED, 496 ownerName = "alternateBouncerToAod", 497 ) 498 ) 499 runCurrent() 500 assertThat(transition?.alpha).isEqualTo(0f) 501 assertThat(transition?.scale).isEqualTo(1f) 502 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 503 assertThat(visible).isFalse() 504 } 505 506 @Test 507 fun lockscreenToOccluded() = 508 testScope.runTest { 509 val transition by collectLastValue(underTest.transition) 510 val visible by collectLastValue(underTest.visible) 511 keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) 512 513 // TransitionState.STARTED: lockscreen -> occluded 514 transitionRepository.sendTransitionStep( 515 TransitionStep( 516 from = KeyguardState.LOCKSCREEN, 517 to = KeyguardState.OCCLUDED, 518 value = 0f, 519 transitionState = TransitionState.STARTED, 520 ownerName = "lockscreenToOccluded", 521 ) 522 ) 523 runCurrent() 524 assertThat(transition?.alpha).isEqualTo(1f) 525 assertThat(transition?.scale).isEqualTo(1f) 526 assertThat(transition?.color).isEqualTo(lockscreenColor) 527 assertThat(visible).isTrue() 528 529 // TransitionState.RUNNING: lockscreen -> occluded 530 transitionRepository.sendTransitionStep( 531 TransitionStep( 532 from = KeyguardState.LOCKSCREEN, 533 to = KeyguardState.OCCLUDED, 534 value = .6f, 535 transitionState = TransitionState.RUNNING, 536 ownerName = "lockscreenToOccluded", 537 ) 538 ) 539 runCurrent() 540 assertThat(transition?.alpha).isIn(Range.closed(.39f, .41f)) 541 assertThat(transition?.scale).isEqualTo(1f) 542 assertThat(transition?.color).isEqualTo(lockscreenColor) 543 assertThat(visible).isTrue() 544 545 // TransitionState.FINISHED: lockscreen -> occluded 546 transitionRepository.sendTransitionStep( 547 TransitionStep( 548 from = KeyguardState.LOCKSCREEN, 549 to = KeyguardState.OCCLUDED, 550 value = 1f, 551 transitionState = TransitionState.FINISHED, 552 ownerName = "lockscreenToOccluded", 553 ) 554 ) 555 runCurrent() 556 assertThat(transition?.alpha).isEqualTo(0f) 557 assertThat(transition?.scale).isEqualTo(1f) 558 assertThat(transition?.color).isEqualTo(lockscreenColor) 559 assertThat(visible).isFalse() 560 } 561 562 @Test 563 fun occludedToLockscreen() = 564 testScope.runTest { 565 val transition by collectLastValue(underTest.transition) 566 val visible by collectLastValue(underTest.visible) 567 568 // TransitionState.STARTED: occluded -> lockscreen 569 transitionRepository.sendTransitionStep( 570 TransitionStep( 571 from = KeyguardState.OCCLUDED, 572 to = KeyguardState.LOCKSCREEN, 573 value = 0f, 574 transitionState = TransitionState.STARTED, 575 ownerName = "occludedToLockscreen", 576 ) 577 ) 578 runCurrent() 579 assertThat(transition?.alpha).isEqualTo(1f) 580 assertThat(transition?.scale).isEqualTo(1f) 581 assertThat(transition?.color).isEqualTo(lockscreenColor) 582 assertThat(visible).isTrue() 583 584 // TransitionState.RUNNING: occluded -> lockscreen 585 transitionRepository.sendTransitionStep( 586 TransitionStep( 587 from = KeyguardState.OCCLUDED, 588 to = KeyguardState.LOCKSCREEN, 589 value = .6f, 590 transitionState = TransitionState.RUNNING, 591 ownerName = "occludedToLockscreen", 592 ) 593 ) 594 runCurrent() 595 assertThat(transition?.alpha).isEqualTo(1f) 596 assertThat(transition?.scale).isEqualTo(1f) 597 assertThat(transition?.color).isEqualTo(lockscreenColor) 598 assertThat(visible).isTrue() 599 600 // TransitionState.FINISHED: occluded -> lockscreen 601 transitionRepository.sendTransitionStep( 602 TransitionStep( 603 from = KeyguardState.OCCLUDED, 604 to = KeyguardState.LOCKSCREEN, 605 value = 1f, 606 transitionState = TransitionState.FINISHED, 607 ownerName = "occludedToLockscreen", 608 ) 609 ) 610 runCurrent() 611 assertThat(transition?.alpha).isEqualTo(1f) 612 assertThat(transition?.scale).isEqualTo(1f) 613 assertThat(transition?.color).isEqualTo(lockscreenColor) 614 assertThat(visible).isTrue() 615 } 616 617 @Test 618 fun qsProgressChange() = 619 testScope.runTest { 620 val transition by collectLastValue(underTest.transition) 621 val visible by collectLastValue(underTest.visible) 622 givenTransitionToLockscreenFinished() 623 624 // qsExpansion = 0f 625 shadeRepository.setQsExpansion(0f) 626 runCurrent() 627 assertThat(transition?.alpha).isEqualTo(1f) 628 assertThat(visible).isEqualTo(true) 629 630 // qsExpansion = .25 631 shadeRepository.setQsExpansion(.2f) 632 runCurrent() 633 assertThat(transition?.alpha).isEqualTo(.6f) 634 assertThat(visible).isEqualTo(true) 635 636 // qsExpansion = .5 637 shadeRepository.setQsExpansion(.5f) 638 runCurrent() 639 assertThat(transition?.alpha).isEqualTo(0f) 640 assertThat(visible).isEqualTo(false) 641 642 // qsExpansion = 1 643 shadeRepository.setQsExpansion(1f) 644 runCurrent() 645 assertThat(transition?.alpha).isEqualTo(0f) 646 assertThat(visible).isEqualTo(false) 647 } 648 649 @Test 650 fun shadeExpansionChanged() = 651 testScope.runTest { 652 val transition by collectLastValue(underTest.transition) 653 val visible by collectLastValue(underTest.visible) 654 givenTransitionToLockscreenFinished() 655 656 // shadeExpansion = 0f 657 shadeRepository.setUdfpsTransitionToFullShadeProgress(0f) 658 runCurrent() 659 assertThat(transition?.alpha).isEqualTo(1f) 660 assertThat(visible).isEqualTo(true) 661 662 // shadeExpansion = .2 663 shadeRepository.setUdfpsTransitionToFullShadeProgress(.2f) 664 runCurrent() 665 assertThat(transition?.alpha).isEqualTo(.8f) 666 assertThat(visible).isEqualTo(true) 667 668 // shadeExpansion = .5 669 shadeRepository.setUdfpsTransitionToFullShadeProgress(.5f) 670 runCurrent() 671 assertThat(transition?.alpha).isEqualTo(.5f) 672 assertThat(visible).isEqualTo(true) 673 674 // shadeExpansion = 1 675 shadeRepository.setUdfpsTransitionToFullShadeProgress(1f) 676 runCurrent() 677 assertThat(transition?.alpha).isEqualTo(0f) 678 assertThat(visible).isEqualTo(false) 679 } 680 681 @Test 682 fun dialogHideAffordancesRequestChanged() = 683 testScope.runTest { 684 val transition by collectLastValue(underTest.transition) 685 givenTransitionToLockscreenFinished() 686 runCurrent() 687 val captor = argumentCaptor<SystemUIDialogManager.Listener>() 688 Mockito.verify(dialogManager).registerListener(captor.capture()) 689 690 captor.value.shouldHideAffordances(true) 691 assertThat(transition?.alpha).isEqualTo(0f) 692 693 captor.value.shouldHideAffordances(false) 694 assertThat(transition?.alpha).isEqualTo(1f) 695 } 696 697 @Test 698 fun occludedToAlternateBouncer() = 699 testScope.runTest { 700 val transition by collectLastValue(underTest.transition) 701 val visible by collectLastValue(underTest.visible) 702 703 // TransitionState.STARTED: occluded -> alternate bouncer 704 transitionRepository.sendTransitionStep( 705 TransitionStep( 706 from = KeyguardState.OCCLUDED, 707 to = KeyguardState.ALTERNATE_BOUNCER, 708 value = 0f, 709 transitionState = TransitionState.STARTED, 710 ownerName = "occludedToAlternateBouncer", 711 ) 712 ) 713 runCurrent() 714 assertThat(transition?.alpha).isEqualTo(1f) 715 assertThat(transition?.scale).isEqualTo(0f) 716 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 717 assertThat(visible).isTrue() 718 719 // TransitionState.RUNNING: occluded -> alternate bouncer 720 transitionRepository.sendTransitionStep( 721 TransitionStep( 722 from = KeyguardState.OCCLUDED, 723 to = KeyguardState.ALTERNATE_BOUNCER, 724 value = .6f, 725 transitionState = TransitionState.RUNNING, 726 ownerName = "occludedToAlternateBouncer", 727 ) 728 ) 729 runCurrent() 730 assertThat(transition?.alpha).isEqualTo(1f) 731 assertThat(transition?.scale) 732 .isEqualTo(Interpolators.FAST_OUT_SLOW_IN.getInterpolation(.6f)) 733 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 734 assertThat(visible).isTrue() 735 736 // TransitionState.FINISHED: occluded -> alternate bouncer 737 transitionRepository.sendTransitionStep( 738 TransitionStep( 739 from = KeyguardState.OCCLUDED, 740 to = KeyguardState.ALTERNATE_BOUNCER, 741 value = 1f, 742 transitionState = TransitionState.FINISHED, 743 ownerName = "occludedToAlternateBouncer", 744 ) 745 ) 746 runCurrent() 747 assertThat(transition?.alpha).isEqualTo(1f) 748 assertThat(transition?.scale).isEqualTo(1f) 749 assertThat(transition?.color).isEqualTo(alternateBouncerColor) 750 assertThat(visible).isTrue() 751 } 752 753 private suspend fun givenTransitionToLockscreenFinished() { 754 transitionRepository.sendTransitionStep( 755 TransitionStep( 756 from = KeyguardState.AOD, 757 to = KeyguardState.LOCKSCREEN, 758 value = 1f, 759 transitionState = TransitionState.FINISHED, 760 ownerName = "givenTransitionToLockscreenFinished", 761 ) 762 ) 763 } 764 } 765