Merge "Using android Q sdk in gradle" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
index fb83cd3..b37c2e0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/FlingAndHoldTouchController.java
@@ -57,7 +57,7 @@
 
     @Override
     public boolean onDrag(float displacement) {
-        mMotionPauseDetector.addPosition(displacement);
+        mMotionPauseDetector.addPosition(displacement, 0);
         return super.onDrag(displacement);
     }
 
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 04fd59c..2626481 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -39,6 +39,7 @@
     <dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
     <dimen name="motion_pause_detector_speed_fast">0.5dp</dimen>
     <dimen name="motion_pause_detector_min_displacement">48dp</dimen>
+    <dimen name="motion_pause_detector_max_orthogonal_displacement">48dp</dimen>
 
     <!-- Launcher app transition -->
     <dimen name="content_trans_y">50dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 5755205..a7f5f0b 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -201,7 +201,11 @@
                     dispatchMotion(ev, displacement - mStartDisplacement, null);
 
                     if (FeatureFlags.SWIPE_HOME.get()) {
-                        mMotionPauseDetector.addPosition(displacement);
+                        boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
+                        float orthogonalDisplacement = !isLandscape
+                                ? ev.getX() - mDownPos.x
+                                : ev.getY() - mDownPos.y;
+                        mMotionPauseDetector.addPosition(displacement, orthogonalDisplacement);
                     }
                 }
                 break;
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 86a8081..a99fc0f 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -478,6 +478,7 @@
         SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, (applier) -> {
             mSyncTransactionApplier = applier;
         });
