Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5d91e7a authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Only show the DND icon in Weather Clock if the DND mode is active" into main

parents d55985df d47f4077
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,10 @@ class FakeZenModeRepository : ZenModeRepository {
        mutableModesFlow.value = mutableModesFlow.value.filter { it.id != id }
        mutableModesFlow.value = mutableModesFlow.value.filter { it.id != id }
    }
    }


    fun replaceMode(modeId: String, mode: ZenMode) {
        mutableModesFlow.value = (mutableModesFlow.value.filter { it.id != modeId }) + mode
    }

    fun getMode(id: String): ZenMode? {
    fun getMode(id: String): ZenMode? {
        return mutableModesFlow.value.find { it.id == id }
        return mutableModesFlow.value.find { it.id == id }
    }
    }
+59 −25
Original line number Original line Diff line number Diff line
@@ -15,12 +15,15 @@
 */
 */
package com.android.keyguard
package com.android.keyguard


import android.app.NotificationManager.zenModeFromInterruptionFilter
import android.content.BroadcastReceiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentFilter
import android.content.res.Resources
import android.content.res.Resources
import android.os.Trace
import android.os.Trace
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
import android.provider.Settings.Global.ZEN_MODE_OFF
import android.text.format.DateFormat
import android.text.format.DateFormat
import android.util.Log
import android.util.Log
import android.util.TypedValue
import android.util.TypedValue
@@ -49,6 +52,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.core.Logger
import com.android.systemui.log.core.Logger
import com.android.systemui.modes.shared.ModesUi
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockFaceController
@@ -63,6 +67,7 @@ import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.Locale
import java.util.Locale
import java.util.TimeZone
import java.util.TimeZone
@@ -97,12 +102,13 @@ constructor(
    private val clockBuffers: ClockMessageBuffers,
    private val clockBuffers: ClockMessageBuffers,
    private val featureFlags: FeatureFlagsClassic,
    private val featureFlags: FeatureFlagsClassic,
    private val zenModeController: ZenModeController,
    private val zenModeController: ZenModeController,
    private val zenModeInteractor: ZenModeInteractor,
) {
) {
    var loggers =
    var loggers =
        listOf(
        listOf(
                clockBuffers.infraMessageBuffer,
                clockBuffers.infraMessageBuffer,
                clockBuffers.smallClockMessageBuffer,
                clockBuffers.smallClockMessageBuffer,
                clockBuffers.largeClockMessageBuffer
                clockBuffers.largeClockMessageBuffer,
            )
            )
            .map { Logger(it, TAG) }
            .map { Logger(it, TAG) }


@@ -146,7 +152,7 @@ constructor(
                        bgExecutor,
                        bgExecutor,
                        regionSamplingEnabled,
                        regionSamplingEnabled,
                        isLockscreen = true,
                        isLockscreen = true,
                        ::updateColors
                        ::updateColors,
                    )
                    )
                    .apply { startRegionSampler() }
                    .apply { startRegionSampler() }


@@ -157,7 +163,7 @@ constructor(
                        bgExecutor,
                        bgExecutor,
                        regionSamplingEnabled,
                        regionSamplingEnabled,
                        isLockscreen = true,
                        isLockscreen = true,
                        ::updateColors
                        ::updateColors,
                    )
                    )
                    .apply { startRegionSampler() }
                    .apply { startRegionSampler() }


@@ -271,7 +277,7 @@ constructor(
        bgExecutor: Executor?,
        bgExecutor: Executor?,
        regionSamplingEnabled: Boolean,
        regionSamplingEnabled: Boolean,
        isLockscreen: Boolean,
        isLockscreen: Boolean,
        updateColors: () -> Unit
        updateColors: () -> Unit,
    ): RegionSampler {
    ): RegionSampler {
        return RegionSampler(
        return RegionSampler(
            sampledView,
            sampledView,
@@ -384,23 +390,29 @@ constructor(
            }
            }
        }
        }


    @VisibleForTesting
    internal fun listenForDnd(scope: CoroutineScope): Job {
        ModesUi.assertInNewMode()
        return scope.launch {
            zenModeInteractor.dndMode.collect {
                val zenMode =
                    if (it != null && it.isActive)
                        zenModeFromInterruptionFilter(
                            it.interruptionFilter,
                            ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                        )
                    else ZEN_MODE_OFF

                handleZenMode(zenMode)
            }
        }
    }

    private val zenModeCallback =
    private val zenModeCallback =
        object : ZenModeController.Callback {
        object : ZenModeController.Callback {
            override fun onZenChanged(zen: Int) {
            override fun onZenChanged(zen: Int) {
                var mode = ZenMode.fromInt(zen)
                if (!ModesUi.isEnabled) {
                if (mode == null) {
                    handleZenMode(zen)
                    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) } }
                }
                }
            }
            }


