diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index b2979730de..fefef2f45e 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -220,7 +220,6 @@ public class RecentsAnimationController { */ public void enableInputConsumer() { UI_HELPER_EXECUTOR.submit(() -> { - mController.hideCurrentInputMethod(); mController.setInputConsumerEnabled(true); }); } 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/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index c9d6394fc8..c178175c7b 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -204,7 +204,11 @@ public class OverviewActionsView extends FrameLayo if (mDp == null) { return; } - if (mDp.areNavButtonsInline) { + boolean largeScreenLandscape = mDp.isTablet && !mDp.isTwoPanels && mDp.isLandscape; + // If in 3-button mode, shift action buttons to accommodate 3-button layout. + // (Special exception for landscape tablets, where there is enough room and we don't need to + // shift the action buttons.) + if (mDp.areNavButtonsInline && !largeScreenLandscape) { // Add extra horizontal spacing int additionalPadding = mDp.hotseatBarEndOffset; if (isLayoutRtl()) { 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/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index 6faedc0a42..f3c5dd6d31 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -602,6 +602,8 @@ public abstract class BaseAllAppsContainerView 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 f5b5a6a76f..5f920972ca 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; + } +}