diff options
8 files changed, 201 insertions, 88 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 57a9b161f..151e2ca13 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -80,6 +80,7 @@ import android.widget.Toast; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsContainerView; +import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.PropertyListBuilder; @@ -2241,8 +2242,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } mPendingExecutor = executor; if (!isInState(ALL_APPS)) { - mAppsView.getAppsStore().setDeferUpdates(true); - mPendingExecutor.execute(() -> mAppsView.getAppsStore().setDeferUpdates(false)); + mAppsView.getAppsStore().enableDeferUpdates(AllAppsStore.DEFER_UPDATES_NEXT_DRAW); + mPendingExecutor.execute(() -> mAppsView.getAppsStore().disableDeferUpdates( + AllAppsStore.DEFER_UPDATES_NEXT_DRAW)); } executor.attachTo(this); diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 0d43e214e..d68ff4451 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -628,11 +628,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo final boolean result = super.dispatchTouchEvent(ev); switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if (result) mAllAppsStore.setDeferUpdates(true); + if (result) mAllAppsStore.enableDeferUpdates( + AllAppsStore.DEFER_UPDATES_USER_INTERACTION); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - mAllAppsStore.setDeferUpdates(false); + mAllAppsStore.disableDeferUpdates(AllAppsStore.DEFER_UPDATES_USER_INTERACTION); break; } return result; diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java index 8e7fec863..160042e69 100644 --- a/src/com/android/launcher3/allapps/AllAppsStore.java +++ b/src/com/android/launcher3/allapps/AllAppsStore.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; @@ -38,12 +37,19 @@ import java.util.function.Predicate; */ public class AllAppsStore { + // Defer updates flag used to defer all apps updates to the next draw. + public static final int DEFER_UPDATES_NEXT_DRAW = 1 << 0; + // Defer updates flag used to defer all apps updates while the user interacts with all apps. + public static final int DEFER_UPDATES_USER_INTERACTION = 1 << 1; + // Defer updates flag used to defer all apps updates by a test's request. + public static final int DEFER_UPDATES_TEST = 1 << 2; + private PackageUserKey mTempKey = new PackageUserKey(null, null); private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>(); private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>(); private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>(); - private boolean mDeferUpdates = false; + private int mDeferUpdatesFlags = 0; private boolean mUpdatePending = false; public Collection<AppInfo> getApps() { @@ -62,17 +68,22 @@ public class AllAppsStore { return mComponentToAppMap.get(key); } - public void setDeferUpdates(boolean deferUpdates) { - if (mDeferUpdates != deferUpdates) { - mDeferUpdates = deferUpdates; + public void enableDeferUpdates(int flag) { + mDeferUpdatesFlags |= flag; + } - if (!mDeferUpdates && mUpdatePending) { - notifyUpdate(); - mUpdatePending = false; - } + public void disableDeferUpdates(int flag) { + mDeferUpdatesFlags &= ~flag; + if (mDeferUpdatesFlags == 0 && mUpdatePending) { + notifyUpdate(); + mUpdatePending = false; } } + public int getDeferUpdatesFlags() { + return mDeferUpdatesFlags; + } + /** * Adds or updates existing apps in the list */ @@ -95,7 +106,7 @@ public class AllAppsStore { private void notifyUpdate() { - if (mDeferUpdates) { + if (mDeferUpdatesFlags != 0) { mUpdatePending = true; return; } diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index b8476aa1d..d2e196138 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -23,9 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherState; +import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; +import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.util.ResourceBasedOverride; +import java.util.concurrent.ExecutionException; + public class TestInformationHandler implements ResourceBasedOverride { public static TestInformationHandler newInstance(Context context) { @@ -77,6 +81,32 @@ public class TestInformationHandler implements ResourceBasedOverride { case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING: TestProtocol.sDebugTracing = false; break; + + case TestProtocol.REQUEST_FREEZE_APP_LIST: + new MainThreadExecutor().execute(() -> + mLauncher.getAppsView().getAppsStore().enableDeferUpdates( + AllAppsStore.DEFER_UPDATES_TEST)); + break; + + case TestProtocol.REQUEST_UNFREEZE_APP_LIST: + new MainThreadExecutor().execute(() -> + mLauncher.getAppsView().getAppsStore().disableDeferUpdates( + AllAppsStore.DEFER_UPDATES_TEST)); + break; + + case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: { + try { + final int deferUpdatesFlags = new MainThreadExecutor().submit(() -> + mLauncher.getAppsView().getAppsStore().getDeferUpdatesFlags()).get(); + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, + deferUpdatesFlags); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + break; + } } return response; } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 02e6bbdd7..6ffc2d9cd 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -57,6 +57,7 @@ public final class TestProtocol { } public static final String TEST_INFO_RESPONSE_FIELD = "response"; + public static final String REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT = "home-to-overview-swipe-height"; public static final String REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT = @@ -65,6 +66,10 @@ public final class TestProtocol { "all-apps-to-overview-swipe-height"; public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT = "home-to-all-apps-swipe-height"; + public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list"; + public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list"; + public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags"; + public static boolean sDebugTracing = false; public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing"; public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 4f8b87c51..d171004fc 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -108,47 +108,63 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { @Test @Ignore public void testPressHomeOnAllAppsContextMenu() throws Exception { - mLauncher.getWorkspace().switchToAllApps().getAppIcon("TestActivity7").openMenu(); + final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); + allApps.freeze(); + try { + allApps.getAppIcon("TestActivity7").openMenu(); + } finally { + allApps.unfreeze(); + } mLauncher.pressHome(); } public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { - assertNotNull("allApps parameter is null", allApps); - - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); - - // Test flinging forward and backward. - test.executeOnLauncher(launcher -> assertEquals( - "All Apps started in already scrolled state", 0, test.getAllAppsScroll(launcher))); - - allApps.flingForward(); - assertTrue("Launcher internal state is not All Apps", - test.isInState(LauncherState.ALL_APPS)); - final Integer flingForwardY = test.getFromLauncher( - launcher -> test.getAllAppsScroll(launcher)); - test.executeOnLauncher( - launcher -> assertTrue("flingForward() didn't scroll App Apps", flingForwardY > 0)); - - allApps.flingBackward(); - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); - final Integer flingBackwardY = test.getFromLauncher( - launcher -> test.getAllAppsScroll(launcher)); - test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", - flingBackwardY < flingForwardY)); - - // Test scrolling down to YouTube. - assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); - // Test scrolling up to Camera. - assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); - // Test failing to find a non-existing app. - final AllApps allAppsFinal = allApps; - expectFail("All apps: could find a non-existing app", - () -> allAppsFinal.getAppIcon("NO APP")); - - assertTrue( - "Launcher internal state is not All Apps", test.isInState(LauncherState.ALL_APPS)); + allApps.freeze(); + try { + assertNotNull("allApps parameter is null", allApps); + + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + + // Test flinging forward and backward. + test.executeOnLauncher(launcher -> assertEquals( + "All Apps started in already scrolled state", 0, + test.getAllAppsScroll(launcher))); + + allApps.flingForward(); + assertTrue("Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + final Integer flingForwardY = test.getFromLauncher( + launcher -> test.getAllAppsScroll(launcher)); + test.executeOnLauncher( + launcher -> assertTrue("flingForward() didn't scroll App Apps", + flingForwardY > 0)); + + allApps.flingBackward(); + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + final Integer flingBackwardY = test.getFromLauncher( + launcher -> test.getAllAppsScroll(launcher)); + test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", + flingBackwardY < flingForwardY)); + + // Test scrolling down to YouTube. + assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); + // Test scrolling up to Camera. + assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); + // Test failing to find a non-existing app. + final AllApps allAppsFinal = allApps; + expectFail("All apps: could find a non-existing app", + () -> allAppsFinal.getAppIcon("NO APP")); + + assertTrue( + "Launcher internal state is not All Apps", + test.isInState(LauncherState.ALL_APPS)); + } finally { + allApps.unfreeze(); + } } @Test @@ -199,12 +215,17 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { } public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { - final AppIcon app = allApps.getAppIcon("TestActivity7"); - assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); - test.executeOnLauncher(launcher -> assertTrue( - "Launcher activity is the top activity; expecting another activity to be the top " - + "one", - test.isInBackground(launcher))); + allApps.freeze(); + try { + final AppIcon app = allApps.getAppIcon("TestActivity7"); + assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); + test.executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + test.isInBackground(launcher))); + } finally { + allApps.unfreeze(); + } } @Test @@ -260,20 +281,23 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { public void testLaunchMenuItem() throws Exception { if (!TestHelpers.isInLauncherProcess()) return; - final AppIconMenu menu = mLauncher. + final AllApps allApps = mLauncher. getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - openMenu(); - - executeOnLauncher( - launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", - isOptionsPopupVisible(launcher))); + switchToAllApps(); + allApps.freeze(); + try { + final AppIconMenu menu = allApps. + getAppIcon(APP_NAME). + openMenu(); - final AppIconMenuItem menuItem = menu.getMenuItem(1); - final String itemName = menuItem.getText(); + executeOnLauncher( + launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", + isOptionsPopupVisible(launcher))); - menuItem.launch(getAppPackageName()); + menu.getMenuItem(1).launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } } @Test @@ -282,12 +306,18 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { // 1. Open all apps and wait for load complete. // 2. Drag icon to homescreen. // 3. Verify that the icon works on homescreen. - mLauncher.getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - dragToWorkspace(). - getWorkspaceAppIcon(APP_NAME). - launch(getAppPackageName()); + final AllApps allApps = mLauncher.getWorkspace(). + switchToAllApps(); + allApps.freeze(); + try { + allApps. + getAppIcon(APP_NAME). + dragToWorkspace(). + getWorkspaceAppIcon(APP_NAME). + launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", @@ -302,21 +332,27 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { // 1. Open all apps and wait for load complete. // 2. Find the app and long press it to show shortcuts. // 3. Press icon center until shortcuts appear - final AppIconMenuItem menuItem = mLauncher. + final AllApps allApps = mLauncher. getWorkspace(). - switchToAllApps(). - getAppIcon(APP_NAME). - openMenu(). - getMenuItem(0); - final String shortcutName = menuItem.getText(); - - // 4. Drag the first shortcut to the home screen. - // 5. Verify that the shortcut works on home screen - // (the app opens and has the same text as the shortcut). - menuItem. - dragToWorkspace(). - getWorkspaceAppIcon(shortcutName). - launch(getAppPackageName()); + switchToAllApps(); + allApps.freeze(); + try { + final AppIconMenuItem menuItem = allApps. + getAppIcon(APP_NAME). + openMenu(). + getMenuItem(0); + final String shortcutName = menuItem.getText(); + + // 4. Drag the first shortcut to the home screen. + // 5. Verify that the shortcut works on home screen + // (the app opens and has the same text as the shortcut). + menuItem. + dragToWorkspace(). + getWorkspaceAppIcon(shortcutName). + launch(getAppPackageName()); + } finally { + allApps.unfreeze(); + } } public static String getAppPackageName() { diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index d03035a87..21d763e30 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -48,6 +48,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { "apps_list_view"); // Wait for the recycler to populate. mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class)); + verifyNotFrozen("All apps freeze flags upon opening all apps"); } @Override @@ -210,4 +211,25 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { verifyActiveContainer(); } } + + /** + * Freezes updating app list upon app install/uninstall/update. + */ + public void freeze() { + mLauncher.getTestInfo(TestProtocol.REQUEST_FREEZE_APP_LIST); + } + + /** + * Resumes updating app list upon app install/uninstall/update. + */ + public void unfreeze() { + mLauncher.getTestInfo(TestProtocol.REQUEST_UNFREEZE_APP_LIST); + verifyNotFrozen("All apps freeze flags upon unfreezing"); + } + + private void verifyNotFrozen(String message) { + mLauncher.assertEquals(message, 0, mLauncher.getTestInfo( + TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS). + getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD)); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index e45fca8c0..8ebe52565 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -292,6 +292,12 @@ public final class LauncherInstrumentation { } } + void assertEquals(String message, long expected, long actual) { + if (expected != actual) { + fail(message + " expected: " + expected + " but was: " + actual); + } + } + void assertNotEquals(String message, int unexpected, int actual) { if (unexpected == actual) { failEquals(message, actual); |