Merge "Disabling testToast on virtual devices" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index a17476e..e9ce692 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
@@ -32,6 +31,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
+import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -78,18 +78,16 @@
     private static final String TAG = "BaseSwipeUpHandler";
     protected static final Rect TEMP_RECT = new Rect();
 
-    // Start resisting when swiping past this factor of mTransitionDragLength.
-    private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = ENABLE_OVERVIEW_ACTIONS.get()
-            ? 2.8f : 1.4f;
-    // This is how far down we can scale down, where 0f is full screen and 1f is recents.
-    private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = ENABLE_OVERVIEW_ACTIONS.get()
-            ? 3.6f : 1.8f;
     private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
 
     // The distance needed to drag to reach the task size in recents.
     protected int mTransitionDragLength;
     // How much further we can drag past recents, as a factor of mTransitionDragLength.
     protected float mDragLengthFactor = 1;
+    // Start resisting when swiping past this factor of mTransitionDragLength.
+    private float mDragLengthFactorStartPullback = 1f;
+    // This is how far down we can scale down, where 0f is full screen and 1f is recents.
+    private float mDragLengthFactorMaxPullback = 1f;
 
     protected final Context mContext;
     protected final RecentsAnimationDeviceState mDeviceState;
@@ -161,12 +159,12 @@
         } else {
             float translation = Math.max(displacement, 0);
             shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
-            if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
+            if (shift > mDragLengthFactorStartPullback) {
                 float pullbackProgress = Utilities.getProgress(shift,
-                        DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
+                        mDragLengthFactorStartPullback, mDragLengthFactor);
                 pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
-                shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
-                        * (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
+                shift = mDragLengthFactorStartPullback + pullbackProgress
+                        * (mDragLengthFactorMaxPullback - mDragLengthFactorStartPullback);
             }
         }
 
@@ -344,6 +342,10 @@
             //   their ability to scale past the target rect.
             float dragFactor = (float) dp.heightPx / mTransitionDragLength;
             mDragLengthFactor = displayRotation == 0 ? dragFactor : Math.min(1.0f, dragFactor);
+            Pair<Float, Float> dragFactorStartAndMaxProgress =
+                    mActivityInterface.getSwipeUpPullbackStartAndMaxProgress();
+            mDragLengthFactorStartPullback = dragFactorStartAndMaxProgress.first;
+            mDragLengthFactorMaxPullback = dragFactorStartAndMaxProgress.second;
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index f19ec69..ccc2150 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -38,6 +38,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.UserHandle;
+import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -54,7 +55,6 @@
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.appprediction.PredictionUiStateManager;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.views.FloatingIconView;
@@ -80,6 +80,8 @@
 public final class LauncherActivityInterface implements BaseActivityInterface<Launcher> {
 
     private Runnable mAdjustInterpolatorsRunnable;
+    private Pair<Float, Float> mSwipeUpPullbackStartAndMaxProgress =
+            BaseActivityInterface.super.getSwipeUpPullbackStartAndMaxProgress();
 
     @Override
     public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
@@ -94,6 +96,11 @@
     }
 
     @Override
+    public Pair<Float, Float> getSwipeUpPullbackStartAndMaxProgress() {
+        return mSwipeUpPullbackStartAndMaxProgress;
+    }
+
+    @Override
     public void onTransitionCancelled(boolean activityVisible) {
         Launcher launcher = getCreatedActivity();
         if (launcher == null) {
@@ -385,6 +392,14 @@
                 return newT <= 1f ? newT : newT + normalizedTranslationY * (newT - 1);
             });
         };
+
+        // Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f.
+        float pullbackStartProgress = (0.75f - fromScaleAndTranslation.scale)
+                / (endScaleAndTranslation.scale - fromScaleAndTranslation.scale);
+        float pullbackMaxProgress = (0.5f - fromScaleAndTranslation.scale)
+                / (endScaleAndTranslation.scale - fromScaleAndTranslation.scale);
+        mSwipeUpPullbackStartAndMaxProgress = new Pair<>(
+                pullbackStartProgress, pullbackMaxProgress);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index d39dfda..fb0cd17 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -54,6 +54,7 @@
 import com.android.quickstep.util.RemoteFadeOutAnimationListener;
 import com.android.quickstep.util.ShelfPeekAnim;
 import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import java.util.stream.Stream;
 
