Merge "Split TaskUtils for Go recents" into ub-launcher3-master
diff --git a/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
new file mode 100644
index 0000000..d9873fe
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.systemui.shared.system.ActivityManagerWrapper
+        .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+
+import android.animation.AnimatorSet;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.os.SystemClock;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
+import com.android.quickstep.views.IconRecentsView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.LatencyTrackerCompat;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Helper class to handle various atomic commands for switching between Overview.
+ */
+@TargetApi(Build.VERSION_CODES.P)
+public class OverviewCommandHelper {
+
+    private final Context mContext;
+    private final ActivityManagerWrapper mAM;
+    private final RecentsModel mRecentsModel;
+    private final MainThreadExecutor mMainThreadExecutor;
+    private final OverviewComponentObserver mOverviewComponentObserver;
+
+    private long mLastToggleTime;
+
+    public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
+        mContext = context;
+        mAM = ActivityManagerWrapper.getInstance();
+        mMainThreadExecutor = new MainThreadExecutor();
+        mRecentsModel = RecentsModel.INSTANCE.get(mContext);
+        mOverviewComponentObserver = observer;
+    }
+
+    public void onOverviewToggle() {
+        // If currently screen pinning, do not enter overview
+        if (mAM.isScreenPinningActive()) {
+            return;
+        }
+
+        mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+        mMainThreadExecutor.execute(new RecentsActivityCommand<>());
+    }
+
+    public void onOverviewShown(boolean triggeredFromAltTab) {
+        mMainThreadExecutor.execute(new ShowRecentsCommand());
+    }
+
+    public void onOverviewHidden() {
+        mMainThreadExecutor.execute(new HideRecentsCommand());
+    }
+
+    public void onTip(int actionType, int viewType) {
+        mMainThreadExecutor.execute(() ->
+                UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
+    }
+
+    private class ShowRecentsCommand extends RecentsActivityCommand {
+
+        @Override
+        protected boolean handleCommand(long elapsedTime) {
+            return mHelper.getVisibleRecentsView() != null;
+        }
+    }
+
+    private class HideRecentsCommand extends RecentsActivityCommand {
+
+        @Override
+        protected boolean handleCommand(long elapsedTime) {
+            IconRecentsView recents = (IconRecentsView) mHelper.getVisibleRecentsView();
+            if (recents == null) {
+                return false;
+            }
+            //TODO: Launch last running task or go to home.
+            return true;
+        }
+    }
+
+    private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable {
+
+        protected final ActivityControlHelper<T> mHelper;
+        private final long mCreateTime;
+        private final AppToOverviewAnimationProvider<T> mAnimationProvider;
+
+        private final long mToggleClickedTime = SystemClock.uptimeMillis();
+        private boolean mUserEventLogged;
+        private ActivityInitListener mListener;
+
+        public RecentsActivityCommand() {
+            mHelper = mOverviewComponentObserver.getActivityControlHelper();
+            mCreateTime = SystemClock.elapsedRealtime();
+            mAnimationProvider =
+                    new AppToOverviewAnimationProvider<>(mHelper, RecentsModel.getRunningTaskId());
+
+            // Preload the plan
+            mRecentsModel.getTasks(null);
+        }
+
+        @Override
+        public void run() {
+            long elapsedTime = mCreateTime - mLastToggleTime;
+            mLastToggleTime = mCreateTime;
+
+            if (handleCommand(elapsedTime)) {
+                // Command already handled.
+                return;
+            }
+
+            if (mHelper.switchToRecentsIfVisible(null /* onCompleteCallback */)) {
+                // If successfully switched, then return
+                return;
+            }
+
+            // Otherwise, start overview.
+            mListener = mHelper.createActivityInitListener(this::onActivityReady);
+            mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
+                    this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
+                    mAnimationProvider.getRecentsLaunchDuration());
+        }
+
+        protected boolean handleCommand(long elapsedTime) {
+            IconRecentsView recents = mHelper.getVisibleRecentsView();
+            if (recents != null) {
+                //TODO: Launch next task in icon recents.
+                return true;
+            } else if (elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+                // The user tried to launch back into overview too quickly, either after
+                // launching an app, or before overview has actually shown, just ignore for now
+                return true;
+            }
+            return false;
+        }
+
+        private boolean onActivityReady(T activity, Boolean wasVisible) {
+            if (!mUserEventLogged) {
+                activity.getUserEventDispatcher().logActionCommand(
+                        LauncherLogProto.Action.Command.RECENTS_BUTTON,
+                        mHelper.getContainerType(),
+                        LauncherLogProto.ContainerType.TASKSWITCHER);
+                mUserEventLogged = true;
+            }
+            return mAnimationProvider.onActivityReady(activity, wasVisible);
+        }
+
+        private AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
+            if (LatencyTrackerCompat.isEnabled(mContext)) {
+                LatencyTrackerCompat.logToggleRecents(
+                        (int) (SystemClock.uptimeMillis() - mToggleClickedTime));
+            }
+
+            mListener.unregister();
+
+            return mAnimationProvider.createWindowAnimation(targetCompats);
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
similarity index 100%
rename from quickstep/src/com/android/quickstep/OverviewCommandHelper.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
index ca8c252..6b3f028 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -30,13 +30,14 @@
 
 public class RecentsRootView extends BaseDragLayer<RecentsActivity> {
 
+    private static final int MIN_SIZE = 10;
     private final RecentsActivity mActivity;
 
-    private final Point mLastKnownSize = new Point(10, 10);
+    private final Point mLastKnownSize = new Point(MIN_SIZE, MIN_SIZE);
 
     public RecentsRootView(Context context, AttributeSet attrs) {
         super(context, attrs, 1 /* alphaChannelCount */);
-        mActivity = (RecentsActivity) BaseActivity.fromContext(context);
+        mActivity = BaseActivity.fromContext(context);
         setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                 | SYSTEM_UI_FLAG_LAYOUT_STABLE);
@@ -53,8 +54,8 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // Check size changes before the actual measure, to avoid multiple measure calls.
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        int height = MeasureSpec.getSize(heightMeasureSpec);
+        int width = Math.max(MIN_SIZE, MeasureSpec.getSize(widthMeasureSpec));
+        int height = Math.max(MIN_SIZE, MeasureSpec.getSize(heightMeasureSpec));
         if (mLastKnownSize.x != width || mLastKnownSize.y != height) {
             mLastKnownSize.set(width, height);
             mActivity.onRootViewSizeChanged();
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 7aea870..01535b0 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -322,7 +322,7 @@
         // Workspace
         final boolean isVerticalLayout = isVerticalBarLayout();
         float invIconSizePx = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
-        iconSizePx = (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale);
+        iconSizePx = Math.max(1, (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale));
         iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
         iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);