diff options
author | 2023-11-22 16:24:25 -0800 | |
---|---|---|
committer | 2023-12-07 22:40:45 -0800 | |
commit | b0980cb3e9fc3f604b4b5436fb44b6d095181dec (patch) | |
tree | a9ac8edeeb4b3cf8568e9e843b6f1a3c27fbc585 | |
parent | 91421d2159c614bbeb41dfa693f2f77ca90d5a9a (diff) |
Delay onBackStarted() until the pointer is pilfered.
This only delays the dispatching of the start event. We still start back navigation as early as the first MOVE, to allow more time to receive back navigation info and avoid jank.
Bug: 308550613
Bug: 301195601
Test: atest OnBackInvokedCallbackGestureTest
Test: atest BackAnimationControllerTest
Flag: NONE
Change-Id: I0802fd716dc5dbce7071e083bd373df5c5ddcc4c
5 files changed, 61 insertions, 27 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 c98090638010..8d8dc10951a6 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 @@ -49,6 +49,11 @@ public interface BackAnimation { @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. */ void setTriggerBack(boolean triggerBack); 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 58436351885a..3e1ef8b7b7ef 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 @@ -110,6 +110,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; @@ -291,6 +292,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } @Override + public void onPilferPointers() { + BackAnimationController.this.onPilferPointers(); + } + + @Override public void setTriggerBack(boolean triggerBack) { mShellExecutor.execute(() -> BackAnimationController.this.setTriggerBack(triggerBack)); } @@ -371,6 +377,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} @@ -470,12 +486,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 @@ -511,13 +530,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); } @@ -815,6 +835,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) { @@ -896,7 +918,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 19eb928d4e30..4bd56d460818 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 0395a9b78b2b..771876f7ce5d 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 3dfd2925a1b2..13058eba12a5 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; @@ -1108,6 +1108,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); } |