Merge "Make exception for TASKBAR_PINNING so it is boot aware." into main
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index ca4f0ea..e788cc4 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -51,6 +51,7 @@
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.INVALID_VELOCITY_ON_SWIPE_UP;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.LAUNCHER_DESTROYED;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -1214,6 +1215,11 @@
 
     private GestureEndTarget calculateEndTarget(
             PointF velocityPxPerMs, float endVelocityPxPerMs, boolean isFlingY, boolean isCancel) {
+
+        ActiveGestureErrorDetector.GestureEvent gestureEvent =
+                velocityPxPerMs.x == 0 && velocityPxPerMs.y == 0
+                        ? INVALID_VELOCITY_ON_SWIPE_UP
+                        : null;
         ActiveGestureLog.INSTANCE.addLog(
                 new ActiveGestureLog.CompoundString("calculateEndTarget: velocities=(x=")
                         .append(Float.toString(dpiFromPx(velocityPxPerMs.x)))
@@ -1221,7 +1227,7 @@
                         .append(Float.toString(dpiFromPx(velocityPxPerMs.y)))
                         .append("dp/ms), angle=")
                         .append(Double.toString(Math.toDegrees(Math.atan2(
-                                -velocityPxPerMs.y, velocityPxPerMs.x)))));
+                                -velocityPxPerMs.y, velocityPxPerMs.x)))), gestureEvent);
 
         if (mGestureState.isHandlingAtomicEvent()) {
             // Button mode, this is only used to go to recents.
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 4d7a5bb..20fa921 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -39,6 +39,7 @@
         SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT,
         SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
         FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED, RECENT_TASKS_MISSING,
+        INVALID_VELOCITY_ON_SWIPE_UP,
 
         /**
          * These GestureEvents are specifically associated to state flags that get set in
@@ -66,6 +67,8 @@
 
     private ActiveGestureErrorDetector() {}
 
+    private static final long ON_START_RECENT_ANIMATION_TIME_LIMIT = 500;
+
     protected static void analyseAndDump(
             @NonNull String prefix,
             @NonNull PrintWriter writer,
@@ -76,6 +79,7 @@
         // Use a Set since the order is inherently checked in the loop.
         final Set<GestureEvent> encounteredEvents = new ArraySet<>();
         // Set flags and check order of operations.
+        long lastStartRecentAnimationEventEntryTime = 0;
         for (ActiveGestureLog.EventEntry eventEntry : eventLog.eventEntries) {
             GestureEvent gestureEvent = eventEntry.getGestureEvent();
             if (gestureEvent == null) {
@@ -234,6 +238,16 @@
                             /* errorMessage= */ "ON_START_RECENTS_ANIMATION "
                                     + "onAnimationStart callback ran before startRecentsAnimation",
                             writer);
+                    errorDetected |= printErrorIfTrue(
+                            eventEntry.getTime() - lastStartRecentAnimationEventEntryTime
+                                    > ON_START_RECENT_ANIMATION_TIME_LIMIT,
+                            prefix,
+                            /* errorMessage= */"ON_START_RECENTS_ANIMATION "
+                                    + "startRecentsAnimation was never called or onAnimationStart "
+                                    + "callback was called more than 500 ms after "
+                                    + "startRecentsAnimation.",
+                            writer);
+                    lastStartRecentAnimationEventEntryTime = 0;
                     break;
                 case ON_CANCEL_RECENTS_ANIMATION:
                     errorDetected |= printErrorIfTrue(
@@ -253,12 +267,21 @@
                                     + "callback",
                             writer);
                     break;
+                case INVALID_VELOCITY_ON_SWIPE_UP:
+                    errorDetected |= printErrorIfTrue(
+                            true,
+                            prefix,
+                            /* errorMessage= */ "invalid velocity on swipe up gesture.",
+                            writer);
+                    break;
+                case START_RECENTS_ANIMATION:
+                    lastStartRecentAnimationEventEntryTime = eventEntry.getTime();
+                    break;
                 case MOTION_DOWN:
                 case SET_END_TARGET:
                 case SET_END_TARGET_HOME:
                 case SET_END_TARGET_ALL_APPS:
                 case SET_END_TARGET_NEW_TASK:
-                case START_RECENTS_ANIMATION:
                 case SET_ON_PAGE_TRANSITION_END_CALLBACK:
                 case CANCEL_CURRENT_ANIMATION:
                 case FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER:
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index d6a2e93..7103e63 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -266,6 +266,10 @@
             time = System.currentTimeMillis();
             duplicateCount = 0;
         }
+
+        public long getTime() {
+            return time;
+        }
     }
 
     /** An entire log of entries associated with a single log ID */
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index cc56faf..d8e1fd4 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -108,7 +108,6 @@
     }
 
     @Test
