summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/window/BackEvent.java49
-rw-r--r--core/java/android/window/BackMotionEvent.java18
-rw-r--r--core/java/android/window/BackProgressAnimator.java29
-rw-r--r--core/java/android/window/BackTouchTracker.java2
-rw-r--r--core/java/android/window/ImeOnBackInvokedDispatcher.java13
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig8
-rw-r--r--core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java4
-rw-r--r--core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt1
12 files changed, 116 insertions, 21 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index c91992c29630..46fda83d3444 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -61645,6 +61645,8 @@ package android.window {
public final class BackEvent {
ctor public BackEvent(float, float, float, int);
+ ctor @FlaggedApi("com.android.window.flags.predictive_back_timestamp_api") public BackEvent(float, float, float, int, long);
+ method @FlaggedApi("com.android.window.flags.predictive_back_timestamp_api") public long getFrameTime();
method @FloatRange(from=0, to=1) public float getProgress();
method public int getSwipeEdge();
method public float getTouchX();
diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java
index d3733b71f7ee..1c3f201c1471 100644
--- a/core/java/android/window/BackEvent.java
+++ b/core/java/android/window/BackEvent.java
@@ -16,8 +16,13 @@
package android.window;
+import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API;
+import static com.android.window.flags.Flags.predictiveBackTimestampApi;
+
+import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
+import android.util.TimeUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,18 +49,25 @@ public final class BackEvent {
private final float mTouchX;
private final float mTouchY;
private final float mProgress;
+ private final long mFrameTime;
@SwipeEdge
private final int mSwipeEdge;
/** @hide */
public static BackEvent fromBackMotionEvent(BackMotionEvent backMotionEvent) {
- return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(),
- backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge());
+ if (predictiveBackTimestampApi()) {
+ return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(),
+ backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge(),
+ backMotionEvent.getFrameTime());
+ } else {
+ return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(),
+ backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge());
+ }
}
/**
- * Creates a new {@link BackEvent} instance.
+ * Creates a new {@link BackEvent} instance with the current uptime as frame time.
*
* @param touchX Absolute X location of the touch point of this event.
* @param touchY Absolute Y location of the touch point of this event.
@@ -67,6 +79,26 @@ public final class BackEvent {
mTouchY = touchY;
mProgress = progress;
mSwipeEdge = swipeEdge;
+ mFrameTime = System.nanoTime() / TimeUtils.NANOS_PER_MS;
+ }
+
+ /**
+ * Creates a new {@link BackEvent} instance.
+ *
+ * @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 swipeEdge Indicates which edge the swipe starts from.
+ * @param frameTime frame time of the back event.
+ */
+ @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API)
+ public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge,
+ long frameTime) {
+ mTouchX = touchX;
+ mTouchY = touchY;
+ mProgress = progress;
+ mSwipeEdge = swipeEdge;
+ mFrameTime = frameTime;
}
/**
@@ -115,13 +147,22 @@ public final class BackEvent {
return mSwipeEdge;
}
+ /**
+ * Returns the frameTime of the BackEvent in milliseconds. Useful for calculating velocity.
+ */
+ @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API)
+ public long getFrameTime() {
+ return mFrameTime;
+ }
+
@Override
public String toString() {
return "BackEvent{"
+ "mTouchX=" + mTouchX
+ ", mTouchY=" + mTouchY
+ ", mProgress=" + mProgress
- + ", mSwipeEdge" + mSwipeEdge
+ + ", mSwipeEdge=" + mSwipeEdge
+ + ", mFrameTime=" + mFrameTime + "ms"
+ "}";
}
}
diff --git a/core/java/android/window/BackMotionEvent.java b/core/java/android/window/BackMotionEvent.java
index 8ac68abd8d8e..a8ec4eeb039a 100644
--- a/core/java/android/window/BackMotionEvent.java
+++ b/core/java/android/window/BackMotionEvent.java
@@ -33,6 +33,7 @@ import android.view.RemoteAnimationTarget;
public final class BackMotionEvent implements Parcelable {
private final float mTouchX;
private final float mTouchY;
+ private final long mFrameTime;
private final float mProgress;
private final boolean mTriggerBack;
@@ -48,6 +49,7 @@ public final class BackMotionEvent implements Parcelable {
*
* @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 frameTime Event time of the corresponding touch event.
* @param progress Value between 0 and 1 on how far along the back gesture is.
* @param triggerBack Indicates whether the back arrow is in the triggered state or not
* @param swipeEdge Indicates which edge the swipe starts from.
@@ -57,12 +59,14 @@ public final class BackMotionEvent implements Parcelable {
public BackMotionEvent(
float touchX,
float touchY,
+ long frameTime,
float progress,
boolean triggerBack,
@BackEvent.SwipeEdge int swipeEdge,
@Nullable RemoteAnimationTarget departingAnimationTarget) {
mTouchX = touchX;
mTouchY = touchY;
+ mFrameTime = frameTime;
mProgress = progress;
mTriggerBack = triggerBack;
mSwipeEdge = swipeEdge;
@@ -76,6 +80,7 @@ public final class BackMotionEvent implements Parcelable {
mTriggerBack = in.readBoolean();
mSwipeEdge = in.readInt();
mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR);
+ mFrameTime = in.readLong();
}
@NonNull
@@ -104,6 +109,7 @@ public final class BackMotionEvent implements Parcelable {
dest.writeBoolean(mTriggerBack);
dest.writeInt(mSwipeEdge);
dest.writeTypedObject(mDepartingAnimationTarget, flags);
+ dest.writeLong(mFrameTime);
}
/**
@@ -148,6 +154,13 @@ public final class BackMotionEvent implements Parcelable {
}
/**
+ * Returns the frame time of the BackMotionEvent in milliseconds.
+ */
+ public long getFrameTime() {
+ return mFrameTime;
+ }
+
+ /**
* Returns the {@link RemoteAnimationTarget} of the top departing application window,
* or {@code null} if the top window should not be moved for the current type of back
* destination.
@@ -162,10 +175,11 @@ public final class BackMotionEvent implements Parcelable {
return "BackMotionEvent{"
+ "mTouchX=" + mTouchX
+ ", mTouchY=" + mTouchY
+ + ", mFrameTime=" + mFrameTime + "ms"
+ ", mProgress=" + mProgress
+ ", mTriggerBack=" + mTriggerBack
- + ", mSwipeEdge" + mSwipeEdge
- + ", mDepartingAnimationTarget" + mDepartingAnimationTarget
+ + ", mSwipeEdge=" + mSwipeEdge
+ + ", mDepartingAnimationTarget=" + mDepartingAnimationTarget
+ "}";
}
}
diff --git a/core/java/android/window/BackProgressAnimator.java b/core/java/android/window/BackProgressAnimator.java
index 465e11a048f0..a5be58b7b183 100644
--- a/core/java/android/window/BackProgressAnimator.java
+++ b/core/java/android/window/BackProgressAnimator.java
@@ -17,6 +17,7 @@
package android.window;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.window.flags.Flags.predictiveBackTimestampApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -66,7 +67,8 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL
reset();
};
private final DynamicAnimation.OnAnimationUpdateListener mOnBackInvokedFlingUpdateListener =
- (animation, progress, velocity) -> updateProgressValue(progress, velocity);
+ (animation, progress, velocity) ->
+ updateProgressValue(progress, velocity, animation.getLastFrameTime());
private void setProgress(float progress) {
@@ -92,7 +94,9 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL
@Override
public void onAnimationUpdate(DynamicAnimation animation, float value, float velocity) {
- if (mBackInvokedFinishRunnable == null) updateProgressValue(value, velocity);
+ if (mBackInvokedFinishRunnable == null) {
+ updateProgressValue(value, velocity, animation.getLastFrameTime());
+ }
}
@@ -137,7 +141,9 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL
mLastBackEvent = event;
mCallback = callback;
mBackAnimationInProgress = true;
- updateProgressValue(0, 0);
+ updateProgressValue(/* progress */ 0, /* velocity */ 0,
+ /* frameTime */ System.nanoTime() / TimeUtils.NANOS_PER_MS);
+ onBackProgressed(event);
}
/**
@@ -146,7 +152,8 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL
public void reset() {
if (mBackCancelledFinishRunnable != null) {
// Ensure that last progress value that apps see is 0
- updateProgressValue(0, 0);
+ updateProgressValue(/* progress */ 0, /* velocity */ 0,
+ /* frameTime */ System.nanoTime() / TimeUtils.NANOS_PER_MS);
invokeBackCancelledRunnable();
} else if (mBackInvokedFinishRunnable != null) {
invokeBackInvokedRunnable();
@@ -236,14 +243,20 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL
return mVelocity / SCALE_FACTOR;
}
- private void updateProgressValue(float progress, float velocity) {
+ private void updateProgressValue(float progress, float velocity, long frameTime) {
mVelocity = velocity;
if (mLastBackEvent == null || mCallback == null || !mBackAnimationInProgress) {
return;
}
- mCallback.onProgressUpdate(
- new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(),
- progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge()));
+ BackEvent backEvent;
+ if (predictiveBackTimestampApi()) {
+ backEvent = new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(),
+ progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge(), frameTime);
+ } else {
+ backEvent = new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(),
+ progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge());
+ }
+ mCallback.onProgressUpdate(backEvent);
}
private void invokeBackCancelledRunnable() {
diff --git a/core/java/android/window/BackTouchTracker.java b/core/java/android/window/BackTouchTracker.java
index 290c494b1bff..39a30253adbd 100644
--- a/core/java/android/window/BackTouchTracker.java
+++ b/core/java/android/window/BackTouchTracker.java
@@ -151,6 +151,7 @@ public class BackTouchTracker {
return new BackMotionEvent(
/* touchX = */ mInitTouchX,
/* touchY = */ mInitTouchY,
+ /* frameTime = */ 0,
/* progress = */ 0,
/* triggerBack = */ mTriggerBack,
/* swipeEdge = */ mSwipeEdge,
@@ -235,6 +236,7 @@ public class BackTouchTracker {
return new BackMotionEvent(
/* touchX = */ mLatestTouchX,
/* touchY = */ mLatestTouchY,
+ /* frameTime = */ 0,
/* progress = */ progress,
/* triggerBack = */ mTriggerBack,
/* swipeEdge = */ mSwipeEdge,
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index 66c35e2fe837..8db1f9509757 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -17,6 +17,7 @@
package android.window;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.window.flags.Flags.predictiveBackTimestampApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -235,8 +236,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
@Override
public void onBackStarted(@NonNull BackEvent backEvent) {
try {
+ long frameTime = 0;
+ if (predictiveBackTimestampApi()) {
+ frameTime = backEvent.getFrameTime();
+ }
mIOnBackInvokedCallback.onBackStarted(
- new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(),
+ new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), frameTime,
backEvent.getProgress(), false, backEvent.getSwipeEdge(),
null));
} catch (RemoteException e) {
@@ -247,8 +252,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
@Override
public void onBackProgressed(@NonNull BackEvent backEvent) {
try {
+ long frameTime = 0;
+ if (predictiveBackTimestampApi()) {
+ frameTime = backEvent.getFrameTime();
+ }
mIOnBackInvokedCallback.onBackProgressed(
- new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(),
+ new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), frameTime,
backEvent.getProgress(), false, backEvent.getSwipeEdge(),
null));
} catch (RemoteException e) {
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 622f8c817d99..460469c13a3e 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -325,3 +325,11 @@ flag {
is_fixed_read_only: true
bug: "362938401"
}
+
+flag {
+ name: "predictive_back_timestamp_api"
+ namespace: "systemui"
+ description: "expose timestamp in BackEvent (API extension)"
+ is_fixed_read_only: true
+ bug: "362938401"
+}
diff --git a/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java
index d4fe7c8d7f36..7a4c1a00a41f 100644
--- a/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java
+++ b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java
@@ -762,6 +762,10 @@ public abstract class DynamicAnimation<T extends DynamicAnimation<T>>
return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
}
+ public long getLastFrameTime() {
+ return mLastFrameTime;
+ }
+
/****************Sub class animations**************/
/**
* Returns the acceleration at the given value with the given velocity.
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index b001cc2929e3..46bd73e316f6 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -21,6 +21,7 @@ import static android.window.OnBackInvokedDispatcher.PRIORITY_OVERLAY;
import static android.window.OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER;
import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER;
+import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -486,6 +487,7 @@ public class WindowOnBackInvokedDispatcherTest {
}
@Test
+ @RequiresFlagsDisabled(FLAG_PREDICTIVE_BACK_TIMESTAMP_API)
public void onBackInvoked_notCalledAfterCallbackUnregistration()
throws RemoteException, InterruptedException {
// Setup a callback that unregisters itself after the gesture is finished but before the
@@ -684,6 +686,7 @@ public class WindowOnBackInvokedDispatcherTest {
return new BackMotionEvent(
/* touchX = */ 0,
/* touchY = */ 0,
+ /* frameTime = */ 0,
/* progress = */ progress,
/* triggerBack = */ false,
/* swipeEdge = */ BackEvent.EDGE_LEFT,
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 b90e6e2fab8a..19b51f143241 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
@@ -355,11 +355,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
int keyAction,
@BackEvent.SwipeEdge int swipeEdge
) {
- mShellExecutor.execute(() -> onMotionEvent(
- /* touchX = */ touchX,
- /* touchY = */ touchY,
- /* keyAction = */ keyAction,
- /* swipeEdge = */ swipeEdge));
+ mShellExecutor.execute(
+ () -> onMotionEvent(touchX, touchY, keyAction, swipeEdge));
}
@Override
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java
index 1da4ef6b5a8b..266e48482568 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java
@@ -53,6 +53,7 @@ public class BackProgressAnimatorTest {
return new BackMotionEvent(
/* touchX = */ touchX,
/* touchY = */ 0,
+ /* frameTime = */ 0,
/* progress = */ progress,
/* triggerBack = */ false,
/* swipeEdge = */ BackEvent.EDGE_LEFT,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt
index 2235c20d7f21..2cc52c5ab9ad 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt
@@ -221,6 +221,7 @@ class CustomCrossActivityBackAnimationTest : ShellTestCase() {
BackMotionEvent(
/* touchX = */ touchX,
/* touchY = */ 0f,
+ /* frameTime = */ 0,
/* progress = */ progress,
/* triggerBack = */ false,
/* swipeEdge = */ BackEvent.EDGE_LEFT,