Play workspace reveal animation for predictive back-to-home
Bug: 382453424
Test: Manual, i.e. tested back-to-home and back-to-allapps animation on phones, tablets and foldables, including interruptions.
Flag: EXEMPT bugfix
Change-Id: Iece001b6b9edd9ca7a909e3ccbe8ebdff2e71d9f
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 2759816..a3984ab 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1670,7 +1670,7 @@
|| mLauncher.getWorkspace().isOverlayShown()
|| shouldPlayFallbackClosingAnimation(appTargets);
- boolean playWorkspaceReveal = !fromPredictiveBack;
+ boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
if (!playFallBackAnimation) {
PointF velocity;
@@ -1689,12 +1689,12 @@
// Skip scaling all apps, otherwise FloatingIconView will get wrong
// layout bounds.
skipAllAppsScale = true;
- } else if (!fromPredictiveBack) {
+ } else {
if (enableScalingRevealHomeAnimation()) {
anim.play(
- new ScalingWorkspaceRevealAnim(
- mLauncher, rectFSpringAnim,
- rectFSpringAnim.getTargetRect()).getAnimators());
+ new ScalingWorkspaceRevealAnim(mLauncher, rectFSpringAnim,
+ rectFSpringAnim.getTargetRect(),
+ !fromPredictiveBack /* playAlphaReveal */).getAnimators());
} else {
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
true /* animateOverviewScrim */, launcherView).getAnimators());
@@ -1713,6 +1713,20 @@
anim.play(getFallbackClosingWindowAnimators(appTargets));
}
+ AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(
+ mLauncher, WALLPAPER_OPEN_ANIMATION_FINISHED_MESSAGE);
+ }
+ };
+ if (rectFSpringAnim != null) {
+ rectFSpringAnim.addAnimatorListener(endListener);
+ } else {
+ anim.addListener(endListener);
+ }
+
// Normally, we run the launcher content animation when we are transitioning
// home, but if home is already visible, then we don't want to animate the
// contents of launcher unless we know that we are animating home as a result
@@ -1721,16 +1735,7 @@
// targets list because it is already visible). In that case, we force
// invisibility on touch down, and only reset it after the animation to home
// is initialized.
- if (launcherIsForceInvisibleOrOpening || fromPredictiveBack) {
- AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- AccessibilityManagerCompat.sendTestProtocolEventToTest(
- mLauncher, WALLPAPER_OPEN_ANIMATION_FINISHED_MESSAGE);
- }
- };
-
+ if (launcherIsForceInvisibleOrOpening) {
if (rectFSpringAnim != null && anim.getChildAnimations().isEmpty()) {
addCujInstrumentation(rectFSpringAnim, Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
} else {
@@ -1739,16 +1744,10 @@
: Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
}
- if (fromPredictiveBack && rectFSpringAnim != null) {
- rectFSpringAnim.addAnimatorListener(endListener);
- } else {
- anim.addListener(endListener);
- }
-
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
- if (mLauncher.isInState(LauncherState.ALL_APPS) && !fromPredictiveBack) {
+ if (mLauncher.isInState(LauncherState.ALL_APPS)) {
Pair<AnimatorSet, Runnable> contentAnimator =
getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
skipAllAppsScale);
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index f0129b4..24636c3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -214,8 +214,7 @@
private int getTaskbarAnimationDuration(boolean isVisible) {
// fast animation duration since we will not be playing workspace reveal animation.
- boolean shouldOverrideToFastAnimation =
- !isHotseatIconOnTopWhenAligned() || mLauncher.getPredictiveBackToHomeInProgress();
+ boolean shouldOverrideToFastAnimation = !isHotseatIconOnTopWhenAligned();
boolean isPinnedTaskbar = DisplayController.isPinnedTaskbar(mLauncher);
if (isVisible || isPinnedTaskbar) {
return getTaskbarToHomeDuration(shouldOverrideToFastAnimation, isPinnedTaskbar);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index cc51adc..4a911a6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1328,10 +1328,6 @@
mTISBindHelper.setPredictiveBackToHomeInProgress(isInProgress);
}
- public boolean getPredictiveBackToHomeInProgress() {
- return mIsPredictiveBackToHomeInProgress;
- }
-
@Override
public boolean areDesktopTasksVisible() {
DesktopVisibilityController desktopVisibilityController = getDesktopVisibilityController();
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 4bd9ffb..1d79e85 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -51,11 +51,14 @@
import android.window.BackProgressAnimator;
import android.window.IBackAnimationHandoffHandler;
import android.window.IOnBackInvokedCallback;
+
+import com.android.app.animation.Animations;
import com.android.app.animation.Interpolators;
import com.android.internal.policy.SystemBarUtils;
import com.android.internal.view.AppearanceRegion;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -65,6 +68,7 @@
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.quickstep.util.BackAnimState;
+import com.android.quickstep.util.ScalingWorkspaceRevealAnim;
import com.android.systemui.shared.system.QuickStepContract;
import java.lang.ref.WeakReference;
@@ -87,7 +91,7 @@
*/
public class LauncherBackAnimationController {
private static final int SCRIM_FADE_DURATION = 233;
- private static final float MIN_WINDOW_SCALE = 0.85f;
+ private static final float MIN_WINDOW_SCALE = 0.75f;
private static final float MAX_SCRIM_ALPHA_DARK = 0.8f;
private static final float MAX_SCRIM_ALPHA_LIGHT = 0.2f;
@@ -318,6 +322,12 @@
addScrimLayer();
}
applyTransaction();
+ if (!mLauncher.getWorkspace().isOverlayShown()
+ && !mLauncher.isInState(LauncherState.ALL_APPS)) {
+ Animations.cancelOngoingAnimation(mLauncher.getWorkspace());
+ Animations.cancelOngoingAnimation(mLauncher.getHotseat());
+ setLauncherScale(ScalingWorkspaceRevealAnim.MIN_SIZE);
+ }
}
private void setLauncherTargetViewVisible(boolean isVisible) {
@@ -328,6 +338,13 @@
}
}
+ private void setLauncherScale(float scale) {
+ mLauncher.getWorkspace().setScaleX(scale);
+ mLauncher.getWorkspace().setScaleY(scale);
+ mLauncher.getHotseat().setScaleX(scale);
+ mLauncher.getHotseat().setScaleY(scale);
+ }
+
void addScrimLayer() {
SurfaceControl parent = mLauncherTarget != null ? mLauncherTarget.leash : null;
if (parent == null || !parent.isValid()) {
@@ -500,6 +517,10 @@
if (mScrimLayer != null) {
removeScrimLayer();
}
+ if (!mLauncher.getWorkspace().isOverlayShown()
+ && !mLauncher.isInState(LauncherState.ALL_APPS)) {
+ setLauncherScale(ScalingWorkspaceRevealAnim.MAX_SIZE);
+ }
}
private void startTransitionAnimations(BackAnimState backAnim) {
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 6087dc2..112b40c 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -329,7 +329,7 @@
protected void playScalingRevealAnimation() {
if (mContainer != null) {
new ScalingWorkspaceRevealAnim(mContainer, mSiblingAnimation,
- getWindowTargetRect()).start();
+ getWindowTargetRect(), true /* playAlphaReveal */).start();
}
}
@@ -379,7 +379,7 @@
if (mContainer != null) {
new ScalingWorkspaceRevealAnim(
mContainer, null /* siblingAnimation */,
- null /* windowTargetRect */).start();
+ null /* windowTargetRect */, true /* playAlphaReveal */).start();
}
}
}
diff --git a/quickstep/src/com/android/quickstep/util/BackAnimState.kt b/quickstep/src/com/android/quickstep/util/BackAnimState.kt
index 9009eaa..c78d4a0 100644
--- a/quickstep/src/com/android/quickstep/util/BackAnimState.kt
+++ b/quickstep/src/com/android/quickstep/util/BackAnimState.kt
@@ -36,14 +36,10 @@
BackAnimState {
override fun addOnAnimCompleteCallback(r: Runnable) {
- val springAnimWait = RunnableList()
- springAnim?.addAnimatorListener(forEndCallback(springAnimWait::executeAllAndDestroy))
- ?: springAnimWait.executeAllAndDestroy()
-
val animWait = RunnableList()
- anim?.addListener(
- forEndCallback(Runnable { springAnimWait.add(animWait::executeAllAndDestroy) })
- ) ?: springAnimWait.add(animWait::executeAllAndDestroy)
+ springAnim?.addAnimatorListener(forEndCallback(animWait::executeAllAndDestroy))
+ ?: anim?.addListener(forEndCallback(animWait::executeAllAndDestroy))
+ ?: animWait.executeAllAndDestroy()
animWait.add(r)
}
diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
index f719bed..63eae92 100644
--- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
+++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
@@ -54,14 +54,15 @@
private val launcher: QuickstepLauncher,
siblingAnimation: RectFSpringAnim?,
windowTargetRect: RectF?,
+ playAlphaReveal: Boolean = true,
) {
companion object {
private const val FADE_DURATION_MS = 200L
private const val SCALE_DURATION_MS = 1000L
private const val MAX_ALPHA = 1f
private const val MIN_ALPHA = 0f
- private const val MAX_SIZE = 1f
- private const val MIN_SIZE = 0.85f
+ internal const val MAX_SIZE = 1f
+ internal const val MIN_SIZE = 0.85f
/**
* Custom interpolator for both the home and wallpaper scaling. Necessary because EMPHASIZED
@@ -132,21 +133,23 @@
SCALE_INTERPOLATOR,
)
- // Fade in quickly at the beginning of the animation, so the content doesn't look like it's
- // popping into existence out of nowhere.
- val fadeClamp = FADE_DURATION_MS.toFloat() / SCALE_DURATION_MS
- workspace.alpha = MIN_ALPHA
- animation.setViewAlpha(
- workspace,
- MAX_ALPHA,
- Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
- )
- hotseat.alpha = MIN_ALPHA
- animation.setViewAlpha(
- hotseat,
- MAX_ALPHA,
- Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
- )
+ if (playAlphaReveal) {
+ // Fade in quickly at the beginning of the animation, so the content doesn't look like
+ // it's popping into existence out of nowhere.
+ val fadeClamp = FADE_DURATION_MS.toFloat() / SCALE_DURATION_MS
+ workspace.alpha = MIN_ALPHA
+ animation.setViewAlpha(
+ workspace,
+ MAX_ALPHA,
+ Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
+ )
+ hotseat.alpha = MIN_ALPHA
+ animation.setViewAlpha(
+ hotseat,
+ MAX_ALPHA,
+ Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
+ )
+ }
val transitionConfig = StateAnimationConfig()