Merge "Fix a couple issues with swiping up from home" into ub-launcher3-edmonton
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 5e25fd8..53a6ceb 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 3e80d2c..b371677 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -93,7 +93,11 @@
                     TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
         }
         OverviewInteractionState.getInstance(launcher)
-                .setBackButtonVisible(!shouldBackButtonBeHidden);
+                .setBackButtonAlpha(shouldBackButtonBeHidden ? 0 : 1, true /* animate */);
+    }
+
+    public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) {
+         OverviewInteractionState.getInstance(launcher).setBackButtonAlpha(alpha,animate);
     }
 
     public static void resetOverview(Launcher launcher) {
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 2d41a5b..d1003a5 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -82,7 +82,10 @@
     private final PointF mLastPos = new PointF();
     private int mActivePointerId = INVALID_POINTER_ID;
     private boolean mPassedInitialSlop;
+    // Used for non-deferred gestures to determine when to start dragging
     private int mQuickStepDragSlop;
+    // Used for deferred gestures to determine both start of animation and dragging
+    private int mQuickStepTouchSlop;
     private float mStartDisplacement;
     private WindowTransformSwipeHandler mInteractionHandler;
     private int mDisplayRotation;
@@ -128,6 +131,7 @@
                 mLastPos.set(mDownPos);
                 mPassedInitialSlop = false;
                 mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx();
+                mQuickStepTouchSlop = NavigationBarCompat.getQuickStepTouchSlopPx();
 
                 // Start the window animation on down to give more time for launcher to draw if the
                 // user didn't start the gesture over the back button
@@ -160,15 +164,22 @@
                 }
                 mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
                 float displacement = getDisplacement(ev);
-                if (!mPassedInitialSlop
-                        && Math.abs(displacement) > mQuickStepDragSlop) {
-                    mPassedInitialSlop = true;
-                    mStartDisplacement = displacement;
-
-                    // If we deferred starting the window animation on touch down, then
-                    // start tracking now
+                if (!mPassedInitialSlop) {
                     if (mIsDeferredDownTarget) {
-                        startTouchTrackingForWindowAnimation(ev.getEventTime());
+                        // Deferred gesture, start the animation and gesture tracking once we pass
+                        // the touch slop
+                        if (Math.abs(displacement) > mQuickStepTouchSlop) {
+                            startTouchTrackingForWindowAnimation(ev.getEventTime());
+                            mPassedInitialSlop = true;
+                            mStartDisplacement = displacement;
+                        }
+                    } else {
+                        // Normal gesture, ensure we pass the drag slop before we start tracking
+                        // the gesture
+                        if (Math.abs(displacement) > mQuickStepDragSlop) {
+                            mPassedInitialSlop = true;
+                            mStartDisplacement = displacement;
+                        }
                     }
                 }
 
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 420406c..d605746 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -17,7 +17,6 @@
 
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.shared.system.SettingsCompat.SWIPE_UP_SETTING_NAME;
 
@@ -46,7 +45,6 @@
  *
  *   - FLAG_DISABLE_QUICK_SCRUB
  *   - FLAG_DISABLE_SWIPE_UP
- *   - FLAG_HIDE_BACK_BUTTON
  *   - FLAG_SHOW_OVERVIEW_BUTTON
  *
  * @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags.
@@ -81,7 +79,7 @@
     }
 
     private static final int MSG_SET_PROXY = 200;
-    private static final int MSG_SET_BACK_BUTTON_VISIBLE = 201;
+    private static final int MSG_SET_BACK_BUTTON_ALPHA = 201;
     private static final int MSG_SET_SWIPE_UP_ENABLED = 202;
 
     private final SwipeUpGestureEnabledSettingObserver mSwipeUpSettingObserver;
@@ -92,13 +90,16 @@
 
     // These are updated on the background thread
     private ISystemUiProxy mISystemUiProxy;
-    private boolean mBackButtonVisible = true;
     private boolean mSwipeUpEnabled = true;
 
     private Runnable mOnSwipeUpSettingChangedListener;
 
     private OverviewInteractionState(Context context) {
         mContext = context;
+
+        // Data posted to the uihandler will be sent to the bghandler. Data is sent to uihandler
+        // because of its high send frequency and data may be very different than the previous value
+        // For example, send back alpha on uihandler to avoid flickering when setting its visibility
         mUiHandler = new Handler(this::handleUiMessage);
         mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
 
@@ -116,9 +117,9 @@
         return mSwipeUpEnabled;
     }
 
-    public void setBackButtonVisible(boolean visible) {
-        mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_VISIBLE);
-        mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_VISIBLE, visible ? 1 : 0, 0)
+    public void setBackButtonAlpha(float alpha, boolean animate) {
+        mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_ALPHA);
+        mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_ALPHA, animate ? 1 : 0, 0, alpha)
                 .sendToTarget();
     }
 
@@ -127,7 +128,7 @@
     }
 
     private boolean handleUiMessage(Message msg) {
-        mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2).sendToTarget();
+        mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2, msg.obj).sendToTarget();
         return true;
     }
 
@@ -136,9 +137,9 @@
             case MSG_SET_PROXY:
                 mISystemUiProxy = (ISystemUiProxy) msg.obj;
                 break;