-    @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
     public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
         assumeTrue("App pairs feature is currently not enabled, no test needed",
                 FeatureFlags.ENABLE_APP_PAIRS.get());
@@ -124,7 +123,6 @@
     }
 
     @Test
-    @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
     public void testSaveAppPairMenuItemDoesNotExistOnSingleTask() throws Exception {
         assumeTrue("App pairs feature is currently not enabled, no test needed",
                 FeatureFlags.ENABLE_APP_PAIRS.get());
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index 32e3b77..276d73e 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -37,11 +37,14 @@
         android:id="@+id/pause_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:maxWidth="@dimen/work_fab_width"
         android:textColor="@color/work_fab_icon_color"
         android:textSize="14sp"
         android:includeFontPadding="false"
         android:textDirection="locale"
         android:text="@string/work_apps_pause_btn_text"
         android:layout_marginStart="@dimen/work_fab_text_start_margin"
+        android:ellipsize="end"
+        android:maxLines="1"
         style="@style/TextHeadline"/>
 </com.android.launcher3.allapps.WorkModeSwitch>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c6fce28..10f47cb 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -141,6 +141,7 @@
     <dimen name="work_fab_icon_size">24dp</dimen>
     <dimen name="work_fab_text_start_margin">8dp</dimen>
     <dimen name="work_card_padding_horizontal">10dp</dimen>
+    <dimen name="work_fab_width">214dp</dimen>
     <dimen name="work_card_button_height">52dp</dimen>
     <dimen name="work_fab_margin">16dp</dimen>
     <dimen name="work_fab_margin_bottom">20dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1b46b4d..a2f4a61 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -433,7 +433,7 @@
     <!-- button string shown to dismiss work tab education -->
     <string name="work_apps_paused_edu_accept">Got it</string>
 
-    <!-- button string shown pause work profile -->
+    <!-- button string shown pause work profile [CHAR LIMIT=28] -->
     <string name="work_apps_pause_btn_text">Pause work apps</string>
     <!-- button string shown enable work profile -->
     <string name="work_apps_enable_btn_text">Unpause</string>
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 211bc0d..9fb175d 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -190,6 +190,10 @@
             "ENABLE_PARAMETRIZE_REORDER", DISABLED,
             "Enables generating the reorder using a set of parameters");
 
+    public static final BooleanFlag ENABLE_NO_LONG_PRESS_DRAG = getDebugFlag(299748096,
+            "ENABLE_NO_LONG_PRESS_DRAG", DISABLED,
+            "Don't trigger the drag if we are still under long press");
+
     // TODO(Block 12): Clean up flags
     public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680,
             "ENABLE_MULTI_INSTANCE", DISABLED,
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 0d51d48..777f4d5 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.dragndrop;
 
 import static com.android.launcher3.Utilities.ATLEAST_Q;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_NO_LONG_PRESS_DRAG;
 
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -87,6 +88,10 @@
     private int mLastTouchClassification;
     protected int mDistanceSinceScroll = 0;
 
+    /**
+     * This variable is to differentiate between a long press and a drag, if it's true that means
+     * it's a long press and when it's false means that we are no longer in a long press.
+     */
     protected boolean mIsInPreDrag;
 
     private final int DRAG_VIEW_SCALE_DURATION_MS = 500;
@@ -370,7 +375,7 @@
     @Override
     public void onDriverDragEnd(float x, float y) {
         if (!endWithFlingAnimation()) {
-            drop(findDropTarget((int) x, (int) y, mCoordinatesTemp), null);
+            drop(findDropTarget((int) x, (int) y), null);
         }
         endDrag();
     }
@@ -432,13 +437,6 @@
     protected void handleMoveEvent(int x, int y) {
         mDragObject.dragView.move(x, y);
 
-        // Drop on someone?
-        final int[] coordinates = mCoordinatesTemp;
-        DropTarget dropTarget = findDropTarget(x, y, coordinates);
-        mDragObject.x = coordinates[0];
-        mDragObject.y = coordinates[1];
-        checkTouchMove(dropTarget);
-
         // Check if we are hovering over the scroll areas
         mDistanceSinceScroll += Math.hypot(mLastTouch.x - x, mLastTouch.y - y);
         mLastTouch.set(x, y);
@@ -451,6 +449,9 @@
                 && mOptions.preDragCondition.shouldStartDrag(distanceDragged)) {
             callOnDragStart();
         }
+
+        // Drop on someone?
+        checkTouchMove(x, y);
     }
 
     public float getDistanceDragged() {
@@ -458,14 +459,15 @@
     }
 
     public void forceTouchMove() {
-        int[] placeholderCoordinates = mCoordinatesTemp;
-        DropTarget dropTarget = findDropTarget(mLastTouch.x, mLastTouch.y, placeholderCoordinates);
-        mDragObject.x = placeholderCoordinates[0];
-        mDragObject.y = placeholderCoordinates[1];
-        checkTouchMove(dropTarget);
+        checkTouchMove(mLastTouch.x, mLastTouch.y);
     }
 
