Transitions - Add occlusion state
Add specific OCCLUDED state, and manage transitions between states. Refactor all transition interactors to focus around the From starting states. Add dream overlay-specific callback, in addition to dreaming information, as the overlay can control exactly when the dream exits. Test: atest KeyguardRepositoryImplTest DreamOverlayCallbackControllerTest DreamOverlayServiceTest KeyguardTransitionScenariosTest DreamingToLockscreenTransitionViewModelTest Bug: 195430376 Change-Id: I096a174729574964cc54fcf5a01522360491693c
This commit is contained in:
@@ -101,13 +101,11 @@ constructor(
|
||||
transitionViewModel.dreamOverlayTranslationY(it.translationYPx)
|
||||
}
|
||||
.collect { px ->
|
||||
setElementsTranslationYAtPosition(
|
||||
px,
|
||||
ComplicationLayoutParams.POSITION_TOP
|
||||
)
|
||||
setElementsTranslationYAtPosition(
|
||||
px,
|
||||
ComplicationLayoutParams.POSITION_BOTTOM
|
||||
ComplicationLayoutParams.iteratePositions(
|
||||
{ position: Int ->
|
||||
setElementsTranslationYAtPosition(px, position)
|
||||
},
|
||||
POSITION_TOP or POSITION_BOTTOM
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -115,15 +113,15 @@ constructor(
|
||||
/* Alpha animations, when moving from DREAMING->LOCKSCREEN state */
|
||||
launch {
|
||||
transitionViewModel.dreamOverlayAlpha.collect { alpha ->
|
||||
setElementsAlphaAtPosition(
|
||||
alpha = alpha,
|
||||
position = ComplicationLayoutParams.POSITION_TOP,
|
||||
fadingOut = true,
|
||||
)
|
||||
setElementsAlphaAtPosition(
|
||||
alpha = alpha,
|
||||
position = ComplicationLayoutParams.POSITION_BOTTOM,
|
||||
fadingOut = true,
|
||||
ComplicationLayoutParams.iteratePositions(
|
||||
{ position: Int ->
|
||||
setElementsAlphaAtPosition(
|
||||
alpha = alpha,
|
||||
position = position,
|
||||
fadingOut = true,
|
||||
)
|
||||
},
|
||||
POSITION_TOP or POSITION_BOTTOM
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,26 +20,39 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.statusbar.policy.CallbackController
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Dream-related callback information */
|
||||
/** Dream overlay-related callback information */
|
||||
@SysUISingleton
|
||||
class DreamCallbackController @Inject constructor() :
|
||||
CallbackController<DreamCallbackController.DreamCallback> {
|
||||
class DreamOverlayCallbackController @Inject constructor() :
|
||||
CallbackController<DreamOverlayCallbackController.Callback> {
|
||||
|
||||
private val callbacks = mutableSetOf<DreamCallbackController.DreamCallback>()
|
||||
private val callbacks = mutableSetOf<DreamOverlayCallbackController.Callback>()
|
||||
|
||||
override fun addCallback(callback: DreamCallbackController.DreamCallback) {
|
||||
var isDreaming = false
|
||||
private set
|
||||
|
||||
override fun addCallback(callback: DreamOverlayCallbackController.Callback) {
|
||||
callbacks.add(callback)
|
||||
}
|
||||
|
||||
override fun removeCallback(callback: DreamCallbackController.DreamCallback) {
|
||||
override fun removeCallback(callback: DreamOverlayCallbackController.Callback) {
|
||||
callbacks.remove(callback)
|
||||
}
|
||||
|
||||
fun onWakeUp() {
|
||||
isDreaming = false
|
||||
callbacks.forEach { it.onWakeUp() }
|
||||
}
|
||||
|
||||
interface DreamCallback {
|
||||
fun onStartDream() {
|
||||
isDreaming = true
|
||||
callbacks.forEach { it.onStartDream() }
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
/** Dream overlay has ended */
|
||||
fun onWakeUp()
|
||||
|
||||
/** Dream overlay has started */
|
||||
fun onStartDream()
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
// A controller for the dream overlay container view (which contains both the status bar and the
|
||||
// content area).
|
||||
private DreamOverlayContainerViewController mDreamOverlayContainerViewController;
|
||||
private final DreamCallbackController mDreamCallbackController;
|
||||
private final DreamOverlayCallbackController mDreamOverlayCallbackController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Nullable
|
||||
private final ComponentName mLowLightDreamComponent;
|
||||
@@ -134,7 +134,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
UiEventLogger uiEventLogger,
|
||||
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
|
||||
ComponentName lowLightDreamComponent,
|
||||
DreamCallbackController dreamCallbackController) {
|
||||
DreamOverlayCallbackController dreamOverlayCallbackController) {
|
||||
mContext = context;
|
||||
mExecutor = executor;
|
||||
mWindowManager = windowManager;
|
||||
@@ -143,7 +143,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback);
|
||||
mStateController = stateController;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mDreamCallbackController = dreamCallbackController;
|
||||
mDreamOverlayCallbackController = dreamOverlayCallbackController;
|
||||
|
||||
final ViewModelStore viewModelStore = new ViewModelStore();
|
||||
final Complication.Host host =
|
||||
@@ -203,6 +203,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
dreamComponent != null && dreamComponent.equals(mLowLightDreamComponent));
|
||||
mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
|
||||
|
||||
mDreamOverlayCallbackController.onStartDream();
|
||||
mStarted = true;
|
||||
});
|
||||
}
|
||||
@@ -219,7 +220,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
public void onWakeUp(@NonNull Runnable onCompletedCallback) {
|
||||
mExecutor.execute(() -> {
|
||||
if (mDreamOverlayContainerViewController != null) {
|
||||
mDreamCallbackController.onWakeUp();
|
||||
mDreamOverlayCallbackController.onWakeUp();
|
||||
mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,8 +29,7 @@ import com.android.systemui.doze.DozeHost
|
||||
import com.android.systemui.doze.DozeMachine
|
||||
import com.android.systemui.doze.DozeTransitionCallback
|
||||
import com.android.systemui.doze.DozeTransitionListener
|
||||
import com.android.systemui.dreams.DreamCallbackController
|
||||
import com.android.systemui.dreams.DreamCallbackController.DreamCallback
|
||||
import com.android.systemui.dreams.DreamOverlayCallbackController
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
|
||||
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.merge
|
||||
|
||||
/** Defines interface for classes that encapsulate application state for the keyguard. */
|
||||
interface KeyguardRepository {
|
||||
@@ -81,6 +79,9 @@ interface KeyguardRepository {
|
||||
*/
|
||||
val isKeyguardShowing: Flow<Boolean>
|
||||
|
||||
/** Is an activity showing over the keyguard? */
|
||||
val isKeyguardOccluded: Flow<Boolean>
|
||||
|
||||
/** Observable for the signal that keyguard is about to go away. */
|
||||
val isKeyguardGoingAway: Flow<Boolean>
|
||||
|
||||
@@ -107,6 +108,9 @@ interface KeyguardRepository {
|
||||
*/
|
||||
val isDreaming: Flow<Boolean>
|
||||
|
||||
/** Observable for whether the device is dreaming with an overlay, see [DreamOverlayService] */
|
||||
val isDreamingWithOverlay: Flow<Boolean>
|
||||
|
||||
/**
|
||||
* Observable for the amount of doze we are currently in.
|
||||
*
|
||||
@@ -179,7 +183,7 @@ constructor(
|
||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
private val dozeTransitionListener: DozeTransitionListener,
|
||||
private val authController: AuthController,
|
||||
private val dreamCallbackController: DreamCallbackController,
|
||||
private val dreamOverlayCallbackController: DreamOverlayCallbackController,
|
||||
) : KeyguardRepository {
|
||||
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
|
||||
override val animateBottomAreaDozingTransitions =
|
||||
@@ -191,28 +195,55 @@ constructor(
|
||||
private val _clockPosition = MutableStateFlow(Position(0, 0))
|
||||
override val clockPosition = _clockPosition.asStateFlow()
|
||||
|
||||
override val isKeyguardShowing: Flow<Boolean> = conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : KeyguardStateController.Callback {
|
||||
override fun onKeyguardShowingChanged() {
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isShowing,
|
||||
TAG,
|
||||
"updated isKeyguardShowing"
|
||||
)
|
||||
}
|
||||
override val isKeyguardShowing: Flow<Boolean> =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : KeyguardStateController.Callback {
|
||||
override fun onKeyguardShowingChanged() {
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isShowing,
|
||||
TAG,
|
||||
"updated isKeyguardShowing"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
keyguardStateController.addCallback(callback)
|
||||
// Adding the callback does not send an initial update.
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isShowing,
|
||||
TAG,
|
||||
"initial isKeyguardShowing"
|
||||
)
|
||||
|
||||
awaitClose { keyguardStateController.removeCallback(callback) }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
keyguardStateController.addCallback(callback)
|
||||
// Adding the callback does not send an initial update.
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isShowing,
|
||||
TAG,
|
||||
"initial isKeyguardShowing"
|
||||
)
|
||||
override val isKeyguardOccluded: Flow<Boolean> =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : KeyguardStateController.Callback {
|
||||
override fun onKeyguardShowingChanged() {
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isOccluded,
|
||||
TAG,
|
||||
"updated isKeyguardOccluded"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
awaitClose { keyguardStateController.removeCallback(callback) }
|
||||
}
|
||||
keyguardStateController.addCallback(callback)
|
||||
// Adding the callback does not send an initial update.
|
||||
trySendWithFailureLogging(
|
||||
keyguardStateController.isOccluded,
|
||||
TAG,
|
||||
"initial isKeyguardOccluded"
|
||||
)
|
||||
|
||||
awaitClose { keyguardStateController.removeCallback(callback) }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
|
||||
val callback =
|
||||
@@ -279,36 +310,45 @@ constructor(
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
override val isDreamingWithOverlay: Flow<Boolean> =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : DreamOverlayCallbackController.Callback {
|
||||
override fun onStartDream() {
|
||||
trySendWithFailureLogging(true, TAG, "updated isDreamingWithOverlay")
|
||||
}
|
||||
override fun onWakeUp() {
|
||||
trySendWithFailureLogging(false, TAG, "updated isDreamingWithOverlay")
|
||||
}
|
||||
}
|
||||
dreamOverlayCallbackController.addCallback(callback)
|
||||
trySendWithFailureLogging(
|
||||
dreamOverlayCallbackController.isDreaming,
|
||||
TAG,
|
||||
"initial isDreamingWithOverlay",
|
||||
)
|
||||
|
||||
awaitClose { dreamOverlayCallbackController.removeCallback(callback) }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
override val isDreaming: Flow<Boolean> =
|
||||
merge(
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : KeyguardUpdateMonitorCallback() {
|
||||
override fun onDreamingStateChanged(isDreaming: Boolean) {
|
||||
trySendWithFailureLogging(isDreaming, TAG, "updated isDreaming")
|
||||
}
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : KeyguardUpdateMonitorCallback() {
|
||||
override fun onDreamingStateChanged(isDreaming: Boolean) {
|
||||
trySendWithFailureLogging(isDreaming, TAG, "updated isDreaming")
|
||||
}
|
||||
keyguardUpdateMonitor.registerCallback(callback)
|
||||
trySendWithFailureLogging(
|
||||
keyguardUpdateMonitor.isDreaming,
|
||||
TAG,
|
||||
"initial isDreaming",
|
||||
)
|
||||
}
|
||||
keyguardUpdateMonitor.registerCallback(callback)
|
||||
trySendWithFailureLogging(
|
||||
keyguardUpdateMonitor.isDreaming,
|
||||
TAG,
|
||||
"initial isDreaming",
|
||||
)
|
||||
|
||||
awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
|
||||
},
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : DreamCallback {
|
||||
override fun onWakeUp() {
|
||||
trySendWithFailureLogging(false, TAG, "updated isDreaming")
|
||||
}
|
||||
}
|
||||
dreamCallbackController.addCallback(callback)
|
||||
|
||||
awaitClose { dreamCallbackController.removeCallback(callback) }
|
||||
}
|
||||
)
|
||||
awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
override val linearDozeAmount: Flow<Float> = conflatedCallbackFlow {
|
||||
|
||||
@@ -131,6 +131,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
||||
}
|
||||
|
||||
override fun startTransition(info: TransitionInfo): UUID? {
|
||||
if (lastStep.from == info.from && lastStep.to == info.to) {
|
||||
Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
|
||||
return null
|
||||
}
|
||||
if (lastStep.transitionState != TransitionState.FINISHED) {
|
||||
Log.i(TAG, "Transition still active: $lastStep, canceling")
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
import com.android.systemui.keyguard.shared.model.TransitionInfo
|
||||
@@ -30,33 +31,33 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SysUISingleton
|
||||
class AodLockscreenTransitionInteractor
|
||||
class FromAodTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
) : TransitionInteractor(AodLockscreenTransitionInteractor::class.simpleName!!) {
|
||||
) : TransitionInteractor(FromAodTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
override fun start() {
|
||||
listenForTransitionToAodFromLockscreen()
|
||||
listenForTransitionToLockscreenFromDozeStates()
|
||||
listenForAodToLockscreen()
|
||||
listenForAodToGone()
|
||||
}
|
||||
|
||||
private fun listenForTransitionToAodFromLockscreen() {
|
||||
private fun listenForAodToLockscreen() {
|
||||
scope.launch {
|
||||
keyguardInteractor
|
||||
.dozeTransitionTo(DozeStateModel.DOZE_AOD)
|
||||
.dozeTransitionTo(DozeStateModel.FINISH)
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (dozeToAod, lastStartedStep) = pair
|
||||
if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
|
||||
if (lastStartedStep.to == KeyguardState.AOD) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.AOD,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
@@ -65,20 +66,20 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForTransitionToLockscreenFromDozeStates() {
|
||||
val canGoToLockscreen = setOf(KeyguardState.AOD, KeyguardState.DOZING)
|
||||
private fun listenForAodToGone() {
|
||||
scope.launch {
|
||||
keyguardInteractor
|
||||
.dozeTransitionTo(DozeStateModel.FINISH)
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
keyguardInteractor.biometricUnlockState
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
|
||||
.collect { pair ->
|
||||
val (dozeToAod, lastStartedStep) = pair
|
||||
if (canGoToLockscreen.contains(lastStartedStep.to)) {
|
||||
val (biometricUnlockState, keyguardState) = pair
|
||||
if (
|
||||
keyguardState == KeyguardState.AOD && isWakeAndUnlock(biometricUnlockState)
|
||||
) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
lastStartedStep.to,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.AOD,
|
||||
KeyguardState.GONE,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
@@ -23,16 +23,18 @@ import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
import com.android.systemui.keyguard.shared.model.TransitionInfo
|
||||
import com.android.systemui.keyguard.shared.model.WakefulnessState
|
||||
import com.android.systemui.shade.data.repository.ShadeRepository
|
||||
import com.android.systemui.util.kotlin.sample
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SysUISingleton
|
||||
class BouncerToGoneTransitionInteractor
|
||||
class FromBouncerTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
@@ -40,15 +42,54 @@ constructor(
|
||||
private val shadeRepository: ShadeRepository,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||
) : TransitionInteractor(BouncerToGoneTransitionInteractor::class.simpleName!!) {
|
||||
) : TransitionInteractor(FromBouncerTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
private var transitionId: UUID? = null
|
||||
|
||||
override fun start() {
|
||||
listenForKeyguardGoingAway()
|
||||
listenForBouncerToGone()
|
||||
listenForBouncerToLockscreenOrAod()
|
||||
}
|
||||
|
||||
private fun listenForKeyguardGoingAway() {
|
||||
private fun listenForBouncerToLockscreenOrAod() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isBouncerShowing
|
||||
.sample(
|
||||
combine(
|
||||
keyguardInteractor.wakefulnessModel,
|
||||
keyguardTransitionInteractor.startedKeyguardTransitionStep,
|
||||
::Pair
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple
|
||||
if (
|
||||
!isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER
|
||||
) {
|
||||
val to =
|
||||
if (
|
||||
wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
|
||||
wakefulnessState.state == WakefulnessState.ASLEEP
|
||||
) {
|
||||
KeyguardState.AOD
|
||||
} else {
|
||||
KeyguardState.LOCKSCREEN
|
||||
}
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
ownerName = name,
|
||||
from = KeyguardState.BOUNCER,
|
||||
to = to,
|
||||
animator = getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForBouncerToGone() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isKeyguardGoingAway
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
|
||||
@@ -21,36 +21,46 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
import com.android.systemui.keyguard.shared.model.TransitionInfo
|
||||
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
|
||||
class LockscreenGoneTransitionInteractor
|
||||
class FromDozingTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
) : TransitionInteractor(LockscreenGoneTransitionInteractor::class.simpleName!!) {
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
) : TransitionInteractor(FromDozingTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
override fun start() {
|
||||
listenForDozingToLockscreen()
|
||||
}
|
||||
|
||||
private fun listenForDozingToLockscreen() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isKeyguardGoingAway
|
||||
keyguardInteractor.dozeTransitionModel
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isKeyguardGoingAway, lastStartedStep) = pair
|
||||
if (isKeyguardGoingAway && lastStartedStep.to == KeyguardState.LOCKSCREEN) {
|
||||
val (dozeTransitionModel, lastStartedTransition) = pair
|
||||
if (
|
||||
isDozeOff(dozeTransitionModel.to) &&
|
||||
lastStartedTransition.to == KeyguardState.DOZING
|
||||
) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.DOZING,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.GONE,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
@@ -59,14 +69,14 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnimator(): ValueAnimator {
|
||||
private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
|
||||
return ValueAnimator().apply {
|
||||
setInterpolator(Interpolators.LINEAR)
|
||||
setDuration(TRANSITION_DURATION_MS)
|
||||
setDuration(duration.inWholeMilliseconds)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TRANSITION_DURATION_MS = 10L
|
||||
private val DEFAULT_DURATION = 500.milliseconds
|
||||
}
|
||||
}
|
||||
@@ -36,75 +36,40 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SysUISingleton
|
||||
class DreamingTransitionInteractor
|
||||
class FromDreamingTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
) : TransitionInteractor(DreamingTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
private val canDreamFrom =
|
||||
setOf(KeyguardState.LOCKSCREEN, KeyguardState.GONE, KeyguardState.DOZING)
|
||||
) : TransitionInteractor(FromDreamingTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
override fun start() {
|
||||
listenForEntryToDreaming()
|
||||
listenForDreamingToLockscreen()
|
||||
listenForDreamingToOccluded()
|
||||
listenForDreamingToGone()
|
||||
listenForDreamingToDozing()
|
||||
}
|
||||
|
||||
private fun listenForEntryToDreaming() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isDreaming
|
||||
.sample(
|
||||
combine(
|
||||
keyguardInteractor.dozeTransitionModel,
|
||||
keyguardTransitionInteractor.finishedKeyguardState,
|
||||
::Pair
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isDreaming, dozeTransitionModel, keyguardState) = triple
|
||||
// Dozing/AOD and dreaming have overlapping events. If the state remains in
|
||||
// FINISH, it means that doze mode is not running and DREAMING is ok to
|
||||
// commence.
|
||||
if (
|
||||
isDozeOff(dozeTransitionModel.to) &&
|
||||
isDreaming &&
|
||||
canDreamFrom.contains(keyguardState)
|
||||
) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
keyguardState,
|
||||
KeyguardState.DREAMING,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForDreamingToLockscreen() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isDreaming
|
||||
// Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which
|
||||
// otherwise would have gone through OCCLUDED first
|
||||
keyguardInteractor.isDreamingWithOverlay
|
||||
.sample(
|
||||
combine(
|
||||
keyguardInteractor.dozeTransitionModel,
|
||||
keyguardTransitionInteractor.startedKeyguardTransitionStep,
|
||||
::Pair,
|
||||
::Pair
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isDreaming, dozeTransitionModel, lastStartedTransition) = triple
|
||||
if (
|
||||
isDozeOff(dozeTransitionModel.to) &&
|
||||
!isDreaming &&
|
||||
!isDreaming &&
|
||||
isDozeOff(dozeTransitionModel.to) &&
|
||||
lastStartedTransition.to == KeyguardState.DREAMING
|
||||
) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
@@ -120,6 +85,42 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForDreamingToOccluded() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isDreaming
|
||||
.sample(
|
||||
combine(
|
||||
keyguardInteractor.isKeyguardOccluded,
|
||||
keyguardTransitionInteractor.startedKeyguardTransitionStep,
|
||||
::Pair,
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isDreaming, isOccluded, lastStartedTransition) = triple
|
||||
if (
|
||||
isOccluded &&
|
||||
!isDreaming &&
|
||||
(lastStartedTransition.to == KeyguardState.DREAMING ||
|
||||
lastStartedTransition.to == KeyguardState.LOCKSCREEN)
|
||||
) {
|
||||
// At the moment, checking for LOCKSCREEN state above provides a corrective
|
||||
// action. There's no great signal to determine when the dream is ending
|
||||
// and a transition to OCCLUDED is beginning directly. For now, the solution
|
||||
// is DREAMING->LOCKSCREEN->OCCLUDED
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
lastStartedTransition.to,
|
||||
KeyguardState.OCCLUDED,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForDreamingToGone() {
|
||||
scope.launch {
|
||||
keyguardInteractor.biometricUnlockState
|
||||
@@ -30,19 +30,44 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SysUISingleton
|
||||
class GoneAodTransitionInteractor
|
||||
class FromGoneTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
) : TransitionInteractor(GoneAodTransitionInteractor::class.simpleName!!) {
|
||||
) : TransitionInteractor(FromGoneTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
override fun start() {
|
||||
listenForGoneToAod()
|
||||
listenForGoneToDreaming()
|
||||
}
|
||||
|
||||
private fun listenForGoneToDreaming() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isAbleToDream
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isAbleToDream, keyguardState) = pair
|
||||
if (isAbleToDream && keyguardState == KeyguardState.GONE) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.GONE,
|
||||
KeyguardState.DREAMING,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForGoneToAod() {
|
||||
scope.launch {
|
||||
keyguardInteractor.wakefulnessModel
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
|
||||
.collect { pair ->
|
||||
val (wakefulnessState, keyguardState) = pair
|
||||
if (
|
||||
@@ -21,11 +21,11 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
import com.android.systemui.keyguard.shared.model.StatusBarState.KEYGUARD
|
||||
import com.android.systemui.keyguard.shared.model.TransitionInfo
|
||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||
import com.android.systemui.keyguard.shared.model.WakefulnessState
|
||||
import com.android.systemui.shade.data.repository.ShadeRepository
|
||||
import com.android.systemui.util.kotlin.sample
|
||||
import java.util.UUID
|
||||
@@ -36,57 +36,54 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SysUISingleton
|
||||
class LockscreenBouncerTransitionInteractor
|
||||
class FromLockscreenTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val shadeRepository: ShadeRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||
) : TransitionInteractor(LockscreenBouncerTransitionInteractor::class.simpleName!!) {
|
||||
) : TransitionInteractor(FromLockscreenTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
private var transitionId: UUID? = null
|
||||
|
||||
override fun start() {
|
||||
listenForDraggingUpToBouncer()
|
||||
listenForBouncer()
|
||||
listenForLockscreenToGone()
|
||||
listenForLockscreenToOccluded()
|
||||
listenForLockscreenToAod()
|
||||
listenForLockscreenToBouncer()
|
||||
listenForLockscreenToDreaming()
|
||||
listenForLockscreenToBouncerDragging()
|
||||
}
|
||||
|
||||
private fun listenForBouncer() {
|
||||
private fun listenForLockscreenToDreaming() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isBouncerShowing
|
||||
.sample(
|
||||
combine(
|
||||
keyguardInteractor.wakefulnessModel,
|
||||
keyguardTransitionInteractor.startedKeyguardTransitionStep,
|
||||
::Pair
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple
|
||||
if (
|
||||
!isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER
|
||||
) {
|
||||
val to =
|
||||
if (
|
||||
wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
|
||||
wakefulnessState.state == WakefulnessState.ASLEEP
|
||||
) {
|
||||
KeyguardState.AOD
|
||||
} else {
|
||||
KeyguardState.LOCKSCREEN
|
||||
}
|
||||
keyguardInteractor.isAbleToDream
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isAbleToDream, lastStartedTransition) = pair
|
||||
if (isAbleToDream && lastStartedTransition.to == KeyguardState.LOCKSCREEN) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
ownerName = name,
|
||||
from = KeyguardState.BOUNCER,
|
||||
to = to,
|
||||
animator = getAnimator(),
|
||||
name,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.DREAMING,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
} else if (
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForLockscreenToBouncer() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isBouncerShowing
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isBouncerShowing, lastStartedTransitionStep) = pair
|
||||
if (
|
||||
isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.LOCKSCREEN
|
||||
) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
@@ -98,13 +95,12 @@ constructor(
|
||||
)
|
||||
)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
|
||||
private fun listenForDraggingUpToBouncer() {
|
||||
private fun listenForLockscreenToBouncerDragging() {
|
||||
scope.launch {
|
||||
shadeRepository.shadeModel
|
||||
.sample(
|
||||
@@ -157,6 +153,76 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForLockscreenToGone() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isKeyguardGoingAway
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isKeyguardGoingAway, lastStartedStep) = pair
|
||||
if (isKeyguardGoingAway && lastStartedStep.to == KeyguardState.LOCKSCREEN) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.GONE,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForLockscreenToOccluded() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isKeyguardOccluded
|
||||
.sample(
|
||||
combine(
|
||||
keyguardTransitionInteractor.finishedKeyguardState,
|
||||
keyguardInteractor.isDreaming,
|
||||
::Pair
|
||||
),
|
||||
::toTriple
|
||||
)
|
||||
.collect { triple ->
|
||||
val (isOccluded, keyguardState, isDreaming) = triple
|
||||
// Occlusion signals come from the framework, and should interrupt any
|
||||
// existing transition
|
||||
if (isOccluded && !isDreaming) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
keyguardState,
|
||||
KeyguardState.OCCLUDED,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForLockscreenToAod() {
|
||||
scope.launch {
|
||||
keyguardInteractor
|
||||
.dozeTransitionTo(DozeStateModel.DOZE_AOD)
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (dozeToAod, lastStartedStep) = pair
|
||||
if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
KeyguardState.AOD,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnimator(): ValueAnimator {
|
||||
return ValueAnimator().apply {
|
||||
setInterpolator(Interpolators.LINEAR)
|
||||
@@ -165,6 +231,6 @@ constructor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TRANSITION_DURATION_MS = 300L
|
||||
private const val TRANSITION_DURATION_MS = 500L
|
||||
}
|
||||
}
|
||||
@@ -21,39 +21,43 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
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.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
|
||||
class AodToGoneTransitionInteractor
|
||||
class FromOccludedTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||
) : TransitionInteractor(AodToGoneTransitionInteractor::class.simpleName!!) {
|
||||
) : TransitionInteractor(FromOccludedTransitionInteractor::class.simpleName!!) {
|
||||
|
||||
override fun start() {
|
||||
listenForOccludedToLockscreen()
|
||||
listenForOccludedToDreaming()
|
||||
}
|
||||
|
||||
private fun listenForOccludedToDreaming() {
|
||||
scope.launch {
|
||||
keyguardInteractor.biometricUnlockState
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
|
||||
keyguardInteractor.isAbleToDream
|
||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
|
||||
.collect { pair ->
|
||||
val (biometricUnlockState, keyguardState) = pair
|
||||
if (
|
||||
keyguardState == KeyguardState.AOD && isWakeAndUnlock(biometricUnlockState)
|
||||
) {
|
||||
val (isAbleToDream, keyguardState) = pair
|
||||
if (isAbleToDream && keyguardState == KeyguardState.OCCLUDED) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.AOD,
|
||||
KeyguardState.GONE,
|
||||
KeyguardState.OCCLUDED,
|
||||
KeyguardState.DREAMING,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
@@ -62,14 +66,37 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnimator(): ValueAnimator {
|
||||
private fun listenForOccludedToLockscreen() {
|
||||
scope.launch {
|
||||
keyguardInteractor.isKeyguardOccluded
|
||||
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||
.collect { pair ->
|
||||
val (isOccluded, lastStartedKeyguardState) = pair
|
||||
// Occlusion signals come from the framework, and should interrupt any
|
||||
// existing transition
|
||||
if (!isOccluded && lastStartedKeyguardState.to == KeyguardState.OCCLUDED) {
|
||||
keyguardTransitionRepository.startTransition(
|
||||
TransitionInfo(
|
||||
name,
|
||||
KeyguardState.OCCLUDED,
|
||||
KeyguardState.LOCKSCREEN,
|
||||
getAnimator(),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
|
||||
return ValueAnimator().apply {
|
||||
setInterpolator(Interpolators.LINEAR)
|
||||
setDuration(TRANSITION_DURATION_MS)
|
||||
setDuration(duration.inWholeMilliseconds)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TRANSITION_DURATION_MS = 500L
|
||||
private val DEFAULT_DURATION = 500.milliseconds
|
||||
val TO_LOCKSCREEN_DURATION = 1183.milliseconds
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,16 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardRepository
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
|
||||
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.util.kotlin.sample
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.merge
|
||||
|
||||
/**
|
||||
* Encapsulates business-logic related to the keyguard but not to a more specific part within it.
|
||||
@@ -52,8 +56,27 @@ constructor(
|
||||
* but not vice-versa.
|
||||
*/
|
||||
val isDreaming: Flow<Boolean> = repository.isDreaming
|
||||
/** Whether the system is dreaming with an overlay active */
|
||||
val isDreamingWithOverlay: Flow<Boolean> = repository.isDreamingWithOverlay
|
||||
|
||||
/**
|
||||
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
|
||||
* that doze mode is not running and DREAMING is ok to commence.
|
||||
*/
|
||||
val isAbleToDream: Flow<Boolean> =
|
||||
merge(isDreaming, isDreamingWithOverlay)
|
||||
.sample(
|
||||
dozeTransitionModel,
|
||||
{ isDreaming, dozeTransitionModel ->
|
||||
isDreaming && isDozeOff(dozeTransitionModel.to)
|
||||
}
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
|
||||
/** Whether the keyguard is showing or not. */
|
||||
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
|
||||
/** Whether the keyguard is occluded (covered by an activity). */
|
||||
val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
|
||||
/** Whether the keyguard is going away. */
|
||||
val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
|
||||
/** Whether the bouncer is showing or not. */
|
||||
@@ -74,8 +97,8 @@ constructor(
|
||||
/** The approximate location on the screen of the face unlock sensor, if one is available. */
|
||||
val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
|
||||
|
||||
fun dozeTransitionTo(state: DozeStateModel): Flow<DozeTransitionModel> {
|
||||
return dozeTransitionModel.filter { it.to == state }
|
||||
fun dozeTransitionTo(vararg states: DozeStateModel): Flow<DozeTransitionModel> {
|
||||
return dozeTransitionModel.filter { states.contains(it.to) }
|
||||
}
|
||||
fun isKeyguardShowing(): Boolean {
|
||||
return repository.isKeyguardShowing()
|
||||
|
||||
@@ -37,13 +37,13 @@ constructor(
|
||||
// exhaustive
|
||||
val ret =
|
||||
when (it) {
|
||||
is LockscreenBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is BouncerToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is DreamingTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromAodTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromDreamingTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromOccludedTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is FromDozingTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
}
|
||||
it.start()
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ constructor(
|
||||
KeyguardState.BOUNCER -> true
|
||||
KeyguardState.LOCKSCREEN -> true
|
||||
KeyguardState.GONE -> true
|
||||
KeyguardState.OCCLUDED -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,25 +32,25 @@ abstract class StartKeyguardTransitionModule {
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun lockscreenBouncer(
|
||||
impl: LockscreenBouncerTransitionInteractor
|
||||
): TransitionInteractor
|
||||
abstract fun fromBouncer(impl: FromBouncerTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun aodLockscreen(impl: AodLockscreenTransitionInteractor): TransitionInteractor
|
||||
abstract fun fromLockscreen(impl: FromLockscreenTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds @IntoSet abstract fun goneAod(impl: GoneAodTransitionInteractor): TransitionInteractor
|
||||
@Binds @IntoSet abstract fun fromAod(impl: FromAodTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds @IntoSet abstract fun aodGone(impl: AodToGoneTransitionInteractor): TransitionInteractor
|
||||
@Binds @IntoSet abstract fun fromGone(impl: FromGoneTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun bouncerGone(impl: BouncerToGoneTransitionInteractor): TransitionInteractor
|
||||
abstract fun fromDreaming(impl: FromDreamingTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor
|
||||
abstract fun fromOccluded(impl: FromOccludedTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds @IntoSet abstract fun dreaming(impl: DreamingTransitionInteractor): TransitionInteractor
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun fromDozing(impl: FromDozingTransitionInteractor): TransitionInteractor
|
||||
}
|
||||
|
||||
@@ -31,4 +31,6 @@ sealed class TransitionInteractor(val name: String) {
|
||||
abstract fun start()
|
||||
|
||||
fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second)
|
||||
|
||||
fun <A, B, C> toTriple(ab: Pair<A, B>, c: C) = Triple(ab.first, ab.second, c)
|
||||
}
|
||||
|
||||
@@ -57,4 +57,8 @@ enum class KeyguardState {
|
||||
* with SWIPE security method or face unlock without bypass.
|
||||
*/
|
||||
GONE,
|
||||
/*
|
||||
* An activity is displaying over the keyguard.
|
||||
*/
|
||||
OCCLUDED,
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.keyguard.domain.interactor.DreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
||||
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.dreams
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -30,23 +31,27 @@ import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class DreamCallbackControllerTest : SysuiTestCase() {
|
||||
class DreamOverlayCallbackControllerTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var callback: DreamCallbackController.DreamCallback
|
||||
@Mock private lateinit var callback: DreamOverlayCallbackController.Callback
|
||||
|
||||
private lateinit var underTest: DreamCallbackController
|
||||
private lateinit var underTest: DreamOverlayCallbackController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
underTest = DreamCallbackController()
|
||||
underTest = DreamOverlayCallbackController()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnWakeUpInvokesCallback() {
|
||||
fun onWakeUpInvokesCallback() {
|
||||
underTest.onStartDream()
|
||||
assertThat(underTest.isDreaming).isEqualTo(true)
|
||||
|
||||
underTest.addCallback(callback)
|
||||
underTest.onWakeUp()
|
||||
verify(callback).onWakeUp()
|
||||
assertThat(underTest.isDreaming).isEqualTo(false)
|
||||
|
||||
// Adding twice should not invoke twice
|
||||
reset(callback)
|
||||
@@ -60,4 +65,27 @@ class DreamCallbackControllerTest : SysuiTestCase() {
|
||||
underTest.onWakeUp()
|
||||
verify(callback, never()).onWakeUp()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onStartDreamInvokesCallback() {
|
||||
underTest.addCallback(callback)
|
||||
|
||||
assertThat(underTest.isDreaming).isEqualTo(false)
|
||||
|
||||
underTest.onStartDream()
|
||||
verify(callback).onStartDream()
|
||||
assertThat(underTest.isDreaming).isEqualTo(true)
|
||||
|
||||
// Adding twice should not invoke twice
|
||||
reset(callback)
|
||||
underTest.addCallback(callback)
|
||||
underTest.onStartDream()
|
||||
verify(callback, times(1)).onStartDream()
|
||||
|
||||
// After remove, no call to callback
|
||||
reset(callback)
|
||||
underTest.removeCallback(callback)
|
||||
underTest.onStartDream()
|
||||
verify(callback, never()).onStartDream()
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
UiEventLogger mUiEventLogger;
|
||||
|
||||
@Mock
|
||||
DreamCallbackController mDreamCallbackController;
|
||||
DreamOverlayCallbackController mDreamOverlayCallbackController;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<View> mViewCaptor;
|
||||
@@ -145,7 +145,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
mKeyguardUpdateMonitor,
|
||||
mUiEventLogger,
|
||||
LOW_LIGHT_COMPONENT,
|
||||
mDreamCallbackController);
|
||||
mDreamOverlayCallbackController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -357,7 +357,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
mService.onWakeUp(callback);
|
||||
mMainExecutor.runAllReady();
|
||||
verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
|
||||
verify(mDreamCallbackController).onWakeUp();
|
||||
verify(mDreamOverlayCallbackController).onWakeUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -28,8 +28,7 @@ import com.android.systemui.doze.DozeHost
|
||||
import com.android.systemui.doze.DozeMachine
|
||||
import com.android.systemui.doze.DozeTransitionCallback
|
||||
import com.android.systemui.doze.DozeTransitionListener
|
||||
import com.android.systemui.dreams.DreamCallbackController
|
||||
import com.android.systemui.dreams.DreamCallbackController.DreamCallback
|
||||
import com.android.systemui.dreams.DreamOverlayCallbackController
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
|
||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
|
||||
@@ -68,7 +67,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
@Mock private lateinit var dozeTransitionListener: DozeTransitionListener
|
||||
@Mock private lateinit var authController: AuthController
|
||||
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||
@Mock private lateinit var dreamCallbackController: DreamCallbackController
|
||||
@Mock private lateinit var dreamOverlayCallbackController: DreamOverlayCallbackController
|
||||
|
||||
private lateinit var underTest: KeyguardRepositoryImpl
|
||||
|
||||
@@ -86,7 +85,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
keyguardUpdateMonitor,
|
||||
dozeTransitionListener,
|
||||
authController,
|
||||
dreamCallbackController,
|
||||
dreamOverlayCallbackController,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -170,6 +169,29 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isKeyguardOccluded() =
|
||||
runTest(UnconfinedTestDispatcher()) {
|
||||
whenever(keyguardStateController.isOccluded).thenReturn(false)
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isKeyguardOccluded.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
val captor = argumentCaptor<KeyguardStateController.Callback>()
|
||||
verify(keyguardStateController).addCallback(captor.capture())
|
||||
|
||||
whenever(keyguardStateController.isOccluded).thenReturn(true)
|
||||
captor.value.onKeyguardShowingChanged()
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
whenever(keyguardStateController.isOccluded).thenReturn(false)
|
||||
captor.value.onKeyguardShowingChanged()
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isDozing() =
|
||||
runTest(UnconfinedTestDispatcher()) {
|
||||
@@ -343,19 +365,22 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isDreamingFromDreamCallbackController() =
|
||||
fun isDreamingFromDreamOverlayCallbackController() =
|
||||
runTest(UnconfinedTestDispatcher()) {
|
||||
whenever(keyguardUpdateMonitor.isDreaming()).thenReturn(true)
|
||||
whenever(dreamOverlayCallbackController.isDreaming).thenReturn(false)
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isDreaming.onEach { latest = it }.launchIn(this)
|
||||
val job = underTest.isDreamingWithOverlay.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isTrue()
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
val listener =
|
||||
withArgCaptor<DreamCallbackController.DreamCallback> {
|
||||
verify(dreamCallbackController).addCallback(capture())
|
||||
withArgCaptor<DreamOverlayCallbackController.Callback> {
|
||||
verify(dreamOverlayCallbackController).addCallback(capture())
|
||||
}
|
||||
|
||||
listener.onStartDream()
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
listener.onWakeUp()
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositoryImpl
|
||||
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
||||
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
import com.android.systemui.keyguard.shared.model.TransitionInfo
|
||||
import com.android.systemui.keyguard.shared.model.WakeSleepReason
|
||||
@@ -42,6 +44,7 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.reset
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@@ -64,8 +67,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
||||
// Used to verify transition requests for test output
|
||||
@Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
|
||||
|
||||
private lateinit var lockscreenBouncerTransitionInteractor:
|
||||
LockscreenBouncerTransitionInteractor
|
||||
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
|
||||
private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@@ -79,17 +82,74 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
||||
transitionRepository = KeyguardTransitionRepositoryImpl()
|
||||
runner = KeyguardTransitionRunner(transitionRepository)
|
||||
|
||||
lockscreenBouncerTransitionInteractor =
|
||||
LockscreenBouncerTransitionInteractor(
|
||||
fromLockscreenTransitionInteractor =
|
||||
FromLockscreenTransitionInteractor(
|
||||
scope = testScope,
|
||||
keyguardInteractor = KeyguardInteractor(keyguardRepository),
|
||||
shadeRepository = shadeRepository,
|
||||
keyguardTransitionRepository = mockTransitionRepository,
|
||||
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
|
||||
)
|
||||
lockscreenBouncerTransitionInteractor.start()
|
||||
fromLockscreenTransitionInteractor.start()
|
||||
|
||||
fromDreamingTransitionInteractor =
|
||||
FromDreamingTransitionInteractor(
|
||||
scope = testScope,
|
||||
keyguardInteractor = KeyguardInteractor(keyguardRepository),
|
||||
keyguardTransitionRepository = mockTransitionRepository,
|
||||
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
|
||||
)
|
||||
fromDreamingTransitionInteractor.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `DREAMING to LOCKSCREEN`() =
|
||||
testScope.runTest {
|
||||
// GIVEN a device is dreaming and occluded
|
||||
keyguardRepository.setDreamingWithOverlay(true)
|
||||
keyguardRepository.setKeyguardOccluded(true)
|
||||
runCurrent()
|
||||
|
||||
// GIVEN a prior transition has run to DREAMING
|
||||
runner.startTransition(
|
||||
testScope,
|
||||
TransitionInfo(
|
||||
ownerName = "",
|
||||
from = KeyguardState.LOCKSCREEN,
|
||||
to = KeyguardState.DREAMING,
|
||||
animator =
|
||||
ValueAnimator().apply {
|
||||
duration = 10
|
||||
interpolator = Interpolators.LINEAR
|
||||
},
|
||||
)
|
||||
)
|
||||
runCurrent()
|
||||
reset(mockTransitionRepository)
|
||||
|
||||
// WHEN doze is complete
|
||||
keyguardRepository.setDozeTransitionModel(
|
||||
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
|
||||
)
|
||||
// AND dreaming has stopped
|
||||
keyguardRepository.setDreamingWithOverlay(false)
|
||||
// AND occluded has stopped
|
||||
keyguardRepository.setKeyguardOccluded(false)
|
||||
runCurrent()
|
||||
|
||||
val info =
|
||||
withArgCaptor<TransitionInfo> {
|
||||
verify(mockTransitionRepository).startTransition(capture())
|
||||
}
|
||||
// THEN a transition to BOUNCER should occur
|
||||
assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
|
||||
assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
|
||||
assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
|
||||
assertThat(info.animator).isNotNull()
|
||||
|
||||
coroutineContext.cancelChildren()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `LOCKSCREEN to BOUNCER via bouncer showing call`() =
|
||||
testScope.runTest {
|
||||
@@ -97,7 +157,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
||||
keyguardRepository.setWakefulnessModel(startingToWake())
|
||||
runCurrent()
|
||||
|
||||
// GIVEN a transition has run to LOCKSCREEN
|
||||
// GIVEN a prior transition has run to LOCKSCREEN
|
||||
runner.startTransition(
|
||||
testScope,
|
||||
TransitionInfo(
|
||||
@@ -122,7 +182,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
||||
verify(mockTransitionRepository).startTransition(capture())
|
||||
}
|
||||
// THEN a transition to BOUNCER should occur
|
||||
assertThat(info.ownerName).isEqualTo("LockscreenBouncerTransitionInteractor")
|
||||
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
||||
assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
|
||||
assertThat(info.to).isEqualTo(KeyguardState.BOUNCER)
|
||||
assertThat(info.animator).isNotNull()
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
|
||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
|
||||
import com.android.systemui.keyguard.domain.interactor.DreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
||||
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||
|
||||
@@ -46,12 +46,18 @@ class FakeKeyguardRepository : KeyguardRepository {
|
||||
private val _isKeyguardShowing = MutableStateFlow(false)
|
||||
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
|
||||
|
||||
private val _isKeyguardOccluded = MutableStateFlow(false)
|
||||
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
|
||||
|
||||
private val _isDozing = MutableStateFlow(false)
|
||||
override val isDozing: Flow<Boolean> = _isDozing
|
||||
|
||||
private val _isDreaming = MutableStateFlow(false)
|
||||
override val isDreaming: Flow<Boolean> = _isDreaming
|
||||
|
||||
private val _isDreamingWithOverlay = MutableStateFlow(false)
|
||||
override val isDreamingWithOverlay: Flow<Boolean> = _isDreamingWithOverlay
|
||||
|
||||
private val _dozeAmount = MutableStateFlow(0f)
|
||||
override val linearDozeAmount: Flow<Float> = _dozeAmount
|
||||
|
||||
@@ -112,10 +118,18 @@ class FakeKeyguardRepository : KeyguardRepository {
|
||||
_isKeyguardShowing.value = isShowing
|
||||
}
|
||||
|
||||
fun setKeyguardOccluded(isOccluded: Boolean) {
|
||||
_isKeyguardOccluded.value = isOccluded
|
||||
}
|
||||
|
||||
fun setDozing(isDozing: Boolean) {
|
||||
_isDozing.value = isDozing
|
||||
}
|
||||
|
||||
fun setDreamingWithOverlay(isDreaming: Boolean) {
|
||||
_isDreamingWithOverlay.value = isDreaming
|
||||
}
|
||||
|
||||
fun setDozeAmount(dozeAmount: Float) {
|
||||
_dozeAmount.value = dozeAmount
|
||||
}
|
||||
@@ -144,6 +158,10 @@ class FakeKeyguardRepository : KeyguardRepository {
|
||||
_fingerprintSensorLocation.tryEmit(location)
|
||||
}
|
||||
|
||||
fun setDozeTransitionModel(model: DozeTransitionModel) {
|
||||
_dozeTransitionModel.value = model
|
||||
}
|
||||
|
||||
override fun isUdfpsSupported(): Boolean {
|
||||
return _isUdfpsSupported.value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user