diff --git a/core/java/android/window/BackMotionEvent.java b/core/java/android/window/BackMotionEvent.java index 8012a1c26baca..c47572313eeb6 100644 --- a/core/java/android/window/BackMotionEvent.java +++ b/core/java/android/window/BackMotionEvent.java @@ -34,6 +34,8 @@ public final class BackMotionEvent implements Parcelable { private final float mTouchX; private final float mTouchY; private final float mProgress; + private final float mVelocityX; + private final float mVelocityY; @BackEvent.SwipeEdge private final int mSwipeEdge; @@ -43,19 +45,32 @@ public final class BackMotionEvent implements Parcelable { /** * Creates a new {@link BackMotionEvent} instance. * + *

Note: Velocity is only computed for last event, for performance reasons.

+ * * @param touchX Absolute X location of the touch point of this event. * @param touchY Absolute Y location of the touch point of this event. * @param progress Value between 0 and 1 on how far along the back gesture is. + * @param velocityX X velocity computed from the touch point of this event. + * Value in pixels/second. {@link Float#NaN} if was not computed. + * @param velocityY Y velocity computed from the touch point of this event. + * Value in pixels/second. {@link Float#NaN} if was not computed. * @param swipeEdge Indicates which edge the swipe starts from. * @param departingAnimationTarget The remote animation target of the departing * application window. */ - public BackMotionEvent(float touchX, float touchY, float progress, + public BackMotionEvent( + float touchX, + float touchY, + float progress, + float velocityX, + float velocityY, @BackEvent.SwipeEdge int swipeEdge, @Nullable RemoteAnimationTarget departingAnimationTarget) { mTouchX = touchX; mTouchY = touchY; mProgress = progress; + mVelocityX = velocityX; + mVelocityY = velocityY; mSwipeEdge = swipeEdge; mDepartingAnimationTarget = departingAnimationTarget; } @@ -64,6 +79,8 @@ public final class BackMotionEvent implements Parcelable { mTouchX = in.readFloat(); mTouchY = in.readFloat(); mProgress = in.readFloat(); + mVelocityX = in.readFloat(); + mVelocityY = in.readFloat(); mSwipeEdge = in.readInt(); mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR); } @@ -91,20 +108,12 @@ public final class BackMotionEvent implements Parcelable { dest.writeFloat(mTouchX); dest.writeFloat(mTouchY); dest.writeFloat(mProgress); + dest.writeFloat(mVelocityX); + dest.writeFloat(mVelocityY); dest.writeInt(mSwipeEdge); dest.writeTypedObject(mDepartingAnimationTarget, flags); } - /** - * Returns the progress of a {@link BackEvent}. - * - * @see BackEvent#getProgress() - */ - @FloatRange(from = 0, to = 1) - public float getProgress() { - return mProgress; - } - /** * Returns the absolute X location of the touch point. */ @@ -119,6 +128,34 @@ public final class BackMotionEvent implements Parcelable { return mTouchY; } + /** + * Returns the progress of a {@link BackEvent}. + * + * @see BackEvent#getProgress() + */ + @FloatRange(from = 0, to = 1) + public float getProgress() { + return mProgress; + } + + /** + * Returns the X velocity computed from the touch point. + * + * @return value in pixels/second or {@link Float#NaN} if was not computed. + */ + public float getVelocityX() { + return mVelocityX; + } + + /** + * Returns the Y velocity computed from the touch point. + * + * @return value in pixels/second or {@link Float#NaN} if was not computed. + */ + public float getVelocityY() { + return mVelocityY; + } + /** * Returns the screen edge that the swipe starts from. */ @@ -143,6 +180,8 @@ public final class BackMotionEvent implements Parcelable { + "mTouchX=" + mTouchX + ", mTouchY=" + mTouchY + ", mProgress=" + mProgress + + ", mVelocityX=" + mVelocityX + + ", mVelocityY=" + mVelocityY + ", mSwipeEdge" + mSwipeEdge + ", mDepartingAnimationTarget" + mDepartingAnimationTarget + "}"; diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index 3b6e8eaafc22d..cde100cc20aaa 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -70,7 +70,13 @@ public class WindowOnBackInvokedDispatcherTest { private ApplicationInfo mApplicationInfo; private final BackMotionEvent mBackEvent = new BackMotionEvent( - 0, 0, 0, BackEvent.EDGE_LEFT, null); + /* touchX = */ 0, + /* touchY = */ 0, + /* progress = */ 0, + /* velocityX = */ 0, + /* velocityY = */ 0, + /* swipeEdge = */ BackEvent.EDGE_LEFT, + /* departingAnimationTarget = */ null); @Before public void setUp() throws Exception { 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 e84a78f426164..133fd87a2f63c 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 @@ -33,12 +33,19 @@ public interface BackAnimation { * * @param touchX the X touch position of the {@link MotionEvent}. * @param touchY the Y touch position of the {@link MotionEvent}. + * @param velocityX the X velocity computed from the {@link MotionEvent}. + * @param velocityY the Y velocity computed from 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(float touchX, float touchY, int keyAction, + void onBackMotion( + float touchX, + float touchY, + float velocityX, + float velocityY, + int keyAction, @BackEvent.SwipeEdge int swipeEdge); /** 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 04f8477eb749a..47d3a5c520745 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 @@ -256,8 +256,20 @@ public class BackAnimationController implements RemoteCallable onMotionEvent(touchX, touchY, keyAction, swipeEdge)); + float touchX, + float touchY, + float velocityX, + float velocityY, + int keyAction, + @BackEvent.SwipeEdge int swipeEdge + ) { + mShellExecutor.execute(() -> onMotionEvent( + /* touchX = */ touchX, + /* touchY = */ touchY, + /* velocityX = */ velocityX, + /* velocityY = */ velocityY, + /* keyAction = */ keyAction, + /* swipeEdge = */ swipeEdge)); } @Override @@ -332,13 +344,18 @@ public class BackAnimationController implements RemoteCallable { mProgressAnimator = new BackProgressAnimator(); @@ -63,9 +70,7 @@ public class BackProgressAnimatorTest { @Test public void testBackProgressed() throws InterruptedException { - final BackMotionEvent backEvent = new BackMotionEvent( - 100, 0, - mTargetProgress, EDGE_LEFT, null); + final BackMotionEvent backEvent = backMotionEventFrom(100, mTargetProgress); mMainThreadHandler.post( () -> mProgressAnimator.onBackProgressed(backEvent)); @@ -78,9 +83,7 @@ public class BackProgressAnimatorTest { @Test public void testBackCancelled() throws InterruptedException { // Give the animator some progress. - final BackMotionEvent backEvent = new BackMotionEvent( - 100, 0, - mTargetProgress, EDGE_LEFT, null); + final BackMotionEvent backEvent = backMotionEventFrom(100, mTargetProgress); mMainThreadHandler.post( () -> mProgressAnimator.onBackProgressed(backEvent)); mTargetProgressCalled.await(1, TimeUnit.SECONDS); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java index ba9c159bad284..d62e6601723a2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java @@ -47,43 +47,45 @@ public class TouchTrackerTest { public void generatesProgress_leftEdge() { mTouchTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0, BackEvent.EDGE_LEFT); float touchX = 10; + float velocityX = 0; + float velocityY = 0; // Pre-commit - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); // Post-commit touchX += 100; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); // Cancel touchX -= 10; mTouchTracker.setTriggerBack(false); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Cancel more touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restart touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restarted, but pre-commit float restartX = touchX; touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - restartX) / FAKE_THRESHOLD, 0f); // Restarted, post-commit touchX += 10; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); } @@ -91,43 +93,45 @@ public class TouchTrackerTest { public void generatesProgress_rightEdge() { mTouchTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0, BackEvent.EDGE_RIGHT); float touchX = INITIAL_X_RIGHT_EDGE - 10; // Fake right edge + float velocityX = 0f; + float velocityY = 0f; // Pre-commit - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); // Post-commit touchX -= 100; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); // Cancel touchX += 10; mTouchTracker.setTriggerBack(false); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Cancel more touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restart touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restarted, but pre-commit float restartX = touchX; touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (restartX - touchX) / FAKE_THRESHOLD, 0f); // Restarted, post-commit touchX -= 10; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); } 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 26b0e8dd98958..b9ef916eebdf3 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -55,6 +55,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; +import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.WindowInsets; import android.view.WindowManager; @@ -173,7 +174,7 @@ public class EdgeBackGestureHandler implements PluginListener