-    private void checkTouchMove(DropTarget dropTarget) {
+    private DropTarget checkTouchMove(final int x, final int y) {
+        // If we are in predrag, don't trigger any other event until we get out of it
+        if (ENABLE_NO_LONG_PRESS_DRAG.get() && mIsInPreDrag) {
+            return mLastDropTarget;
+        }
+        DropTarget dropTarget = findDropTarget(x, y);
         if (dropTarget != null) {
             if (mLastDropTarget != dropTarget) {
                 if (mLastDropTarget != null) {
@@ -474,12 +476,11 @@
                 dropTarget.onDragEnter(mDragObject);
             }
             dropTarget.onDragOver(mDragObject);
-        } else {
-            if (mLastDropTarget != null) {
-                mLastDropTarget.onDragExit(mDragObject);
-            }
+        } else if (mLastDropTarget != null) {
+            mLastDropTarget.onDragExit(mDragObject);
         }
         mLastDropTarget = dropTarget;
+        return mLastDropTarget;
     }
 
     /**
@@ -487,13 +488,8 @@
      * we manually ensure appropriate drag and drop events get emulated for accessible drag.
      */
     public void completeAccessibleDrag(int[] location) {
-        final int[] coordinates = mCoordinatesTemp;
-
         // We make sure that we prime the target for drop.
-        DropTarget dropTarget = findDropTarget(location[0], location[1], coordinates);
-        mDragObject.x = coordinates[0];
-        mDragObject.y = coordinates[1];
-        checkTouchMove(dropTarget);
+        DropTarget dropTarget = checkTouchMove(location[0], location[1]);
 
         dropTarget.prepareAccessibilityDrop();
         // Perform the drop
@@ -502,10 +498,6 @@
     }
 
     protected void drop(DropTarget dropTarget, Runnable flingAnimation) {
-        final int[] coordinates = mCoordinatesTemp;
-        mDragObject.x = coordinates[0];
-        mDragObject.y = coordinates[1];
-
         // Move dragging to the final target.
         if (dropTarget != mLastDropTarget) {
             if (mLastDropTarget != null) {
@@ -542,9 +534,9 @@
         dispatchDropComplete(dropTargetAsView, accepted);
     }
 
-    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
-        mDragObject.x = x;
-        mDragObject.y = y;
+    private DropTarget findDropTarget(final int x, final int y) {
+        mCoordinatesTemp[0] = x;
+        mCoordinatesTemp[1] = y;
 
         final Rect r = mRectTemp;
         final ArrayList<DropTarget> dropTargets = mDropTargets;
@@ -556,17 +548,17 @@
 
             target.getHitRectRelativeToDragLayer(r);
             if (r.contains(x, y)) {
-                dropCoordinates[0] = x;
-                dropCoordinates[1] = y;
-                mActivity.getDragLayer().mapCoordInSelfToDescendant((View) target, dropCoordinates);
+                mActivity.getDragLayer().mapCoordInSelfToDescendant((View) target,
+                        mCoordinatesTemp);
+                mDragObject.x = mCoordinatesTemp[0];
+                mDragObject.y = mCoordinatesTemp[1];
                 return target;
             }
         }
-        // Pass all unhandled drag to workspace. Workspace finds the correct
-        // cell layout to drop to in the existing drag/drop logic.
-        dropCoordinates[0] = x;
-        dropCoordinates[1] = y;
-        return getDefaultDropTarget(dropCoordinates);
+        DropTarget dropTarget = getDefaultDropTarget(mCoordinatesTemp);
+        mDragObject.x = mCoordinatesTemp[0];
+        mDragObject.y = mCoordinatesTemp[1];
+        return dropTarget;
     }
 
     protected abstract DropTarget getDefaultDropTarget(int[] dropCoordinates);
diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java
index dec4b5c..07000ed 100644
--- a/src/com/android/launcher3/util/Executors.java
+++ b/src/com/android/launcher3/util/Executors.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.util;
 
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Process;
@@ -62,7 +64,9 @@
 
     /** A background executor to preinflate views. */
     public static final ExecutorService VIEW_PREINFLATION_EXECUTOR =
-            java.util.concurrent.Executors.newSingleThreadExecutor();
+            java.util.concurrent.Executors.newSingleThreadExecutor(
+                    new SimpleThreadFactory(
+                            "preinflate-allapps-icons", THREAD_PRIORITY_BACKGROUND));
 
     /**
      * Utility method to get a started handler thread statically