summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt16
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt136
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/PreviewKeyguardBlueprintViewBinder.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt63
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt94
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt80
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt79
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt2
27 files changed, 692 insertions, 174 deletions
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1b09c6afeafc..ef0053da53a9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -766,6 +766,8 @@
<dimen name="keyguard_clock_switch_y_shift">14dp</dimen>
<!-- When large clock is showing, offset the smartspace by this amount -->
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
+ <!-- The amount to translate lockscreen elements on the GONE->AOD transition -->
+ <dimen name="keyguard_enter_from_top_translation_y">-100dp</dimen>
<dimen name="notification_scrim_corner_radius">32dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 01a75d9e0f16..e47d36f76a14 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -15,6 +15,8 @@
*/
package com.android.keyguard
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -37,7 +39,7 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.DisplaySpecific
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags.DOZING_MIGRATION_1
+import com.android.systemui.flags.Flags.MIGRATE_KEYGUARD_STATUS_VIEW
import com.android.systemui.flags.Flags.REGION_SAMPLING
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -61,6 +63,7 @@ import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import java.util.Locale
import java.util.TimeZone
@@ -297,7 +300,7 @@ constructor(
object : KeyguardUpdateMonitorCallback() {
override fun onKeyguardVisibilityChanged(visible: Boolean) {
isKeyguardVisible = visible
- if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) {
+ if (!featureFlags.isEnabled(MIGRATE_KEYGUARD_STATUS_VIEW)) {
if (!isKeyguardVisible) {
clock?.run {
smallClock.animations.doze(if (isDozing) 1f else 0f)
@@ -342,9 +345,9 @@ constructor(
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
disposableHandle =
parent.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.STARTED) {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
listenForDozing(this)
- if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
+ if (featureFlags.isEnabled(MIGRATE_KEYGUARD_STATUS_VIEW)) {
listenForDozeAmountTransition(this)
listenForAnyStateToAodTransition(this)
} else {
@@ -454,8 +457,9 @@ constructor(
@VisibleForTesting
internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
return scope.launch {
- keyguardTransitionInteractor.anyStateToAodTransition
- .filter { it.transitionState == TransitionState.FINISHED }
+ keyguardTransitionInteractor.transitionStepsToState(AOD)
+ .filter { it.transitionState == TransitionState.STARTED }
+ .filter { it.from != LOCKSCREEN }
.collect { handleDoze(1f) }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 79642bdae1ce..758d1fef6e2e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -54,6 +54,9 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.TransitionState;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
@@ -102,10 +105,11 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
private final Rect mClipBounds = new Rect();
private final KeyguardInteractor mKeyguardInteractor;
private final PowerInteractor mPowerInteractor;
+ private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private Boolean mSplitShadeEnabled = false;
private Boolean mStatusViewCentered = true;
-
+ private boolean mGoneToAodTransitionRunning = false;
private DumpManager mDumpManager;
private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
@@ -135,6 +139,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
FeatureFlags featureFlags,
InteractionJankMonitor interactionJankMonitor,
KeyguardInteractor keyguardInteractor,
+ KeyguardTransitionInteractor keyguardTransitionInteractor,
DumpManager dumpManager,
PowerInteractor powerInteractor) {
super(keyguardStatusView);
@@ -144,12 +149,13 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
mConfigurationController = configurationController;
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
- logger.getBuffer());
+ featureFlags, logger.getBuffer());
mInteractionJankMonitor = interactionJankMonitor;
mFeatureFlags = featureFlags;
mDumpManager = dumpManager;
mKeyguardInteractor = keyguardInteractor;
mPowerInteractor = powerInteractor;
+ mKeyguardTransitionInteractor = keyguardTransitionInteractor;
}
@Override
@@ -199,6 +205,15 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
dozeTimeTick();
}
}, context);
+
+ collectFlow(mView, mKeyguardTransitionInteractor.getGoneToAodTransition(),
+ (TransitionStep step) -> {
+ if (step.getTransitionState() == TransitionState.RUNNING) {
+ mGoneToAodTransitionRunning = true;
+ } else {
+ mGoneToAodTransitionRunning = false;
+ }
+ }, context);
}
public KeyguardStatusView getView() {
@@ -266,7 +281,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
* Set keyguard status view alpha.
*/
public void setAlpha(float alpha) {
- if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
+ if (!mKeyguardVisibilityHelper.isVisibilityAnimating() && !mGoneToAodTransitionRunning) {
mView.setAlpha(alpha);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index c64ae0106b4a..d524e4a8c408 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -23,6 +23,8 @@ import android.util.Property;
import android.view.View;
import com.android.app.animation.Interpolators;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.statusbar.StatusBarState;
@@ -53,6 +55,7 @@ public class KeyguardVisibilityHelper {
private boolean mKeyguardViewVisibilityAnimating;
private boolean mLastOccludedState = false;
private final AnimationProperties mAnimationProperties = new AnimationProperties();
+ private final FeatureFlags mFeatureFlags;
private final LogBuffer mLogBuffer;
public KeyguardVisibilityHelper(View view,
@@ -60,12 +63,14 @@ public class KeyguardVisibilityHelper {
DozeParameters dozeParameters,
ScreenOffAnimationController screenOffAnimationController,
boolean animateYPos,
+ FeatureFlags featureFlags,
LogBuffer logBuffer) {
mView = view;
mKeyguardStateController = keyguardStateController;
mDozeParameters = dozeParameters;
mScreenOffAnimationController = screenOffAnimationController;
mAnimateYPos = animateYPos;
+ mFeatureFlags = featureFlags;
mLogBuffer = logBuffer;
}
@@ -162,13 +167,17 @@ public class KeyguardVisibilityHelper {
animProps,
true /* animate */);
} else if (mScreenOffAnimationController.shouldAnimateInKeyguard()) {
- log("ScreenOff transition");
- mKeyguardViewVisibilityAnimating = true;
+ if (mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ log("Using GoneToAodTransition");
+ mKeyguardViewVisibilityAnimating = false;
+ } else {
+ log("ScreenOff transition");
+ mKeyguardViewVisibilityAnimating = true;
- // Ask the screen off animation controller to animate the keyguard visibility for us
- // since it may need to be cancelled due to keyguard lifecycle events.
- mScreenOffAnimationController.animateInKeyguard(
- mView, mSetVisibleEndRunnable);
+ // Ask the screen off animation controller to animate the keyguard visibility
+ // for us since it may need to be cancelled due to keyguard lifecycle events.
+ mScreenOffAnimationController.animateInKeyguard(mView, mSetVisibleEndRunnable);
+ }
} else {
log("Direct set Visibility to VISIBLE");
mView.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 86bf368791bc..a511713eddd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -20,6 +20,7 @@ package com.android.systemui.keyguard
import android.content.Context
import android.view.LayoutInflater
import android.view.View
+import com.android.internal.jank.InteractionJankMonitor
import com.android.keyguard.KeyguardStatusView
import com.android.keyguard.KeyguardStatusViewController
import com.android.keyguard.LockIconView
@@ -71,6 +72,7 @@ constructor(
private val keyguardIndicationController: KeyguardIndicationController,
private val lockIconViewController: LockIconViewController,
private val shadeInteractor: ShadeInteractor,
+ private val interactionJankMonitor: InteractionJankMonitor
) : CoreStartable {
private var rootViewHandle: DisposableHandle? = null
@@ -140,6 +142,7 @@ constructor(
keyguardStateController,
shadeInteractor,
{ keyguardStatusViewController!!.getClockController() },
+ interactionJankMonitor,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 38eb730d1498..6e0aa4c7682d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -26,10 +26,11 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
-import javax.inject.Inject
@SysUISingleton
class FromAodTransitionInteractor
@@ -86,15 +87,19 @@ constructor(
}
}
}
-
override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator {
return ValueAnimator().apply {
interpolator = Interpolators.LINEAR
- duration = TRANSITION_DURATION_MS
+ duration =
+ when (toState) {
+ KeyguardState.LOCKSCREEN -> TO_LOCKSCREEN_DURATION
+ else -> DEFAULT_DURATION
+ }.inWholeMilliseconds
}
}
companion object {
- private const val TRANSITION_DURATION_MS = 500L
+ val TO_LOCKSCREEN_DURATION = 500.milliseconds
+ private val DEFAULT_DURATION = 500.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index ad51e74090d9..c67153a5963d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -114,7 +114,8 @@ constructor(
.collect { (isAsleep, lastStartedStep, isAodAvailable) ->
if (lastStartedStep.to == KeyguardState.GONE && isAsleep) {
startTransitionTo(
- if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING
+ if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING,
+ resetIfCancelled = true,
)
}
}
@@ -127,6 +128,7 @@ constructor(
duration =
when (toState) {
KeyguardState.DREAMING -> TO_DREAMING_DURATION
+ KeyguardState.AOD -> TO_AOD_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -134,5 +136,6 @@ constructor(
companion object {
private val DEFAULT_DURATION = 500.milliseconds
val TO_DREAMING_DURATION = 933.milliseconds
+ val TO_AOD_DURATION = 1100.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 660bd84006d7..c39a4c9c4172 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -33,6 +33,9 @@ import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
+import java.util.UUID
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -40,9 +43,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
-import java.util.UUID
-import javax.inject.Inject
-import kotlin.time.Duration.Companion.milliseconds
@SysUISingleton
class FromLockscreenTransitionInteractor
@@ -355,6 +355,7 @@ constructor(
when (toState) {
KeyguardState.DREAMING -> TO_DREAMING_DURATION
KeyguardState.OCCLUDED -> TO_OCCLUDED_DURATION
+ KeyguardState.AOD -> TO_AOD_DURATION
else -> DEFAULT_DURATION
}.inWholeMilliseconds
}
@@ -364,5 +365,6 @@ constructor(
private val DEFAULT_DURATION = 400.milliseconds
val TO_DREAMING_DURATION = 933.milliseconds
val TO_OCCLUDED_DURATION = 450.milliseconds
+ val TO_AOD_DURATION = 500.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 6e19fdbefab5..b953b4879a4a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -39,7 +39,6 @@ import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
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.KeyguardRootViewVisibilityState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.res.R
@@ -49,6 +48,8 @@ import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
@@ -64,8 +65,6 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
-import javax.inject.Inject
-import javax.inject.Provider
/**
* Encapsulates business-logic related to the keyguard but not to a more specific part within it.
@@ -148,9 +147,7 @@ constructor(
.combine(dozeTransitionModel) { isDreaming, dozeTransitionModel ->
isDreaming && isDozeOff(dozeTransitionModel.to)
}
- .sample(powerInteractor.isAwake) { isAbleToDream, isAwake ->
- isAbleToDream && isAwake
- }
+ .sample(powerInteractor.isAwake) { isAbleToDream, isAwake -> isAbleToDream && isAwake }
.flatMapLatest { isAbleToDream ->
flow {
delay(50)
@@ -217,11 +214,8 @@ constructor(
val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
/** Notifies when a new configuration is set */
- val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange
-
- /** Represents the current state of the KeyguardRootView visibility */
- val keyguardRootViewVisibilityState: Flow<KeyguardRootViewVisibilityState> =
- repository.keyguardRootViewVisibility
+ val configurationChange: Flow<Unit> =
+ configurationRepository.onAnyConfigurationChange.onStart { emit(Unit) }
/** The position of the keyguard clock. */
val clockPosition: Flow<Position> = repository.clockPosition
@@ -235,12 +229,17 @@ constructor(
R.dimen.keyguard_translate_distance_on_swipe_up
)
shadeRepository.shadeModel.map {
- // On swipe up, translate the keyguard to reveal the bouncer
- MathUtils.lerp(
- translationDistance,
- 0,
- Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it.expansionAmount)
- )
+ if (it.expansionAmount == 0f) {
+ // Reset the translation value
+ 0f
+ } else {
+ // On swipe up, translate the keyguard to reveal the bouncer
+ MathUtils.lerp(
+ translationDistance,
+ 0,
+ Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it.expansionAmount)
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index ac4ad39a38a5..c72e6ce0b7d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -20,21 +20,24 @@ import android.annotation.DrawableRes
import android.view.View
import android.view.View.OnLayoutChangeListener
import android.view.ViewGroup
+import android.view.ViewGroup.OnHierarchyChangeListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.animation.Interpolators
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
+import com.android.keyguard.KeyguardClockSwitch.MISSING_CLOCK_ID
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.shared.model.TintedIcon
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ClockController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.temporarydisplay.ViewPriority
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -48,8 +51,6 @@ import kotlinx.coroutines.launch
@ExperimentalCoroutinesApi
object KeyguardRootViewBinder {
- private var onLayoutChangeListener: OnLayoutChange? = null
-
@JvmStatic
fun bind(
view: ViewGroup,
@@ -60,7 +61,14 @@ object KeyguardRootViewBinder {
keyguardStateController: KeyguardStateController,
shadeInteractor: ShadeInteractor,
clockControllerProvider: Provider<ClockController>?,
+ interactionJankMonitor: InteractionJankMonitor?,
): DisposableHandle {
+ var onLayoutChangeListener: OnLayoutChange? = null
+ val childViews = mutableMapOf<Int, View?>()
+ val statusViewId = R.id.keyguard_status_view
+ val burnInLayerId = R.id.burn_in_layer
+ val aodNotificationIconContainerId = R.id.aod_notification_icon_container
+ val largeClockId = R.id.lockscreen_clock_view_large
val disposableHandle =
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -86,36 +94,74 @@ object KeyguardRootViewBinder {
if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
launch {
+ viewModel.burnInLayerVisibility.collect { visibility ->
+ childViews[burnInLayerId]?.visibility = visibility
+ // Reset alpha only for the icons, as they currently have their
+ // own animator
+ childViews[aodNotificationIconContainerId]?.alpha = 0f
+ }
+ }
+
+ launch {
+ viewModel.burnInLayerAlpha.collect { alpha ->
+ childViews[statusViewId]?.alpha = alpha
+ childViews[aodNotificationIconContainerId]?.alpha = alpha
+ }
+ }
+
+ launch {
+ viewModel.lockscreenStateAlpha.collect { alpha ->
+ childViews[statusViewId]?.alpha = alpha
+ }
+ }
+
+ launch {
viewModel.translationY.collect { y ->
- val burnInLayer = view.requireViewById<View>(R.id.burn_in_layer)
- burnInLayer.translationY = y
+ childViews[burnInLayerId]?.translationY = y
}
}
- }
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
launch {
viewModel.translationX.collect { x ->
- val burnInLayer = view.requireViewById<View>(R.id.burn_in_layer)
- burnInLayer.translationX = x
+ childViews[burnInLayerId]?.translationX = x
}
}
- }
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
launch {
viewModel.scale.collect { (scale, scaleClockOnly) ->
if (scaleClockOnly) {
- val largeClock =
- view.findViewById<View?>(R.id.lockscreen_clock_view_large)
- largeClock?.let {
+ childViews[largeClockId]?.let {
it.scaleX = scale
it.scaleY = scale
}
} else {
- val burnInLayer = view.requireViewById<View>(R.id.burn_in_layer)
- burnInLayer.scaleX = scale
- burnInLayer.scaleY = scale
+ childViews[burnInLayerId]?.scaleX = scale
+ childViews[burnInLayerId]?.scaleY = scale
+ }
+ }
+ }
+
+ interactionJankMonitor?.let { jankMonitor ->
+ launch {
+ viewModel.goneToAodTransition.collect {
+ when (it.transitionState) {
+ TransitionState.STARTED -> {
+ val clockId =
+ clockControllerProvider?.get()?.config?.id
+ ?: MISSING_CLOCK_ID
+ val builder =
+ InteractionJankMonitor.Configuration.Builder
+ .withView(CUJ_SCREEN_OFF_SHOW_AOD, view)
+ .setTag(clockId)
+
+ jankMonitor.begin(builder)
+ }
+ TransitionState.CANCELED ->
+ jankMonitor.cancel(CUJ_SCREEN_OFF_SHOW_AOD)
+ TransitionState.FINISHED ->
+ jankMonitor.end(CUJ_SCREEN_OFF_SHOW_AOD)
+ TransitionState.RUNNING -> Unit
+ }
}
}
}
@@ -132,54 +178,32 @@ object KeyguardRootViewBinder {
}
}
}
-
- repeatOnLifecycle(Lifecycle.State.STARTED) {
- if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- launch {
- viewModel.keyguardRootViewVisibilityState.collect { visibilityState ->
- view.animate().cancel()
- val goingToFullShade = visibilityState.goingToFullShade
- val statusBarState = visibilityState.statusBarState
- val isOcclusionTransitionRunning =
- visibilityState.occlusionTransitionRunning
- if (goingToFullShade) {
- view
- .animate()
- .alpha(0f)
- .setStartDelay(
- keyguardStateController.keyguardFadingAwayDelay
- )
- .setDuration(
- keyguardStateController.shortenedFadingAwayDuration
- )
- .setInterpolator(Interpolators.ALPHA_OUT)
- .withEndAction { view.visibility = View.GONE }
- .start()
- } else if (
- statusBarState == StatusBarState.KEYGUARD ||
- statusBarState == StatusBarState.SHADE_LOCKED
- ) {
- view.visibility = View.VISIBLE
- if (!isOcclusionTransitionRunning) {
- view.alpha = 1f
- }
- } else {
- view.visibility = View.GONE
- }
- }
- }
- }
- }
}
viewModel.clockControllerProvider = clockControllerProvider
onLayoutChangeListener = OnLayoutChange(viewModel)
view.addOnLayoutChangeListener(onLayoutChangeListener)
+ // Views will be added or removed after the call to bind(). This is needed to avoid many
+ // calls to findViewById
+ view.setOnHierarchyChangeListener(
+ object : OnHierarchyChangeListener {
+ override fun onChildViewAdded(parent: View, child: View) {
+ childViews.put(child.id, view)
+ }
+
+ override fun onChildViewRemoved(parent: View, child: View) {
+ childViews.remove(child.id)
+ }
+ }
+ )
+
return object : DisposableHandle {
override fun dispose() {
disposableHandle.dispose()
view.removeOnLayoutChangeListener(onLayoutChangeListener)
+ view.setOnHierarchyChangeListener(null)
+ childViews.clear()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/PreviewKeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/PreviewKeyguardBlueprintViewBinder.kt
index f3586bae1a9e..2feaa2e81c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/PreviewKeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/PreviewKeyguardBlueprintViewBinder.kt
@@ -24,6 +24,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
+import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.launch
/**
@@ -46,8 +47,8 @@ class PreviewKeyguardBlueprintViewBinder {
constraintLayout: ConstraintLayout,
viewModel: KeyguardBlueprintViewModel,
finishedAddViewCallback: () -> Unit
- ) {
- constraintLayout.repeatWhenAttached {
+ ): DisposableHandle {
+ return constraintLayout.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.blueprint.collect { blueprint ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 4a2954dc6559..c1c29c416902 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -322,7 +322,7 @@ constructor(
@OptIn(ExperimentalCoroutinesApi::class)
private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) {
- val keyguardRootView = KeyguardRootView(previewContext, null).apply { removeAllViews() }
+ val keyguardRootView = KeyguardRootView(previewContext, null)
disposables.add(
KeyguardRootViewBinder.bind(
keyguardRootView,
@@ -333,6 +333,7 @@ constructor(
keyguardStateController,
shadeInteractor,
null, // clock provider only needed for burn in
+ null, // jank monitor not required for preview mode
)
)
rootView.addView(
@@ -342,26 +343,29 @@ constructor(
FrameLayout.LayoutParams.MATCH_PARENT,
),
)
- PreviewKeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) {
- if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- setupShortcuts(keyguardRootView)
- }
- setUpUdfps(previewContext, rootView)
-
- if (!shouldHideClock) {
- setUpClock(previewContext, rootView)
- KeyguardPreviewClockViewBinder.bind(
- largeClockHostView,
- smallClockHostView,
- clockViewModel,
- )
- }
- setUpSmartspace(previewContext, rootView)
- smartSpaceView?.let {
- KeyguardPreviewSmartspaceViewBinder.bind(it, smartspaceViewModel)
+ disposables.add(
+ PreviewKeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
+ setupShortcuts(keyguardRootView)
+ }
+ setUpUdfps(previewContext, rootView)
+
+ if (!shouldHideClock) {
+ setUpClock(previewContext, rootView)
+ KeyguardPreviewClockViewBinder.bind(
+ largeClockHostView,
+ smallClockHostView,
+ clockViewModel,
+ )
+ }
+
+ setUpSmartspace(previewContext, rootView)
+ smartSpaceView?.let {
+ KeyguardPreviewSmartspaceViewBinder.bind(it, smartspaceViewModel)
+ }
}
- }
+ )
}
private fun setupShortcuts(keyguardRootView: ConstraintLayout) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
new file mode 100644
index 000000000000..024707ad2885
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToLockscreenTransitionViewModel.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromAodTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Breaks down AOD->LOCKSCREEN transition into discrete steps for corresponding views to consume.
+ */
+@SysUISingleton
+class AodToLockscreenTransitionViewModel
+@Inject
+constructor(
+ private val interactor: KeyguardTransitionInteractor,
+) {
+
+ private val transitionAnimation =
+ KeyguardTransitionAnimationFlow(
+ transitionDuration = TO_LOCKSCREEN_DURATION,
+ transitionFlow = interactor.aodToLockscreenTransition,
+ )
+
+ /** Ensure alpha is set to be visible */
+ val lockscreenAlpha: Flow<Float> =
+ transitionAnimation.createFlow(
+ duration = 500.milliseconds,
+ onStart = { 1f },
+ onStep = { 1f },
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
new file mode 100644
index 000000000000..601dbccb1de1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModel.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.ui.viewmodel
+
+import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_AOD_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+
+/** Breaks down GONE->AOD transition into discrete steps for corresponding views to consume. */
+@SysUISingleton
+class GoneToAodTransitionViewModel
+@Inject
+constructor(
+ private val interactor: KeyguardTransitionInteractor,
+) {
+
+ private val transitionAnimation =
+ KeyguardTransitionAnimationFlow(
+ transitionDuration = TO_AOD_DURATION,
+ transitionFlow = interactor.goneToAodTransition,
+ )
+
+ /** y-translation from the top of the screen for AOD */
+ fun enterFromTopTranslationY(translatePx: Int): Flow<Float> {
+ return transitionAnimation.createFlow(
+ startTime = 600.milliseconds,
+ duration = 500.milliseconds,
+ onStart = { translatePx },
+ onStep = { translatePx + it * -translatePx },
+ onFinish = { 0f },
+ onCancel = { 0f },
+ interpolator = EMPHASIZED_DECELERATE,
+ )
+ }
+
+ /** alpha animation upon entering AOD */
+ val enterFromTopAnimationAlpha: Flow<Float> =
+ transitionAnimation.createFlow(
+ startTime = 600.milliseconds,
+ duration = 500.milliseconds,
+ onStart = { 0f },
+ onStep = { it },
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 89835fecd95c..1f98082c4065 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -17,14 +17,19 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.content.Context
import android.util.MathUtils
+import android.view.View.VISIBLE
import com.android.app.animation.Interpolators
import com.android.systemui.common.shared.model.SharedNotificationContainerPosition
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
-import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.plugins.ClockController
+import com.android.systemui.res.R
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -32,17 +37,23 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
@OptIn(ExperimentalCoroutinesApi::class)
class KeyguardRootViewModel
@Inject
constructor(
+ private val context: Context,
private val keyguardInteractor: KeyguardInteractor,
private val burnInInteractor: BurnInInteractor,
+ private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
+ private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) {
data class PreviewMode(val isInPreviewMode: Boolean = false)
@@ -56,9 +67,12 @@ constructor(
public var clockControllerProvider: Provider<ClockController>? = null
- /** Represents the current state of the KeyguardRootView visibility */
- val keyguardRootViewVisibilityState: Flow<KeyguardRootViewVisibilityState> =
- keyguardInteractor.keyguardRootViewVisibilityState
+ val burnInLayerVisibility: Flow<Int> =
+ keyguardTransitionInteractor.startedKeyguardState
+ .filter { it == AOD || it == LOCKSCREEN }
+ .map { VISIBLE }
+
+ val goneToAodTransition = keyguardTransitionInteractor.goneToAodTransition
/** An observable for the alpha level for the entire keyguard root view. */
val alpha: Flow<Float> =
@@ -70,9 +84,14 @@ constructor(
}
}
- private val burnIn: Flow<BurnInModel> =
- combine(keyguardInteractor.dozeAmount, burnInInteractor.keyguardBurnIn) { dozeAmount, burnIn
- ->
+ private fun burnIn(): Flow<BurnInModel> {
+ val dozingAmount: Flow<Float> =
+ merge(
+ keyguardTransitionInteractor.goneToAodTransition.map { it.value },
+ keyguardTransitionInteractor.dozeAmountTransition.map { it.value },
+ )
+
+ return combine(dozingAmount, burnInInteractor.keyguardBurnIn) { dozeAmount, burnIn ->
val interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(dozeAmount)
val useScaleOnly =
clockControllerProvider?.get()?.config?.useAlternateSmartspaceAODTransition ?: false
@@ -91,13 +110,61 @@ constructor(
)
}
}
+ }
+
+ /** Specific alpha value for elements visible during [KeyguardState.LOCKSCREEN] */
+ val lockscreenStateAlpha: Flow<Float> = aodToLockscreenTransitionViewModel.lockscreenAlpha
+
+ /** For elements that appear and move during the animation -> AOD */
+ val burnInLayerAlpha: Flow<Float> =
+ previewMode.flatMapLatest {
+ if (it.isInPreviewMode) {
+ flowOf(1f)
+ } else {
+ goneToAodTransitionViewModel.enterFromTopAnimationAlpha
+ }
+ }
val translationY: Flow<Float> =
- merge(keyguardInteractor.keyguardTranslationY, burnIn.map { it.translationY.toFloat() })
+ previewMode.flatMapLatest {
+ if (it.isInPreviewMode) {
+ flowOf(0f)
+ } else {
+ keyguardInteractor.configurationChange.flatMapLatest { _ ->
+ val enterFromTopAmount =
+ context.resources.getDimensionPixelSize(
+ R.dimen.keyguard_enter_from_top_translation_y
+ )
+ combine(
+ keyguardInteractor.keyguardTranslationY.onStart { emit(0f) },
+ burnIn().map { it.translationY.toFloat() }.onStart { emit(0f) },
+ goneToAodTransitionViewModel
+ .enterFromTopTranslationY(enterFromTopAmount)
+ .onStart { emit(0f) },
+ ) { keyguardTransitionY, burnInTranslationY, goneToAodTransitionTranslationY ->
+ // All 3 values need to be combined for a smooth translation
+ keyguardTransitionY + burnInTranslationY + goneToAodTransitionTranslationY
+ }
+ }
+ }
+ }
- val translationX: Flow<Float> = burnIn.map { it.translationX.toFloat() }
+ val translationX: Flow<Float> =
+ previewMode.flatMapLatest {
+ if (it.isInPreviewMode) {
+ flowOf(0f)
+ } else {
+ burnIn().map { it.translationX.toFloat() }
+ }
+ }
- val scale: Flow<Pair<Float, Boolean>> = burnIn.map { Pair(it.scale, it.scaleClockOnly) }
+ val scale: Flow<Pair<Float, Boolean>> =
+ previewMode.flatMapLatest { previewMode ->
+ burnIn().map {
+ val scale = if (previewMode.isInPreviewMode) 1f else it.scale
+ Pair(scale, it.scaleClockOnly)
+ }
+ }
/**
* Puts this view-model in "preview mode", which means it's being used for UI that is rendering
@@ -105,11 +172,14 @@ constructor(
* lock screen.
*/
fun enablePreviewMode() {
- val newPreviewMode = PreviewMode(true)
- previewMode.value = newPreviewMode
+ previewMode.value = PreviewMode(true)
}
fun onSharedNotificationContainerPositionChanged(top: Float, bottom: Float) {
+ // Notifications should not be visible in preview mode
+ if (previewMode.value.isInPreviewMode) {
+ return
+ }
keyguardInteractor.sharedNotificationContainerPosition.value =
SharedNotificationContainerPosition(top, bottom)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 51972c2d025c..8dc97c0f797c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1446,9 +1446,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mBarState);
}
- if (mFeatureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- setKeyguardVisibility(mBarState, false);
- } else {
+ if (!mFeatureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
setKeyguardBottomAreaVisibility(mBarState, false);
}
@@ -2358,14 +2356,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
}
- private void setKeyguardVisibility(int statusBarState, boolean goingToFullShade) {
- mKeyguardInteractor.setKeyguardRootVisibility(
- statusBarState,
- goingToFullShade,
- mIsOcclusionTransitionRunning
- );
- }
-
@Deprecated
private void setKeyguardBottomAreaVisibility(int statusBarState, boolean goingToFullShade) {
mKeyguardBottomArea.animate().cancel();
@@ -4443,11 +4433,13 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
&& statusBarState == KEYGUARD) {
// This means we're doing the screen off animation - position the keyguard status
// view where it'll be on AOD, so we can animate it in.
- mKeyguardStatusViewController.updatePosition(
- mClockPositionResult.clockX,
- mClockPositionResult.clockYFullyDozing,
- mClockPositionResult.clockScale,
- false /* animate */);
+ if (!mFeatureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
+ mKeyguardStatusViewController.updatePosition(
+ mClockPositionResult.clockX,
+ mClockPositionResult.clockYFullyDozing,
+ mClockPositionResult.clockScale,
+ false /* animate */);
+ }
}
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
@@ -4456,9 +4448,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
goingToFullShade,
mBarState);
- if (mFeatureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- setKeyguardVisibility(statusBarState, goingToFullShade);
- } else {
+ if (!mFeatureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
}
@@ -4562,7 +4552,12 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
public void showAodUi() {
setDozing(true /* dozing */, false /* animate */);
mStatusBarStateController.setUpcomingState(KEYGUARD);
- mStatusBarStateListener.onStateChanged(KEYGUARD);
+
+ if (mFeatureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
+ mStatusBarStateController.setState(KEYGUARD);
+ } else {
+ mStatusBarStateListener.onStateChanged(KEYGUARD);
+ }
mStatusBarStateListener.onDozeAmountChanged(1f, 1f);
setExpandedFraction(1f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 2c15e27b8148..de37170b1f7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -34,6 +34,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.TraceUtils
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
/**
* When to show the keyguard (AOD) view. This should be once the light reveal scrim is barely
@@ -65,7 +67,8 @@ class UnlockedScreenOffAnimationController @Inject constructor(
private val notifShadeWindowControllerLazy: dagger.Lazy<NotificationShadeWindowController>,
private val interactionJankMonitor: InteractionJankMonitor,
private val powerManager: PowerManager,
- private val handler: Handler = Handler()
+ private val handler: Handler = Handler(),
+ private val featureFlags: FeatureFlags,
) : WakefulnessLifecycle.Observer, ScreenOffAnimation {
private lateinit var centralSurfaces: CentralSurfaces
private lateinit var shadeViewController: ShadeViewController
@@ -285,7 +288,11 @@ class UnlockedScreenOffAnimationController @Inject constructor(
// up, with unpredictable consequences.
if (!powerManager.isInteractive(Display.DEFAULT_DISPLAY) &&
shouldAnimateInKeyguard) {
- aodUiAnimationPlaying = true
+ if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ // Tracking this state should no longer be relevant, as the isInteractive
+ // check covers it
+ aodUiAnimationPlaying = true
+ }
// Show AOD. That'll cause the KeyguardVisibilityHelper to call
// #animateInKeyguard.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 62e238164514..b614b6d0547d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -38,6 +38,7 @@ import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.res.R;
import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.user.UserSwitchDialogController;
@@ -148,6 +149,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
DozeParameters dozeParameters,
ScreenOffAnimationController screenOffAnimationController,
UserSwitchDialogController userSwitchDialogController,
+ FeatureFlags featureFlags,
UiEventLogger uiEventLogger) {
super(view);
if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController");
@@ -160,7 +162,8 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
mStatusBarStateController = statusBarStateController;
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
keyguardStateController, dozeParameters,
- screenOffAnimationController, /* animateYPos= */ false, /* logBuffer= */ null);
+ screenOffAnimationController, /* animateYPos= */ false,
+ featureFlags, /* logBuffer= */ null);
mUserSwitchDialogController = userSwitchDialogController;
mUiEventLogger = uiEventLogger;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index bb074ac33ddb..dfe26865f978 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -38,10 +38,11 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardVisibilityHelper;
import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
import com.android.settingslib.drawable.CircleFramedDrawable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -160,6 +161,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
KeyguardStateController keyguardStateController,
SysuiStatusBarStateController statusBarStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
+ FeatureFlags featureFlags,
DozeParameters dozeParameters,
ScreenOffAnimationController screenOffAnimationController) {
super(keyguardUserSwitcherView);
@@ -174,7 +176,8 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
mUserSwitcherController, this);
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
keyguardStateController, dozeParameters,
- screenOffAnimationController, /* animateYPos= */ false, /* logBuffer= */ null);
+ screenOffAnimationController, /* animateYPos= */ false,
+ featureFlags, /* logBuffer= */ null);
mBackground = new KeyguardUserSwitcherScrim(context);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 6afa5256523c..4d8768f5e9e0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -25,9 +25,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.log.LogBuffer
import com.android.systemui.plugins.ClockAnimations
import com.android.systemui.plugins.ClockController
@@ -47,8 +49,8 @@ import com.android.systemui.util.mockito.mock
import java.util.TimeZone
import java.util.concurrent.Executor
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.yield
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -90,10 +92,10 @@ class ClockEventControllerTest : SysuiTestCase() {
@Mock private lateinit var smallClockEvents: ClockFaceEvents
@Mock private lateinit var largeClockEvents: ClockFaceEvents
@Mock private lateinit var parentView: View
- @Mock private lateinit var transitionRepository: KeyguardTransitionRepository
private lateinit var repository: FakeKeyguardRepository
@Mock private lateinit var smallLogBuffer: LogBuffer
@Mock private lateinit var largeLogBuffer: LogBuffer
+ @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
private lateinit var underTest: ClockEventController
@Before
@@ -125,17 +127,13 @@ class ClockEventControllerTest : SysuiTestCase() {
withDeps.featureFlags.apply {
set(Flags.REGION_SAMPLING, false)
- set(Flags.DOZING_MIGRATION_1, false)
+ set(Flags.MIGRATE_KEYGUARD_STATUS_VIEW, false)
set(Flags.FACE_AUTH_REFACTOR, false)
}
underTest =
ClockEventController(
withDeps.keyguardInteractor,
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- featureFlags = withDeps.featureFlags,
- )
- .keyguardTransitionInteractor,
+ keyguardTransitionInteractor,
broadcastDispatcher,
batteryController,
keyguardUpdateMonitor,
@@ -316,6 +314,68 @@ class ClockEventControllerTest : SysuiTestCase() {
}
@Test
+ fun listenForDozeAmountTransition_updatesClockDozeAmount() =
+ runBlocking(IMMEDIATE) {
+ val transitionStep = MutableStateFlow(TransitionStep())
+ whenever(keyguardTransitionInteractor.dozeAmountTransition).thenReturn(transitionStep)
+
+ val job = underTest.listenForDozeAmountTransition(this)
+ transitionStep.value =
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ value = 0.4f
+ )
+ yield()
+
+ verify(animations, times(2)).doze(0.4f)
+
+ job.cancel()
+ }
+
+ @Test
+ fun listenForTransitionToAodFromGone_updatesClockDozeAmountToOne() =
+ runBlocking(IMMEDIATE) {
+ val transitionStep = MutableStateFlow(TransitionStep())
+ whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.AOD))
+ .thenReturn(transitionStep)
+
+ val job = underTest.listenForAnyStateToAodTransition(this)
+ transitionStep.value =
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ yield()
+
+ verify(animations, times(2)).doze(1f)
+
+ job.cancel()
+ }
+
+ @Test
+ fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() =
+ runBlocking(IMMEDIATE) {
+ val transitionStep = MutableStateFlow(TransitionStep())
+ whenever(keyguardTransitionInteractor.transitionStepsToState(KeyguardState.AOD))
+ .thenReturn(transitionStep)
+
+ val job = underTest.listenForAnyStateToAodTransition(this)
+ transitionStep.value =
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ yield()
+
+ verify(animations, never()).doze(1f)
+
+ job.cancel()
+ }
+
+ @Test
fun unregisterListeners_validate() =
runBlocking(IMMEDIATE) {
underTest.unregisterListeners()
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
index 3b8e02f7455a..22c75d85d4a1 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,6 +33,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.power.data.repository.FakePowerRepository;
import com.android.systemui.power.domain.interactor.PowerInteractorFactory;
import com.android.systemui.statusbar.notification.AnimatableProperty;
@@ -60,6 +63,7 @@ public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {
@Mock protected FeatureFlags mFeatureFlags;
@Mock protected InteractionJankMonitor mInteractionJankMonitor;
@Mock protected ViewTreeObserver mViewTreeObserver;
+ @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@Mock protected DumpManager mDumpManager;
protected FakeKeyguardRepository mFakeKeyguardRepository;
protected FakePowerRepository mFakePowerRepository;
@@ -90,6 +94,7 @@ public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {
mFeatureFlags,
mInteractionJankMonitor,
deps.getKeyguardInteractor(),
+ mKeyguardTransitionInteractor,
mDumpManager,
PowerInteractorFactory.create(
mFakePowerRepository
@@ -105,8 +110,8 @@ public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {
};
when(mKeyguardStatusView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
-
when(mKeyguardClockSwitchController.getView()).thenReturn(mKeyguardClockSwitch);
+ when(mKeyguardTransitionInteractor.getGoneToAodTransition()).thenReturn(emptyFlow());
}
protected void givenViewAttached() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
new file mode 100644
index 000000000000..255f4df17244
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToAodTransitionViewModelTest.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GoneToAodTransitionViewModelTest : SysuiTestCase() {
+ private lateinit var underTest: GoneToAodTransitionViewModel
+ private lateinit var repository: FakeKeyguardTransitionRepository
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+
+ repository = FakeKeyguardTransitionRepository()
+ val interactor =
+ KeyguardTransitionInteractorFactory.create(
+ scope = testScope.backgroundScope,
+ repository = repository,
+ )
+ .keyguardTransitionInteractor
+ underTest = GoneToAodTransitionViewModel(interactor)
+ }
+
+ @Test
+ fun enterFromTopTranslationY() =
+ testScope.runTest {
+ val pixels = -100f
+ val enterFromTopTranslationY by
+ collectLastValue(underTest.enterFromTopTranslationY(pixels.toInt()))
+
+ // The animation should only start > halfway through
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(enterFromTopTranslationY).isEqualTo(pixels)
+
+ repository.sendTransitionStep(step(0.5f))
+ assertThat(enterFromTopTranslationY).isEqualTo(pixels)
+
+ repository.sendTransitionStep(step(.85f))
+ assertThat(enterFromTopTranslationY).isIn(Range.closed(pixels, 0f))
+
+ // At the end, the translation should be complete and set to zero
+ repository.sendTransitionStep(step(1f))
+ assertThat(enterFromTopTranslationY).isEqualTo(0f)
+ }
+
+ @Test
+ fun enterFromTopAnimationAlpha() =
+ testScope.runTest {
+ val enterFromTopAnimationAlpha by collectLastValue(underTest.enterFromTopAnimationAlpha)
+
+ // The animation should only start > halfway through
+ repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+ assertThat(enterFromTopAnimationAlpha).isEqualTo(0f)
+
+ repository.sendTransitionStep(step(0.5f))
+ assertThat(enterFromTopAnimationAlpha).isEqualTo(0f)
+
+ repository.sendTransitionStep(step(.85f))
+ assertThat(enterFromTopAnimationAlpha).isIn(Range.closed(0f, 1f))
+
+ repository.sendTransitionStep(step(1f))
+ assertThat(enterFromTopAnimationAlpha).isEqualTo(1f)
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ value = value,
+ transitionState = state,
+ ownerName = "GoneToAodTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 71688db76a8b..4f545cb0e288 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -17,8 +17,10 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
@@ -26,12 +28,17 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.plugins.ClockController
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import javax.inject.Provider
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@@ -41,6 +48,7 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Answers
import org.mockito.Mock
+import org.mockito.Mockito.anyInt
import org.mockito.MockitoAnnotations
@SmallTest
@@ -51,10 +59,20 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
private lateinit var testScope: TestScope
private lateinit var repository: FakeKeyguardRepository
private lateinit var keyguardInteractor: KeyguardInteractor
+ private lateinit var configurationRepository: FakeConfigurationRepository
@Mock private lateinit var burnInInteractor: BurnInInteractor
+ @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ @Mock private lateinit var goneToAodTransitionViewModel: GoneToAodTransitionViewModel
+ @Mock
+ private lateinit var aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var clockController: ClockController
private val burnInFlow = MutableStateFlow(BurnInModel())
+ private val goneToAodTransitionViewModelVisibility = MutableStateFlow(0)
+ private val enterFromTopAnimationAlpha = MutableStateFlow(0f)
+ private val goneToAodTransitionStep = MutableSharedFlow<TransitionStep>(replay = 1)
+ private val dozeAmountTransitionStep = MutableSharedFlow<TransitionStep>(replay = 1)
+ private val startedKeyguardState = MutableStateFlow(KeyguardState.GONE)
@Before
fun setUp() {
@@ -71,9 +89,30 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
keyguardInteractor = withDeps.keyguardInteractor
repository = withDeps.repository
+ configurationRepository = withDeps.configurationRepository
+
+ whenever(goneToAodTransitionViewModel.enterFromTopTranslationY(anyInt()))
+ .thenReturn(emptyFlow<Float>())
+ whenever(goneToAodTransitionViewModel.enterFromTopAnimationAlpha)
+ .thenReturn(enterFromTopAnimationAlpha)
whenever(burnInInteractor.keyguardBurnIn).thenReturn(burnInFlow)
- underTest = KeyguardRootViewModel(keyguardInteractor, burnInInteractor)
+
+ whenever(keyguardTransitionInteractor.goneToAodTransition)
+ .thenReturn(goneToAodTransitionStep)
+ whenever(keyguardTransitionInteractor.dozeAmountTransition)
+ .thenReturn(dozeAmountTransitionStep)
+ whenever(keyguardTransitionInteractor.startedKeyguardState).thenReturn(startedKeyguardState)
+
+ underTest =
+ KeyguardRootViewModel(
+ context,
+ keyguardInteractor,
+ burnInInteractor,
+ goneToAodTransitionViewModel,
+ aodToLockscreenTransitionViewModel,
+ keyguardTransitionInteractor,
+ )
underTest.clockControllerProvider = Provider { clockController }
}
@@ -118,7 +157,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
val scale by collectLastValue(underTest.scale)
// Set to not dozing (on lockscreen)
- repository.setDozeAmount(0f)
+ dozeAmountTransitionStep.emit(TransitionStep(value = 0f))
// Trigger a change to the burn-in model
burnInFlow.value =
@@ -141,8 +180,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
val scale by collectLastValue(underTest.scale)
// Set to dozing (on AOD)
- repository.setDozeAmount(1f)
-
+ dozeAmountTransitionStep.emit(TransitionStep(value = 1f))
// Trigger a change to the burn-in model
burnInFlow.value =
BurnInModel(
@@ -150,10 +188,15 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
translationY = 30,
scale = 0.5f,
)
-
assertThat(translationX).isEqualTo(20)
assertThat(translationY).isEqualTo(30)
assertThat(scale).isEqualTo(Pair(0.5f, true /* scaleClockOnly */))
+
+ // Set to the beginning of GONE->AOD transition
+ goneToAodTransitionStep.emit(TransitionStep(value = 0f))
+ assertThat(translationX).isEqualTo(0)
+ assertThat(translationY).isEqualTo(0)
+ assertThat(scale).isEqualTo(Pair(1f, true /* scaleClockOnly */))
}
@Test
@@ -166,7 +209,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
val scale by collectLastValue(underTest.scale)
// Set to dozing (on AOD)
- repository.setDozeAmount(1f)
+ dozeAmountTransitionStep.emit(TransitionStep(value = 1f))
// Trigger a change to the burn-in model
burnInFlow.value =
@@ -180,4 +223,28 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
assertThat(translationY).isEqualTo(0)
assertThat(scale).isEqualTo(Pair(0.5f, false /* scaleClockOnly */))
}
+
+ @Test
+ fun burnInLayerVisibility() =
+ testScope.runTest {
+ val burnInLayerVisibility by collectLastValue(underTest.burnInLayerVisibility)
+
+ startedKeyguardState.value = KeyguardState.OCCLUDED
+ assertThat(burnInLayerVisibility).isNull()
+
+ startedKeyguardState.value = KeyguardState.AOD
+ assertThat(burnInLayerVisibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun burnInLayerAlpha() =
+ testScope.runTest {
+ val burnInLayerAlpha by collectLastValue(underTest.burnInLayerAlpha)
+
+ enterFromTopAnimationAlpha.value = 0.2f
+ assertThat(burnInLayerAlpha).isEqualTo(0.2f)
+
+ enterFromTopAnimationAlpha.value = 1f
+ assertThat(burnInLayerAlpha).isEqualTo(1f)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 4f0cec5759e5..6223e250d603 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -390,6 +390,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mFeatureFlags,
mInteractionJankMonitor,
mKeyguardInteractor,
+ mKeyguardTransitionInteractor,
mDumpManager,
mPowerInteractor));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
index e6f8c4861a94..9aafee4770de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
import android.os.Handler
import android.os.PowerManager
import android.testing.AndroidTestingRunner
@@ -80,10 +82,14 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
@Mock
private lateinit var handler: Handler
+ private lateinit var featureFlags: FakeFeatureFlags
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
-
+ featureFlags = FakeFeatureFlags().apply {
+ set(Flags.MIGRATE_KEYGUARD_STATUS_VIEW, false)
+ }
controller = UnlockedScreenOffAnimationController(
context,
wakefulnessLifecycle,
@@ -95,7 +101,8 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
dagger.Lazy<NotificationShadeWindowController> { notifShadeWindowController },
interactionJankMonitor,
powerManager,
- handler = handler
+ handler = handler,
+ featureFlags,
)
controller.initialize(centralSurfaces, shadeViewController, lightRevealScrim)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
index 1250228e2d37..d33806e131d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy
+import com.android.systemui.flags.FakeFeatureFlags
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.ViewUtils
@@ -77,11 +78,13 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
private lateinit var view: FrameLayout
private lateinit var testableLooper: TestableLooper
private lateinit var keyguardQsUserSwitchController: KeyguardQsUserSwitchController
+ private lateinit var featureFlags: FakeFeatureFlags
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
+ featureFlags = FakeFeatureFlags()
view = LayoutInflater.from(context)
.inflate(R.layout.keyguard_qs_user_switch, null) as FrameLayout
@@ -98,6 +101,7 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
dozeParameters,
screenOffAnimationController,
userSwitchDialogController,
+ featureFlags,
uiEventLogger)
ViewUtils.attachView(view)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
index 10b284a03a59..5dcc7423ecc6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/data/repository/FakeConfigurationRepository.kt
@@ -47,7 +47,7 @@ class FakeConfigurationRepository @Inject constructor() : ConfigurationRepositor
}
override fun getDimensionPixelSize(id: Int): Int {
- throw IllegalStateException("Don't use for tests")
+ return 0
}
}