Adding support for swipe operation when on home screen

Bug: 137197916
Change-Id: Ic85bf9767d4a9a77dafc1c60c02555f3d2a5d8a2
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 23fe2de..72a9da6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -70,7 +70,7 @@
  * Base class for swipe up handler with some utility methods
  */
 @TargetApi(Build.VERSION_CODES.Q)
-public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity>
+public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q extends RecentsView>
         implements SwipeAnimationListener {
 
     private static final String TAG = "BaseSwipeUpHandler";
@@ -109,7 +109,7 @@
     protected final RecentsAnimationWrapper mRecentsAnimationWrapper;
 
     protected T mActivity;
-    protected RecentsView mRecentsView;
+    protected Q mRecentsView;
     protected DeviceProfile mDp;
     private final int mPageSpacing;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index d033252..922f8e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -86,6 +86,7 @@
 import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.quickstep.util.SwipeAnimationTargetSet;
 import com.android.quickstep.views.LiveTileOverlay;
+import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.InputConsumerController;
@@ -98,7 +99,7 @@
 
 @TargetApi(Build.VERSION_CODES.O)
 public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
-        extends BaseSwipeUpHandler<T>
+        extends BaseSwipeUpHandler<T, RecentsView>
         implements OnApplyWindowInsetsListener {
     private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index eaf6eba..2e9c0a3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 
+import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -31,6 +32,10 @@
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
+
+import java.util.ArrayList;
 
 public class FallbackRecentsView extends RecentsView<RecentsActivity> {
 
@@ -54,6 +59,8 @@
     private float mZoomScale = 1f;
     private float mZoomTranslationY = 0f;
 
+    private RunningTaskInfo mRunningTaskInfo;
+
     public FallbackRecentsView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -151,4 +158,41 @@
         TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY));
         FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
     }
+
+    public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
+        mRunningTaskInfo = runningTaskInfo;
+        onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
+    }
+
+    @Override
+    public void setCurrentTask(int runningTaskId) {
+        super.setCurrentTask(runningTaskId);
+        if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
+            mRunningTaskInfo = null;
+        }
+    }
+
+    @Override
+    protected void applyLoadPlan(ArrayList<Task> tasks) {
+        // When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
+        // as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
+        // track the index of the next task appropriately, as it we are switching on any other app.
+        if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
+            // Check if the task list has running task
+            boolean found = false;
+            for (Task t : tasks) {
+                if (t.key.id == mRunningTaskId) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
+                newList.addAll(tasks);
+                newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
+                tasks = newList;
+            }
+        }
+        super.applyLoadPlan(tasks);
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 53e9461..7abf62d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -47,10 +47,12 @@
 import com.android.quickstep.util.SwipeAnimationTargetSet;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.ActivityOptionsCompat;
 import com.android.systemui.shared.system.InputConsumerController;
 
-public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler<RecentsActivity> {
+public class FallbackNoButtonInputConsumer extends
+        BaseSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
 
     private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
 
@@ -97,6 +99,11 @@
 
     private final boolean mInQuickSwitchMode;
     private final boolean mContinuingLastGesture;
+    private final boolean mRunningOverHome;
+    private final boolean mSwipeUpOverHome;
+
+
+    private final RunningTaskInfo mRunningTaskInfo;
 
     private Animator mFinishAnimation;
 
@@ -108,9 +115,18 @@
         super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
         mLauncherAlpha.value = 1;
 
+        mRunningTaskInfo = runningTaskInfo;
         mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
         mContinuingLastGesture = continuingLastGesture;
-        mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
+        mRunningOverHome = ActivityManagerWrapper.isHomeTask(runningTaskInfo);
+        mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
+
+        if (mSwipeUpOverHome) {
+            mClipAnimationHelper.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
+        } else {
+            mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
+        }
+
         initStateCallbacks();
     }
 
@@ -149,10 +165,14 @@
         mRecentsView.setDisallowScrollToClearAll(true);
         mRecentsView.getClearAllButton().setVisibilityAlpha(0);
 
-        ((FallbackRecentsView) mRecentsView).setZoomProgress(1);
+        mRecentsView.setZoomProgress(1);
 
         if (!mContinuingLastGesture) {
-            mRecentsView.onGestureAnimationStart(mRunningTaskId);
+            if (mRunningOverHome) {
+                mRecentsView.onGestureAnimationStart(mRunningTaskInfo);
+            } else {
+                mRecentsView.onGestureAnimationStart(mRunningTaskId);
+            }
         }
         setStateOnUiThread(STATE_RECENTS_PRESENT);
         return true;
