Add a 5 second timeout to launch animation touch blocking
This is a workaround for b/288507023, which is caused by launch animations hanging. It does not address the cause of the animation not completing, but it will allow users to resume interacting with their device after 5 seconds. Test: added unit test Test: simulated the bug with a temporary change and verified manually Bug: 288507023 Change-Id: I5c240a9ee852bf57e8ec251b733708086e825b45
This commit is contained in:
@@ -107,7 +107,14 @@ public class NotificationShadeWindowViewController {
|
|||||||
private boolean mTouchActive;
|
private boolean mTouchActive;
|
||||||
private boolean mTouchCancelled;
|
private boolean mTouchCancelled;
|
||||||
private MotionEvent mDownEvent;
|
private MotionEvent mDownEvent;
|
||||||
|
// TODO rename to mLaunchAnimationRunning
|
||||||
private boolean mExpandAnimationRunning;
|
private boolean mExpandAnimationRunning;
|
||||||
|
/**
|
||||||
|
* When mExpandAnimationRunning is true and the touch dispatcher receives a down even after
|
||||||
|
* uptime exceeds this, the dispatcher will stop blocking touches for the launch animation,
|
||||||
|
* which has presumabely not completed due to an error.
|
||||||
|
*/
|
||||||
|
private long mLaunchAnimationTimeout;
|
||||||
private NotificationStackScrollLayout mStackScrollLayout;
|
private NotificationStackScrollLayout mStackScrollLayout;
|
||||||
private PhoneStatusBarViewController mStatusBarViewController;
|
private PhoneStatusBarViewController mStatusBarViewController;
|
||||||
private final CentralSurfaces mService;
|
private final CentralSurfaces mService;
|
||||||
@@ -280,8 +287,13 @@ public class NotificationShadeWindowViewController {
|
|||||||
return logDownDispatch(ev, "touch cancelled", false);
|
return logDownDispatch(ev, "touch cancelled", false);
|
||||||
}
|
}
|
||||||
if (mExpandAnimationRunning) {
|
if (mExpandAnimationRunning) {
|
||||||
|
if (isDown && mClock.uptimeMillis() > mLaunchAnimationTimeout) {
|
||||||
|
mShadeLogger.d("NSWVC: launch animation timed out");
|
||||||
|
setExpandAnimationRunning(false);
|
||||||
|
} else {
|
||||||
return logDownDispatch(ev, "expand animation running", false);
|
return logDownDispatch(ev, "expand animation running", false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
|
if (mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
|
||||||
// If the user was sliding their finger across the lock screen,
|
// If the user was sliding their finger across the lock screen,
|
||||||
@@ -530,8 +542,12 @@ public class NotificationShadeWindowViewController {
|
|||||||
pw.println(mTouchActive);
|
pw.println(mTouchActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setExpandAnimationRunning(boolean running) {
|
@VisibleForTesting
|
||||||
|
void setExpandAnimationRunning(boolean running) {
|
||||||
if (mExpandAnimationRunning != running) {
|
if (mExpandAnimationRunning != running) {
|
||||||
|
if (running) {
|
||||||
|
mLaunchAnimationTimeout = mClock.uptimeMillis() + 5000;
|
||||||
|
}
|
||||||
mExpandAnimationRunning = running;
|
mExpandAnimationRunning = running;
|
||||||
mNotificationShadeWindowController.setLaunchingActivity(mExpandAnimationRunning);
|
mNotificationShadeWindowController.setLaunchingActivity(mExpandAnimationRunning);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
@Mock lateinit var keyEventInteractor: KeyEventInteractor
|
@Mock lateinit var keyEventInteractor: KeyEventInteractor
|
||||||
private val notificationExpansionRepository = NotificationExpansionRepository()
|
private val notificationExpansionRepository = NotificationExpansionRepository()
|
||||||
|
|
||||||
|
private lateinit var fakeClock: FakeSystemClock
|
||||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||||
private lateinit var interactionEventHandler: InteractionEventHandler
|
private lateinit var interactionEventHandler: InteractionEventHandler
|
||||||
|
|
||||||
@@ -151,6 +152,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
|
featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
|
||||||
|
|
||||||
testScope = TestScope()
|
testScope = TestScope()
|
||||||
|
fakeClock = FakeSystemClock()
|
||||||
underTest =
|
underTest =
|
||||||
NotificationShadeWindowViewController(
|
NotificationShadeWindowViewController(
|
||||||
lockscreenShadeTransitionController,
|
lockscreenShadeTransitionController,
|
||||||
@@ -183,7 +185,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
primaryBouncerToGoneTransitionViewModel,
|
primaryBouncerToGoneTransitionViewModel,
|
||||||
notificationExpansionRepository,
|
notificationExpansionRepository,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
FakeSystemClock(),
|
fakeClock,
|
||||||
BouncerMessageInteractor(
|
BouncerMessageInteractor(
|
||||||
FakeBouncerMessageRepository(),
|
FakeBouncerMessageRepository(),
|
||||||
mock(BouncerMessageFactory::class.java),
|
mock(BouncerMessageFactory::class.java),
|
||||||
@@ -331,6 +333,33 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
assertThat(returnVal).isTrue()
|
assertThat(returnVal).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleDispatchTouchEvent_launchAnimationRunningTimesOut() =
|
||||||
|
testScope.runTest {
|
||||||
|
// GIVEN touch dispatcher in a state that returns true
|
||||||
|
underTest.setStatusBarViewController(phoneStatusBarViewController)
|
||||||
|
whenever(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()).thenReturn(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
assertThat(interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)).isTrue()
|
||||||
|
|
||||||
|
// WHEN launch animation is running for 2 seconds
|
||||||
|
fakeClock.setUptimeMillis(10000)
|
||||||
|
underTest.setExpandAnimationRunning(true)
|
||||||
|
fakeClock.advanceTime(2000)
|
||||||
|
|
||||||
|
// THEN touch is ignored
|
||||||
|
assertThat(interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)).isFalse()
|
||||||
|
|
||||||
|
// WHEN Launch animation is running for 6 seconds
|
||||||
|
fakeClock.advanceTime(4000)
|
||||||
|
|
||||||
|
// THEN move is ignored, down is handled, and window is notified
|
||||||
|
assertThat(interactionEventHandler.handleDispatchTouchEvent(MOVE_EVENT)).isFalse()
|
||||||
|
assertThat(interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)).isTrue()
|
||||||
|
verify(notificationShadeWindowController).setLaunchingActivity(false)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() {
|
fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() {
|
||||||
// down event should be intercepted by keyguardViewManager
|
// down event should be intercepted by keyguardViewManager
|
||||||
@@ -372,6 +401,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||||
|
private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||||
private const val VIEW_BOTTOM = 100
|
private const val VIEW_BOTTOM = 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user