diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-01-26 21:39:59 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-01-26 21:39:59 +0000 |
commit | 5ce74ca4688558052279299f13ed8cc45d87c2a4 (patch) | |
tree | a152eac4176e5d71341d4fea7483bac8c7aa5b7d | |
parent | 4e0b08b5c1ab83d01ea08a51409d3b95bc640beb (diff) | |
parent | 955d37e6d7f8868d50154d47f12fec340d380ae6 (diff) | |
download | base-5ce74ca4688558052279299f13ed8cc45d87c2a4.tar.gz |
Merge cherrypicks of [16691349] into sc-v2-release.
Change-Id: Ic38459ae48b114728380cc232acb7d9082d9be8b
2 files changed, 96 insertions, 9 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index 83ab8cb80b29..4ba794fe8408 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -6,6 +6,7 @@ import android.animation.ValueAnimator import android.content.Context import android.database.ContentObserver import android.os.Handler +import android.os.PowerManager import android.provider.Settings import android.view.Surface import android.view.View @@ -50,9 +51,10 @@ class UnlockedScreenOffAnimationController @Inject constructor( private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>, private val keyguardStateController: KeyguardStateController, private val dozeParameters: dagger.Lazy<DozeParameters>, - private val globalSettings: GlobalSettings + private val globalSettings: GlobalSettings, + private val powerManager: PowerManager, + private val handler: Handler = Handler() ) : WakefulnessLifecycle.Observer { - private val handler = Handler() private lateinit var statusBar: StatusBar private lateinit var lightRevealScrim: LightRevealScrim @@ -205,10 +207,18 @@ class UnlockedScreenOffAnimationController @Inject constructor( lightRevealAnimationPlaying = true lightRevealAnimator.start() handler.postDelayed({ - aodUiAnimationPlaying = true - - // Show AOD. That'll cause the KeyguardVisibilityHelper to call #animateInKeyguard. - statusBar.notificationPanelViewController.showAodUi() + // Only run this callback if the device is sleeping (not interactive). This callback + // is removed in onStartedWakingUp, but since that event is asynchronously + // dispatched, a race condition could make it possible for this callback to be run + // as the device is waking up. That results in the AOD UI being shown while we wake + // up, with unpredictable consequences. + if (!powerManager.isInteractive) { + aodUiAnimationPlaying = true + + // Show AOD. That'll cause the KeyguardVisibilityHelper to call + // #animateInKeyguard. + statusBar.notificationPanelViewController.showAodUi() + } }, (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong()) } else { decidedToAnimateGoingToSleep = false diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt index a8a33dabf1aa..fb8c9858be0b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.phone import android.animation.Animator +import android.os.Handler +import android.os.PowerManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.View @@ -28,13 +30,20 @@ import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.StatusBarStateControllerImpl import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.settings.GlobalSettings +import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito +import org.mockito.Mockito.`when` +import org.mockito.Mockito.anyLong +import org.mockito.Mockito.mockingDetails +import org.mockito.Mockito.never import org.mockito.Mockito.spy +import org.mockito.Mockito.times +import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest @@ -52,13 +61,19 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var globalSettings: GlobalSettings @Mock - private lateinit var statusbar: StatusBar + private lateinit var statusBar: StatusBar + @Mock + private lateinit var notificationPanelViewController: NotificationPanelViewController @Mock private lateinit var lightRevealScrim: LightRevealScrim @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var statusBarStateController: StatusBarStateControllerImpl + @Mock + private lateinit var powerManager: PowerManager + @Mock + private lateinit var handler: Handler @Before fun setUp() { @@ -71,9 +86,24 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator }, keyguardStateController, dagger.Lazy<DozeParameters> { dozeParameters }, - globalSettings + globalSettings, + powerManager, + handler = handler ) - controller.initialize(statusbar, lightRevealScrim) + controller.initialize(statusBar, lightRevealScrim) + `when`(statusBar.notificationPanelViewController).thenReturn( + notificationPanelViewController) + + // Screen off does not run if the panel is expanded, so we should say it's collapsed to test + // screen off. + `when`(notificationPanelViewController.isFullyCollapsed).thenReturn(true) + } + + @After + fun cleanUp() { + // Tell the screen off controller to cancel the animations and clean up its state, or + // subsequent tests will act unpredictably as the animator continues running. + controller.onStartedWakingUp() } @Test @@ -89,4 +119,51 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { listener.value.onAnimationEnd(null) Mockito.verify(animator).setListener(null) } + + /** + * The AOD UI is shown during the screen off animation, after a delay to allow the light reveal + * animation to start. If the device is woken up during the screen off, we should *never* do + * this. + * + * This test confirms that we do show the AOD UI when the device is not woken up + * (PowerManager#isInteractive = false). + */ + @Test + fun testAodUiShownIfNotInteractive() { + `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true) + `when`(powerManager.isInteractive).thenReturn(false) + + val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) + controller.onStartedGoingToSleep() + + verify(handler).postDelayed(callbackCaptor.capture(), anyLong()) + + callbackCaptor.value.run() + + verify(notificationPanelViewController, times(1)).showAodUi() + } + + /** + * The AOD UI is shown during the screen off animation, after a delay to allow the light reveal + * animation to start. If the device is woken up during the screen off, we should *never* do + * this. + * + * This test confirms that we do not show the AOD UI when the device is woken up during screen + * off (PowerManager#isInteractive = true). + */ + @Test + fun testAodUiNotShownIfInteractive() { + `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true) + `when`(powerManager.isInteractive).thenReturn(true) + + val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) + controller.onStartedGoingToSleep() + + mockingDetails(handler).printInvocations() + + verify(handler).postDelayed(callbackCaptor.capture(), anyLong()) + callbackCaptor.value.run() + + verify(notificationPanelViewController, never()).showAodUi() + } }
\ No newline at end of file |