+        mRecentsView.setEnableFreeScroll(false);
         mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
             if (!mBgLongSwipeMode && !mIsGoingToHome) {
                 updateFinalShift();
@@ -910,7 +911,8 @@
         Interpolator interpolator = DEACCEL;
         final int nextPage = mRecentsView != null ? mRecentsView.getNextPage() : -1;
         final int runningTaskIndex = mRecentsView != null ? mRecentsView.getRunningTaskIndex() : -1;
-        boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex;
+        boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex
+                && mRecentsView.getTaskViewAt(nextPage) != null;
         final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW;
         if (!isFling) {
             if (SWIPE_HOME.get()) {
@@ -922,7 +924,11 @@
                     endTarget = currentShift < MIN_PROGRESS_FOR_OVERVIEW ? LAST_TASK : HOME;
                 }
             } else {
-                endTarget = reachedOverviewThreshold && mGestureStarted ? RECENTS : LAST_TASK;
+                endTarget = reachedOverviewThreshold && mGestureStarted
+                        ? RECENTS
+                        : goingToNewTask
+                                ? NEW_TASK
+                                : LAST_TASK;
             }
             endShift = endTarget.endShift;
             long expectedDuration = Math.abs(Math.round((endShift - currentShift)
@@ -932,7 +938,9 @@
             interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
         } else {
             if (SWIPE_HOME.get() && endVelocity < 0 && !mIsShelfPeeking) {
-                endTarget = HOME;
+                // If swiping at a diagonal, base end target on the faster velocity.
+                endTarget = goingToNewTask && Math.abs(velocityX) > Math.abs(endVelocity)
+                        ? NEW_TASK : HOME;
             } else if (endVelocity < 0 && (!goingToNewTask || reachedOverviewThreshold)) {
                 // If user scrolled to a new task, only go to recents if they already passed
                 // the overview threshold. Otherwise, we'll snap to the new task and launch it.
@@ -970,27 +978,21 @@
             duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
         } else if (endTarget == RECENTS) {
             mRecentsAnimationWrapper.enableTouchProxy();
+            if (mRecentsView != null) {
+                duration = Math.max(duration, mRecentsView.getScroller().getDuration());
+            }
             if (SWIPE_HOME.get()) {
                 setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
             }
         } else if (endTarget == NEW_TASK) {
-            // We aren't goingToRecents, and user scrolled/flung to a new task; snap to the closest
-            // task in that direction and launch it (in startNewTask()).
-            int taskToLaunch = runningTaskIndex + (nextPage > runningTaskIndex ? 1 : -1);
-            if (taskToLaunch >= mRecentsView.getTaskViewCount()) {
+            // Let RecentsView handle the scrolling to the task, which we launch in startNewTask().
+            if (mRecentsView != null) {
+                duration = Math.max(duration, mRecentsView.getScroller().getDuration());
+            }
+        } else if (endTarget == LAST_TASK) {
+            if (mRecentsView != null && nextPage != runningTaskIndex) {
                 // Scrolled to Clear all button, snap back to current task and resume it.
                 mRecentsView.snapToPage(runningTaskIndex, Math.toIntExact(duration));
-                goingToNewTask = false;
-            } else {
-                float distance = Math.abs(mRecentsView.getScrollForPage(taskToLaunch)
-                        - mRecentsView.getScrollX());
-                int durationX = (int) Math.abs(distance / velocityXPxPerMs);
-                if (durationX > MAX_SWIPE_DURATION) {
-                    durationX = Math.toIntExact(MAX_SWIPE_DURATION);
-                }
-                interpolator = Interpolators.scrollInterpolatorForVelocity(velocityXPxPerMs);
-                mRecentsView.snapToPage(taskToLaunch, durationX, interpolator);
-                duration = Math.max(duration, durationX);
             }
         }
         animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
@@ -1195,6 +1197,7 @@
         mLayoutListener.finish();
         mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
 
+        mRecentsView.setEnableFreeScroll(true);
         mRecentsView.setRunningTaskIconScaledDown(false);
         mRecentsView.setOnScrollChangeListener(null);
         mQuickScrubController.cancelActiveQuickscrub();
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 7969eec..1156b87 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -36,12 +36,15 @@
     private final float mSpeedSomewhatFast;
     private final float mSpeedFast;
     private final float mMinDisplacementForPause;
+    private final float mMaxOrthogonalDisplacementForPause;
 
     private Long mPreviousTime = null;
     private Float mPreviousPosition = null;
     private Float mPreviousVelocity = null;
 
+    private TotalDisplacement mTotalDisplacement = new TotalDisplacement();
     private Float mFirstPosition = null;
+    private Float mFirstOrthogonalPosition = null;
 
     private OnMotionPauseListener mOnMotionPauseListener;
     private boolean mIsPaused;
@@ -54,6 +57,8 @@
         mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
         mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
         mMinDisplacementForPause = res.getDimension(R.dimen.motion_pause_detector_min_displacement);
+        mMaxOrthogonalDisplacementForPause = res.getDimension(
+                R.dimen.motion_pause_detector_max_orthogonal_displacement);
     }
 
     /**
@@ -70,20 +75,26 @@
     /**
      * Computes velocity and acceleration to determine whether the motion is paused.
      * @param position The x or y component of the motion being tracked.
+     * @param orthogonalPosition The x or y component (opposite of {@param position}) of the motion.
      *
      * TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
      */
-    public void addPosition(float position) {
+    public void addPosition(float position, float orthogonalPosition) {
         if (mFirstPosition == null) {
             mFirstPosition = position;
         }
+        if (mFirstOrthogonalPosition == null) {
+            mFirstOrthogonalPosition = orthogonalPosition;
+        }
         long time = SystemClock.uptimeMillis();
         if (mPreviousTime != null && mPreviousPosition != null) {
             long changeInTime = Math.max(1, time - mPreviousTime);
             float changeInPosition = position - mPreviousPosition;
             float velocity = changeInPosition / changeInTime;
             if (mPreviousVelocity != null) {
-                checkMotionPaused(velocity, mPreviousVelocity, Math.abs(position - mFirstPosition));
+                mTotalDisplacement.set(Math.abs(position - mFirstPosition),
+                        Math.abs(orthogonalPosition - mFirstOrthogonalPosition));
+                checkMotionPaused(velocity, mPreviousVelocity, mTotalDisplacement);
             }
             mPreviousVelocity = velocity;
         }
@@ -91,7 +102,8 @@
         mPreviousPosition = position;
     }
 
-    private void checkMotionPaused(float velocity, float prevVelocity, float totalDisplacement) {
+    private void checkMotionPaused(float velocity, float prevVelocity,
+            TotalDisplacement totalDisplacement) {
         float speed = Math.abs(velocity);
         float previousSpeed = Math.abs(prevVelocity);
         boolean isPaused;
@@ -113,8 +125,10 @@
                 }
             }
         }
-        boolean passedMinDisplacement = totalDisplacement >= mMinDisplacementForPause;
-        isPaused &= passedMinDisplacement;
+        boolean passedMinDisplacement = totalDisplacement.primary >= mMinDisplacementForPause;
+        boolean passedMaxOrthogonalDisplacement =
+                totalDisplacement.orthogonal >= mMaxOrthogonalDisplacementForPause;
+        isPaused &= passedMinDisplacement && !passedMaxOrthogonalDisplacement;
         if (mIsPaused != isPaused) {
             mIsPaused = isPaused;
             if (mIsPaused) {
@@ -131,6 +145,8 @@
         mPreviousPosition = null;
         mPreviousVelocity = null;
         mFirstPosition = null;
+        mFirstOrthogonalPosition = null;
+        mTotalDisplacement.set(0, 0);
         setOnMotionPauseListener(null);
         mIsPaused = mHasEverBeenPaused = false;
     }
@@ -142,4 +158,18 @@
     public interface OnMotionPauseListener {
         void onMotionPauseChanged(boolean isPaused);
     }
+
+    /**
+     * Contains the displacement from the first tracked position,
+     * along both the primary and orthogonal axes.
+     */
+    private class TotalDisplacement {
+        public float primary;
+        public float orthogonal;
+
+        public void set(float primaryDisplacement, float orthogonalDisplacement) {
+            this.primary = primaryDisplacement;
+            this.orthogonal = orthogonalDisplacement;
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c6f293d..5b84d23 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -83,6 +83,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.OverScroller;
 import com.android.launcher3.util.PendingAnimation;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.ViewPool;
@@ -339,6 +340,10 @@
         updateEmptyMessage();
     }
 
+    public OverScroller getScroller() {
+        return mScroller;
+    }
+
     public boolean isRtl() {
         return mIsRtl;
     }
@@ -412,7 +417,7 @@
     public TaskView getTaskView(int taskId) {
         for (int i = 0; i < getTaskViewCount(); i++) {
             TaskView tv = (TaskView) getChildAt(i);
-            if (tv.getTask().key != null && tv.getTask().key.id == taskId) {
+            if (tv.getTask() != null && tv.getTask().key != null && tv.getTask().key.id == taskId) {
                 return tv;
             }
         }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ec3a966..fc3af7e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -153,7 +153,8 @@
  * Default launcher application.
  */
 public class Launcher extends BaseDraggingActivity implements LauncherExterns,
-        LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
+        LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate,
+        InvariantDeviceProfile.OnIDPChangeListener {
     public static final String TAG = "Launcher";
     static final boolean LOGD = false;
 
@@ -285,8 +286,9 @@
         LauncherAppState app = LauncherAppState.getInstance(this);
         mOldConfig = new Configuration(getResources().getConfiguration());
         mModel = app.setLauncher(this);
-        initDeviceProfile(app.getInvariantDeviceProfile());
-
+        InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
+        initDeviceProfile(idp);
+        idp.addOnChangeListener(this);
         mSharedPrefs = Utilities.getPrefs(this);
         mIconCache = app.getIconCache();
         mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);
@@ -406,6 +408,12 @@
         }
     }
 
+    @Override
+    public void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) {
+        initDeviceProfile(idp);
+        getRootView().dispatchInsets();
+    }
+
     private void initDeviceProfile(InvariantDeviceProfile idp) {
         // Load configuration-specific DeviceProfile
         mDeviceProfile = idp.getDeviceProfile(this);
@@ -1322,7 +1330,7 @@
 
         TextKeyListener.getInstance().release();
         clearPendingBinds();
-
+        LauncherAppState.getIDP(this).removeOnChangeListener(this);
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onDestroy();
         }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 8f9e7c8..018ec5f 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1053,7 +1053,7 @@
     }
 
 
-    protected void setEnableFreeScroll(boolean freeScroll) {
+    public void setEnableFreeScroll(boolean freeScroll) {
         boolean wasFreeScroll = mFreeScroll;
         mFreeScroll = freeScroll;