Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt +25 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,16 @@ package com.android.systemui.statusbar.phone import android.os.Handler import android.os.PowerManager import android.platform.test.annotations.RequiresFlagsEnabled import android.testing.TestableLooper.RunWithLooper import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.server.display.feature.flags.Flags as displayManagerFlags import com.android.server.power.feature.flags.Flags as powerManagerFlags import com.android.systemui.SysuiTestCase import com.android.systemui.display.domain.interactor.DisplayStateInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.shade.ShadeViewController Loading @@ -36,6 +40,7 @@ import com.android.systemui.testKosmos import com.android.systemui.util.mockito.eq import com.android.systemui.util.settings.GlobalSettings import junit.framework.Assert.assertFalse import kotlinx.coroutines.flow.MutableStateFlow import org.junit.After import org.junit.Before import org.junit.Test Loading Loading @@ -68,6 +73,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateControllerImpl @Mock private lateinit var interactionJankMonitor: InteractionJankMonitor @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var displayStateInteractor: DisplayStateInteractor @Mock private lateinit var handler: Handler val kosmos = testKosmos() Loading @@ -88,6 +94,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { powerManager, { shadeLockscreenInteractor }, { panelExpansionInteractor }, { displayStateInteractor }, handler, ) controller.initialize(centralSurfaces, shadeViewController, lightRevealScrim) Loading @@ -112,6 +119,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiShownIfNotInteractive() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -127,6 +135,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiShowNotInvokedIfWakingUp() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -151,6 +160,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiNotShownIfInteractive() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(true) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -166,6 +176,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive()).thenReturn(false) `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -184,4 +195,18 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { controller.startAnimation() assertFalse(controller.isAnimationPlaying()) } @RequiresFlagsEnabled( displayManagerFlags.FLAG_SEPARATE_TIMEOUTS, powerManagerFlags.FLAG_SEPARATE_TIMEOUTS_FLICKER, ) @Test fun testNoAnimationPlaying_whenDefaultDisplayIsOff() { `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(true)) `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) assertFalse(controller.shouldPlayUnlockedScreenOffAnimation()) controller.startAnimation() assertFalse(controller.isAnimationPlaying()) } } packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayStateInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ import kotlinx.coroutines.flow.stateIn /** Aggregates display state information. */ interface DisplayStateInteractor { /** Whether the default display is currently off. */ val isDefaultDisplayOff: Flow<Boolean> val isDefaultDisplayOff: StateFlow<Boolean> /** Whether the device is currently in rear display mode. */ val isInRearDisplayMode: StateFlow<Boolean> Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +11 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ import com.android.app.tracing.namedRunnable import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD import com.android.server.power.feature.flags.Flags as powerManagerFlags import com.android.systemui.DejankUtils import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.display.domain.interactor.DisplayStateInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.shade.ShadeViewController Loading Loading @@ -69,6 +71,7 @@ constructor( private val powerManager: PowerManager, private val shadeLockscreenInteractorLazy: Lazy<ShadeLockscreenInteractor>, private val panelExpansionInteractorLazy: Lazy<PanelExpansionInteractor>, private val displayStateInteractorLazy: Lazy<DisplayStateInteractor>, @Main private val handler: Handler, ) : WakefulnessLifecycle.Observer, ScreenOffAnimation { private lateinit var centralSurfaces: CentralSurfaces Loading Loading @@ -368,6 +371,14 @@ constructor( return false } // If this display is off, skip animation to reduce flickers. if ( powerManagerFlags.separateTimeoutsFlicker() && displayStateInteractorLazy.get().isDefaultDisplayOff.value ) { return false } // Otherwise, good to go. return true } Loading packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +2 −5 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.runBlocking import org.mockito.kotlin.mock Loading Loading @@ -126,9 +125,7 @@ class FakeDisplayRepository @Inject constructor() : DisplayRepository { override val pendingDisplay: Flow<PendingDisplay?> get() = pendingDisplayFlow private val _defaultDisplayOff: MutableStateFlow<Boolean> = MutableStateFlow(false) override val defaultDisplayOff: Flow<Boolean> get() = _defaultDisplayOff.asStateFlow() override val defaultDisplayOff = MutableStateFlow(false) override fun getDisplay(displayId: Int): Display? { return displays.value.find { it.displayId == displayId } Loading @@ -148,7 +145,7 @@ class FakeDisplayRepository @Inject constructor() : DisplayRepository { suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId) fun setDefaultDisplayOff(defaultDisplayOff: Boolean) { _defaultDisplayOff.value = defaultDisplayOff this.defaultDisplayOff.value = defaultDisplayOff } } Loading services/core/java/com/android/server/power/PowerGroup.java +10 −4 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ public class PowerGroup { // interactivity state private void updateScreenPolicyLocked(boolean quiescent, boolean dozeAfterScreenOff, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean brightWhenDozing) { boolean brightWhenDozing, boolean allAdjacentGroupsAreNonInteractive) { final int wakefulness = getWakefulnessLocked(); final int wakeLockSummary = getWakeLockSummaryLocked(); int policyReason = Display.STATE_REASON_DEFAULT_POLICY; Loading @@ -543,7 +543,12 @@ public class PowerGroup { } else if (wakefulness == WAKEFULNESS_DOZING) { if ((wakeLockSummary & WAKE_LOCK_DOZE) != 0) { policy = DisplayPowerRequest.POLICY_DOZE; } else if (dozeAfterScreenOff) { } else if (dozeAfterScreenOff || (mFeatureFlags.isSeparateTimeoutsFlickerEnabled() && allAdjacentGroupsAreNonInteractive && mGroupId == Display.DEFAULT_DISPLAY_GROUP)) { // If we force dozeAfterScreenOff or // if we have adjacent groups, but they are all non-interactive now, // then set policy to OFF instead to reduce flickers. policy = DisplayPowerRequest.POLICY_OFF; } else if (brightWhenDozing) { policy = DisplayPowerRequest.POLICY_BRIGHT; Loading Loading @@ -585,9 +590,10 @@ public class PowerGroup { PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean waitForNegativeProximity, boolean brightWhenDozing) { boolean brightWhenDozing, boolean allAdjacentGroupsAreNonInteractive) { updateScreenPolicyLocked(quiescent, dozeAfterScreenOff, bootCompleted, screenBrightnessBoostInProgress, brightWhenDozing); bootCompleted, screenBrightnessBoostInProgress, brightWhenDozing, allAdjacentGroupsAreNonInteractive); mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; mDisplayPowerRequest.screenBrightnessOverrideTag = overrideTag; mDisplayPowerRequest.useProximitySensor = useProximitySensor; Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt +25 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,16 @@ package com.android.systemui.statusbar.phone import android.os.Handler import android.os.PowerManager import android.platform.test.annotations.RequiresFlagsEnabled import android.testing.TestableLooper.RunWithLooper import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.server.display.feature.flags.Flags as displayManagerFlags import com.android.server.power.feature.flags.Flags as powerManagerFlags import com.android.systemui.SysuiTestCase import com.android.systemui.display.domain.interactor.DisplayStateInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.shade.ShadeViewController Loading @@ -36,6 +40,7 @@ import com.android.systemui.testKosmos import com.android.systemui.util.mockito.eq import com.android.systemui.util.settings.GlobalSettings import junit.framework.Assert.assertFalse import kotlinx.coroutines.flow.MutableStateFlow import org.junit.After import org.junit.Before import org.junit.Test Loading Loading @@ -68,6 +73,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateControllerImpl @Mock private lateinit var interactionJankMonitor: InteractionJankMonitor @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var displayStateInteractor: DisplayStateInteractor @Mock private lateinit var handler: Handler val kosmos = testKosmos() Loading @@ -88,6 +94,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { powerManager, { shadeLockscreenInteractor }, { panelExpansionInteractor }, { displayStateInteractor }, handler, ) controller.initialize(centralSurfaces, shadeViewController, lightRevealScrim) Loading @@ -112,6 +119,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiShownIfNotInteractive() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -127,6 +135,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiShowNotInvokedIfWakingUp() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -151,6 +160,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { fun testAodUiNotShownIfInteractive() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(true) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -166,6 +176,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive()).thenReturn(false) `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(false) `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(false)) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) controller.startAnimation() Loading @@ -184,4 +195,18 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { controller.startAnimation() assertFalse(controller.isAnimationPlaying()) } @RequiresFlagsEnabled( displayManagerFlags.FLAG_SEPARATE_TIMEOUTS, powerManagerFlags.FLAG_SEPARATE_TIMEOUTS_FLICKER, ) @Test fun testNoAnimationPlaying_whenDefaultDisplayIsOff() { `when`(displayStateInteractor.isDefaultDisplayOff).thenReturn(MutableStateFlow(true)) `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) assertFalse(controller.shouldPlayUnlockedScreenOffAnimation()) controller.startAnimation() assertFalse(controller.isAnimationPlaying()) } }
packages/SystemUI/src/com/android/systemui/display/domain/interactor/DisplayStateInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ import kotlinx.coroutines.flow.stateIn /** Aggregates display state information. */ interface DisplayStateInteractor { /** Whether the default display is currently off. */ val isDefaultDisplayOff: Flow<Boolean> val isDefaultDisplayOff: StateFlow<Boolean> /** Whether the device is currently in rear display mode. */ val isInRearDisplayMode: StateFlow<Boolean> Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +11 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ import com.android.app.tracing.namedRunnable import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD import com.android.server.power.feature.flags.Flags as powerManagerFlags import com.android.systemui.DejankUtils import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.display.domain.interactor.DisplayStateInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.shade.ShadeViewController Loading Loading @@ -69,6 +71,7 @@ constructor( private val powerManager: PowerManager, private val shadeLockscreenInteractorLazy: Lazy<ShadeLockscreenInteractor>, private val panelExpansionInteractorLazy: Lazy<PanelExpansionInteractor>, private val displayStateInteractorLazy: Lazy<DisplayStateInteractor>, @Main private val handler: Handler, ) : WakefulnessLifecycle.Observer, ScreenOffAnimation { private lateinit var centralSurfaces: CentralSurfaces Loading Loading @@ -368,6 +371,14 @@ constructor( return false } // If this display is off, skip animation to reduce flickers. if ( powerManagerFlags.separateTimeoutsFlicker() && displayStateInteractorLazy.get().isDefaultDisplayOff.value ) { return false } // Otherwise, good to go. return true } Loading
packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +2 −5 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.runBlocking import org.mockito.kotlin.mock Loading Loading @@ -126,9 +125,7 @@ class FakeDisplayRepository @Inject constructor() : DisplayRepository { override val pendingDisplay: Flow<PendingDisplay?> get() = pendingDisplayFlow private val _defaultDisplayOff: MutableStateFlow<Boolean> = MutableStateFlow(false) override val defaultDisplayOff: Flow<Boolean> get() = _defaultDisplayOff.asStateFlow() override val defaultDisplayOff = MutableStateFlow(false) override fun getDisplay(displayId: Int): Display? { return displays.value.find { it.displayId == displayId } Loading @@ -148,7 +145,7 @@ class FakeDisplayRepository @Inject constructor() : DisplayRepository { suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId) fun setDefaultDisplayOff(defaultDisplayOff: Boolean) { _defaultDisplayOff.value = defaultDisplayOff this.defaultDisplayOff.value = defaultDisplayOff } } Loading
services/core/java/com/android/server/power/PowerGroup.java +10 −4 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ public class PowerGroup { // interactivity state private void updateScreenPolicyLocked(boolean quiescent, boolean dozeAfterScreenOff, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean brightWhenDozing) { boolean brightWhenDozing, boolean allAdjacentGroupsAreNonInteractive) { final int wakefulness = getWakefulnessLocked(); final int wakeLockSummary = getWakeLockSummaryLocked(); int policyReason = Display.STATE_REASON_DEFAULT_POLICY; Loading @@ -543,7 +543,12 @@ public class PowerGroup { } else if (wakefulness == WAKEFULNESS_DOZING) { if ((wakeLockSummary & WAKE_LOCK_DOZE) != 0) { policy = DisplayPowerRequest.POLICY_DOZE; } else if (dozeAfterScreenOff) { } else if (dozeAfterScreenOff || (mFeatureFlags.isSeparateTimeoutsFlickerEnabled() && allAdjacentGroupsAreNonInteractive && mGroupId == Display.DEFAULT_DISPLAY_GROUP)) { // If we force dozeAfterScreenOff or // if we have adjacent groups, but they are all non-interactive now, // then set policy to OFF instead to reduce flickers. policy = DisplayPowerRequest.POLICY_OFF; } else if (brightWhenDozing) { policy = DisplayPowerRequest.POLICY_BRIGHT; Loading Loading @@ -585,9 +590,10 @@ public class PowerGroup { PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean waitForNegativeProximity, boolean brightWhenDozing) { boolean brightWhenDozing, boolean allAdjacentGroupsAreNonInteractive) { updateScreenPolicyLocked(quiescent, dozeAfterScreenOff, bootCompleted, screenBrightnessBoostInProgress, brightWhenDozing); bootCompleted, screenBrightnessBoostInProgress, brightWhenDozing, allAdjacentGroupsAreNonInteractive); mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; mDisplayPowerRequest.screenBrightnessOverrideTag = overrideTag; mDisplayPowerRequest.useProximitySensor = useProximitySensor; Loading