From 6ca6b5c5146b2f536839dcc61a2c5c7007fd7a40 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Fri, 13 Nov 2020 16:10:45 +0000 Subject: [PATCH] Use opacity rule for animating windows Windows that are being animated will use the opacity rule previously only applied to SAW. This means that if their opacity is below the maximum obscuring opacity allowed (now this is 0.8), then the touch is allowed. During some animations (ie. exit animations) the window is made pass-through on purpose so the user can interact with the new content as soon as possible. This is specially problematic with animations that take long to finish and the alpha takes time to settle on 0. The result is the user has to wait until the animation finishes to be able to interact w/ the device. Applying this rule allows the user to interact w/ the device as soon as the alpha in the animation is below the threshold (0.8). We chose to use the same mechanism for SAW (including the same threshold) for code simplicity and because these animations are either controlled by the system or when they are supplied by the app they are limited to 3s (ag/10438533), so they are safe. We had previously connected the touch occlusion mode of the InputWindowHandle to the WindowState in populateInputWindowHandle(), but that method is only called if the window has an input channel. If the window doesn't have an input channel it falls into the early return of UpdateInputForAllWindowsConsumer.accept() that calls populateOverlayInputInfo() instead (overlay here comes from the fact that it doesn't handle input, I *suspect*). Since now, the default occlusion mode (BLOCK_UNTRUSTED) was the appropriate for such windows. However, now we need animation windows to be USE_OPACITY, and some of those animation windows (eg. exit animations) don't have an input channel, so now we also connect the occlusion mode of InputWindowHandle to the WindowState in populateOverlayInputInfo(). Test: Verify on exit animation, touch is not blocked. Test: atest WindowUntrustedTouchTest Bug: 158002302 Bug: 172787052 Change-Id: Idbf847b758299d40764240cf3e84629efb3038b0 --- .../java/com/android/server/wm/InputMonitor.java | 12 +++++++++--- .../core/java/com/android/server/wm/WindowState.java | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 457df4e47689a..a3504568fa06b 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -516,9 +516,9 @@ final class InputMonitor { if (w.mInputChannelToken == null || w.mRemoved || (!w.canReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) { if (w.mWinAnimator.hasSurface()) { - // Assign an InputInfo with type to the overlay window which can't receive input - // event. This is used to omit Surfaces from occlusion detection. - populateOverlayInputInfo(inputWindowHandle, w.isVisible()); + // Make sure the input info can't receive input event. It may be omitted from + // occlusion detection depending on the type or if it's a trusted overlay. + populateOverlayInputInfo(inputWindowHandle, w); setInputWindowInfoIfNeeded(mInputTransaction, w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle); return; @@ -596,6 +596,12 @@ final class InputMonitor { } } + static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle, + WindowState w) { + populateOverlayInputInfo(inputWindowHandle, w.isVisible()); + inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode()); + } + // This would reset InputWindowHandle fields to prevent it could be found by input event. // We need to check if any new field of InputWindowHandle could impact the result. @VisibleForTesting diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 04d777299ecc1..aa8581690d0b5 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -125,6 +125,7 @@ import static com.android.server.wm.IdentifierProto.USER_ID; import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS; import static com.android.server.wm.MoveAnimationSpecProto.FROM; import static com.android.server.wm.MoveAnimationSpecProto.TO; +import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -964,6 +965,9 @@ class WindowState extends WindowContainer implements WindowManagerP if (WindowManager.LayoutParams.isSystemAlertWindowType(mAttrs.type)) { return TouchOcclusionMode.USE_OPACITY; } + if (isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_ALL)) { + return TouchOcclusionMode.USE_OPACITY; + } return TouchOcclusionMode.BLOCK_UNTRUSTED; }