1 /* <lambda>null2 * Copyright (C) 2022 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.data.repository 18 19 import android.graphics.Point 20 import android.hardware.biometrics.BiometricSourceType 21 import androidx.test.ext.junit.runners.AndroidJUnit4 22 import androidx.test.filters.SmallTest 23 import com.android.keyguard.KeyguardUpdateMonitor 24 import com.android.keyguard.KeyguardUpdateMonitorCallback 25 import com.android.systemui.RoboPilotTest 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.biometrics.AuthController 28 import com.android.systemui.common.shared.model.Position 29 import com.android.systemui.coroutines.collectLastValue 30 import com.android.systemui.doze.DozeMachine 31 import com.android.systemui.doze.DozeTransitionCallback 32 import com.android.systemui.doze.DozeTransitionListener 33 import com.android.systemui.dreams.DreamOverlayCallbackController 34 import com.android.systemui.keyguard.ScreenLifecycle 35 import com.android.systemui.keyguard.WakefulnessLifecycle 36 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel 37 import com.android.systemui.keyguard.shared.model.BiometricUnlockSource 38 import com.android.systemui.keyguard.shared.model.DozeStateModel 39 import com.android.systemui.keyguard.shared.model.DozeTransitionModel 40 import com.android.systemui.keyguard.shared.model.ScreenModel 41 import com.android.systemui.keyguard.shared.model.ScreenState 42 import com.android.systemui.keyguard.shared.model.WakefulnessModel 43 import com.android.systemui.keyguard.shared.model.WakefulnessState 44 import com.android.systemui.plugins.statusbar.StatusBarStateController 45 import com.android.systemui.statusbar.phone.BiometricUnlockController 46 import com.android.systemui.statusbar.phone.DozeParameters 47 import com.android.systemui.statusbar.phone.KeyguardBypassController 48 import com.android.systemui.statusbar.policy.KeyguardStateController 49 import com.android.systemui.util.mockito.argumentCaptor 50 import com.android.systemui.util.mockito.whenever 51 import com.android.systemui.util.mockito.withArgCaptor 52 import com.android.systemui.util.time.FakeSystemClock 53 import com.google.common.truth.Truth.assertThat 54 import kotlinx.coroutines.ExperimentalCoroutinesApi 55 import kotlinx.coroutines.flow.launchIn 56 import kotlinx.coroutines.flow.onCompletion 57 import kotlinx.coroutines.flow.onEach 58 import kotlinx.coroutines.test.StandardTestDispatcher 59 import kotlinx.coroutines.test.TestScope 60 import kotlinx.coroutines.test.runCurrent 61 import kotlinx.coroutines.test.runTest 62 import org.junit.Before 63 import org.junit.Test 64 import org.junit.runner.RunWith 65 import org.mockito.Mock 66 import org.mockito.Mockito.atLeastOnce 67 import org.mockito.Mockito.verify 68 import org.mockito.MockitoAnnotations 69 70 @OptIn(ExperimentalCoroutinesApi::class) 71 @SmallTest 72 @RoboPilotTest 73 @RunWith(AndroidJUnit4::class) 74 class KeyguardRepositoryImplTest : SysuiTestCase() { 75 76 @Mock private lateinit var statusBarStateController: StatusBarStateController 77 @Mock private lateinit var keyguardStateController: KeyguardStateController 78 @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle 79 @Mock private lateinit var screenLifecycle: ScreenLifecycle 80 @Mock private lateinit var biometricUnlockController: BiometricUnlockController 81 @Mock private lateinit var dozeTransitionListener: DozeTransitionListener 82 @Mock private lateinit var authController: AuthController 83 @Mock private lateinit var keyguardBypassController: KeyguardBypassController 84 @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor 85 @Mock private lateinit var dreamOverlayCallbackController: DreamOverlayCallbackController 86 @Mock private lateinit var dozeParameters: DozeParameters 87 private val mainDispatcher = StandardTestDispatcher() 88 private val testDispatcher = StandardTestDispatcher() 89 private val testScope = TestScope(testDispatcher) 90 private lateinit var systemClock: FakeSystemClock 91 92 private lateinit var underTest: KeyguardRepositoryImpl 93 94 @Before 95 fun setUp() { 96 MockitoAnnotations.initMocks(this) 97 systemClock = FakeSystemClock() 98 underTest = 99 KeyguardRepositoryImpl( 100 statusBarStateController, 101 wakefulnessLifecycle, 102 screenLifecycle, 103 biometricUnlockController, 104 keyguardStateController, 105 keyguardBypassController, 106 keyguardUpdateMonitor, 107 dozeTransitionListener, 108 dozeParameters, 109 authController, 110 dreamOverlayCallbackController, 111 mainDispatcher, 112 testScope.backgroundScope, 113 systemClock, 114 ) 115 } 116 117 @Test 118 fun animateBottomAreaDozingTransitions() = 119 testScope.runTest { 120 assertThat(underTest.animateBottomAreaDozingTransitions.value).isEqualTo(false) 121 122 underTest.setAnimateDozingTransitions(true) 123 assertThat(underTest.animateBottomAreaDozingTransitions.value).isTrue() 124 125 underTest.setAnimateDozingTransitions(false) 126 assertThat(underTest.animateBottomAreaDozingTransitions.value).isFalse() 127 128 underTest.setAnimateDozingTransitions(true) 129 assertThat(underTest.animateBottomAreaDozingTransitions.value).isTrue() 130 } 131 132 @Test 133 fun bottomAreaAlpha() = 134 testScope.runTest { 135 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(1f) 136 137 underTest.setBottomAreaAlpha(0.1f) 138 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(0.1f) 139 140 underTest.setBottomAreaAlpha(0.2f) 141 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(0.2f) 142 143 underTest.setBottomAreaAlpha(0.3f) 144 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(0.3f) 145 146 underTest.setBottomAreaAlpha(0.5f) 147 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(0.5f) 148 149 underTest.setBottomAreaAlpha(1.0f) 150 assertThat(underTest.bottomAreaAlpha.value).isEqualTo(1f) 151 } 152 153 @Test 154 fun clockPosition() = 155 testScope.runTest { 156 assertThat(underTest.clockPosition.value).isEqualTo(Position(0, 0)) 157 158 underTest.setClockPosition(0, 1) 159 assertThat(underTest.clockPosition.value).isEqualTo(Position(0, 1)) 160 161 underTest.setClockPosition(1, 9) 162 assertThat(underTest.clockPosition.value).isEqualTo(Position(1, 9)) 163 164 underTest.setClockPosition(1, 0) 165 assertThat(underTest.clockPosition.value).isEqualTo(Position(1, 0)) 166 167 underTest.setClockPosition(3, 1) 168 assertThat(underTest.clockPosition.value).isEqualTo(Position(3, 1)) 169 } 170 171 @Test 172 fun dozeTimeTick() = 173 testScope.runTest { 174 val lastDozeTimeTick by collectLastValue(underTest.dozeTimeTick) 175 assertThat(lastDozeTimeTick).isEqualTo(0L) 176 177 // WHEN dozeTimeTick updated 178 systemClock.setUptimeMillis(systemClock.uptimeMillis() + 5) 179 underTest.dozeTimeTick() 180 181 // THEN listeners were updated to the latest uptime millis 182 assertThat(systemClock.uptimeMillis()).isEqualTo(lastDozeTimeTick) 183 } 184 185 @Test 186 fun isKeyguardShowing() = 187 testScope.runTest { 188 whenever(keyguardStateController.isShowing).thenReturn(false) 189 var latest: Boolean? = null 190 val job = underTest.isKeyguardShowing.onEach { latest = it }.launchIn(this) 191 192 runCurrent() 193 assertThat(latest).isFalse() 194 assertThat(underTest.isKeyguardShowing()).isFalse() 195 196 val captor = argumentCaptor<KeyguardStateController.Callback>() 197 verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture()) 198 199 whenever(keyguardStateController.isShowing).thenReturn(true) 200 captor.value.onKeyguardShowingChanged() 201 runCurrent() 202 assertThat(latest).isTrue() 203 assertThat(underTest.isKeyguardShowing()).isTrue() 204 205 whenever(keyguardStateController.isShowing).thenReturn(false) 206 captor.value.onKeyguardShowingChanged() 207 runCurrent() 208 assertThat(latest).isFalse() 209 assertThat(underTest.isKeyguardShowing()).isFalse() 210 211 job.cancel() 212 } 213 214 @Test 215 fun isBypassEnabled_disabledInController() { 216 whenever(keyguardBypassController.isBypassEnabled).thenReturn(false) 217 whenever(keyguardBypassController.bypassEnabled).thenReturn(false) 218 assertThat(underTest.isBypassEnabled()).isFalse() 219 } 220 221 @Test 222 fun isBypassEnabled_enabledInController() { 223 whenever(keyguardBypassController.isBypassEnabled).thenReturn(true) 224 whenever(keyguardBypassController.bypassEnabled).thenReturn(true) 225 assertThat(underTest.isBypassEnabled()).isTrue() 226 } 227 228 @Test 229 fun isAodAvailable() = runTest { 230 val flow = underTest.isAodAvailable 231 var isAodAvailable = collectLastValue(flow) 232 runCurrent() 233 234 val callback = 235 withArgCaptor<DozeParameters.Callback> { verify(dozeParameters).addCallback(capture()) } 236 237 whenever(dozeParameters.getAlwaysOn()).thenReturn(false) 238 callback.onAlwaysOnChange() 239 assertThat(isAodAvailable()).isEqualTo(false) 240 241 whenever(dozeParameters.getAlwaysOn()).thenReturn(true) 242 callback.onAlwaysOnChange() 243 assertThat(isAodAvailable()).isEqualTo(true) 244 245 flow.onCompletion { verify(dozeParameters).removeCallback(callback) } 246 } 247 248 @Test 249 fun isKeyguardOccluded() = 250 testScope.runTest { 251 whenever(keyguardStateController.isOccluded).thenReturn(false) 252 var latest: Boolean? = null 253 val job = underTest.isKeyguardOccluded.onEach { latest = it }.launchIn(this) 254 255 runCurrent() 256 assertThat(latest).isFalse() 257 258 val captor = argumentCaptor<KeyguardStateController.Callback>() 259 verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture()) 260 261 whenever(keyguardStateController.isOccluded).thenReturn(true) 262 captor.value.onKeyguardShowingChanged() 263 runCurrent() 264 assertThat(latest).isTrue() 265 266 whenever(keyguardStateController.isOccluded).thenReturn(false) 267 captor.value.onKeyguardShowingChanged() 268 runCurrent() 269 assertThat(latest).isFalse() 270 271 job.cancel() 272 } 273 274 @Test 275 fun isKeyguardUnlocked() = 276 testScope.runTest { 277 whenever(keyguardStateController.isUnlocked).thenReturn(false) 278 val isKeyguardUnlocked by collectLastValue(underTest.isKeyguardUnlocked) 279 280 runCurrent() 281 assertThat(isKeyguardUnlocked).isFalse() 282 283 val captor = argumentCaptor<KeyguardStateController.Callback>() 284 verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture()) 285 286 whenever(keyguardStateController.isUnlocked).thenReturn(true) 287 captor.value.onUnlockedChanged() 288 runCurrent() 289 assertThat(isKeyguardUnlocked).isTrue() 290 291 whenever(keyguardStateController.isUnlocked).thenReturn(false) 292 captor.value.onKeyguardShowingChanged() 293 runCurrent() 294 assertThat(isKeyguardUnlocked).isFalse() 295 } 296 297 @Test 298 fun isDozing() = 299 testScope.runTest { 300 underTest.setIsDozing(true) 301 assertThat(underTest.isDozing.value).isEqualTo(true) 302 303 underTest.setIsDozing(false) 304 assertThat(underTest.isDozing.value).isEqualTo(false) 305 } 306 307 @Test 308 fun isDozing_startsWithCorrectInitialValueForIsDozing() = 309 testScope.runTest { 310 assertThat(underTest.lastDozeTapToWakePosition.value).isEqualTo(null) 311 312 val expectedPoint = Point(100, 200) 313 underTest.setLastDozeTapToWakePosition(expectedPoint) 314 assertThat(underTest.lastDozeTapToWakePosition.value).isEqualTo(expectedPoint) 315 } 316 317 @Test 318 fun dozeAmount() = 319 testScope.runTest { 320 val values = mutableListOf<Float>() 321 val job = underTest.linearDozeAmount.onEach(values::add).launchIn(this) 322 323 val captor = argumentCaptor<StatusBarStateController.StateListener>() 324 runCurrent() 325 verify(statusBarStateController).addCallback(captor.capture()) 326 327 captor.value.onDozeAmountChanged(0.433f, 0.4f) 328 runCurrent() 329 captor.value.onDozeAmountChanged(0.498f, 0.5f) 330 runCurrent() 331 captor.value.onDozeAmountChanged(0.661f, 0.65f) 332 runCurrent() 333 334 assertThat(values).isEqualTo(listOf(0f, 0.433f, 0.498f, 0.661f)) 335 336 job.cancel() 337 runCurrent() 338 verify(statusBarStateController).removeCallback(captor.value) 339 } 340 341 @Test 342 fun isActiveDreamLockscreenHosted() = 343 testScope.runTest { 344 underTest.setIsActiveDreamLockscreenHosted(true) 345 assertThat(underTest.isActiveDreamLockscreenHosted.value).isEqualTo(true) 346 347 underTest.setIsActiveDreamLockscreenHosted(false) 348 assertThat(underTest.isActiveDreamLockscreenHosted.value).isEqualTo(false) 349 } 350 351 @Test 352 fun wakefulness() = 353 testScope.runTest { 354 val values = mutableListOf<WakefulnessModel>() 355 val job = underTest.wakefulness.onEach(values::add).launchIn(this) 356 357 runCurrent() 358 val captor = argumentCaptor<WakefulnessLifecycle.Observer>() 359 verify(wakefulnessLifecycle).addObserver(captor.capture()) 360 361 whenever(wakefulnessLifecycle.wakefulness) 362 .thenReturn(WakefulnessLifecycle.WAKEFULNESS_WAKING) 363 captor.value.onStartedWakingUp() 364 runCurrent() 365 366 whenever(wakefulnessLifecycle.wakefulness) 367 .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE) 368 captor.value.onFinishedWakingUp() 369 runCurrent() 370 371 whenever(wakefulnessLifecycle.wakefulness) 372 .thenReturn(WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP) 373 captor.value.onStartedGoingToSleep() 374 runCurrent() 375 376 whenever(wakefulnessLifecycle.wakefulness) 377 .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) 378 captor.value.onFinishedGoingToSleep() 379 runCurrent() 380 381 assertThat(values.map { it.state }) 382 .isEqualTo( 383 listOf( 384 // Initial value will be ASLEEP 385 WakefulnessState.ASLEEP, 386 WakefulnessState.STARTING_TO_WAKE, 387 WakefulnessState.AWAKE, 388 WakefulnessState.STARTING_TO_SLEEP, 389 WakefulnessState.ASLEEP, 390 ) 391 ) 392 393 job.cancel() 394 } 395 396 @Test 397 fun screenModel() = 398 testScope.runTest { 399 val values = mutableListOf<ScreenModel>() 400 val job = underTest.screenModel.onEach(values::add).launchIn(this) 401 402 runCurrent() 403 val captor = argumentCaptor<ScreenLifecycle.Observer>() 404 verify(screenLifecycle).addObserver(captor.capture()) 405 406 whenever(screenLifecycle.getScreenState()).thenReturn(ScreenLifecycle.SCREEN_TURNING_ON) 407 captor.value.onScreenTurningOn() 408 runCurrent() 409 410 whenever(screenLifecycle.getScreenState()).thenReturn(ScreenLifecycle.SCREEN_ON) 411 captor.value.onScreenTurnedOn() 412 runCurrent() 413 414 whenever(screenLifecycle.getScreenState()) 415 .thenReturn(ScreenLifecycle.SCREEN_TURNING_OFF) 416 captor.value.onScreenTurningOff() 417 runCurrent() 418 419 whenever(screenLifecycle.getScreenState()).thenReturn(ScreenLifecycle.SCREEN_OFF) 420 captor.value.onScreenTurnedOff() 421 runCurrent() 422 423 assertThat(values.map { it.state }) 424 .isEqualTo( 425 listOf( 426 // Initial value will be OFF 427 ScreenState.SCREEN_OFF, 428 ScreenState.SCREEN_TURNING_ON, 429 ScreenState.SCREEN_ON, 430 ScreenState.SCREEN_TURNING_OFF, 431 ScreenState.SCREEN_OFF, 432 ) 433 ) 434 435 job.cancel() 436 } 437 438 @Test 439 fun isUdfpsSupported() = 440 testScope.runTest { 441 whenever(keyguardUpdateMonitor.isUdfpsSupported).thenReturn(true) 442 assertThat(underTest.isUdfpsSupported()).isTrue() 443 444 whenever(keyguardUpdateMonitor.isUdfpsSupported).thenReturn(false) 445 assertThat(underTest.isUdfpsSupported()).isFalse() 446 } 447 448 @Test 449 fun isKeyguardGoingAway() = 450 testScope.runTest { 451 whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false) 452 var latest: Boolean? = null 453 val job = underTest.isKeyguardGoingAway.onEach { latest = it }.launchIn(this) 454 runCurrent() 455 assertThat(latest).isFalse() 456 457 val captor = argumentCaptor<KeyguardStateController.Callback>() 458 verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture()) 459 460 whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(true) 461 captor.value.onKeyguardGoingAwayChanged() 462 runCurrent() 463 assertThat(latest).isTrue() 464 465 whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false) 466 captor.value.onKeyguardGoingAwayChanged() 467 runCurrent() 468 assertThat(latest).isFalse() 469 470 job.cancel() 471 } 472 473 @Test 474 fun isDreamingFromKeyguardUpdateMonitor() = 475 TestScope(mainDispatcher).runTest { 476 whenever(keyguardUpdateMonitor.isDreaming()).thenReturn(false) 477 var latest: Boolean? = null 478 val job = underTest.isDreaming.onEach { latest = it }.launchIn(this) 479 480 runCurrent() 481 assertThat(latest).isFalse() 482 483 val captor = argumentCaptor<KeyguardUpdateMonitorCallback>() 484 verify(keyguardUpdateMonitor).registerCallback(captor.capture()) 485 486 captor.value.onDreamingStateChanged(true) 487 runCurrent() 488 assertThat(latest).isTrue() 489 490 captor.value.onDreamingStateChanged(false) 491 runCurrent() 492 assertThat(latest).isFalse() 493 494 job.cancel() 495 } 496 497 @Test 498 fun isDreamingFromDreamOverlayCallbackController() = 499 testScope.runTest { 500 whenever(dreamOverlayCallbackController.isDreaming).thenReturn(false) 501 var latest: Boolean? = null 502 val job = underTest.isDreamingWithOverlay.onEach { latest = it }.launchIn(this) 503 504 runCurrent() 505 assertThat(latest).isFalse() 506 507 val listener = 508 withArgCaptor<DreamOverlayCallbackController.Callback> { 509 verify(dreamOverlayCallbackController).addCallback(capture()) 510 } 511 512 listener.onStartDream() 513 runCurrent() 514 assertThat(latest).isTrue() 515 516 listener.onWakeUp() 517 runCurrent() 518 assertThat(latest).isFalse() 519 520 job.cancel() 521 } 522 523 @Test 524 fun biometricUnlockState() = 525 testScope.runTest { 526 val values = mutableListOf<BiometricUnlockModel>() 527 val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this) 528 529 runCurrent() 530 val captor = argumentCaptor<BiometricUnlockController.BiometricUnlockEventsListener>() 531 verify(biometricUnlockController).addListener(captor.capture()) 532 533 listOf( 534 BiometricUnlockController.MODE_NONE, 535 BiometricUnlockController.MODE_WAKE_AND_UNLOCK, 536 BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, 537 BiometricUnlockController.MODE_SHOW_BOUNCER, 538 BiometricUnlockController.MODE_ONLY_WAKE, 539 BiometricUnlockController.MODE_UNLOCK_COLLAPSING, 540 BiometricUnlockController.MODE_DISMISS_BOUNCER, 541 BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM, 542 ) 543 .forEach { 544 whenever(biometricUnlockController.mode).thenReturn(it) 545 captor.value.onModeChanged(it) 546 runCurrent() 547 } 548 549 assertThat(values) 550 .isEqualTo( 551 listOf( 552 // Initial value will be NONE, followed by onModeChanged() call 553 BiometricUnlockModel.NONE, 554 BiometricUnlockModel.NONE, 555 BiometricUnlockModel.WAKE_AND_UNLOCK, 556 BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING, 557 BiometricUnlockModel.SHOW_BOUNCER, 558 BiometricUnlockModel.ONLY_WAKE, 559 BiometricUnlockModel.UNLOCK_COLLAPSING, 560 BiometricUnlockModel.DISMISS_BOUNCER, 561 BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM, 562 ) 563 ) 564 565 job.cancel() 566 runCurrent() 567 verify(biometricUnlockController).removeListener(captor.value) 568 } 569 570 @Test 571 fun dozeTransitionModel() = 572 testScope.runTest { 573 // For the initial state 574 whenever(dozeTransitionListener.oldState).thenReturn(DozeMachine.State.UNINITIALIZED) 575 whenever(dozeTransitionListener.newState).thenReturn(DozeMachine.State.UNINITIALIZED) 576 577 val values = mutableListOf<DozeTransitionModel>() 578 val job = underTest.dozeTransitionModel.onEach(values::add).launchIn(this) 579 580 runCurrent() 581 val listener = 582 withArgCaptor<DozeTransitionCallback> { 583 verify(dozeTransitionListener).addCallback(capture()) 584 } 585 586 // These don't have to reflect real transitions from the DozeMachine. Only that the 587 // transitions are properly emitted 588 listener.onDozeTransition(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE) 589 runCurrent() 590 listener.onDozeTransition(DozeMachine.State.DOZE, DozeMachine.State.DOZE_AOD) 591 runCurrent() 592 listener.onDozeTransition(DozeMachine.State.DOZE_AOD_DOCKED, DozeMachine.State.FINISH) 593 runCurrent() 594 listener.onDozeTransition( 595 DozeMachine.State.DOZE_REQUEST_PULSE, 596 DozeMachine.State.DOZE_PULSING 597 ) 598 runCurrent() 599 listener.onDozeTransition( 600 DozeMachine.State.DOZE_SUSPEND_TRIGGERS, 601 DozeMachine.State.DOZE_PULSE_DONE 602 ) 603 runCurrent() 604 listener.onDozeTransition( 605 DozeMachine.State.DOZE_AOD_PAUSING, 606 DozeMachine.State.DOZE_AOD_PAUSED 607 ) 608 runCurrent() 609 610 assertThat(values) 611 .isEqualTo( 612 listOf( 613 // Initial value will be UNINITIALIZED 614 DozeTransitionModel( 615 DozeStateModel.UNINITIALIZED, 616 DozeStateModel.UNINITIALIZED 617 ), 618 DozeTransitionModel(DozeStateModel.INITIALIZED, DozeStateModel.DOZE), 619 DozeTransitionModel(DozeStateModel.DOZE, DozeStateModel.DOZE_AOD), 620 DozeTransitionModel(DozeStateModel.DOZE_AOD_DOCKED, DozeStateModel.FINISH), 621 DozeTransitionModel( 622 DozeStateModel.DOZE_REQUEST_PULSE, 623 DozeStateModel.DOZE_PULSING 624 ), 625 DozeTransitionModel( 626 DozeStateModel.DOZE_SUSPEND_TRIGGERS, 627 DozeStateModel.DOZE_PULSE_DONE 628 ), 629 DozeTransitionModel( 630 DozeStateModel.DOZE_AOD_PAUSING, 631 DozeStateModel.DOZE_AOD_PAUSED 632 ), 633 ) 634 ) 635 636 job.cancel() 637 runCurrent() 638 verify(dozeTransitionListener).removeCallback(listener) 639 } 640 641 @Test 642 fun fingerprintSensorLocation() = 643 testScope.runTest { 644 val values = mutableListOf<Point?>() 645 val job = underTest.fingerprintSensorLocation.onEach(values::add).launchIn(this) 646 647 runCurrent() 648 val captor = argumentCaptor<AuthController.Callback>() 649 verify(authController).addCallback(captor.capture()) 650 651 // An initial, null value should be initially emitted so that flows combined with this 652 // one 653 // emit values immediately. The sensor location is expected to be nullable, so anyone 654 // consuming it should handle that properly. 655 assertThat(values).isEqualTo(listOf(null)) 656 657 listOf(Point(500, 500), Point(0, 0), null, Point(250, 250)) 658 .onEach { 659 whenever(authController.fingerprintSensorLocation).thenReturn(it) 660 captor.value.onFingerprintLocationChanged() 661 runCurrent() 662 } 663 .also { dispatchedSensorLocations -> 664 assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations) 665 } 666 667 job.cancel() 668 } 669 670 @Test 671 fun faceSensorLocation() = 672 testScope.runTest { 673 val values = mutableListOf<Point?>() 674 val job = underTest.faceSensorLocation.onEach(values::add).launchIn(this) 675 676 val captor = argumentCaptor<AuthController.Callback>() 677 runCurrent() 678 verify(authController).addCallback(captor.capture()) 679 680 // An initial, null value should be initially emitted so that flows combined with this 681 // one 682 // emit values immediately. The sensor location is expected to be nullable, so anyone 683 // consuming it should handle that properly. 684 assertThat(values).isEqualTo(listOf(null)) 685 686 listOf( 687 Point(500, 500), 688 Point(0, 0), 689 null, 690 Point(250, 250), 691 ) 692 .onEach { 693 whenever(authController.faceSensorLocation).thenReturn(it) 694 captor.value.onFaceSensorLocationChanged() 695 runCurrent() 696 } 697 .also { dispatchedSensorLocations -> 698 assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations) 699 } 700 701 job.cancel() 702 } 703 704 @Test 705 fun biometricUnlockSource() = 706 testScope.runTest { 707 val values = mutableListOf<BiometricUnlockSource?>() 708 val job = underTest.biometricUnlockSource.onEach(values::add).launchIn(this) 709 710 runCurrent() 711 val captor = argumentCaptor<KeyguardUpdateMonitorCallback>() 712 verify(keyguardUpdateMonitor).registerCallback(captor.capture()) 713 714 // An initial, null value should be initially emitted so that flows combined with this 715 // one 716 // emit values immediately. The biometric unlock source is expected to be nullable, so 717 // anyone consuming it should handle that properly. 718 assertThat(values).isEqualTo(listOf(null)) 719 720 listOf( 721 BiometricSourceType.FINGERPRINT, 722 BiometricSourceType.IRIS, 723 null, 724 BiometricSourceType.FACE, 725 BiometricSourceType.FINGERPRINT, 726 ) 727 .onEach { biometricSourceType -> 728 captor.value.onBiometricAuthenticated(0, biometricSourceType, false) 729 runCurrent() 730 } 731 732 assertThat(values) 733 .isEqualTo( 734 listOf( 735 null, 736 BiometricUnlockSource.FINGERPRINT_SENSOR, 737 BiometricUnlockSource.FACE_SENSOR, 738 null, 739 BiometricUnlockSource.FACE_SENSOR, 740 BiometricUnlockSource.FINGERPRINT_SENSOR, 741 ) 742 ) 743 744 job.cancel() 745 } 746 } 747