From 6e264abf4a393ff691c032026a9635acff1c8215 Mon Sep 17 00:00:00 2001 From: Justin Weir Date: Fri, 18 Aug 2023 09:33:00 -0400 Subject: 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 Merged-In: I5c240a9ee852bf57e8ec251b733708086e825b45 --- .../NotificationShadeWindowViewController.java | 17 +++++++++++- .../NotificationShadeWindowViewControllerTest.kt | 32 +++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 02360434344d..4260bd97759d 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -105,7 +105,14 @@ public class NotificationShadeWindowViewController { private boolean mTouchActive; private boolean mTouchCancelled; private MotionEvent mDownEvent; + // TODO rename to mLaunchAnimationRunning 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 PhoneStatusBarViewController mStatusBarViewController; private final CentralSurfaces mService; @@ -266,7 +273,12 @@ public class NotificationShadeWindowViewController { return logDownDispatch(ev, "touch cancelled", false); } if (mExpandAnimationRunning) { - return logDownDispatch(ev, "expand animation running", false); + if (isDown && mClock.uptimeMillis() > mLaunchAnimationTimeout) { + mShadeLogger.d("NSWVC: launch animation timed out"); + setExpandAnimationRunning(false); + } else { + return logDownDispatch(ev, "expand animation running", false); + } } if (mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { @@ -548,6 +560,9 @@ public class NotificationShadeWindowViewController { public void setExpandAnimationRunning(boolean running) { if (mExpandAnimationRunning != running) { + if (running) { + mLaunchAnimationTimeout = mClock.uptimeMillis() + 5000; + } mExpandAnimationRunning = running; mNotificationShadeWindowController.setLaunchingActivity(mExpandAnimationRunning); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index 7a41d7121dfa..8ef8324d07dc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -110,6 +110,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel + private lateinit var fakeClock: FakeSystemClock private lateinit var interactionEventHandlerCaptor: ArgumentCaptor private lateinit var interactionEventHandler: InteractionEventHandler @@ -148,6 +149,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { ), inputProxy = inputProxy, ) + fakeClock = FakeSystemClock() underTest = NotificationShadeWindowViewController( lockscreenShadeTransitionController, @@ -176,7 +178,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { primaryBouncerToGoneTransitionViewModel, featureFlags, { multiShadeInteractor }, - FakeSystemClock(), + fakeClock, { MultiShadeMotionEventInteractor( applicationContext = context, @@ -330,6 +332,33 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { 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 fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() { // down event should be intercepted by keyguardViewManager @@ -350,6 +379,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { companion object { 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 } } -- cgit v1.2.3-59-g8ed1b