summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shan Huang <shanh@google.com> 2023-11-22 16:24:25 -0800
committer Shan Huang <shanh@google.com> 2023-12-07 22:40:45 -0800
commitb0980cb3e9fc3f604b4b5436fb44b6d095181dec (patch)
treea9ac8edeeb4b3cf8568e9e843b6f1a3c27fbc585
parent91421d2159c614bbeb41dfa693f2f77ca90d5a9a (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
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java33
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java3
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);
}