diff options
2 files changed, 49 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 802ed8069a69..798f2d586bab 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -107,7 +107,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; @@ -280,7 +287,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()) { @@ -530,8 +542,12 @@ public class NotificationShadeWindowViewController { pw.println(mTouchActive); } - private void setExpandAnimationRunning(boolean running) { + @VisibleForTesting + 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 dc506a5b1d25..3cce4232ab7a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -123,6 +123,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock lateinit var keyEventInteractor: KeyEventInteractor private val notificationExpansionRepository = NotificationExpansionRepository() + private lateinit var fakeClock: FakeSystemClock private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler> private lateinit var interactionEventHandler: InteractionEventHandler @@ -151,6 +152,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false) testScope = TestScope() + fakeClock = FakeSystemClock() underTest = NotificationShadeWindowViewController( lockscreenShadeTransitionController, @@ -183,7 +185,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { primaryBouncerToGoneTransitionViewModel, notificationExpansionRepository, featureFlags, - FakeSystemClock(), + fakeClock, BouncerMessageInteractor( FakeBouncerMessageRepository(), mock(BouncerMessageFactory::class.java), @@ -332,6 +334,33 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { } @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 whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT)) @@ -372,6 +401,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 } } |