Merge "When scrolling in All apps, scroll to last clickable row" into ub-launcher3-master
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 481ca6c..3bdeb14 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -29,6 +29,8 @@
 import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.testing.TestProtocol;
 
+import java.util.stream.Collectors;
+
 /**
  * Operations on AllApps opened from Home. Also a parent for All Apps opened from Overview.
  */
@@ -75,7 +77,7 @@
             return false;
         }
         if (iconBounds.bottom > displayBottom) {
-            LauncherInstrumentation.log("hasClickableIcon: icon center bellow bottom offset");
+            LauncherInstrumentation.log("hasClickableIcon: icon bottom below bottom offset");
             return false;
         }
         LauncherInstrumentation.log("hasClickableIcon: icon is clickable");
@@ -108,11 +110,6 @@
                     ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mLauncher.getResources()) + 1;
             int deviceHeight = mLauncher.getDevice().getDisplayHeight();
             int displayBottom = deviceHeight - bottomGestureMargin;
-            allAppsContainer.setGestureMargins(
-                    0,
-                    getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1,
-                    0,
-                    bottomGestureMargin);
             final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
             if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector,
                     displayBottom)) {
@@ -124,7 +121,12 @@
                             displayBottom)) {
                         mLauncher.scrollToLastVisibleRow(
                                 allAppsContainer,
-                                mLauncher.getObjectsInContainer(allAppsContainer, "icon"),
+                                mLauncher.getObjectsInContainer(allAppsContainer, "icon")
+                                        .stream()
+                                        .filter(icon ->
+                                                icon.getVisibleBounds().bottom
+                                                        <= displayBottom)
+                                        .collect(Collectors.toList()),
                                 searchBox.getVisibleBounds().bottom
                                         - allAppsContainer.getVisibleBounds().top);
                         final int newScroll = getAllAppsScroll();
@@ -171,7 +173,8 @@
                         "Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
                         ++attempts <= MAX_SCROLL_ATTEMPTS);
 
-                mLauncher.scroll(allAppsContainer, Direction.UP, margins, 12);
+                mLauncher.scroll(
+                        allAppsContainer, Direction.UP, margins, 12, false);
             }
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
@@ -199,7 +202,7 @@
             final UiObject2 allAppsContainer = verifyActiveContainer();
             // Start the gesture in the center to avoid starting at elements near the top.
             mLauncher.scroll(
-                    allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10);
+                    allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10, false);
             verifyActiveContainer();
         }
     }
@@ -213,7 +216,7 @@
             final UiObject2 allAppsContainer = verifyActiveContainer();
             // Start the gesture in the center, for symmetry with forward.
             mLauncher.scroll(
-                    allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10);
+                    allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10, false);
             verifyActiveContainer();
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 0d9038f..6583d32 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -106,7 +106,7 @@
                 }
 
                 if (mLauncher.isFallbackOverview()) {
-                    mLauncher.linearGesture(startX, startY, endX, endY, 10);
+                    mLauncher.linearGesture(startX, startY, endX, endY, 10, false);
                     new BaseOverview(mLauncher);
                 } else {
                     mLauncher.swipeToState(startX, startY, endX, endY, 10, expectedState);
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 8ccfc05..339e14f 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -55,7 +55,8 @@
             final int leftMargin = mLauncher.getTestInfo(
                     TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN).
                     getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
-            mLauncher.scroll(overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20);
+            mLauncher.scroll(
+                    overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20, false);
             verifyActiveContainer();
         }
     }
@@ -89,7 +90,8 @@
             final int rightMargin = mLauncher.getTestInfo(
                     TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN).
                     getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
-            mLauncher.scroll(overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20);
+            mLauncher.scroll(
+                    overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false);
             verifyActiveContainer();
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 37e99ed..4024ff0 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -544,7 +544,8 @@
                 linearGesture(
                         displaySize.x / 2, displaySize.y - 1,
                         displaySize.x / 2, 0,
-                        ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
+                        ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
+                        false);
                 try (LauncherInstrumentation.Closable c = addContextLayer(
                         "Swiped up from context menu to home")) {
                     waitUntilGone("deep_shortcuts_container");
@@ -769,7 +770,7 @@
 
     void swipeToState(int startX, int startY, int endX, int endY, int steps, int expectedState) {
         final Bundle parcel = (Bundle) executeAndWaitForEvent(
-                () -> linearGesture(startX, startY, endX, endY, steps),
+                () -> linearGesture(startX, startY, endX, endY, steps, false),
                 event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()),
                 "Swipe failed to receive an event for the swipe end");
         assertEquals("Swipe switched launcher to a wrong state;",
@@ -782,33 +783,38 @@
                 ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, getResources()) + 1;
     }
 