@@ -196,7 +216,7 @@
 
     @Override
     public Intent getLaunchIntent() {
-        if (mInQuickSwitchMode) {
+        if (mInQuickSwitchMode || mSwipeUpOverHome) {
             return mOverviewComponentObserver.getOverviewIntent();
         } else {
             return mOverviewComponentObserver.getHomeIntent();
@@ -282,16 +302,27 @@
         mRecentsView.getClearAllButton().setVisibilityAlpha(1);
     }
 
-
     private void finishAnimationTargetSetAnimationComplete() {
         switch (mEndTarget) {
-            case HOME:
-                mRecentsAnimationWrapper.finish(true, null, true);
+            case HOME: {
+                if (mSwipeUpOverHome) {
+                    mRecentsAnimationWrapper.finish(false, null, false);
+                    // Send a home intent to clear the task stack
+                    mContext.startActivity(mOverviewComponentObserver.getHomeIntent());
+                } else {
+                    mRecentsAnimationWrapper.finish(true, null, true);
+                }
                 break;
+            }
             case LAST_TASK:
                 mRecentsAnimationWrapper.finish(false, null, false);
                 break;
             case RECENTS: {
+                if (mSwipeUpOverHome) {
+                    mRecentsAnimationWrapper.finish(true, null, true);
+                    break;
+                }
+
                 ThumbnailData thumbnail =
                         mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId);
                 mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
@@ -367,6 +398,10 @@
     public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
         super.onRecentsAnimationStart(targetSet);
         mRecentsAnimationWrapper.enableInputConsumer();
+
+        if (mRunningOverHome) {
+            mClipAnimationHelper.prepareAnimation(mDp, true);
+        }
         applyTransformUnchecked();
 
         setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 6bf3155..66ddc72 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -269,7 +269,7 @@
     private int mTaskListChangeId = -1;
 
     // Only valid until the launcher state changes to NORMAL
-    private int mRunningTaskId = -1;
+    protected int mRunningTaskId = -1;
     private boolean mRunningTaskTileHidden;
     private Task mTmpRunningTask;
 
@@ -532,7 +532,7 @@
         return true;
     }
 
-    private void applyLoadPlan(ArrayList<Task> tasks) {
+    protected void applyLoadPlan(ArrayList<Task> tasks) {
         if (mPendingAnimation != null) {
             mPendingAnimation.addEndListener((onEndListener) -> applyLoadPlan(tasks));
             return;
@@ -855,12 +855,14 @@
      * is called.  Also scrolls the view to this task.
      */
     public void showCurrentTask(int runningTaskId) {
-        if (getChildCount() == 0) {
+        if (getTaskView(runningTaskId) == null) {
+            boolean wasEmpty = getChildCount() == 0;
             // Add an empty view for now until the task plan is loaded and applied
             final TaskView taskView = mTaskViewPool.getView();
-            addView(taskView);
-            addView(mClearAllButton);
-
+            addView(taskView, 0);
+            if (wasEmpty) {
+                addView(mClearAllButton);
+            }
             // The temporary running task is only used for the duration between the start of the
             // gesture and the task list is loaded and applied
             mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(),
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 7a1d0e8..d807b89 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -28,8 +28,6 @@
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.KeyguardManagerCompat;
-import com.android.systemui.shared.system.RecentTaskInfoCompat;
-import com.android.systemui.shared.system.TaskDescriptionCompat;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -86,8 +84,9 @@
                 : () -> callback.accept(copyOf(mTasks));
 
         if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
-            // The list is up to date, callback with the same list
-            mMainThreadExecutor.execute(resultCallback);
+            // The list is up to date, send the callback on the next frame,
+            // so that requestID can be returned first.
+            mMainThreadExecutor.getHandler().post(resultCallback);
             return requestLoadId;
         }
 
@@ -165,15 +164,11 @@
         int taskCount = rawTasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
-            RecentTaskInfoCompat t = new RecentTaskInfoCompat(rawTask);
             Task.TaskKey taskKey = new Task.TaskKey(rawTask);
             Task task;
             if (!loadKeysOnly) {
-                ActivityManager.TaskDescription rawTd = t.getTaskDescription();
-                TaskDescriptionCompat td = new TaskDescriptionCompat(rawTd);
-                boolean isLocked = tmpLockedUsers.get(t.getUserId());
-                task = new Task(taskKey, td.getPrimaryColor(), td.getBackgroundColor(),
-                        t.supportsSplitScreenMultiWindow(), isLocked, rawTd, t.getTopActivity());
+                boolean isLocked = tmpLockedUsers.get(taskKey.userId);
+                task = Task.from(taskKey, rawTask, isLocked);
             } else {
                 task = new Task(taskKey);
             }