Merge "Place recents above app only after the initial touch down"
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 9a3a67f..7675a79 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -304,7 +304,8 @@
mCurrentAnimation.setEndAction(this::clearState);
mCurrentAnimation.startWithVelocity(mActivity, goingToEnd,
- velocity, mEndDisplacement, animationDuration);
+ velocity * orientationHandler.getSecondaryTranslationDirectionFactor(),
+ mEndDisplacement, animationDuration);
}
private void clearState() {
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 87fee79..16ca43d 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -16,8 +16,9 @@
package com.android.quickstep.util;
+import static com.android.systemui.shared.system.InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_PIP;
+
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
@@ -26,7 +27,9 @@
import androidx.annotation.NonNull;
+import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.systemui.shared.pip.PipSurfaceTransactionHelper;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
/**
* An {@link Animator} that animates an Activity to PiP (picture-in-picture) window when
@@ -76,9 +79,27 @@
startBounds.right - sourceRectHint.right,
startBounds.bottom - sourceRectHint.bottom);
- addListener(new AnimatorListenerAdapter() {
+ addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ InteractionJankMonitorWrapper.begin(CUJ_APP_CLOSE_TO_PIP);
+ super.onAnimationStart(animation);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ InteractionJankMonitorWrapper.cancel(CUJ_APP_CLOSE_TO_PIP);
+ }
+
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ InteractionJankMonitorWrapper.end(CUJ_APP_CLOSE_TO_PIP);
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (!mHasAnimationEnded) super.onAnimationEnd(animation);
SwipePipToHomeAnimator.this.onAnimationEnd();
}
});
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index aeed16a..e151777 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -1099,11 +1099,20 @@
* @return the max _id in the provided table.
*/
@Thunk static int getMaxId(SQLiteDatabase db, String query, Object... args) {
- int max = (int) DatabaseUtils.longForQuery(db,
- String.format(Locale.ENGLISH, query, args),
- null);
- if (max < 0) {
- throw new RuntimeException("Error: could not query max id");
+ int max = 0;
+ try (SQLiteStatement prog = db.compileStatement(
+ String.format(Locale.ENGLISH, query, args))) {
+ max = (int) DatabaseUtils.longForQuery(prog, null);
+ if (max < 0) {
+ throw new RuntimeException("Error: could not query max id");
+ }
+ } catch (IllegalArgumentException exception) {
+ String message = exception.getMessage();
+ if (message.contains("re-open") && message.contains("already-closed")) {
+ // Don't crash trying to end a transaction an an already closed DB. See b/173162852.
+ } else {
+ throw exception;
+ }
}
return max;
}
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index edaf51d..f6d1651 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -29,6 +29,8 @@
import android.animation.ValueAnimator;
import android.content.Context;
+import com.android.launcher3.Utilities;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -133,15 +135,20 @@
/**
* Starts playing the animation with the provided velocity optionally playing any
- * physics based animations
+ * physics based animations.
+ * @param goingToEnd Whether we are going to the end (progress = 1) or not (progress = 0).
+ * @param velocityPxPerMs The velocity at which to start the animation, in pixels / millisecond.
+ * @param endDistance The distance (pixels) that the animation will travel from progress 0 to 1.
+ * @param animationDuration The duration of the non-physics based animation.
*/
public void startWithVelocity(Context context, boolean goingToEnd,
- float velocity, float scale, long animationDuration) {
- float scaleInverse = 1 / Math.abs(scale);
- float scaledVelocity = velocity * scaleInverse;
+ float velocityPxPerMs, float endDistance, long animationDuration) {
+ float distanceInverse = 1 / Math.abs(endDistance);
+ float velocityProgressPerMs = velocityPxPerMs * distanceInverse;
+ float oneFrameProgress = velocityProgressPerMs * getSingleFrameMs(context);
float nextFrameProgress = boundToRange(getProgressFraction()
- + scaledVelocity * getSingleFrameMs(context), 0f, 1f);
+ + oneFrameProgress, 0f, 1f);
// Update setters for spring
int springFlag = goingToEnd
@@ -154,8 +161,8 @@
SpringAnimationBuilder s = new SpringAnimationBuilder(context)
.setStartValue(mCurrentFraction)
.setEndValue(goingToEnd ? 1 : 0)
- .setStartVelocity(scaledVelocity)
- .setMinimumVisibleChange(scaleInverse)
+ .setStartVelocity(velocityProgressPerMs)
+ .setMinimumVisibleChange(distanceInverse)
.setDampingRatio(h.springProperty.mDampingRatio)
.setStiffness(h.springProperty.mStiffness)
.computeParams();
@@ -164,8 +171,18 @@
springDuration = Math.max(expectedDurationL, springDuration);
float expectedDuration = expectedDurationL;
- h.mapper = (progress, globalEndProgress) ->
- mAnimationPlayer.getCurrentPlayTime() / expectedDuration;
+ h.mapper = (progress, globalEndProgress) -> {
+ if (expectedDuration <= 0 || oneFrameProgress >= 1) {
+ return 1;
+ } else {
+ // Start from one frame ahead of the current position.
+ return Utilities.mapToRange(
+ mAnimationPlayer.getCurrentPlayTime() / expectedDuration,
+ 0, 1,
+ Math.abs(oneFrameProgress), 1,
+ LINEAR);
+ }
+ };
h.anim.setInterpolator(s::getInterpolatedValue);
}
}
@@ -174,7 +191,7 @@
if (springDuration <= animationDuration) {
mAnimationPlayer.setDuration(animationDuration);
- mAnimationPlayer.setInterpolator(scrollInterpolatorForVelocity(velocity));
+ mAnimationPlayer.setInterpolator(scrollInterpolatorForVelocity(velocityPxPerMs));
} else {
// Since spring requires more time to run, we let the other animations play with
// current time and interpolation and by clamping the duration.
@@ -182,7 +199,7 @@
float cutOff = animationDuration / (float) springDuration;
mAnimationPlayer.setInterpolator(
- clampToProgress(scrollInterpolatorForVelocity(velocity), 0, cutOff));
+ clampToProgress(scrollInterpolatorForVelocity(velocityPxPerMs), 0, cutOff));
}
mAnimationPlayer.start();
}