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 c98090638010355476917ae8f7ff7e51e2e26b52..8d8dc10951a67121639cc2f2629503bb1227401e 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 @@ -48,6 +48,11 @@ public interface BackAnimation { int keyAction, @BackEvent.SwipeEdge int swipeEdge); + /** + * Called when the input pointers are pilfered. + */ + void onPilferPointers(); + /** * 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 cf858dcb0637f5dcd8d192f8d6e6455e93c893a6..d8c691b01b61f494a6032c41b003803c273b5a1e 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 @@ -111,6 +111,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont /** Tracks if we should start the back gesture on the next motion move event */ private boolean mShouldStartOnNextMoveEvent = false; + private boolean mOnBackStartDispatched = false; private final FlingAnimationUtils mFlingAnimationUtils; @@ -303,6 +304,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont /* swipeEdge = */ swipeEdge)); } + @Override + public void onPilferPointers() { + BackAnimationController.this.onPilferPointers(); + } + @Override public void setTriggerBack(boolean triggerBack) { mShellExecutor.execute(() -> BackAnimationController.this.setTriggerBack(triggerBack)); @@ -384,6 +390,16 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return null; } + @VisibleForTesting + void onPilferPointers() { + mCurrentTracker.updateStartLocation(); + // Dispatch onBackStarted, only to app callbacks. + // System callbacks will receive onBackStarted when the remote animation starts. + if (!shouldDispatchToAnimator()) { + tryDispatchOnBackStarted(mActiveCallback, mCurrentTracker.createStartEvent(null)); + } + } + /** * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} @@ -483,12 +499,15 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback(); // App is handling back animation. Cancel system animation latency tracking. cancelLatencyTracking(); - dispatchOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null)); + tryDispatchOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null)); } } private void onMove() { - if (!mBackGestureStarted || mBackNavigationInfo == null || mActiveCallback == null) { + if (!mBackGestureStarted + || mBackNavigationInfo == null + || mActiveCallback == null + || !mOnBackStartDispatched) { return; } // Skip dispatching if the move corresponds to the queued instead of the current gesture @@ -524,13 +543,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont && mBackNavigationInfo.isPrepareRemoteAnimation(); } - private void dispatchOnBackStarted(IOnBackInvokedCallback callback, + private void tryDispatchOnBackStarted(IOnBackInvokedCallback callback, BackMotionEvent backEvent) { - if (callback == null) { + if (callback == null || mOnBackStartDispatched) { return; } try { callback.onBackStarted(backEvent); + mOnBackStartDispatched = true; } catch (RemoteException e) { Log.e(TAG, "dispatchOnBackStarted error: ", e); } @@ -828,6 +848,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont void finishBackNavigation(boolean triggerBack) { ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()"); mActiveCallback = null; + mShouldStartOnNextMoveEvent = false; + mOnBackStartDispatched = false; mShellBackAnimationRegistry.resetDefaultCrossActivity(); cancelLatencyTracking(); if (mBackNavigationInfo != null) { @@ -909,7 +931,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont ::onBackAnimationFinished)); if (apps.length >= 1) { - dispatchOnBackStarted( + mCurrentTracker.updateStartLocation(); + tryDispatchOnBackStarted( mActiveCallback, mCurrentTracker.createStartEvent(apps[0])); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java index 19eb928d4e30afa0cb07ef08d901dd2d73382b1e..4bd56d460818a198b4941813fa0e3bb8e10cb98c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java @@ -104,6 +104,15 @@ class TouchTracker { mStartThresholdX = mInitTouchX; } + /** Update the start location used to compute the progress + * to the latest touch location. + */ + void updateStartLocation() { + mInitTouchX = mLatestTouchX; + mInitTouchY = mLatestTouchY; + mStartThresholdX = mInitTouchX; + } + void reset() { mInitTouchX = 0; mInitTouchY = 0; 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 0395a9b78b2ba02045970ae793b19b850b8f8ba5..771876f7ce5dbd1270ba011991e014b5994120be 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 @@ -182,8 +182,7 @@ public class BackAnimationControllerTest extends ShellTestCase { } private void triggerBackGesture() { - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - doMotionEvent(MotionEvent.ACTION_MOVE, 0); + doStartEvents(0, 0); mController.setTriggerBack(true); } @@ -244,10 +243,7 @@ public class BackAnimationControllerTest extends ShellTestCase { /* enableAnimation = */ true, /* isAnimationCallback = */ false); - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - - // Check that back start and progress is dispatched when first move. - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); @@ -270,10 +266,8 @@ public class BackAnimationControllerTest extends ShellTestCase { /* enableAnimation = */ true, /* isAnimationCallback = */ true); - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - // Check that back start and progress is dispatched when first move. - doMotionEvent(MotionEvent.ACTION_MOVE, 100, 3000); + doStartEvents(0, 100); simulateRemoteAnimationStart(); @@ -359,8 +353,7 @@ public class BackAnimationControllerTest extends ShellTestCase { .injectInputEvent(any(KeyEvent.class), any(Integer.class)); // Verify that we start accepting gestures again once transition finishes. - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); verify(mAnimatorCallback).onBackStarted(any()); @@ -399,8 +392,7 @@ public class BackAnimationControllerTest extends ShellTestCase { .injectInputEvent(any(KeyEvent.class), any(Integer.class)); // Verify that we start accepting gestures again once transition finishes. - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); verify(mAnimatorCallback).onBackStarted(any()); @@ -427,8 +419,7 @@ public class BackAnimationControllerTest extends ShellTestCase { mShellExecutor.flushAll(); reset(mAnimatorCallback); - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); verify(mAnimatorCallback).onBackStarted(any()); } @@ -441,9 +432,7 @@ public class BackAnimationControllerTest extends ShellTestCase { /* enableAnimation = */ true, /* isAnimationCallback = */ false); - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - // Check that back start and progress is dispatched when first move. - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); verify(mAnimatorCallback).onBackStarted(any()); @@ -563,10 +552,8 @@ public class BackAnimationControllerTest extends ShellTestCase { /* enableAnimation = */ true, /* isAnimationCallback = */ false); - doMotionEvent(MotionEvent.ACTION_DOWN, 0); - // Check that back start and progress is dispatched when first move. - doMotionEvent(MotionEvent.ACTION_MOVE, 100); + doStartEvents(0, 100); simulateRemoteAnimationStart(); @@ -593,6 +580,15 @@ public class BackAnimationControllerTest extends ShellTestCase { /* swipeEdge */ BackEvent.EDGE_LEFT); } + /** + * Simulate event sequence that starts a back navigation. + */ + private void doStartEvents(int startX, int moveX) { + doMotionEvent(MotionEvent.ACTION_DOWN, startX); + mController.onPilferPointers(); + doMotionEvent(MotionEvent.ACTION_MOVE, moveX); + } + private void simulateRemoteAnimationStart() throws RemoteException { RemoteAnimationTarget animationTarget = createAnimationTarget(); RemoteAnimationTarget[] targets = new RemoteAnimationTarget[]{animationTarget}; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 9846f4b6c9800d9207ae73474b2e090e98882691..e660b97b5c6b9a441c74ea0deae8d1a3c6c611bd 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -69,7 +69,6 @@ import androidx.annotation.DimenRes; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.policy.GestureNavigationSettingsObserver; -import com.android.systemui.res.R; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; @@ -81,6 +80,7 @@ import com.android.systemui.plugins.NavigationEdgeBackPlugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.PluginManager; import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.res.R; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputChannelCompat; @@ -1113,6 +1113,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack // Capture inputs mInputMonitor.pilferPointers(); if (mBackAnimation != null) { + mBackAnimation.onPilferPointers(); // Notify FalsingManager that an intentional gesture has occurred. mFalsingManager.isFalseTouch(BACK_GESTURE); }