From db78c194d8dd8774c77d0ec8e8913b3eeaef8325 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Thu, 16 Jun 2022 21:57:33 -0700 Subject: Pass the values of the MotionEvent instead of the event instance itself to BackAnimation. The original MotionEvent instance may have been recycled by the time BackAnimation processes it, since BackAnimation runs in a different thread. This could cause crashes from both Java side and native side, as described in b/233163975#comment11. We work around this by passing the numerical values that BackAnimation need instead of the MotionEvent itself. Test: Swipe back in various scenarios. Make sure back can be triggered. Try cancel. Make sure back can be cancelled. Test: atest BackAnimationControllerTest Bug: 233163975 Change-Id: I4792debc705536b49d1caafcc43e5466941c1d43 Merged-In: I4792debc705536b49d1caafcc43e5466941c1d43 --- .../com/android/wm/shell/back/BackAnimation.java | 8 ++++--- .../wm/shell/back/BackAnimationController.java | 27 +++++++++++----------- .../wm/shell/back/BackAnimationControllerTest.java | 2 +- .../gestural/NavigationBarEdgePanel.java | 2 +- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index e71a59d26740..8c0affb0a432 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -31,13 +31,15 @@ public interface BackAnimation { /** * Called when a {@link MotionEvent} is generated by a back gesture. * - * @param event the original {@link MotionEvent} - * @param action the original {@link KeyEvent#getAction()} when the event was dispatched to + * @param touchX the X touch position of the {@link MotionEvent}. + * @param touchY the Y touch position of the {@link MotionEvent}. + * @param keyAction the original {@link KeyEvent#getAction()} when the event was dispatched to * the process. This is forwarded separately because the input pipeline may mutate * the {#event} action state later. * @param swipeEdge the edge from which the swipe begins. */ - void onBackMotion(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge); + void onBackMotion(float touchX, float touchY, int keyAction, + @BackEvent.SwipeEdge int swipeEdge); /** * Sets whether the back gesture is past the trigger threshold or not. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 7760df17a8cd..20234244adcd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -184,8 +184,8 @@ public class BackAnimationController implements RemoteCallable onMotionEvent(event, action, swipeEdge)); + float touchX, float touchY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { + mShellExecutor.execute(() -> onMotionEvent(touchX, touchY, keyAction, swipeEdge)); } @Override @@ -256,33 +256,34 @@ public class BackAnimationController implements RemoteCallable= 0 ? PROGRESS_THRESHOLD : mProgressThreshold; float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1); int backType = mBackNavigationInfo.getType(); RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget(); BackEvent backEvent = new BackEvent( - event.getX(), event.getY(), progress, swipeEdge, animationTarget); + touchX, touchY, progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index fcfcbfa091db..e7c5cb2183db 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -298,7 +298,7 @@ public class BackAnimationControllerTest { private void doMotionEvent(int actionDown, int coordinate) { mController.onMotionEvent( - MotionEvent.obtain(0, mEventTime, actionDown, coordinate, coordinate, 0), + coordinate, coordinate, actionDown, BackEvent.EDGE_LEFT); mEventTime += 10; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java index a74c59618c95..eba9d3fdcab8 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java @@ -486,7 +486,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl public void onMotionEvent(MotionEvent event) { if (mBackAnimation != null) { mBackAnimation.onBackMotion( - event, + event.getX(), event.getY(), event.getActionMasked(), mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); } -- cgit v1.2.3-59-g8ed1b