From 4af206765057f43e7047a81977461de39ccad9c2 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 15 May 2020 14:30:11 -0700 Subject: [PATCH] Fix regression in adding recents input consumer leading to ANR - Because cantReceiveTouchInput() accounts for whether an activity is being controlled by recents (it shouldn't receive touches), we happen to skip adding the recents input consumer below. However, because the activity input window is skipped and the input consumer is not added, we end up with no focused window, which then means that the next touch on a nav button will try to inject a keyevent to no focused windows, which triggers an ANR. Ensure that we fall through to the logic below to add the recents input consumer specifically in the case where an app window shouldn't receive touches, but should have the recents input consumer applied. Bug: 156394972 Test: Take surface trace while swiping up and ensure the input consumer is relz to the app window being controlled Change-Id: I9606dbef4565508514f4ff2f9ef464e9737bd7cc Signed-off-by: Winson Chung --- .../com/android/server/wm/InputMonitor.java | 22 +++++++++---------- .../server/wm/RecentsAnimationController.java | 3 ++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 1b1898b76506f..efcd61df5c750 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -469,8 +469,12 @@ final class InputMonitor { public void accept(WindowState w) { final InputChannel inputChannel = w.mInputChannel; final InputWindowHandle inputWindowHandle = w.mInputWindowHandle; + final RecentsAnimationController recentsAnimationController = + mService.getRecentsAnimationController(); + final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null + && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord); if (inputChannel == null || inputWindowHandle == null || w.mRemoved - || w.cantReceiveTouchInput()) { + || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) { if (w.mWinAnimator.hasSurface()) { mInputTransaction.setInputWindowInfo( w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), @@ -486,22 +490,16 @@ final class InputMonitor { final boolean hasFocus = w.isFocused(); final boolean isVisible = w.isVisibleLw(); - if (mAddRecentsAnimationInputConsumerHandle) { - final RecentsAnimationController recentsAnimationController = - mService.getRecentsAnimationController(); - if (recentsAnimationController != null - && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord)) { - if (recentsAnimationController.updateInputConsumerForApp( - mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) { - mRecentsAnimationInputConsumer.show(mInputTransaction, w); - mAddRecentsAnimationInputConsumerHandle = false; - } + if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) { + if (recentsAnimationController.updateInputConsumerForApp( + mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) { + mRecentsAnimationInputConsumer.show(mInputTransaction, w); + mAddRecentsAnimationInputConsumerHandle = false; } } if (w.inPinnedWindowingMode()) { if (mAddPipInputConsumerHandle) { - final Task rootTask = w.getTask().getRootTask(); mPipInputConsumer.mWindowHandle.replaceTouchableRegionWithCrop( rootTask.getSurfaceControl()); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index d6ddcd0cc9f92..cbc1bdfa0e9ea 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -799,7 +799,8 @@ public class RecentsAnimationController implements DeathRecipient { // Only apply the input consumer if it is enabled, it is not the target (home/recents) // being revealed with the transition, and we are actively animating the app as a part of // the animation - return mInputConsumerEnabled && !isTargetApp(activity) && isAnimatingApp(activity); + return mInputConsumerEnabled && activity != null + && !isTargetApp(activity) && isAnimatingApp(activity); } boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,