Merge "Check that PowerManager#isInteractive is false before showing the AOD UI for screen off." into sc-v2-dev
This commit is contained in:
@@ -6,6 +6,7 @@ import android.animation.ValueAnimator
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.ContentObserver
|
import android.database.ContentObserver
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.os.PowerManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -50,9 +51,10 @@ class UnlockedScreenOffAnimationController @Inject constructor(
|
|||||||
private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>,
|
private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>,
|
||||||
private val keyguardStateController: KeyguardStateController,
|
private val keyguardStateController: KeyguardStateController,
|
||||||
private val dozeParameters: dagger.Lazy<DozeParameters>,
|
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 {
|
) : WakefulnessLifecycle.Observer {
|
||||||
private val handler = Handler()
|
|
||||||
|
|
||||||
private lateinit var statusBar: StatusBar
|
private lateinit var statusBar: StatusBar
|
||||||
private lateinit var lightRevealScrim: LightRevealScrim
|
private lateinit var lightRevealScrim: LightRevealScrim
|
||||||
@@ -205,10 +207,18 @@ class UnlockedScreenOffAnimationController @Inject constructor(
|
|||||||
lightRevealAnimationPlaying = true
|
lightRevealAnimationPlaying = true
|
||||||
lightRevealAnimator.start()
|
lightRevealAnimator.start()
|
||||||
handler.postDelayed({
|
handler.postDelayed({
|
||||||
aodUiAnimationPlaying = true
|
// 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.
|
// Show AOD. That'll cause the KeyguardVisibilityHelper to call
|
||||||
statusBar.notificationPanelViewController.showAodUi()
|
// #animateInKeyguard.
|
||||||
|
statusBar.notificationPanelViewController.showAodUi()
|
||||||
|
}
|
||||||
}, (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong())
|
}, (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong())
|
||||||
} else {
|
} else {
|
||||||
decidedToAnimateGoingToSleep = false
|
decidedToAnimateGoingToSleep = false
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package com.android.systemui.statusbar.phone
|
package com.android.systemui.statusbar.phone
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.PowerManager
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import android.view.View
|
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.StatusBarStateControllerImpl
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.settings.GlobalSettings
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito
|
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.spy
|
||||||
|
import org.mockito.Mockito.times
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -52,13 +61,19 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var globalSettings: GlobalSettings
|
private lateinit var globalSettings: GlobalSettings
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var statusbar: StatusBar
|
private lateinit var statusBar: StatusBar
|
||||||
|
@Mock
|
||||||
|
private lateinit var notificationPanelViewController: NotificationPanelViewController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var lightRevealScrim: LightRevealScrim
|
private lateinit var lightRevealScrim: LightRevealScrim
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var statusBarStateController: StatusBarStateControllerImpl
|
private lateinit var statusBarStateController: StatusBarStateControllerImpl
|
||||||
|
@Mock
|
||||||
|
private lateinit var powerManager: PowerManager
|
||||||
|
@Mock
|
||||||
|
private lateinit var handler: Handler
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -71,9 +86,24 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
|
|||||||
dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
|
dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
|
||||||
keyguardStateController,
|
keyguardStateController,
|
||||||
dagger.Lazy<DozeParameters> { dozeParameters },
|
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
|
@Test
|
||||||
@@ -89,4 +119,51 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
|
|||||||
listener.value.onAnimationEnd(null)
|
listener.value.onAnimationEnd(null)
|
||||||
Mockito.verify(animator).setListener(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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user