From 86a844c976e618c931a46959e3fa37875c5fefae Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Sat, 9 Jul 2022 23:43:51 -0700 Subject: [PATCH] Add splitFromOverviewForTablet test Design doc: go/split_tapl Bug: 238553914 Test: run this test Change-Id: Ibb385d852f73dee10470d14c4962cf482740105d --- .../util/SplitSelectStateController.java | 4 +++ .../android/quickstep/TaplTestsQuickstep.java | 14 ++++++++ .../launcher3/ui/AbstractLauncherUiTest.java | 17 ++++++--- .../android/launcher3/tapl/BaseOverview.java | 22 ++++++++++++ .../tapl/LauncherInstrumentation.java | 15 ++++++-- .../com/android/launcher3/tapl/Overview.java | 4 +-- .../launcher3/tapl/OverviewActions.java | 19 +++++++++- .../android/launcher3/tapl/OverviewTask.java | 25 +++++++++++-- .../launcher3/tapl/SplitScreenSelect.java | 35 +++++++++++++++++++ 9 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 tests/tapl/com/android/launcher3/tapl/SplitScreenSelect.java diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index f1189c9146..e89c842b5f 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -42,6 +42,8 @@ import androidx.annotation.Nullable; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import com.android.quickstep.SystemUiProxy; @@ -171,6 +173,8 @@ public class SplitSelectStateController { public void launchTasks(int taskId1, @Nullable PendingIntent taskPendingIntent, @Nullable Intent fillInIntent, int taskId2, @StagePosition int stagePosition, Consumer callback, boolean freezeTaskList, float splitRatio) { + TestLogging.recordEvent( + TestProtocol.SEQUENCE_MAIN, "launchSplitTasks"); // Assume initial task is for top/left part of screen final int[] taskIds = stagePosition == STAGE_POSITION_TOP_OR_LEFT ? new int[]{taskId1, taskId2} diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index 4bf247c75d..81df3c0f1a 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -179,6 +179,20 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { actionsView.clickAndDismissScreenshot(); } + @Test + @PortraitLandscape + public void testSplitFromOverviewForTablet() { + assumeTrue(mLauncher.isTablet()); + + startTestActivity(2); + startTestActivity(3); + + mLauncher.goHome().switchToOverview().getOverviewActions() + .clickSplit() + .getTestActivityTask(2) + .open(); + } + private int getCurrentOverviewPage(Launcher launcher) { return launcher.getOverviewPanel().getCurrentPage(); } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 6f8b9d2967..1f6e1ec420 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -563,10 +563,13 @@ public abstract class AbstractLauncherUiTest { break; } case OVERVIEW: { - checkLauncherStateInOverview(launcher, expectedContainerType, isStarted, - isResumed); - assertTrue(TestProtocol.stateOrdinalToString(ordinal), - ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL); + verifyOverviewState(launcher, expectedContainerType, isStarted, isResumed, + ordinal, TestProtocol.OVERVIEW_STATE_ORDINAL); + break; + } + case SPLIT_SCREEN_SELECT: { + verifyOverviewState(launcher, expectedContainerType, isStarted, isResumed, + ordinal, TestProtocol.OVERVIEW_SPLIT_SELECT_ORDINAL); break; } case TASKBAR_ALL_APPS: @@ -632,5 +635,9 @@ public abstract class AbstractLauncherUiTest { return homeAppIcon; } - + private void verifyOverviewState(Launcher launcher, ContainerType expectedContainerType, + boolean isStarted, boolean isResumed, int ordinal, int expectedOrdinal) { + checkLauncherStateInOverview(launcher, expectedContainerType, isStarted, isResumed); + assertEquals(TestProtocol.stateOrdinalToString(ordinal), ordinal, expectedOrdinal); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index b7bca02e44..6a11336bb9 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -19,6 +19,7 @@ package com.android.launcher3.tapl; import android.graphics.Rect; import androidx.annotation.NonNull; +import androidx.test.uiautomator.By; import androidx.test.uiautomator.BySelector; import androidx.test.uiautomator.Direction; import androidx.test.uiautomator.UiObject2; @@ -168,6 +169,27 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { return new OverviewTask(mLauncher, widestTask, this); } + /** Returns an overview task matching TestActivity {@param activityNumber}. */ + @NonNull + public OverviewTask getTestActivityTask(int activityNumber) { + final List taskViews = getTasks(); + mLauncher.assertNotEquals("Unable to find a task", 0, taskViews.size()); + + final String activityName = "TestActivity" + activityNumber; + UiObject2 task = null; + for (UiObject2 taskView : taskViews) { + // TODO(b/239452415): Use equals instead of descEndsWith + if (taskView.getParent().hasObject(By.descEndsWith(activityName))) { + task = taskView; + break; + } + } + mLauncher.assertNotNull( + "Unable to find a task with " + activityName + " from the task list", task); + + return new OverviewTask(mLauncher, task, this); + } + /** * Returns a list of all tasks fully visible in the tablet grid overview. */ diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index fa6141ad23..925124af60 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -121,8 +121,8 @@ public final class LauncherInstrumentation { // Types for launcher containers that the user is interacting with. "Background" is a // pseudo-container corresponding to inactive launcher covered by another app. public enum ContainerType { - WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP, - TASKBAR_ALL_APPS + WORKSPACE, HOME_ALL_APPS, OVERVIEW, SPLIT_SCREEN_SELECT, WIDGETS, FALLBACK_OVERVIEW, + LAUNCHED_APP, TASKBAR_ALL_APPS } public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON} @@ -744,7 +744,8 @@ public final class LauncherInstrumentation { return waitForLauncherObject(APPS_RES_ID); } - case OVERVIEW: { + case OVERVIEW: + case SPLIT_SCREEN_SELECT: { waitUntilLauncherObjectGone(APPS_RES_ID); waitUntilLauncherObjectGone(WORKSPACE_RES_ID); waitUntilLauncherObjectGone(WIDGETS_RES_ID); @@ -1090,6 +1091,14 @@ public final class LauncherInstrumentation { return object; } + @NonNull + UiObject2 waitForSystemUiObject(BySelector selector) { + final UiObject2 object = TestHelpers.wait( + Until.findObject(selector), WAIT_TIME_MS); + assertNotNull("Can't find a systemui object with selector: " + selector, object); + return object; + } + @NonNull UiObject2 waitForNavigationUiObject(String resId) { String resPackage = getNavigationButtonResPackage(); diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java index 66a51a56a2..50c21368e0 100644 --- a/tests/tapl/com/android/launcher3/tapl/Overview.java +++ b/tests/tapl/com/android/launcher3/tapl/Overview.java @@ -21,7 +21,7 @@ import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType; /** * Overview pane. */ -public final class Overview extends BaseOverview { +public class Overview extends BaseOverview { Overview(LauncherInstrumentation launcher) { super(launcher); @@ -29,7 +29,7 @@ public final class Overview extends BaseOverview { @Override protected ContainerType getContainerType() { - return LauncherInstrumentation.ContainerType.OVERVIEW; + return ContainerType.OVERVIEW; } @Override diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java index d1b1a846fe..5710713830 100644 --- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java +++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java @@ -86,7 +86,6 @@ public class OverviewActions { "clicked select button")) { return getSelectModeButtons(); } - } } @@ -103,4 +102,22 @@ public class OverviewActions { return new SelectModeButtons(selectModeButtons, mLauncher); } } + + /** + * Clicks split button and enters split select mode. + */ + @NonNull + public SplitScreenSelect clickSplit() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to click split button to enter split select mode")) { + UiObject2 split = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_split"); + mLauncher.clickLauncherObject(split); + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer( + "clicked split")) { + return new SplitScreenSelect(mLauncher); + } + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java index c8caa42b6d..ac7424ef26 100644 --- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java +++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java @@ -20,6 +20,8 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CH import android.graphics.Rect; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; import androidx.test.uiautomator.UiObject2; import com.android.launcher3.testing.TestProtocol; @@ -32,8 +34,12 @@ import java.util.stream.Collectors; * A recent task in the overview panel carousel. */ public final class OverviewTask { + private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; + static final Pattern TASK_START_EVENT = Pattern.compile("startActivityFromRecentsAsync"); + static final Pattern SPLIT_START_EVENT = + Pattern.compile("launchSplitTasks"); private final LauncherInstrumentation mLauncher; private final UiObject2 mTask; private final BaseOverview mOverview; @@ -125,7 +131,7 @@ public final class OverviewTask { } /** - * Clicks at the task. + * Clicks the task. */ public LaunchedAppState open() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { @@ -136,8 +142,21 @@ public final class OverviewTask { () -> "Launching task didn't open a new window: " + mTask.getParent().getContentDescription(), "clicking an overview task"); - mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT); - return new LaunchedAppState(mLauncher); + if (mOverview.getContainerType() + == LauncherInstrumentation.ContainerType.SPLIT_SCREEN_SELECT) { + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SPLIT_START_EVENT); + + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "launched splitscreen")) { + + BySelector divider = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle"); + mLauncher.waitForSystemUiObject(divider); + return new LaunchedAppState(mLauncher); + } + } else { + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT); + return new LaunchedAppState(mLauncher); + } } } } diff --git a/tests/tapl/com/android/launcher3/tapl/SplitScreenSelect.java b/tests/tapl/com/android/launcher3/tapl/SplitScreenSelect.java new file mode 100644 index 0000000000..3cf3ed662f --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/SplitScreenSelect.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 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 com.android.launcher3.tapl.LauncherInstrumentation.ContainerType; + +/** + * Represents a special state in Overview where the initial split app is shoved to the side and a + * second split app can be selected. + */ +public class SplitScreenSelect extends Overview { + + SplitScreenSelect(LauncherInstrumentation launcher) { + super(launcher); + } + + @Override + protected ContainerType getContainerType() { + return ContainerType.SPLIT_SCREEN_SELECT; + } +}