Loading packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt +4 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,10 @@ class FakeZenModeRepository : ZenModeRepository { 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? { return mutableModesFlow.value.find { it.id == id } } Loading packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +59 −25 Original line number Diff line number Diff line Loading @@ -15,12 +15,15 @@ */ package com.android.keyguard import android.app.NotificationManager.zenModeFromInterruptionFilter import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources 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.util.Log import android.util.TypedValue Loading Loading @@ -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.lifecycle.repeatWhenAttached 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.ClockController import com.android.systemui.plugins.clocks.ClockFaceController Loading @@ -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.ConfigurationController import com.android.systemui.statusbar.policy.ZenModeController import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor import com.android.systemui.util.concurrency.DelayableExecutor import java.util.Locale import java.util.TimeZone Loading Loading @@ -97,12 +102,13 @@ constructor( private val clockBuffers: ClockMessageBuffers, private val featureFlags: FeatureFlagsClassic, private val zenModeController: ZenModeController, private val zenModeInteractor: ZenModeInteractor, ) { var loggers = listOf( clockBuffers.infraMessageBuffer, clockBuffers.smallClockMessageBuffer, clockBuffers.largeClockMessageBuffer clockBuffers.largeClockMessageBuffer, ) .map { Logger(it, TAG) } Loading Loading @@ -146,7 +152,7 @@ constructor( bgExecutor, regionSamplingEnabled, isLockscreen = true, ::updateColors ::updateColors, ) .apply { startRegionSampler() } Loading @@ -157,7 +163,7 @@ constructor( bgExecutor, regionSamplingEnabled, isLockscreen = true, ::updateColors ::updateColors, ) .apply { startRegionSampler() } Loading Loading @@ -271,7 +277,7 @@ constructor( bgExecutor: Executor?, regionSamplingEnabled: Boolean, isLockscreen: Boolean, updateColors: () -> Unit updateColors: () -> Unit, ): RegionSampler { return RegionSampler( sampledView, Loading Loading @@ -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 = 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) } } if (!ModesUi.isEnabled) { handleZenMode(zen) } } Loading @@ -409,7 +421,7 @@ constructor( alarmData = AlarmData( if (nextAlarmMillis > 0) nextAlarmMillis else null, SysuiR.string::status_bar_alarm.name SysuiR.string::status_bar_alarm.name, ) .also { data -> mainExecutor.execute { clock?.run { events.onAlarmDataChanged(data) } } Loading @@ -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) { if (isRegistered) { return Loading @@ -424,7 +454,7 @@ constructor( isRegistered = true broadcastDispatcher.registerReceiver( localeBroadcastReceiver, IntentFilter(Intent.ACTION_LOCALE_CHANGED) IntentFilter(Intent.ACTION_LOCALE_CHANGED), ) configurationController.addCallback(configListener) batteryController.addCallback(batteryCallback) Loading @@ -434,6 +464,9 @@ constructor( parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { listenForDozing(this) if (ModesUi.isEnabled) { listenForDnd(this) } if (MigrateClocksToBlueprint.isEnabled) { listenForDozeAmountTransition(this) listenForAnyStateToAodTransition(this) Loading @@ -449,7 +482,9 @@ constructor( bgExecutor.execute { // Query ZenMode data if (!ModesUi.isEnabled) { zenModeCallback.onZenChanged(zenModeController.zen) } zenModeCallback.onNextAlarmChanged() } } Loading Loading @@ -605,10 +640,9 @@ constructor( @VisibleForTesting internal fun listenForDozing(scope: CoroutineScope): Job { return scope.launch { combine( keyguardInteractor.dozeAmount, keyguardInteractor.isDozing, ) { localDozeAmount, localIsDozing -> combine(keyguardInteractor.dozeAmount, keyguardInteractor.isDozing) { localDozeAmount, localIsDozing -> localDozeAmount > dozeAmount || localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } Loading packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +95 −27 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package com.android.keyguard import android.content.BroadcastReceiver import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.view.View import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.test.ext.junit.runners.AndroidJUnit4 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.broadcast.BroadcastDispatcher import com.android.systemui.flags.Flags Loading @@ -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.TransitionState 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.LogcatOnlyMessageBuffer import com.android.systemui.plugins.clocks.ClockAnimations Loading @@ -46,9 +52,15 @@ import com.android.systemui.plugins.clocks.ClockFaceController import com.android.systemui.plugins.clocks.ClockFaceEvents import com.android.systemui.plugins.clocks.ClockMessageBuffers 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.ConfigurationController 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.mockito.any import com.android.systemui.util.mockito.argumentCaptor Loading @@ -57,9 +69,12 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import java.util.TimeZone import java.util.concurrent.Executor import java.util.concurrent.TimeUnit import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.yield import org.junit.Assert.assertEquals import org.junit.Before Loading @@ -73,15 +88,26 @@ import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.times 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.junit.MockitoJUnit @RunWith(AndroidJUnit4::class) @SmallTest @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) class ClockEventControllerTest : SysuiTestCase() { private val kosmos = testKosmos() private val zenModeRepository = kosmos.fakeZenModeRepository private val testScope = kosmos.testScope @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 batteryController: BatteryController @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor Loading @@ -89,7 +115,6 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var animations: ClockAnimations @Mock private lateinit var events: ClockEvents @Mock private lateinit var clock: ClockController @Mock private lateinit var mainExecutor: DelayableExecutor @Mock private lateinit var bgExecutor: Executor @Mock private lateinit var smallClockController: ClockFaceController @Mock private lateinit var smallClockView: View Loading @@ -102,12 +127,10 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var smallClockEvents: ClockFaceEvents @Mock private lateinit var largeClockEvents: ClockFaceEvents @Mock private lateinit var parentView: View private lateinit var repository: FakeKeyguardRepository @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 private var zenModeControllerCallback: ZenModeController.Callback? = null @Before fun setUp() { Loading @@ -129,12 +152,11 @@ class ClockEventControllerTest : SysuiTestCase() { whenever(largeClockController.config) .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE)) zenModeRepository.addMode(MANUAL_DND_INACTIVE) repository = FakeKeyguardRepository() val withDeps = KeyguardInteractorFactory.create( repository = repository, ) val withDeps = KeyguardInteractorFactory.create(repository = repository) withDeps.featureFlags.apply { set(Flags.REGION_SAMPLING, false) } underTest = Loading @@ -151,7 +173,8 @@ class ClockEventControllerTest : SysuiTestCase() { bgExecutor, clockBuffers, withDeps.featureFlags, zenModeController zenModeController, kosmos.zenModeInteractor, ) underTest.clock = clock Loading @@ -161,6 +184,10 @@ class ClockEventControllerTest : SysuiTestCase() { repository.setIsDozing(true) repository.setDozeAmount(1f) } val zenCallbackCaptor = argumentCaptor<ZenModeController.Callback>() verify(zenModeController).addCallback(zenCallbackCaptor.capture()) zenModeControllerCallback = zenCallbackCaptor.value } @Test Loading Loading @@ -349,17 +376,12 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToAodFromGone_updatesClockDozeAmountToOne() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = AOD))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToAodTransition(this) transitionStep.value = TransitionStep( from = GONE, to = AOD, transitionState = TransitionState.STARTED, ) TransitionStep(from = GONE, to = AOD, transitionState = TransitionState.STARTED) yield() verify(animations, times(2)).doze(1f) Loading @@ -371,8 +393,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToZero() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = LOCKSCREEN))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToLockscreenTransition(this) Loading @@ -393,8 +414,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = AOD))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToAodTransition(this) Loading @@ -415,8 +435,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = LOCKSCREEN))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToLockscreenTransition(this) Loading @@ -437,8 +456,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForAnyStateToDozingTransition_UpdatesClockDozeAmountToOne() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = DOZING))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = DOZING))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToDozingTransition(this) Loading Loading @@ -498,7 +516,57 @@ class ClockEventControllerTest : SysuiTestCase() { 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 { 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() } } Loading
packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt +4 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,10 @@ class FakeZenModeRepository : ZenModeRepository { 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? { return mutableModesFlow.value.find { it.id == id } } Loading
packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +59 −25 Original line number Diff line number Diff line Loading @@ -15,12 +15,15 @@ */ package com.android.keyguard import android.app.NotificationManager.zenModeFromInterruptionFilter import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.res.Resources 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.util.Log import android.util.TypedValue Loading Loading @@ -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.lifecycle.repeatWhenAttached 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.ClockController import com.android.systemui.plugins.clocks.ClockFaceController Loading @@ -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.ConfigurationController import com.android.systemui.statusbar.policy.ZenModeController import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor import com.android.systemui.util.concurrency.DelayableExecutor import java.util.Locale import java.util.TimeZone Loading Loading @@ -97,12 +102,13 @@ constructor( private val clockBuffers: ClockMessageBuffers, private val featureFlags: FeatureFlagsClassic, private val zenModeController: ZenModeController, private val zenModeInteractor: ZenModeInteractor, ) { var loggers = listOf( clockBuffers.infraMessageBuffer, clockBuffers.smallClockMessageBuffer, clockBuffers.largeClockMessageBuffer clockBuffers.largeClockMessageBuffer, ) .map { Logger(it, TAG) } Loading Loading @@ -146,7 +152,7 @@ constructor( bgExecutor, regionSamplingEnabled, isLockscreen = true, ::updateColors ::updateColors, ) .apply { startRegionSampler() } Loading @@ -157,7 +163,7 @@ constructor( bgExecutor, regionSamplingEnabled, isLockscreen = true, ::updateColors ::updateColors, ) .apply { startRegionSampler() } Loading Loading @@ -271,7 +277,7 @@ constructor( bgExecutor: Executor?, regionSamplingEnabled: Boolean, isLockscreen: Boolean, updateColors: () -> Unit updateColors: () -> Unit, ): RegionSampler { return RegionSampler( sampledView, Loading Loading @@ -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 = 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) } } if (!ModesUi.isEnabled) { handleZenMode(zen) } } Loading @@ -409,7 +421,7 @@ constructor( alarmData = AlarmData( if (nextAlarmMillis > 0) nextAlarmMillis else null, SysuiR.string::status_bar_alarm.name SysuiR.string::status_bar_alarm.name, ) .also { data -> mainExecutor.execute { clock?.run { events.onAlarmDataChanged(data) } } Loading @@ -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) { if (isRegistered) { return Loading @@ -424,7 +454,7 @@ constructor( isRegistered = true broadcastDispatcher.registerReceiver( localeBroadcastReceiver, IntentFilter(Intent.ACTION_LOCALE_CHANGED) IntentFilter(Intent.ACTION_LOCALE_CHANGED), ) configurationController.addCallback(configListener) batteryController.addCallback(batteryCallback) Loading @@ -434,6 +464,9 @@ constructor( parent.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { listenForDozing(this) if (ModesUi.isEnabled) { listenForDnd(this) } if (MigrateClocksToBlueprint.isEnabled) { listenForDozeAmountTransition(this) listenForAnyStateToAodTransition(this) Loading @@ -449,7 +482,9 @@ constructor( bgExecutor.execute { // Query ZenMode data if (!ModesUi.isEnabled) { zenModeCallback.onZenChanged(zenModeController.zen) } zenModeCallback.onNextAlarmChanged() } } Loading Loading @@ -605,10 +640,9 @@ constructor( @VisibleForTesting internal fun listenForDozing(scope: CoroutineScope): Job { return scope.launch { combine( keyguardInteractor.dozeAmount, keyguardInteractor.isDozing, ) { localDozeAmount, localIsDozing -> combine(keyguardInteractor.dozeAmount, keyguardInteractor.isDozing) { localDozeAmount, localIsDozing -> localDozeAmount > dozeAmount || localIsDozing } .collect { localIsDozing -> isDozing = localIsDozing } Loading
packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +95 −27 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package com.android.keyguard import android.content.BroadcastReceiver import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.view.View import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.test.ext.junit.runners.AndroidJUnit4 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.broadcast.BroadcastDispatcher import com.android.systemui.flags.Flags Loading @@ -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.TransitionState 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.LogcatOnlyMessageBuffer import com.android.systemui.plugins.clocks.ClockAnimations Loading @@ -46,9 +52,15 @@ import com.android.systemui.plugins.clocks.ClockFaceController import com.android.systemui.plugins.clocks.ClockFaceEvents import com.android.systemui.plugins.clocks.ClockMessageBuffers 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.ConfigurationController 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.mockito.any import com.android.systemui.util.mockito.argumentCaptor Loading @@ -57,9 +69,12 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import java.util.TimeZone import java.util.concurrent.Executor import java.util.concurrent.TimeUnit import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.yield import org.junit.Assert.assertEquals import org.junit.Before Loading @@ -73,15 +88,26 @@ import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.times 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.junit.MockitoJUnit @RunWith(AndroidJUnit4::class) @SmallTest @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) class ClockEventControllerTest : SysuiTestCase() { private val kosmos = testKosmos() private val zenModeRepository = kosmos.fakeZenModeRepository private val testScope = kosmos.testScope @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 batteryController: BatteryController @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor Loading @@ -89,7 +115,6 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var animations: ClockAnimations @Mock private lateinit var events: ClockEvents @Mock private lateinit var clock: ClockController @Mock private lateinit var mainExecutor: DelayableExecutor @Mock private lateinit var bgExecutor: Executor @Mock private lateinit var smallClockController: ClockFaceController @Mock private lateinit var smallClockView: View Loading @@ -102,12 +127,10 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var smallClockEvents: ClockFaceEvents @Mock private lateinit var largeClockEvents: ClockFaceEvents @Mock private lateinit var parentView: View private lateinit var repository: FakeKeyguardRepository @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 private var zenModeControllerCallback: ZenModeController.Callback? = null @Before fun setUp() { Loading @@ -129,12 +152,11 @@ class ClockEventControllerTest : SysuiTestCase() { whenever(largeClockController.config) .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE)) zenModeRepository.addMode(MANUAL_DND_INACTIVE) repository = FakeKeyguardRepository() val withDeps = KeyguardInteractorFactory.create( repository = repository, ) val withDeps = KeyguardInteractorFactory.create(repository = repository) withDeps.featureFlags.apply { set(Flags.REGION_SAMPLING, false) } underTest = Loading @@ -151,7 +173,8 @@ class ClockEventControllerTest : SysuiTestCase() { bgExecutor, clockBuffers, withDeps.featureFlags, zenModeController zenModeController, kosmos.zenModeInteractor, ) underTest.clock = clock Loading @@ -161,6 +184,10 @@ class ClockEventControllerTest : SysuiTestCase() { repository.setIsDozing(true) repository.setDozeAmount(1f) } val zenCallbackCaptor = argumentCaptor<ZenModeController.Callback>() verify(zenModeController).addCallback(zenCallbackCaptor.capture()) zenModeControllerCallback = zenCallbackCaptor.value } @Test Loading Loading @@ -349,17 +376,12 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToAodFromGone_updatesClockDozeAmountToOne() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = AOD))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToAodTransition(this) transitionStep.value = TransitionStep( from = GONE, to = AOD, transitionState = TransitionState.STARTED, ) TransitionStep(from = GONE, to = AOD, transitionState = TransitionState.STARTED) yield() verify(animations, times(2)).doze(1f) Loading @@ -371,8 +393,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToLSFromOccluded_updatesClockDozeAmountToZero() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = LOCKSCREEN))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToLockscreenTransition(this) Loading @@ -393,8 +414,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForTransitionToAodFromLockscreen_neverUpdatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = AOD))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = AOD))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToAodTransition(this) Loading @@ -415,8 +435,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForAnyStateToLockscreenTransition_neverUpdatesClockDozeAmount() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = LOCKSCREEN))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = LOCKSCREEN))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToLockscreenTransition(this) Loading @@ -437,8 +456,7 @@ class ClockEventControllerTest : SysuiTestCase() { fun listenForAnyStateToDozingTransition_UpdatesClockDozeAmountToOne() = runBlocking(IMMEDIATE) { val transitionStep = MutableStateFlow(TransitionStep()) whenever(keyguardTransitionInteractor .transition(Edge.create(to = DOZING))) whenever(keyguardTransitionInteractor.transition(Edge.create(to = DOZING))) .thenReturn(transitionStep) val job = underTest.listenForAnyStateToDozingTransition(this) Loading Loading @@ -498,7 +516,57 @@ class ClockEventControllerTest : SysuiTestCase() { 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 { 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() } }