-            case MSG_SET_BACK_BUTTON_VISIBLE:
-                mBackButtonVisible = msg.arg1 != 0;
-                break;
+            case MSG_SET_BACK_BUTTON_ALPHA:
+                applyBackButtonAlpha((float) msg.obj, msg.arg1 == 1);
+                return true;
             case MSG_SET_SWIPE_UP_ENABLED:
                 mSwipeUpEnabled = msg.arg1 != 0;
                 resetHomeBounceSeenOnQuickstepEnabledFirstTime();
@@ -162,10 +163,8 @@
             return;
         }
 
-        int flags;
-        if (mSwipeUpEnabled) {
-            flags = mBackButtonVisible ? 0 : FLAG_HIDE_BACK_BUTTON;
-        } else {
+        int flags = 0;
+        if (!mSwipeUpEnabled) {
             flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON;
         }
         try {
@@ -175,6 +174,18 @@
         }
     }
 
+    @WorkerThread
+    private void applyBackButtonAlpha(float alpha, boolean animate) {
+        if (mISystemUiProxy == null) {
+            return;
+        }
+        try {
+            mISystemUiProxy.setBackButtonAlpha(alpha, animate);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Unable to update overview back button alpha", e);
+        }
+    }
+
     private class SwipeUpGestureEnabledSettingObserver extends ContentObserver {
         private Handler mHandler;
         private ContentResolver mResolver;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 01e5cba..aeff476 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -39,6 +39,8 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.Handler;
+import android.os.UserHandle;
 import android.text.Layout;
 import android.text.StaticLayout;
 import android.text.TextPaint;
@@ -78,6 +80,8 @@
 import com.android.systemui.shared.recents.model.TaskStack;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.BackgroundExecutor;
+import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 
 import java.util.ArrayList;
@@ -166,10 +170,38 @@
             if (!mHandleTaskStackChanges) {
                 return;
             }
-            TaskView taskView = getTaskView(taskId);
-            if (taskView != null) {
-                dismissTask(taskView, true /* animate */, false /* removeTask */);
-            }
+            BackgroundExecutor.get().submit(() -> {
+                TaskView taskView = getTaskView(taskId);
+                if (taskView == null) {
+                    return;
+                }
+                Handler handler = taskView.getHandler();
+                if (handler == null) {
+                    return;
+                }
+
+                // TODO: Add callbacks from AM reflecting adding/removing from the recents list, and
+                //       remove all these checks
+                Task.TaskKey taskKey = taskView.getTask().key;
+                if (PackageManagerWrapper.getInstance().getActivityInfo(taskKey.getComponent(),
+                        taskKey.userId) == null) {
+                    // The package was uninstalled
+                    handler.post(() ->
+                            dismissTask(taskView, true /* animate */, false /* removeTask */));
+                } else {
+                    RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(getContext());
+                    RecentsTaskLoadPlan.PreloadOptions opts =
+                            new RecentsTaskLoadPlan.PreloadOptions();
+                    opts.loadTitles = false;
+                    loadPlan.preloadPlan(opts, mModel.getRecentsTaskLoader(), -1,
+                            UserHandle.myUserId());
+                    if (loadPlan.getTaskStack().findTaskWithId(taskId) == null) {
+                        // The task was removed from the recents list
+                        handler.post(() ->
+                                dismissTask(taskView, true /* animate */, false /* removeTask */));
+                    }
+                }
+            });
         }
 
         @Override
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2c3e3ee..b5c821a 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -25,9 +25,11 @@
 import com.android.launcher3.LauncherStateManager.AnimationConfig;
 import com.android.launcher3.LauncherStateManager.StateHandler;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorSetBuilder;
 import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ScrimView;
 
@@ -182,6 +184,13 @@
         anim.setDuration(config.duration);
         anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
         anim.addListener(getProgressAnimatorListener());
+        if (toState.hideBackButton) {
+            anim.addUpdateListener(animation -> {
+                final float alpha = (float) animation.getAnimatedValue();
+                UiFactory.setBackButtonAlpha(mLauncher, 1 - Utilities.boundToRange(alpha, 0, 1),
+                        false /* animate */);
+            });
+        }
 
         builder.play(anim);
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 24382b7..0e68538 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -42,6 +42,7 @@
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -223,6 +224,8 @@
             cancelAtomicComponentsController();
         }
         mProgressMultiplier = initCurrentAnimation(animComponents);
+        mCurrentAnimation.getAnimationPlayer().addUpdateListener(animation ->
+                setBackButtonAlphaWithProgress((float) animation.getAnimatedValue()));
         mCurrentAnimation.dispatchOnStart();
         return true;
     }
@@ -281,6 +284,7 @@
             mAtomicComponentsController.setPlayFraction(fraction - mAtomicComponentsStartProgress);
         }
         maybeUpdateAtomicAnim(mFromState, mToState, fraction);
+        setBackButtonAlphaWithProgress(fraction);
     }
 
     /**
@@ -473,6 +477,14 @@
         }
     }
 
+    private void setBackButtonAlphaWithProgress(float progress) {
+        if (mFromState.hideBackButton ^ mToState.hideBackButton) {
+            progress = Utilities.boundToRange(progress, 0, 1);
+            final float alpha = mToState.hideBackButton ? 1 - progress : progress;
+            UiFactory.setBackButtonAlpha(mLauncher, alpha, false /* animate */);
+        }
+    }
+
     private void logReachedState(int logAction) {
         // Transition complete. log the action
         mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index e93dd5a..db98f9a 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -56,4 +56,6 @@
     }
 
     public static void prepareToShowOverview(Launcher launcher) { }
+
+    public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) { }
 }