-    int getBottomGestureMargin(UiObject2 container) {
-        return container.getVisibleBounds().bottom - getRealDisplaySize().y
-                + getBottomGestureSize();
+    int getBottomGestureMarginInContainer(UiObject2 container) {
+        final int bottomGestureStartOnScreen = getRealDisplaySize().y - getBottomGestureSize();
+        return container.getVisibleBounds().bottom - bottomGestureStartOnScreen;
     }
 
-    void scrollToLastVisibleRow(UiObject2 container, Collection<UiObject2> items, int topPadding) {
+    void scrollToLastVisibleRow(
+            UiObject2 container,
+            Collection<UiObject2> items,
+            int topPaddingInContainer) {
         final UiObject2 lowestItem = Collections.max(items, (i1, i2) ->
                 Integer.compare(i1.getVisibleBounds().top, i2.getVisibleBounds().top));
 
-        final int gestureStart = lowestItem.getVisibleBounds().top + getTouchSlop();
-        final int distance = gestureStart - container.getVisibleBounds().top - topPadding;
-        final int bottomMargin = container.getVisibleBounds().height() - distance;
+        final int itemRowCurrentTopOnScreen = lowestItem.getVisibleBounds().top;
+        final Rect containerRect = container.getVisibleBounds();
+        final int itemRowNewTopOnScreen = containerRect.top + topPaddingInContainer;
+        final int distance = itemRowCurrentTopOnScreen - itemRowNewTopOnScreen + getTouchSlop();
 
-        // TODO: Make the gesture steps dependent on the distance so that it can run for various
-        //       screen sizes
+        final int bottomGestureMarginInContainer = getBottomGestureMarginInContainer(container);
         scroll(
                 container,
                 Direction.DOWN,
                 new Rect(
                         0,
+                        containerRect.height() - distance - bottomGestureMarginInContainer,
                         0,
-                        0,
-                        Math.max(bottomMargin, getBottomGestureMargin(container))),
-                80);
+                        bottomGestureMarginInContainer),
+                10,
+                true);
     }
 
-    void scroll(UiObject2 container, Direction direction, Rect margins, int steps) {
+    void scroll(
+            UiObject2 container, Direction direction, Rect margins, int steps, boolean slowDown) {
         final Rect rect = container.getVisibleBounds();
         if (margins != null) {
             rect.left += margins.left;
@@ -853,7 +859,7 @@
         }
 
         executeAndWaitForEvent(
-                () -> linearGesture(startX, startY, endX, endY, steps),
+                () -> linearGesture(startX, startY, endX, endY, steps, slowDown),
                 event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
                 "Didn't receive a scroll end message: " + startX + ", " + startY
                         + ", " + endX + ", " + endY);
@@ -861,13 +867,17 @@
 
     // Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
     // fixed interval each time.
-    void linearGesture(int startX, int startY, int endX, int endY, int steps) {
+    void linearGesture(int startX, int startY, int endX, int endY, int steps, boolean slowDown) {
         log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
         final long downTime = SystemClock.uptimeMillis();
         final Point start = new Point(startX, startY);
         final Point end = new Point(endX, endY);
         sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
-        final long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start, end);
+        long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start, end);
+        if (slowDown) {
+            endTime = movePointer(downTime, endTime + GESTURE_STEP_MS, 5 * GESTURE_STEP_MS, end,
+                    end);
+        }
         sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end);
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 91f0fc4..2ee424b 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -52,7 +52,7 @@
             final Rect taskBounds = mTask.getVisibleBounds();
             final int centerX = taskBounds.centerX();
             final int centerY = taskBounds.centerY();
-            mLauncher.linearGesture(centerX, centerY, centerX, 0, 10);
+            mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false);
             mLauncher.waitForIdle();
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index 5fcaa55..d208c66 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -48,8 +48,9 @@
             mLauncher.scroll(
                     widgetsContainer,
                     Direction.DOWN,
-                    new Rect(0, 0, 0, mLauncher.getBottomGestureMargin(widgetsContainer) + 1),
-                    FLING_STEPS);
+                    new Rect(0, 0, 0,
+                            mLauncher.getBottomGestureMarginInContainer(widgetsContainer) + 1),
+                    FLING_STEPS, false);
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung forward")) {
                 verifyActiveContainer();
             }
@@ -69,7 +70,7 @@
                     widgetsContainer,
                     Direction.UP,
                     new Rect(0, 0, widgetsContainer.getVisibleBounds().width(), 0),
-                    FLING_STEPS);
+                    FLING_STEPS, false);
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) {
                 verifyActiveContainer();
             }
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index db3314e..a0d1a5e 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -182,7 +182,7 @@
         final UiObject2 workspace = verifyActiveContainer();
         mLauncher.scroll(workspace, Direction.RIGHT,
                 new Rect(0, 0, mLauncher.getEdgeSensitivityWidth() + 1, 0),
-                FLING_STEPS);
+                FLING_STEPS, false);
         verifyActiveContainer();
     }
 
@@ -194,7 +194,7 @@
         final UiObject2 workspace = verifyActiveContainer();
         mLauncher.scroll(workspace, Direction.LEFT,
                 new Rect(mLauncher.getEdgeSensitivityWidth() + 1, 0, 0, 0),
-                FLING_STEPS);
+                FLING_STEPS, false);
         verifyActiveContainer();
     }