diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java index 6f4d34c8c7..5026f36e08 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -58,6 +58,12 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()); return response; } + + case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: { + response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, + FeatureFlags.ENABLE_OVERVIEW_SHARE.get()); + return response; + } } return super.call(method); diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index bf093fdabf..ecd4e2bd67 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -36,6 +36,7 @@ import com.android.launcher3.tapl.AllAppsFromOverview; import com.android.launcher3.tapl.Background; import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel; import com.android.launcher3.tapl.Overview; +import com.android.launcher3.tapl.OverviewActions; import com.android.launcher3.tapl.OverviewTask; import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.ui.TaplTestsLauncher3; @@ -68,11 +69,14 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { }); } - private void startTestApps() throws Exception { + public static void startTestApps() throws Exception { startAppFast(getAppPackageName()); startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); startTestActivity(2); + } + private void startTestAppsWithCheck() throws Exception { + startTestApps(); executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", @@ -105,7 +109,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { @Test @PortraitLandscape public void testOverview() throws Exception { - startTestApps(); + startTestAppsWithCheck(); // mLauncher.pressHome() also tests an important case of pressing home while in background. Overview overview = mLauncher.pressHome().switchToOverview(); assertTrue("Launcher internal state didn't switch to Overview", @@ -189,6 +193,22 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { 0, getTaskCount(launcher))); } + /** + * Smoke test for action buttons: Presses all the buttons and makes sure no crashes occur. + */ + @Test + @NavigationModeSwitch + @PortraitLandscape + public void testOverviewActions() throws Exception { + if (mLauncher.getNavigationModel() != NavigationModel.TWO_BUTTON) { + startTestAppsWithCheck(); + OverviewActions actionsView = + mLauncher.pressHome().switchToOverview().getOverviewActions(); + actionsView.clickAndDismissScreenshot(); + actionsView.clickAndDismissShare(); + } + } + private int getCurrentOverviewPage(Launcher launcher) { return launcher.getOverviewPanel().getCurrentPage(); } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 626d9dd966..58bff090e8 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -98,6 +98,7 @@ public final class TestProtocol { public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; public static final String REQUEST_OVERVIEW_ACTIONS_ENABLED = "overview-actions-enabled"; + public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled"; public static boolean sDisableSensorRotation; public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation"; diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index 223ae298b9..588b6b8f07 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -27,7 +27,7 @@ import java.util.Collections; import java.util.List; /** - * Common overview pane for both Launcher and fallback recents + * Common overview panel for both Launcher and fallback recents */ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { private static final int FLINGS_FOR_DISMISS_LIMIT = 40; @@ -135,4 +135,19 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { public boolean hasTasks() { return getTasks().size() > 0; } + + /** + * Gets Overview Actions. + * + * @return The Overview Actions + */ + @NonNull + public OverviewActions getOverviewActions() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get overview actions")) { + verifyActiveContainer(); + UiObject2 overviewActions = mLauncher.waitForLauncherObject("action_buttons"); + return new OverviewActions(overviewActions, mLauncher); + } + } } \ No newline at end of file diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 94c75b0bea..85f3234bf1 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -154,6 +154,7 @@ public final class LauncherInstrumentation { private static final String CONTEXT_MENU_RES_ID = "deep_shortcuts_container"; public static final int WAIT_TIME_MS = 10000; private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; + private static final String ANDROID_PACKAGE = "android"; private static WeakReference sActiveContainer = new WeakReference<>(null); @@ -926,6 +927,14 @@ public final class LauncherInstrumentation { return waitForObjectBySelector(getOverviewObjectSelector(resName)); } + @NonNull + UiObject2 waitForAndroidObject(String resId) { + final UiObject2 object = mDevice.wait( + Until.findObject(By.res(ANDROID_PACKAGE, resId)), WAIT_TIME_MS); + assertNotNull("Can't find a android object with id: " + resId, object); + return object; + } + private UiObject2 waitForObjectBySelector(BySelector selector) { final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS); assertNotNull("Can't find a view in Launcher, selector: " + selector, object); @@ -1302,6 +1311,11 @@ public final class LauncherInstrumentation { TestProtocol.TEST_INFO_RESPONSE_FIELD); } + boolean overviewShareEnabled() { + return getTestInfo(TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED).getBoolean( + TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + private void disableSensorRotation() { getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION); } diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java new file mode 100644 index 0000000000..a30a404764 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiObject2; + +import com.android.launcher3.testing.TestProtocol; + +/** + * View containing overview actions + */ +public class OverviewActions { + private final UiObject2 mOverviewActions; + private final LauncherInstrumentation mLauncher; + + OverviewActions(UiObject2 overviewActions, LauncherInstrumentation launcherInstrumentation) { + this.mOverviewActions = overviewActions; + this.mLauncher = launcherInstrumentation; + } + + /** + * Clicks screenshot button and closes screenshot ui. + */ + @NonNull + public Overview clickAndDismissScreenshot() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to click screenshot button and exit screenshot ui")) { + UiObject2 screenshot = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_screenshot"); + mLauncher.clickLauncherObject(screenshot); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked screenshot button")) { + UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject( + "global_screenshot_dismiss_image"); + if (mLauncher.getNavigationModel() + != LauncherInstrumentation.NavigationModel.THREE_BUTTON) { + mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, + LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS); + mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, + LauncherInstrumentation.EVENT_TOUCH_UP_TIS); + } + closeScreenshot.click(); + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer( + "dismissed screenshot")) { + return new Overview(mLauncher); + } + } + } + } + + /** + * Click share button, then drags sharesheet down to remove it. + * + * Share is currently hidden behind flag, test is kept in case share becomes a default feature. + * If share is completely removed then remove this test as well. + */ + @NonNull + public Overview clickAndDismissShare() { + if (mLauncher.overviewShareEnabled()) { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to click share button and dismiss sharesheet")) { + UiObject2 share = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_share"); + mLauncher.clickLauncherObject(share); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked share button")) { + mLauncher.waitForAndroidObject("contentPanel"); + mLauncher.getDevice().pressBack(); + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer( + "dismissed sharesheet")) { + return new Overview(mLauncher); + } + } + } + } + return new Overview(mLauncher); + } + + /** + * Click select button + * + * @return The select mode buttons that are now shown instead of action buttons. + */ + @NonNull + public SelectModeButtons clickSelect() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click select button")) { + UiObject2 select = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_select"); + mLauncher.clickLauncherObject(select); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked select button")) { + return getSelectModeButtons(); + } + + } + } + + /** + * Gets the Select Mode Buttons. + * + * @return The Select Mode Buttons. + */ + @NonNull + private SelectModeButtons getSelectModeButtons() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get select mode buttons")) { + UiObject2 selectModeButtons = mLauncher.waitForLauncherObject("select_mode_buttons"); + return new SelectModeButtons(selectModeButtons, mLauncher); + } + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java new file mode 100644 index 0000000000..35074184d6 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiObject2; + +/** + * View containing select mode buttons + */ +public class SelectModeButtons { + private final UiObject2 mSelectModeButtons; + private final LauncherInstrumentation mLauncher; + + SelectModeButtons(UiObject2 selectModeButtons, + LauncherInstrumentation launcherInstrumentation) { + mSelectModeButtons = selectModeButtons; + mLauncher = launcherInstrumentation; + } + + /** + * Click close button. + */ + @NonNull + public Overview clickClose() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click close button")) { + UiObject2 close = mLauncher.waitForObjectInContainer(mSelectModeButtons, "close"); + mLauncher.clickLauncherObject(close); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked close button")) { + return new Overview(mLauncher); + } + } + } + + /** + * Click feedback button. + */ + @NonNull + public Background clickFeedback() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click feedback button")) { + UiObject2 feedback = mLauncher.waitForObjectInContainer(mSelectModeButtons, "feedback"); + mLauncher.clickLauncherObject(feedback); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked feedback button")) { + return new Background(mLauncher); + } + } + } +}