@@ -409,7 +421,7 @@ constructor(
                alarmData =
                alarmData =
                    AlarmData(
                    AlarmData(
                            if (nextAlarmMillis > 0) nextAlarmMillis else null,
                            if (nextAlarmMillis > 0) nextAlarmMillis else null,
                            SysuiR.string::status_bar_alarm.name
                            SysuiR.string::status_bar_alarm.name,
                        )
                        )
                        .also { data ->
                        .also { data ->
                            mainExecutor.execute { clock?.run { events.onAlarmDataChanged(data) } }
                            mainExecutor.execute { clock?.run { events.onAlarmDataChanged(data) } }
@@ -417,6 +429,24 @@ constructor(
            }
            }
        }
        }


    private fun handleZenMode(zen: Int) {
        val 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) } }
                }
    }

    fun registerListeners(parent: View) {
    fun registerListeners(parent: View) {
        if (isRegistered) {
        if (isRegistered) {
            return
            return
@@ -424,7 +454,7 @@ constructor(
        isRegistered = true
        isRegistered = true
        broadcastDispatcher.registerReceiver(
        broadcastDispatcher.registerReceiver(
            localeBroadcastReceiver,
            localeBroadcastReceiver,
            IntentFilter(Intent.ACTION_LOCALE_CHANGED)
            IntentFilter(Intent.ACTION_LOCALE_CHANGED),
        )
        )
        configurationController.addCallback(configListener)
        configurationController.addCallback(configListener)
        batteryController.addCallback(batteryCallback)
        batteryController.addCallback(batteryCallback)
@@ -434,6 +464,9 @@ constructor(
            parent.repeatWhenAttached {
            parent.repeatWhenAttached {
                repeatOnLifecycle(Lifecycle.State.CREATED) {
                repeatOnLifecycle(Lifecycle.State.CREATED) {
                    listenForDozing(this)
                    listenForDozing(this)
                    if (ModesUi.isEnabled) {
                        listenForDnd(this)
                    }
                    if (MigrateClocksToBlueprint.isEnabled) {
                    if (MigrateClocksToBlueprint.isEnabled) {
                        listenForDozeAmountTransition(this)
                        listenForDozeAmountTransition(this)
                        listenForAnyStateToAodTransition(this)
                        listenForAnyStateToAodTransition(this)
@@ -449,7 +482,9 @@ constructor(


        bgExecutor.execute {
        bgExecutor.execute {
            // Query ZenMode data
            // Query ZenMode data
            if (!ModesUi.isEnabled) {
                zenModeCallback.onZenChanged(zenModeController.zen)
                zenModeCallback.onZenChanged(zenModeController.zen)
            }
            zenModeCallback.onNextAlarmChanged()
            zenModeCallback.onNextAlarmChanged()
        }
        }
    }
    }
@@ -605,10 +640,9 @@ constructor(
    @VisibleForTesting
    @VisibleForTesting
    internal fun listenForDozing(scope: CoroutineScope): Job {
    internal fun listenForDozing(scope: CoroutineScope): Job {
        return scope.launch {
        return scope.launch {
            combine(
            combine(keyguardInteractor.dozeAmount, keyguardInteractor.isDozing) {
                    keyguardInteractor.dozeAmount,
                    localDozeAmount,
                    keyguardInteractor.isDozing,
                    localIsDozing ->
                ) { localDozeAmount, localIsDozing ->
                    localDozeAmount > dozeAmount || localIsDozing
                    localDozeAmount > dozeAmount || localIsDozing
                }
                }
                .collect { localIsDozing -> isDozing = localIsDozing }
                .collect { localIsDozing -> isDozing = localIsDozing }
+95 −27
Original line number Original line Diff line number Diff line
@@ -17,11 +17,16 @@ package com.android.keyguard


import android.content.BroadcastReceiver
import android.content.BroadcastReceiver
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import android.view.View
import android.view.View
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import android.widget.FrameLayout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.modes.TestModeBuilder.MANUAL_DND_ACTIVE
import com.android.settingslib.notification.modes.TestModeBuilder.MANUAL_DND_INACTIVE
import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.flags.Flags
import com.android.systemui.flags.Flags
@@ -36,6 +41,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.core.LogcatOnlyMessageBuffer
import com.android.systemui.log.core.LogcatOnlyMessageBuffer
import com.android.systemui.plugins.clocks.ClockAnimations
import com.android.systemui.plugins.clocks.ClockAnimations
@@ -46,9 +52,15 @@ import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.plugins.clocks.ClockFaceEvents
import com.android.systemui.plugins.clocks.ClockFaceEvents
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockTickRate
import com.android.systemui.plugins.clocks.ClockTickRate
import com.android.systemui.plugins.clocks.ZenData
import com.android.systemui.plugins.clocks.ZenData.ZenMode
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.argumentCaptor
@@ -57,9 +69,12 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.mock
import java.util.TimeZone
import java.util.TimeZone
import java.util.concurrent.Executor
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import kotlinx.coroutines.yield
import org.junit.Assert.assertEquals
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Before
@@ -73,15 +88,26 @@ import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import com.android.systemui.Flags as AConfigFlags
import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit


@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
@SmallTest
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
class ClockEventControllerTest : SysuiTestCase() {
class ClockEventControllerTest : SysuiTestCase() {


    private val kosmos = testKosmos()
    private val zenModeRepository = kosmos.fakeZenModeRepository
    private val testScope = kosmos.testScope

    @JvmField @Rule val mockito = MockitoJUnit.rule()
    @JvmField @Rule val mockito = MockitoJUnit.rule()

    private val mainExecutor = ImmediateExecutor()
    private lateinit var repository: FakeKeyguardRepository
    private val messageBuffer = LogcatOnlyMessageBuffer(LogLevel.DEBUG)
    private val clockBuffers = ClockMessageBuffers(messageBuffer, messageBuffer, messageBuffer)
    private lateinit var underTest: ClockEventController

    @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
    @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
    @Mock private lateinit var batteryController: BatteryController
    @Mock private lateinit var batteryController: BatteryController
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@@ -89,7 +115,6 @@ class ClockEventControllerTest : SysuiTestCase() {
    @Mock private lateinit var animations: ClockAnimations
    @Mock private lateinit var animations: ClockAnimations
    @Mock private lateinit var events: ClockEvents
    @Mock private lateinit var events: ClockEvents
    @Mock private lateinit var clock: ClockController
    @Mock private lateinit var clock: ClockController
    @Mock private lateinit var mainExecutor: DelayableExecutor
    @Mock private lateinit var bgExecutor: Executor
    @Mock private lateinit var bgExecutor: Executor
    @Mock private lateinit var smallClockController: ClockFaceController
    @Mock private lateinit var smallClockController: ClockFaceController
    @Mock private lateinit var smallClockView: View
    @Mock private lateinit var smallClockView: View
@@ -102,12 +127,10 @@ class ClockEventControllerTest : SysuiTestCase() {
    @Mock private lateinit var smallClockEvents: ClockFaceEvents
    @Mock private lateinit var smallClockEvents: ClockFaceEvents
    @Mock private lateinit var largeClockEvents: ClockFaceEvents
    @Mock private lateinit var largeClockEvents: ClockFaceEvents
    @Mock private lateinit var parentView: View
    @Mock private lateinit var parentView: View
    private lateinit var repository: FakeKeyguardRepository
    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    private val messageBuffer = LogcatOnlyMessageBuffer(LogLevel.DEBUG)

    private val clockBuffers = ClockMessageBuffers(messageBuffer, messageBuffer, messageBuffer)
    private lateinit var underTest: ClockEventController
    @Mock private lateinit var zenModeController: ZenModeController
    @Mock private lateinit var zenModeController: ZenModeController
    private var zenModeControllerCallback: ZenModeController.Callback? = null


    @Before
    @Before
    fun setUp() {
    fun setUp() {
@@ -129,12 +152,11 @@ class ClockEventControllerTest : SysuiTestCase() {
        whenever(largeClockController.config)
        whenever(largeClockController.config)
            .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE))
            .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE))


        zenModeRepository.addMode(MANUAL_DND_INACTIVE)

        repository = FakeKeyguardRepository()
        repository = FakeKeyguardRepository()


        val withDeps =
        val withDeps = KeyguardInteractorFactory.create(repository = repository)
            KeyguardInteractorFactory.create(
                repository = repository,
            )


        withDeps.featureFlags.apply { set(Flags.REGION_SAMPLING, false) }
        withDeps.featureFlags.apply { set(Flags.REGION_SAMPLING, false) }
        underTest =
        underTest =
@@ -151,7 +173,8 @@ class ClockEventControllerTest : SysuiTestCase() {
                bgExecutor,
                bgExecutor,
                clockBuffers,
                clockBuffers,
                withDeps.featureFlags,
                withDeps.featureFlags,
                zenModeController
                zenModeController,
                kosmos.zenModeInteractor,
            )
            )
        underTest.clock = clock
        underTest.clock = clock


@@ -161,6 +184,10 @@ class ClockEventControllerTest : SysuiTestCase() {
            repository.setIsDozing(true)
            repository.setIsDozing(true)
            repository.setDozeAmount(1f)
            repository.setDozeAmount(1f)
        }
        }

        val zenCallbackCaptor = argumentCaptor<ZenModeController.Callback>()
        verify(zenModeController).addCallback(zenCallbackCaptor.capture())
        zenModeControllerCallback = zenCallbackCaptor.value
    }
    }


    @Test
    @Test
@@ -349,17 +376,12 @@ class ClockEventControllerTest : SysuiTestCase() {
    fun listenForTransitionToAodFromGone_updatesClockDozeAmountToOne() =
    fun listenForTransitionToAodFromGone_updatesClockDozeAmountToOne() =
        runBlocking(IMMEDIATE) {
        runBlocking(IMMEDIATE) {
            val transitionStep = MutableStateFlow(TransitionStep())
            val transitionStep = MutableStateFlow(TransitionStep())
            whenever(keyguardTransitionInteractor
            whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD)))
                .transition(Edge.create(to = AOD)))
                .thenReturn(transitionStep)
                .thenReturn(transitionStep)


            val job = underTest.listenForAnyStateToAodTransition(this)
            val job = underTest.listenForAnyStateToAodTransition(this)
            transitionStep.value =
            transitionStep.value =
                TransitionStep(
                TransitionStep(from = GONE, to = AOD, transitionState = TransitionState.STARTED)
                    from = GONE,
                    to = AOD,
                    transitionState = TransitionState.STARTED,
                )
            yield()
            yield()


            verify(animations, times(2)).doze(1f)
            verify(animations, times(2)).doze(1f)
@@ -371,8 +393,7 @@ class ClockEventControllerTest : SysuiTestCase() {
    fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToZero() =
    fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToZero() =
        runBlocking(IMMEDIATE) {
        runBlocking(IMMEDIATE) {
            val transitionStep = MutableStateFlow(TransitionStep())
            val transitionStep = MutableStateFlow(TransitionStep())
            whenever(keyguardTransitionInteractor
            whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN)))
                .transition(Edge.create(to = LOCKSCREEN)))
                .thenReturn(transitionStep)
                .thenReturn(transitionStep)


            val job = underTest.listenForAnyStateToLockscreenTransition(this)
            val job = underTest.listenForAnyStateToLockscreenTransition(this)
@@ -393,8 +414,7 @@ class ClockEventControllerTest : SysuiTestCase() {
    fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() =
    fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() =
        runBlocking(IMMEDIATE) {
        runBlocking(IMMEDIATE) {
            val transitionStep = MutableStateFlow(TransitionStep())
            val transitionStep = MutableStateFlow(TransitionStep())
            whenever(keyguardTransitionInteractor
            whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD)))
                .transition(Edge.create(to = AOD)))
                .thenReturn(transitionStep)
                .thenReturn(transitionStep)


            val job = underTest.listenForAnyStateToAodTransition(this)
            val job = underTest.listenForAnyStateToAodTransition(this)
@@ -415,8 +435,7 @@ class ClockEventControllerTest : SysuiTestCase() {
    fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() =
    fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() =
        runBlocking(IMMEDIATE) {
        runBlocking(IMMEDIATE) {
            val transitionStep = MutableStateFlow(TransitionStep())
            val transitionStep = MutableStateFlow(TransitionStep())
            whenever(keyguardTransitionInteractor
            whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN)))
                .transition(Edge.create(to = LOCKSCREEN)))
                .thenReturn(transitionStep)
                .thenReturn(transitionStep)


            val job = underTest.listenForAnyStateToLockscreenTransition(this)
            val job = underTest.listenForAnyStateToLockscreenTransition(this)
@@ -437,8 +456,7 @@ class ClockEventControllerTest : SysuiTestCase() {
    fun listenForAnyStateToDozingTransition_UpdatesClockDozeAmountToOne() =
    fun listenForAnyStateToDozingTransition_UpdatesClockDozeAmountToOne() =
        runBlocking(IMMEDIATE) {
        runBlocking(IMMEDIATE) {
            val transitionStep = MutableStateFlow(TransitionStep())
            val transitionStep = MutableStateFlow(TransitionStep())
            whenever(keyguardTransitionInteractor
            whenever(keyguardTransitionInteractor.transition(Edge.create(to = DOZING)))
                .transition(Edge.create(to = DOZING)))
                .thenReturn(transitionStep)
                .thenReturn(transitionStep)


            val job = underTest.listenForAnyStateToDozingTransition(this)
            val job = underTest.listenForAnyStateToDozingTransition(this)
@@ -498,7 +516,57 @@ class ClockEventControllerTest : SysuiTestCase() {
            verify(smallClockFrame.viewTreeObserver).removeOnGlobalLayoutListener(any())
            verify(smallClockFrame.viewTreeObserver).removeOnGlobalLayoutListener(any())
        }
        }


    @Test
    @EnableFlags(android.app.Flags.FLAG_MODES_UI)
    fun listenForDnd_onDndChange_updatesClockZenMode() =
        testScope.runTest {
            underTest.listenForDnd(testScope.backgroundScope)

            zenModeRepository.replaceMode(MANUAL_DND_INACTIVE.id, MANUAL_DND_ACTIVE)
            runCurrent()

            verify(events)
                .onZenDataChanged(
                    eq(ZenData(ZenMode.IMPORTANT_INTERRUPTIONS, R.string::dnd_is_on.name))
                )

            zenModeRepository.replaceMode(MANUAL_DND_ACTIVE.id, MANUAL_DND_INACTIVE)
            runCurrent()

            verify(events).onZenDataChanged(eq(ZenData(ZenMode.OFF, R.string::dnd_is_off.name)))
        }

    @Test
    @DisableFlags(android.app.Flags.FLAG_MODES_UI)
    fun zenModeControllerCallback_onDndChange_updatesClockZenMode() =
        runBlocking(IMMEDIATE) {
            zenModeControllerCallback!!.onZenChanged(
                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
            )

            verify(events)
                .onZenDataChanged(
                    eq(ZenData(ZenMode.IMPORTANT_INTERRUPTIONS, R.string::dnd_is_on.name))
                )

            zenModeControllerCallback!!.onZenChanged(Settings.Global.ZEN_MODE_OFF)

            verify(events).onZenDataChanged(eq(ZenData(ZenMode.OFF, R.string::dnd_is_off.name)))
        }

    companion object {
    companion object {
        private val IMMEDIATE = Dispatchers.Main.immediate
        private val IMMEDIATE = Dispatchers.Main.immediate
    }
    }
}
}

private class ImmediateExecutor : DelayableExecutor {
    override fun execute(runnable: Runnable) {
        runnable.run()
    }

    override fun executeDelayed(runnable: Runnable, delay: Long, unit: TimeUnit) =
        runnable.apply { run() }

    override fun executeAtTime(runnable: Runnable, uptimeMillis: Long, unit: TimeUnit) =
        runnable.apply { run() }
}