From ee0bc03d58aa3672e5afd14524682887b37ac1b0 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Tue, 20 Sep 2022 13:54:29 -0700 Subject: [PATCH] Decrease TAPL All Apps scrolling flakiness scrolling in all apps did not factor in additional top padding in the all apps list recycler. This made it so that apps could occasionally scroll and be obcured by that top padding, making them un-tappable. Added this padding to the scrolling logic to make scrolling less flaky. Test: TaplTestsTaskbar, TaplTestsLauncher3 and presubmit Fixes: 248064856 Change-Id: Id76b92b4bc354917f3688ac53673d0ed7a905f02 --- .../taskbar/TaskbarActivityContext.java | 5 +++ .../allapps/TaskbarAllAppsController.java | 8 ++++ .../QuickstepTestInformationHandler.java | 20 ++++++++++ .../testing/TestInformationHandler.java | 5 +++ .../testing/shared/TestProtocol.java | 3 ++ .../com/android/launcher3/tapl/AllApps.java | 40 ++++++++++++++----- .../launcher3/tapl/AllAppsFromTaskbar.java | 8 ++++ .../android/launcher3/tapl/HomeAllApps.java | 8 ++++ 8 files changed, 86 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 4c5e0bea8c..496a146f6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -907,4 +907,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers.dumpLogs(prefix + "\t", pw); mDeviceProfile.dump(this, prefix, pw); } + + @VisibleForTesting + public int getTaskbarAllAppsTopPadding() { + return mControllers.taskbarAllAppsController.getTaskbarAllAppsTopPadding(); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java index ea37944d69..85c63183ad 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar.allapps; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.R; import com.android.launcher3.appprediction.PredictionRowView; @@ -123,4 +124,11 @@ public final class TaskbarAllAppsController { .findFixedRowByType(PredictionRowView.class) .setPredictedApps(mPredictedApps); } + + + @VisibleForTesting + public int getTaskbarAllAppsTopPadding() { + // Allow null-pointer since this should only be null if the apps view is not showing. + return mAppsView.getActiveRecyclerView().getClipBounds().top; + } } diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index b7cdecd115..9621ce6eba 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -20,6 +20,7 @@ import com.android.quickstep.util.TISBindHelper; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; +import java.util.function.Function; public class QuickstepTestInformationHandler extends TestInformationHandler { @@ -112,6 +113,13 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size)); return response; } + + case TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING: { + return getTISBinderUIProperty(Bundle::putInt, tisBinder -> + tisBinder.getTaskbarManager() + .getCurrentActivityContext() + .getTaskbarAllAppsTopPadding()); + } } return super.call(method, arg, extras); @@ -159,4 +167,16 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { throw new RuntimeException(e); } } + + private Bundle getTISBinderUIProperty( + BundleSetter bundleSetter, Function provider) { + Bundle response = new Bundle(); + + runOnTISBinder(tisBinder -> bundleSetter.set( + response, + TestProtocol.TEST_INFO_RESPONSE_FIELD, + provider.apply(tisBinder))); + + return response; + } } diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index d3c9bc9676..7abf1e66a0 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -219,6 +219,11 @@ public class TestInformationHandler implements ResourceBasedOverride { return response; } + case TestProtocol.REQUEST_ALL_APPS_TOP_PADDING: { + return getLauncherUIProperty(Bundle::putInt, + l -> l.getAppsView().getActiveRecyclerView().getClipBounds().top); + } + default: return null; } diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java index 5116b01ba5..10bb87779f 100644 --- a/src/com/android/launcher3/testing/shared/TestProtocol.java +++ b/src/com/android/launcher3/testing/shared/TestProtocol.java @@ -112,6 +112,9 @@ public final class TestProtocol { "get-activities-created-count"; public static final String REQUEST_GET_ACTIVITIES = "get-activities"; public static final String REQUEST_HAS_TIS = "has-touch-interaction-service"; + public static final String REQUEST_TASKBAR_ALL_APPS_TOP_PADDING = + "taskbar-all-apps-top-padding"; + public static final String REQUEST_ALL_APPS_TOP_PADDING = "all-apps-top-padding"; public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size"; public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center"; diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 4791846626..6bbdf48da0 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -46,8 +46,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { super(launcher); final UiObject2 allAppsContainer = verifyActiveContainer(); mHeight = mLauncher.getVisibleBounds(allAppsContainer).height(); - final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, - "apps_list_view"); + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); // Wait for the recycler to populate. mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class)); verifyNotFrozen("All apps freeze flags upon opening all apps"); @@ -78,6 +77,11 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.log("hasClickableIcon: icon center is under search box"); return false; } + if (iconCenterInRecyclerTopPadding(appListRecycler, icon)) { + LauncherInstrumentation.log( + "hasClickableIcon: icon center is under the app list recycler's top padding."); + return false; + } if (iconBounds.bottom > displayBottom) { LauncherInstrumentation.log("hasClickableIcon: icon bottom below bottom offset"); return false; @@ -92,6 +96,13 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { iconCenter.x, iconCenter.y); } + private boolean iconCenterInRecyclerTopPadding(UiObject2 appListRecycler, UiObject2 icon) { + final Point iconCenter = icon.getVisibleCenter(); + + return iconCenter.y <= mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding(); + } + /** * Finds an icon. If the icon doesn't exist, return null. * Scrolls the app list when needed to make sure the icon is visible. @@ -105,9 +116,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "getting app icon " + appName + " on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, - "apps_list_view"); - final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); int deviceHeight = mLauncher.getRealDisplaySize().y; int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen(); @@ -128,10 +137,9 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { mLauncher.getVisibleBounds(icon).top < bottomGestureStartOnScreen) .collect(Collectors.toList()), - hasSearchBox() - ? mLauncher.getVisibleBounds(searchBox).bottom - - mLauncher.getVisibleBounds(allAppsContainer).top - : 0); + mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding() + - mLauncher.getVisibleBounds(allAppsContainer).top); verifyActiveContainer(); final int newScroll = getAllAppsScroll(); mLauncher.assertTrue( @@ -180,16 +188,22 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { protected abstract boolean hasSearchBox(); + protected abstract int getAppsListRecyclerTopPadding(); + private void scrollBackToBeginning() { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to scroll back in all apps")) { LauncherInstrumentation.log("Scrolling to the beginning"); final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); int attempts = 0; final Rect margins = new Rect( - 0, hasSearchBox() ? mLauncher.getVisibleBounds(searchBox).bottom + 1 : 0, 0, 5); + /* left= */ 0, + mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding() + 1, + /* right= */ 0, + /* bottom= */ 5); for (int scroll = getAllAppsScroll(); scroll != 0; @@ -220,6 +234,10 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); } + private UiObject2 getAppListRecycler(UiObject2 allAppsContainer) { + return mLauncher.waitForObjectInContainer(allAppsContainer, "apps_list_view"); + } + private UiObject2 getSearchBox(UiObject2 allAppsContainer) { return mLauncher.waitForObjectInContainer(allAppsContainer, "search_container_all_apps"); } diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java index 516402563d..f804e28ceb 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java +++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java @@ -18,6 +18,8 @@ package com.android.launcher3.tapl; import androidx.annotation.NonNull; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.shared.TestProtocol; + /** * Operations on AllApps opened from the Taskbar. */ @@ -48,4 +50,10 @@ public class AllAppsFromTaskbar extends AllApps { protected boolean hasSearchBox() { return false; } + + @Override + protected int getAppsListRecyclerTopPadding() { + return mLauncher.getTestInfo(TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING) + .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java index 7123de44a9..9a4c6d4dce 100644 --- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java @@ -18,6 +18,8 @@ package com.android.launcher3.tapl; import androidx.annotation.NonNull; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.shared.TestProtocol; + public class HomeAllApps extends AllApps { private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background"; @@ -47,6 +49,12 @@ public class HomeAllApps extends AllApps { return true; } + @Override + protected int getAppsListRecyclerTopPadding() { + return mLauncher.getTestInfo(TestProtocol.REQUEST_ALL_APPS_TOP_PADDING) + .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + /** * Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only. * @param tapRight Tap on the right of bottom sheet if true, or left otherwise.