Restore clock doze transition
I had recently updated the doze path to listen to any change
to/from AOD. This works for other code, but not clocks. Put
the prior code back.
(Apologies, ktfmt changed way more code than I did)
Fixes: 327910913
Test: atest ClockEventControllerTest
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint
TEAMFOOD
Change-Id: I7315f545a75def7a727b8ecd16824f04e0d6ac31
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 169a4e0..f28d405 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -15,8 +15,6 @@
*/
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
@@ -43,14 +41,16 @@
import com.android.systemui.flags.Flags.REGION_SAMPLING
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.core.Logger
+import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockTickRate
-import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.WeatherData
import com.android.systemui.plugins.clocks.ZenData
import com.android.systemui.plugins.clocks.ZenData.ZenMode
@@ -61,16 +61,18 @@
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.Locale
+import java.util.TimeZone
+import java.util.concurrent.Executor
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
-import java.util.Locale
-import java.util.TimeZone
-import java.util.concurrent.Executor
-import javax.inject.Inject
/**
* Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
@@ -93,11 +95,13 @@
private val featureFlags: FeatureFlagsClassic,
private val zenModeController: ZenModeController,
) {
- var loggers = listOf(
- clockBuffers.infraMessageBuffer,
- clockBuffers.smallClockMessageBuffer,
- clockBuffers.largeClockMessageBuffer
- ).map { Logger(it, TAG) }
+ var loggers =
+ listOf(
+ clockBuffers.infraMessageBuffer,
+ clockBuffers.smallClockMessageBuffer,
+ clockBuffers.largeClockMessageBuffer
+ )
+ .map { Logger(it, TAG) }
var clock: ClockController? = null
get() = field
@@ -108,11 +112,12 @@
}
private fun disconnectClock(clock: ClockController?) {
- if (clock == null) { return; }
+ if (clock == null) {
+ return
+ }
smallClockOnAttachStateChangeListener?.let {
clock.smallClock.view.removeOnAttachStateChangeListener(it)
- smallClockFrame?.viewTreeObserver
- ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
+ smallClockFrame?.viewTreeObserver?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
largeClockOnAttachStateChangeListener?.let {
clock.largeClock.view.removeOnAttachStateChangeListener(it)
@@ -120,7 +125,9 @@
}
private fun connectClock(clock: ClockController?) {
- if (clock == null) { return; }
+ if (clock == null) {
+ return
+ }
val clockStr = clock.toString()
loggers.forEach { it.d({ "New Clock: $str1" }) { str1 = clockStr } }
@@ -129,23 +136,27 @@
if (!regionSamplingEnabled) {
updateColors()
} else {
- smallRegionSampler = createRegionSampler(
- clock.smallClock.view,
- mainExecutor,
- bgExecutor,
- regionSamplingEnabled,
- isLockscreen = true,
- ::updateColors
- ).apply { startRegionSampler() }
+ smallRegionSampler =
+ createRegionSampler(
+ clock.smallClock.view,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ isLockscreen = true,
+ ::updateColors
+ )
+ .apply { startRegionSampler() }
- largeRegionSampler = createRegionSampler(
- clock.largeClock.view,
- mainExecutor,
- bgExecutor,
- regionSamplingEnabled,
- isLockscreen = true,
- ::updateColors
- ).apply { startRegionSampler() }
+ largeRegionSampler =
+ createRegionSampler(
+ clock.largeClock.view,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingEnabled,
+ isLockscreen = true,
+ ::updateColors
+ )
+ .apply { startRegionSampler() }
updateColors()
}
@@ -158,49 +169,49 @@
}
clock.events.onWeatherDataChanged(it)
}
- zenData?.let {
- clock.events.onZenDataChanged(it)
- }
- alarmData?.let {
- clock.events.onAlarmDataChanged(it)
- }
+ zenData?.let { clock.events.onZenDataChanged(it) }
+ alarmData?.let { clock.events.onAlarmDataChanged(it) }
- smallClockOnAttachStateChangeListener = object : OnAttachStateChangeListener {
- var pastVisibility: Int? = null
- override fun onViewAttachedToWindow(view: View) {
- clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
- // Match the asing for view.parent's layout classes.
- smallClockFrame = (view.parent as ViewGroup)?.also { frame ->
- pastVisibility = frame.visibility
- onGlobalLayoutListener = OnGlobalLayoutListener {
- val currentVisibility = frame.visibility
- if (pastVisibility != currentVisibility) {
- pastVisibility = currentVisibility
- // when small clock is visible,
- // recalculate bounds and sample
- if (currentVisibility == View.VISIBLE) {
- smallRegionSampler?.stopRegionSampler()
- smallRegionSampler?.startRegionSampler()
+ smallClockOnAttachStateChangeListener =
+ object : OnAttachStateChangeListener {
+ var pastVisibility: Int? = null
+ override fun onViewAttachedToWindow(view: View) {
+ clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ // Match the asing for view.parent's layout classes.
+ smallClockFrame =
+ (view.parent as ViewGroup)?.also { frame ->
+ pastVisibility = frame.visibility
+ onGlobalLayoutListener = OnGlobalLayoutListener {
+ val currentVisibility = frame.visibility
+ if (pastVisibility != currentVisibility) {
+ pastVisibility = currentVisibility
+ // when small clock is visible,
+ // recalculate bounds and sample
+ if (currentVisibility == View.VISIBLE) {
+ smallRegionSampler?.stopRegionSampler()
+ smallRegionSampler?.startRegionSampler()
+ }
+ }
}
+ frame.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
- }
- frame.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
+ }
+
+ override fun onViewDetachedFromWindow(p0: View) {
+ smallClockFrame
+ ?.viewTreeObserver
+ ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
}
-
- override fun onViewDetachedFromWindow(p0: View) {
- smallClockFrame?.viewTreeObserver
- ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
- }
- }
clock.smallClock.view.addOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
- largeClockOnAttachStateChangeListener = object : OnAttachStateChangeListener {
- override fun onViewAttachedToWindow(p0: View) {
- clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ largeClockOnAttachStateChangeListener =
+ object : OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(p0: View) {
+ clock.events.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+ }
+ override fun onViewDetachedFromWindow(p0: View) {}
}
- override fun onViewDetachedFromWindow(p0: View) {}
- }
clock.largeClock.view.addOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
}
@@ -263,7 +274,9 @@
bgExecutor,
regionSamplingEnabled,
isLockscreen,
- ) { updateColors() }
+ ) {
+ updateColors()
+ }
}
var smallRegionSampler: RegionSampler? = null
@@ -364,35 +377,36 @@
}
}
- private val zenModeCallback = object : ZenModeController.Callback {
- override fun onZenChanged(zen: Int) {
- var mode = ZenMode.fromInt(zen)
- if (mode == null) {
- Log.e(TAG, "Failed to get zen mode from int: $zen")
- return
- }
-
- zenData = ZenData(
- mode,
- if (mode == ZenMode.OFF) SysuiR.string::dnd_is_off.name
- else SysuiR.string::dnd_is_on.name
- ).also { data ->
- mainExecutor.execute {
- clock?.run { events.onZenDataChanged(data) }
+ private val zenModeCallback =
+ object : ZenModeController.Callback {
+ override fun onZenChanged(zen: Int) {
+ var mode = ZenMode.fromInt(zen)
+ if (mode == null) {
+ Log.e(TAG, "Failed to get zen mode from int: $zen")
+ return
}
- }
- }
- override fun onNextAlarmChanged() {
- val nextAlarmMillis = zenModeController.getNextAlarm()
- alarmData = AlarmData(
- if (nextAlarmMillis > 0) nextAlarmMillis else null,
- SysuiR.string::status_bar_alarm.name
- ).also { data ->
- clock?.run { events.onAlarmDataChanged(data) }
+ zenData =
+ ZenData(
+ mode,
+ if (mode == ZenMode.OFF) SysuiR.string::dnd_is_off.name
+ else SysuiR.string::dnd_is_on.name
+ )
+ .also { data ->
+ mainExecutor.execute { clock?.run { events.onZenDataChanged(data) } }
+ }
+ }
+
+ override fun onNextAlarmChanged() {
+ val nextAlarmMillis = zenModeController.getNextAlarm()
+ alarmData =
+ AlarmData(
+ if (nextAlarmMillis > 0) nextAlarmMillis else null,
+ SysuiR.string::status_bar_alarm.name
+ )
+ .also { data -> clock?.run { events.onAlarmDataChanged(data) } }
}
}
- }
fun registerListeners(parent: View) {
if (isRegistered) {
@@ -413,6 +427,7 @@
listenForDozing(this)
if (migrateClocksToBlueprint()) {
listenForDozeAmountTransition(this)
+ listenForAnyStateToAodTransition(this)
} else {
listenForDozeAmount(this)
}
@@ -444,12 +459,15 @@
largeRegionSampler?.stopRegionSampler()
smallTimeListener?.stop()
largeTimeListener?.stop()
- clock?.smallClock?.view
- ?.removeOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
- smallClockFrame?.viewTreeObserver
- ?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
- clock?.largeClock?.view
- ?.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
+ clock
+ ?.smallClock
+ ?.view
+ ?.removeOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
+ smallClockFrame?.viewTreeObserver?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
+ clock
+ ?.largeClock
+ ?.view
+ ?.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
}
/**
@@ -473,12 +491,10 @@
largeTimeListener = null
clock?.let {
- smallTimeListener = TimeListener(it.smallClock, mainExecutor).apply {
- update(shouldTimeListenerRun)
- }
- largeTimeListener = TimeListener(it.largeClock, mainExecutor).apply {
- update(shouldTimeListenerRun)
- }
+ smallTimeListener =
+ TimeListener(it.smallClock, mainExecutor).apply { update(shouldTimeListenerRun) }
+ largeTimeListener =
+ TimeListener(it.largeClock, mainExecutor).apply { update(shouldTimeListenerRun) }
}
}
@@ -517,7 +533,27 @@
@VisibleForTesting
internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job {
return scope.launch {
- keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) }
+ merge(
+ keyguardTransitionInteractor.aodToLockscreenTransition.map { step ->
+ step.copy(value = 1f - step.value)
+ },
+ keyguardTransitionInteractor.lockscreenToAodTransition,
+ )
+ .collect { handleDoze(it.value) }
+ }
+ }
+
+ /**
+ * When keyguard is displayed again after being gone, the clock must be reset to full dozing.
+ */
+ @VisibleForTesting
+ internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
+ return scope.launch {
+ keyguardTransitionInteractor
+ .transitionStepsToState(AOD)
+ .filter { it.transitionState == TransitionState.STARTED }
+ .filter { it.from != LOCKSCREEN }
+ .collect { handleDoze(1f) }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 0f8a813..3d0d8fb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -21,8 +21,8 @@
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
import com.android.systemui.Flags as AConfigFlags
+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
@@ -319,7 +319,10 @@
fun listenForDozeAmountTransition_updatesClockDozeAmount() =
runBlocking(IMMEDIATE) {
val transitionStep = MutableStateFlow(TransitionStep())
- whenever(keyguardTransitionInteractor.dozeAmountTransition).thenReturn(transitionStep)
+ whenever(keyguardTransitionInteractor.lockscreenToAodTransition)
+ .thenReturn(transitionStep)
+ whenever(keyguardTransitionInteractor.aodToLockscreenTransition)
+ .thenReturn(transitionStep)
val job = underTest.listenForDozeAmountTransition(this)
transitionStep.value =
@@ -336,6 +339,48 @@
}
@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()