Add tap to wake light reveal with tap position awareness

tablet for now does not register this sensor on AOC and will need a FW update to support this. The code will default back to LiftReveal for devices that do not report a tap location.

Bug: b/271267950
Test: Added unit test and manually tested on pixel 6a and tablet
Change-Id: I0dc68be926ae1df54beedda5fb1eabd426358fad
This commit is contained in:
Andreas Miko
2023-04-27 21:13:45 +02:00
parent 819b087abc
commit 159238f2b3
26 changed files with 187 additions and 149 deletions

View File

@@ -217,7 +217,7 @@ public class DozeSensors {
true /* settingDef */,
true /* configured */,
DozeLog.REASON_SENSOR_TAP,
false /* reports touch coordinates */,
true /* reports touch coordinates */,
true /* touchscreen */,
false /* ignoresSetting */,
dozeParameters.singleTapUsesProx(mDevicePosture) /* requiresProx */,

View File

@@ -323,9 +323,7 @@ public class DozeTriggers implements DozeMachine.Part {
return;
}
if (isDoubleTap || isTap) {
if (screenX != -1 && screenY != -1) {
mDozeHost.onSlpiTap(screenX, screenY);
}
mDozeHost.onSlpiTap(screenX, screenY);
gentleWakeUp(pulseReason);
} else if (isPickup) {
if (shouldDropPickupEvent()) {

View File

@@ -45,7 +45,6 @@ import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus
import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus
import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.log.SessionTracker
import com.android.systemui.log.table.TableLogBuffer
@@ -239,9 +238,7 @@ constructor(
// Clear auth status when keyguard is going away or when the user is switching or device
// starts going to sleep.
merge(
keyguardRepository.wakefulness.map {
WakefulnessModel.isSleepingOrStartingToSleep(it)
},
keyguardRepository.wakefulness.map { it.isStartingToSleepOrAsleep() },
keyguardRepository.isKeyguardGoingAway,
userRepository.userSwitchingInProgress
)
@@ -315,9 +312,7 @@ constructor(
tableLogBuffer
),
logAndObserve(
keyguardRepository.wakefulness
.map { WakefulnessModel.isSleepingOrStartingToSleep(it) }
.isFalse(),
keyguardRepository.wakefulness.map { it.isStartingToSleepOrAsleep() }.isFalse(),
"deviceNotSleepingOrNotStartingToSleep",
tableLogBuffer
),

View File

@@ -18,7 +18,6 @@ package com.android.systemui.keyguard.data.repository
import android.os.Build
import android.util.Log
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
@@ -104,7 +103,6 @@ interface KeyguardBouncerRepository {
class KeyguardBouncerRepositoryImpl
@Inject
constructor(
private val viewMediatorCallback: ViewMediatorCallback,
private val clock: SystemClock,
@Application private val applicationScope: CoroutineScope,
@BouncerLog private val buffer: TableLogBuffer,

View File

@@ -26,7 +26,6 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.doze.DozeHost
import com.android.systemui.doze.DozeMachine
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
@@ -105,7 +104,7 @@ interface KeyguardRepository {
* returns `false`. In order to account for that, observers should also use the
* [linearDozeAmount] flow to check if it's greater than `0`
*/
val isDozing: Flow<Boolean>
val isDozing: StateFlow<Boolean>
/**
* Observable for whether the device is dreaming.
@@ -133,6 +132,8 @@ interface KeyguardRepository {
/** Doze state information, as it transitions */
val dozeTransitionModel: Flow<DozeTransitionModel>
val lastDozeTapToWakePosition: StateFlow<Point?>
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState>
@@ -181,6 +182,10 @@ interface KeyguardRepository {
/** Sets whether quick settings or quick-quick settings is visible. */
fun setQuickSettingsVisible(isVisible: Boolean)
fun setLastDozeTapToWakePosition(position: Point)
fun setIsDozing(isDozing: Boolean)
}
/** Encapsulates application state for the keyguard. */
@@ -189,7 +194,6 @@ class KeyguardRepositoryImpl
@Inject
constructor(
statusBarStateController: StatusBarStateController,
dozeHost: DozeHost,
wakefulnessLifecycle: WakefulnessLifecycle,
biometricUnlockController: BiometricUnlockController,
private val keyguardStateController: KeyguardStateController,
@@ -333,24 +337,19 @@ constructor(
awaitClose { keyguardStateController.removeCallback(callback) }
}
override val isDozing: Flow<Boolean> =
conflatedCallbackFlow {
val callback =
object : DozeHost.Callback {
override fun onDozingChanged(isDozing: Boolean) {
trySendWithFailureLogging(isDozing, TAG, "updated isDozing")
}
}
dozeHost.addCallback(callback)
trySendWithFailureLogging(
statusBarStateController.isDozing,
TAG,
"initial isDozing",
)
private val _isDozing = MutableStateFlow(statusBarStateController.isDozing)
override val isDozing: StateFlow<Boolean> = _isDozing.asStateFlow()
awaitClose { dozeHost.removeCallback(callback) }
}
.distinctUntilChanged()
override fun setIsDozing(isDozing: Boolean) {
_isDozing.value = isDozing
}
private val _lastDozeTapToWakePosition = MutableStateFlow<Point?>(null)
override val lastDozeTapToWakePosition = _lastDozeTapToWakePosition.asStateFlow()
override fun setLastDozeTapToWakePosition(position: Point) {
_lastDozeTapToWakePosition.value = position
}
override val isDreamingWithOverlay: Flow<Boolean> =
conflatedCallbackFlow {

View File

@@ -24,7 +24,6 @@ import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LiftReveal
import com.android.systemui.statusbar.LightRevealEffect
@@ -43,7 +42,7 @@ val DEFAULT_REVEAL_EFFECT = LiftReveal
/**
* Encapsulates state relevant to the light reveal scrim, the view used to reveal/hide screen
* contents during transitions between AOD and lockscreen/unlocked.
* contents during transitions between DOZE or AOD and lockscreen/unlocked.
*/
interface LightRevealScrimRepository {
@@ -64,13 +63,20 @@ constructor(
) : LightRevealScrimRepository {
/** The reveal effect used if the device was locked/unlocked via the power button. */
private val powerButtonReveal =
PowerButtonReveal(
context.resources
.getDimensionPixelSize(R.dimen.physical_power_button_center_screen_location_y)
.toFloat()
private val powerButtonRevealEffect: Flow<LightRevealEffect?> =
flowOf(
PowerButtonReveal(
context.resources
.getDimensionPixelSize(R.dimen.physical_power_button_center_screen_location_y)
.toFloat()
)
)
private val tapRevealEffect: Flow<LightRevealEffect?> =
keyguardRepository.lastDozeTapToWakePosition.map {
it?.let { constructCircleRevealFromPoint(it) }
}
/**
* Reveal effect to use for a fingerprint unlock. This is reconstructed if the fingerprint
* sensor location on the screen (in pixels) changes due to configuration changes.
@@ -102,18 +108,11 @@ constructor(
/** The reveal effect we'll use for the next non-biometric unlock (tap, power button, etc). */
private val nonBiometricRevealEffect: Flow<LightRevealEffect?> =
keyguardRepository.wakefulness.map { wakefulnessModel ->
val wakingUpFromPowerButton =
wakefulnessModel.isWakingUpOrAwake &&
wakefulnessModel.lastWakeReason == WakeSleepReason.POWER_BUTTON
val sleepingFromPowerButton =
!wakefulnessModel.isWakingUpOrAwake &&
wakefulnessModel.lastSleepReason == WakeSleepReason.POWER_BUTTON
if (wakingUpFromPowerButton || sleepingFromPowerButton) {
powerButtonReveal
} else {
LiftReveal
keyguardRepository.wakefulness.flatMapLatest { wakefulnessModel ->
when {
wakefulnessModel.isTransitioningFromPowerButton() -> powerButtonRevealEffect
wakefulnessModel.isAwakeFromTap() -> tapRevealEffect
else -> flowOf(LiftReveal)
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.keyguard.domain.interactor
import android.graphics.Point
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
@SysUISingleton
class DozeInteractor
@Inject
constructor(
private val keyguardRepository: KeyguardRepository,
) {
fun setIsDozing(isDozing: Boolean) {
keyguardRepository.setIsDozing(isDozing)
}
fun setLastTapToWakePosition(position: Point) {
keyguardRepository.setLastDozeTapToWakePosition(position)
}
}

View File

@@ -24,13 +24,11 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@SysUISingleton
@@ -54,7 +52,7 @@ constructor(
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { (wakefulnessModel, lastStartedTransition) ->
if (
isWakingOrStartingToWake(wakefulnessModel) &&
wakefulnessModel.isStartingToWake() &&
lastStartedTransition.to == KeyguardState.DOZING
) {
keyguardTransitionRepository.startTransition(

View File

@@ -33,7 +33,6 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDoz
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -108,18 +107,12 @@ constructor(
*/
val isAbleToDream: Flow<Boolean> =
merge(isDreaming, isDreamingWithOverlay)
.combine(
dozeTransitionModel,
{ isDreaming, dozeTransitionModel ->
isDreaming && isDozeOff(dozeTransitionModel.to)
}
)
.sample(
wakefulnessModel,
{ isAbleToDream, wakefulnessModel ->
isAbleToDream && isWakingOrStartingToWake(wakefulnessModel)
}
)
.combine(dozeTransitionModel) { isDreaming, dozeTransitionModel ->
isDreaming && isDozeOff(dozeTransitionModel.to)
}
.sample(wakefulnessModel) { isAbleToDream, wakefulnessModel ->
isAbleToDream && wakefulnessModel.isStartingToWake()
}
.flatMapLatest { isAbleToDream ->
flow {
delay(50)

View File

@@ -23,6 +23,9 @@ enum class WakeSleepReason {
/** The physical power button was pressed to wake up or sleep the device. */
POWER_BUTTON,
/** The user has taped or double tapped to wake the screen */
TAP,
/** Something else happened to wake up or sleep the device. */
OTHER;
@@ -30,6 +33,7 @@ enum class WakeSleepReason {
fun fromPowerManagerWakeReason(reason: Int): WakeSleepReason {
return when (reason) {
PowerManager.WAKE_REASON_POWER_BUTTON -> POWER_BUTTON
PowerManager.WAKE_REASON_TAP -> TAP
else -> OTHER
}
}

View File

@@ -20,26 +20,31 @@ import com.android.systemui.keyguard.WakefulnessLifecycle
/** Model device wakefulness states. */
data class WakefulnessModel(
val state: WakefulnessState,
val isWakingUpOrAwake: Boolean,
val lastWakeReason: WakeSleepReason,
val lastSleepReason: WakeSleepReason,
) {
fun isStartingToWake() = state == WakefulnessState.STARTING_TO_WAKE
fun isStartingToSleep() = state == WakefulnessState.STARTING_TO_SLEEP
fun isStartingToSleepOrAsleep() = isStartingToSleep() || state == WakefulnessState.ASLEEP
fun isStartingToSleepFromPowerButton() =
isStartingToSleep() && lastWakeReason == WakeSleepReason.POWER_BUTTON
fun isWakingFromPowerButton() =
isStartingToWake() && lastWakeReason == WakeSleepReason.POWER_BUTTON
fun isTransitioningFromPowerButton() =
isStartingToSleepFromPowerButton() || isWakingFromPowerButton()
fun isAwakeFromTap() =
state == WakefulnessState.STARTING_TO_WAKE && lastWakeReason == WakeSleepReason.TAP
companion object {
fun isSleepingOrStartingToSleep(model: WakefulnessModel): Boolean {
return model.state == WakefulnessState.ASLEEP ||
model.state == WakefulnessState.STARTING_TO_SLEEP
}
fun isWakingOrStartingToWake(model: WakefulnessModel): Boolean {
return model.state == WakefulnessState.AWAKE ||
model.state == WakefulnessState.STARTING_TO_WAKE
}
fun fromWakefulnessLifecycle(wakefulnessLifecycle: WakefulnessLifecycle): WakefulnessModel {
return WakefulnessModel(
WakefulnessState.fromWakefulnessLifecycleInt(wakefulnessLifecycle.wakefulness),
wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_WAKING ||
wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE,
WakeSleepReason.fromPowerManagerWakeReason(wakefulnessLifecycle.lastWakeReason),
WakeSleepReason.fromPowerManagerSleepReason(wakefulnessLifecycle.lastSleepReason),
)

View File

@@ -20,6 +20,7 @@ import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWA
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
import android.annotation.NonNull;
import android.graphics.Point;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -38,6 +39,7 @@ import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -99,6 +101,7 @@ public final class DozeServiceHost implements DozeHost {
private CentralSurfaces mCentralSurfaces;
private boolean mAlwaysOnSuppressed;
private boolean mPulsePending;
private DozeInteractor mDozeInteractor;
@Inject
public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager,
@@ -115,6 +118,7 @@ public final class DozeServiceHost implements DozeHost {
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
AuthController authController,
NotificationIconAreaController notificationIconAreaController,
DozeInteractor dozeInteractor,
BurnInInteractor burnInInteractor) {
super();
mDozeLog = dozeLog;
@@ -136,6 +140,7 @@ public final class DozeServiceHost implements DozeHost {
mNotificationIconAreaController = notificationIconAreaController;
mBurnInInteractor = burnInInteractor;
mHeadsUpManagerPhone.addListener(mOnHeadsUpChangedListener);
mDozeInteractor = dozeInteractor;
}
// TODO: we should try to not pass status bar in here if we can avoid it.
@@ -226,6 +231,7 @@ public final class DozeServiceHost implements DozeHost {
for (Callback callback : mCallbacks) {
callback.onDozingChanged(dozing);
}
mDozeInteractor.setIsDozing(dozing);
mStatusBarStateController.setIsDozing(dozing);
}
@@ -360,7 +366,14 @@ public final class DozeServiceHost implements DozeHost {
@Override
public void onSlpiTap(float screenX, float screenY) {
if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
if (screenX < 0 || screenY < 0) return;
dispatchTouchEventToAmbientIndicationContainer(screenX, screenY);
mDozeInteractor.setLastTapToWakePosition(new Point((int) screenX, (int) screenY));
}
private void dispatchTouchEventToAmbientIndicationContainer(float screenX, float screenY) {
if (mAmbientIndicationContainer != null
&& mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
int[] locationOnScreen = new int[2];
mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen);

View File

@@ -136,7 +136,7 @@ class ClockEventControllerTest : SysuiTestCase() {
runBlocking(IMMEDIATE) {
underTest.registerListeners(parentView)
repository.setDozing(true)
repository.setIsDozing(true)
repository.setDozeAmount(1f)
}
}

View File

@@ -75,7 +75,6 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest :
MockitoAnnotations.initMocks(this)
keyguardBouncerRepository =
KeyguardBouncerRepositoryImpl(
mock(com.android.keyguard.ViewMediatorCallback::class.java),
FakeSystemClock(),
testScope.backgroundScope,
bouncerLogger,

View File

@@ -300,6 +300,22 @@ public class DozeTriggersTest extends SysuiTestCase {
verify(mMachine).wakeUp(DozeLog.REASON_SENSOR_PICKUP);
}
@Test
public void test_onSensor_tap() {
mTriggers.onSensor(DozeLog.REASON_SENSOR_TAP, 100, 200, null);
verify(mHost).onSlpiTap(100, 200);
verify(mMachine).wakeUp(DozeLog.REASON_SENSOR_TAP);
}
@Test
public void test_onSensor_double_tap() {
mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP, 100, 200, null);
verify(mHost).onSlpiTap(100, 200);
verify(mMachine).wakeUp(DozeLog.REASON_SENSOR_DOUBLE_TAP);
}
@Test
public void testPickupGestureDroppedKeyguardOccluded() {
// GIVEN device is in doze (screen blank, but running doze sensors)

View File

@@ -530,7 +530,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
state = WakefulnessState.STARTING_TO_SLEEP,
isWakingUpOrAwake = false,
lastWakeReason = WakeSleepReason.OTHER,
lastSleepReason = WakeSleepReason.OTHER,
)
@@ -545,7 +544,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
state = WakefulnessState.ASLEEP,
isWakingUpOrAwake = false,
lastWakeReason = WakeSleepReason.OTHER,
lastSleepReason = WakeSleepReason.OTHER,
)
@@ -682,7 +680,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
WakefulnessState.STARTING_TO_SLEEP,
isWakingUpOrAwake = false,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
lastSleepReason = WakeSleepReason.POWER_BUTTON
)
@@ -708,7 +705,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
WakefulnessState.ASLEEP,
isWakingUpOrAwake = false,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
lastSleepReason = WakeSleepReason.POWER_BUTTON
)
@@ -765,7 +761,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
state = WakefulnessState.STARTING_TO_SLEEP,
isWakingUpOrAwake = false,
lastWakeReason = WakeSleepReason.OTHER,
lastSleepReason = WakeSleepReason.OTHER,
)
@@ -1006,7 +1001,6 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
keyguardRepository.setWakefulnessModel(
WakefulnessModel(
WakefulnessState.STARTING_TO_WAKE,
true,
WakeSleepReason.OTHER,
WakeSleepReason.OTHER
)

View File

@@ -50,7 +50,6 @@ class KeyguardBouncerRepositoryTest : SysuiTestCase() {
val testCoroutineScope = TestCoroutineScope()
underTest =
KeyguardBouncerRepositoryImpl(
viewMediatorCallback,
systemClock,
testCoroutineScope,
bouncerLogger,

View File

@@ -27,7 +27,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.shared.model.Position
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.DozeHost
import com.android.systemui.doze.DozeMachine
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
@@ -69,7 +68,6 @@ import org.mockito.MockitoAnnotations
class KeyguardRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var dozeHost: DozeHost
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
@@ -91,7 +89,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
underTest =
KeyguardRepositoryImpl(
statusBarStateController,
dozeHost,
wakefulnessLifecycle,
biometricUnlockController,
keyguardStateController,
@@ -262,42 +259,21 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Test
fun isDozing() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isDozing.onEach { latest = it }.launchIn(this)
underTest.setIsDozing(true)
assertThat(underTest.isDozing.value).isEqualTo(true)
runCurrent()
val captor = argumentCaptor<DozeHost.Callback>()
verify(dozeHost).addCallback(captor.capture())
captor.value.onDozingChanged(true)
runCurrent()
assertThat(latest).isTrue()
captor.value.onDozingChanged(false)
runCurrent()
assertThat(latest).isFalse()
job.cancel()
runCurrent()
verify(dozeHost).removeCallback(captor.value)
underTest.setIsDozing(false)
assertThat(underTest.isDozing.value).isEqualTo(false)
}
@Test
fun isDozing_startsWithCorrectInitialValueForIsDozing() =
testScope.runTest {
var latest: Boolean? = null
assertThat(underTest.lastDozeTapToWakePosition.value).isEqualTo(null)
whenever(statusBarStateController.isDozing).thenReturn(true)
var job = underTest.isDozing.onEach { latest = it }.launchIn(this)
runCurrent()
assertThat(latest).isTrue()
job.cancel()
whenever(statusBarStateController.isDozing).thenReturn(false)
job = underTest.isDozing.onEach { latest = it }.launchIn(this)
runCurrent()
assertThat(latest).isFalse()
job.cancel()
val expectedPoint = Point(100, 200)
underTest.setLastDozeTapToWakePosition(expectedPoint)
assertThat(underTest.lastDozeTapToWakePosition.value).isEqualTo(expectedPoint)
}
@Test

View File

@@ -18,7 +18,6 @@ package com.android.systemui.keyguard.domain.interactor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
@@ -39,7 +38,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@@ -62,7 +60,6 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
bouncerRepository =
KeyguardBouncerRepositoryImpl(
mock(ViewMediatorCallback::class.java),
FakeSystemClock(),
TestCoroutineScope(),
bouncerLogger,

View File

@@ -313,7 +313,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
@Test
fun quickAffordance_bottomStartAffordanceHiddenWhileDozing() =
testScope.runTest {
repository.setDozing(true)
repository.setIsDozing(true)
homeControls.setState(
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
icon = ICON,
@@ -348,7 +348,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
fun quickAffordanceAlwaysVisible_evenWhenLockScreenNotShowingAndDozing() =
testScope.runTest {
repository.setKeyguardShowing(false)
repository.setDozing(true)
repository.setIsDozing(true)
val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
homeControls.setState(
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
@@ -623,7 +623,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
testScope.runTest {
featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
dockManager.setIsDocked(false)
val firstUseLongPress by collectLastValue (underTest.useLongPress())
val firstUseLongPress by collectLastValue(underTest.useLongPress())
runCurrent()
assertThat(firstUseLongPress).isTrue()

View File

@@ -871,7 +871,6 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
private fun startingToWake() =
WakefulnessModel(
WakefulnessState.STARTING_TO_WAKE,
true,
WakeSleepReason.OTHER,
WakeSleepReason.OTHER
)
@@ -879,7 +878,6 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
private fun startingToSleep() =
WakefulnessModel(
WakefulnessState.STARTING_TO_SLEEP,
true,
WakeSleepReason.OTHER,
WakeSleepReason.OTHER
)

View File

@@ -505,9 +505,9 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
val value = collectLastValue(underTest.isOverlayContainerVisible)
assertThat(value()).isTrue()
repository.setDozing(true)
repository.setIsDozing(true)
assertThat(value()).isFalse()
repository.setDozing(false)
repository.setIsDozing(false)
assertThat(value()).isTrue()
}

View File

@@ -327,7 +327,7 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
fun unseenNotificationIsMarkedAsSeenWhenKeyguardGoesAway() {
// GIVEN: Keyguard is showing, not dozing, unseen notification is present
keyguardRepository.setKeyguardShowing(true)
keyguardRepository.setDozing(false)
keyguardRepository.setIsDozing(false)
runKeyguardCoordinatorTest {
val fakeEntry = NotificationEntryBuilder().build()
collectionListener.onEntryAdded(fakeEntry)

View File

@@ -25,8 +25,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.graphics.Point;
import android.os.PowerManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -42,6 +44,7 @@ import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -95,6 +98,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
@Mock private DozeHost.Callback mCallback;
@Mock private BurnInInteractor mBurnInInteractor;
@Mock private DozeInteractor mDozeInteractor;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -104,7 +108,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
() -> mAssistManager, mDozeScrimController,
mKeyguardUpdateMonitor, mPulseExpansionHandler,
mNotificationShadeWindowController, mNotificationWakeUpCoordinator,
mAuthController, mNotificationIconAreaController,
mAuthController, mNotificationIconAreaController, mDozeInteractor,
mBurnInInteractor);
mDozeServiceHost.initialize(
@@ -216,6 +220,19 @@ public class DozeServiceHostTest extends SysuiTestCase {
assertFalse(mDozeServiceHost.isPulsePending());
verify(mDozeScrimController).pulseOutNow();
}
@Test
public void onSlpiTap_calls_DozeInteractor() {
mDozeServiceHost.onSlpiTap(100, 200);
verify(mDozeInteractor).setLastTapToWakePosition(new Point(100, 200));
}
@Test
public void onSlpiTap_doesnt_pass_negative_values() {
mDozeServiceHost.onSlpiTap(-1, 200);
mDozeServiceHost.onSlpiTap(100, -2);
verifyZeroInteractions(mDozeInteractor);
}
@Test
public void dozeTimeTickSentTBurnInInteractor() {
// WHEN dozeTimeTick

View File

@@ -146,7 +146,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
fun onFolded_aodDisabled_doesNotLogLatency() =
runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
keyguardRepository.setIsDozing(true)
setAodEnabled(enabled = false)
yield()
@@ -163,7 +163,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
fun onFolded_aodEnabled_logsLatency() =
runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
keyguardRepository.setIsDozing(true)
setAodEnabled(enabled = true)
yield()
@@ -181,7 +181,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
fun onFolded_onScreenTurningOnInvokedTwice_doesNotLogLatency() =
runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
keyguardRepository.setIsDozing(true)
setAodEnabled(enabled = true)
yield()
@@ -203,7 +203,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
fun onFolded_onScreenTurningOnWithoutDozingThenWithDozing_doesNotLogLatency() =
runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(false)
keyguardRepository.setIsDozing(false)
setAodEnabled(enabled = true)
yield()
@@ -214,7 +214,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
// Now enable dozing and trigger a second run through the aod animation code. It should
// not rerun the animation
keyguardRepository.setDozing(true)
keyguardRepository.setIsDozing(true)
yield()
simulateScreenTurningOn()
@@ -228,7 +228,7 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
fun onFolded_animationCancelled_doesNotLogLatency() =
runBlocking(IMMEDIATE) {
val job = underTest.listenForDozing(this)
keyguardRepository.setDozing(true)
keyguardRepository.setIsDozing(true)
setAodEnabled(enabled = true)
yield()

View File

@@ -54,7 +54,10 @@ class FakeKeyguardRepository : KeyguardRepository {
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
private val _isDozing = MutableStateFlow(false)
override val isDozing: Flow<Boolean> = _isDozing
override val isDozing: StateFlow<Boolean> = _isDozing
private val _lastDozeTapToWakePosition = MutableStateFlow<Point?>(null)
override val lastDozeTapToWakePosition = _lastDozeTapToWakePosition.asStateFlow()
private val _isAodAvailable = MutableStateFlow(false)
override val isAodAvailable: Flow<Boolean> = _isAodAvailable
@@ -76,12 +79,7 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _wakefulnessModel =
MutableStateFlow(
WakefulnessModel(
WakefulnessState.ASLEEP,
false,
WakeSleepReason.OTHER,
WakeSleepReason.OTHER
)
WakefulnessModel(WakefulnessState.ASLEEP, WakeSleepReason.OTHER, WakeSleepReason.OTHER)
)
override val wakefulness: Flow<WakefulnessModel> = _wakefulnessModel
@@ -137,10 +135,14 @@ class FakeKeyguardRepository : KeyguardRepository {
_isKeyguardOccluded.value = isOccluded
}
fun setDozing(isDozing: Boolean) {
override fun setIsDozing(isDozing: Boolean) {
_isDozing.value = isDozing
}
override fun setLastDozeTapToWakePosition(position: Point) {
_lastDozeTapToWakePosition.value = position
}
fun setAodAvailable(isAodAvailable: Boolean) {
_isAodAvailable.value = isAodAvailable
}