@@ -158,6 +159,12 @@
     }
 
     @Override
+    protected void onUiChangedWhileSleeping() {
+        // Remove the snapshot because the content view may have obvious changes.
+        ActivityManagerWrapper.getInstance().invalidateHomeTaskSnapshot(this);
+    }
+
+    @Override
     public void startIntentSenderForResult(IntentSender intent, int requestCode,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
         if (requestCode != -1) {
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 64e053f..1d71fe2 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
+import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -50,6 +51,15 @@
 
     int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
 
+    /**
+     * @return The progress of the swipe where we start resisting the user, where 0 is fullscreen
+     * and 1 is recents. These values should probably be greater than 1 to let the user swipe past
+     * recents before we start resisting them.
+     */
+    default Pair<Float, Float> getSwipeUpPullbackStartAndMaxProgress() {
+        return new Pair<>(1.4f, 1.8f);
+    }
+
     void onSwipeUpToRecentsComplete();
 
     default void onSwipeUpToHomeComplete() { }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3e10323..20ebc7a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -924,6 +924,9 @@
 
     @Override
     protected void onStop() {
+        final boolean wasActive = isUserActive();
+        final LauncherState origState = getStateManager().getState();
+        final int origDragLayerChildCount = mDragLayer.getChildCount();
         super.onStop();
 
         if (mDeferOverlayCallbacks) {
@@ -941,6 +944,20 @@
 
         // Workaround for b/78520668, explicitly trim memory once UI is hidden
         onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
+
+        if (wasActive) {
+            // The expected condition is that this activity is stopped because the device goes to
+            // sleep and the UI may have noticeable changes.
+            mDragLayer.post(() -> {
+                if ((!getStateManager().isInStableState(origState)
+                        // The drag layer may be animating (e.g. dismissing QSB).
+                        || mDragLayer.getAlpha() < 1
+                        // Maybe an ArrowPopup is closed.
+                        || mDragLayer.getChildCount() != origDragLayerChildCount)) {
+                    onUiChangedWhileSleeping();
+                }
+            });
+        }
     }
 
     @Override
@@ -1336,11 +1353,16 @@
             // Reset AllApps to its initial state only if we are not in the middle of
             // processing a multi-step drop
             if (mPendingRequestArgs == null) {
+                if (!isInState(NORMAL)) {
+                    onUiChangedWhileSleeping();
+                }
                 mStateManager.goToState(NORMAL);
             }
         }
     };
 
+    protected void onUiChangedWhileSleeping() { }
+
     private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
         mWorkspace.updateNotificationDots(updatedDots);
         mAppsView.getAppsStore().updateNotificationDots(updatedDots);
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 195e69b..9f25729 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -164,6 +164,15 @@
     }
 
     /**
+     * @return {@code true} if the state matches the current state and there is no active
+     *         transition to different state.
+     */
+    public boolean isInStableState(LauncherState state) {
+        return mState == state && mCurrentStableState == state
+                && (mConfig.mTargetState == null || mConfig.mTargetState == state);
+    }
+
+    /**
      * @see #goToState(LauncherState, boolean, Runnable)
      */
     public void goToState(LauncherState state) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index b689a0a..aab6671 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -143,6 +143,11 @@
             "ENABLE_LSQ_VELOCITY_PROVIDER", false,
             "Use Least Square algorithm for motion pause detection.");
 
+    public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS =
+            getDebugFlag(
+            "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", false,
+            "Always use hardware optimization for folder animations.");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index e33d89f..69f93de 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -26,6 +26,7 @@
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS;
 import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_CUSTOM;
 import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_EMPTY;
 import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_FOLDER_LABEL_STATE_UNSPECIFIED;
@@ -546,6 +547,8 @@
     }
 
     private boolean shouldUseHardwareLayerForAnimation(CellLayout currentCellLayout) {
+        if (ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS.get()) return true;
+
         int folderCount = 0;
         final ShortcutAndWidgetContainer container = currentCellLayout.getShortcutsAndWidgets();
         for (int i = container.getChildCount() - 1; i >= 0; --i) {