Merge "Add new quickstep test for many tasks open at once." into sc-v2-dev

This commit is contained in:
Pat Manning
2021-10-20 15:20:26 +00:00
committed by Android (Google) Code Review
9 changed files with 261 additions and 24 deletions

View File

@@ -63,6 +63,17 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.height());
return response;
}
case TestProtocol.REQUEST_GET_GRID_TASK_SIZE_RECT_FOR_TABLET: {
if (!mDeviceProfile.isTablet) {
return null;
}
Rect gridTaskRect = new Rect();
LauncherActivityInterface.INSTANCE.calculateGridTaskSize(mContext, mDeviceProfile,
gridTaskRect, PagedOrientationHandler.PORTRAIT);
response.putParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD, gridTaskRect);
return response;
}
}
return super.call(method, arg);

View File

@@ -1484,6 +1484,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return groupViewCount;
}
/**
* Returns the number of tasks in the top row of the overview grid.
*/
public int getTopRowTaskCountForTablet() {
return mTopRowIdSet.size();
}
/**
* Returns the number of tasks in the bottom row of the overview grid.
*/
public int getBottomRowTaskCountForTablet() {
return getTaskViewCount() - mTopRowIdSet.size() - 1;
}
protected void onTaskStackUpdated() {
// Lazily update the empty message only when the task stack is reapplied
updateEmptyMessage();
@@ -3170,7 +3184,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
* Returns all the tasks in the bottom row, without the focused task
*/
private IntArray getBottomRowIdArray() {
int bottomRowIdArraySize = getTaskViewCount() - mTopRowIdSet.size() - 1;
int bottomRowIdArraySize = getBottomRowTaskCountForTablet();
if (bottomRowIdArraySize <= 0) {
return new IntArray(0);
}

View File

@@ -146,7 +146,8 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
// Test dismissing all tasks.
mLauncher.pressHome().switchToOverview().dismissAllTasks();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
assertTrue("Launcher internal state is not Home",
isInState(() -> LauncherState.NORMAL));
executeOnLauncher(
launcher -> assertEquals("Still have tasks after dismissing all",
0, getTaskCount(launcher)));
@@ -180,6 +181,14 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
return launcher.<RecentsView>getOverviewPanel().getTaskViewCount();
}
private int getTopRowTaskCountForTablet(Launcher launcher) {
return launcher.<RecentsView>getOverviewPanel().getTopRowTaskCountForTablet();
}
private int getBottomRowTaskCountForTablet(Launcher launcher) {
return launcher.<RecentsView>getOverviewPanel().getBottomRowTaskCountForTablet();
}
@Test
@NavigationModeSwitch
@PortraitLandscape
@@ -276,4 +285,70 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
isTestActivityRunning(2));
getAndAssertBackground();
}
@Test
@PortraitLandscape
public void testOverviewForTablet() throws Exception {
if (!mLauncher.isTablet()) {
return;
}
for (int i = 2; i <= 12; i++) {
startTestActivity(i);
}
Overview overview = mLauncher.pressHome().switchToOverview();
executeOnLauncher(
launcher -> assertTrue("Don't have at least 11 tasks",
getTaskCount(launcher) >= 11));
// Test scroll the first task off screen
overview.scrollCurrentTaskOffScreen();
assertTrue("Launcher internal state is not Overview",
isInState(() -> LauncherState.OVERVIEW));
executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
getCurrentOverviewPage(launcher) > 0));
// Test opening the task.
overview.getCurrentTask().open();
assertTrue("Test activity didn't open from Overview",
mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity8")),
DEFAULT_UI_TIMEOUT));
// Scroll the task offscreen as it is now first
overview = mLauncher.pressHome().switchToOverview();
overview.scrollCurrentTaskOffScreen();
assertTrue("Launcher internal state is not Overview",
isInState(() -> LauncherState.OVERVIEW));
executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
getCurrentOverviewPage(launcher) > 0));
// Test dismissing the later task.
final Integer numTasks = getFromLauncher(this::getTaskCount);
overview.getCurrentTask().dismiss();
executeOnLauncher(
launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
numTasks - 1, getTaskCount(launcher)));
executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after dismissal",
(Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
launcher)) <= 1)));
// Test dismissing more tasks.
assertTrue("Launcher internal state didn't remain in Overview",
isInState(() -> LauncherState.OVERVIEW));
overview.getCurrentTask().dismiss();
assertTrue("Launcher internal state didn't remain in Overview",
isInState(() -> LauncherState.OVERVIEW));
overview.getCurrentTask().dismiss();
executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after multiple dismissals",
(Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
launcher)) <= 1)));
// Test dismissing all tasks.
mLauncher.pressHome().switchToOverview().dismissAllTasks();
assertTrue("Launcher internal state is not Home",
isInState(() -> LauncherState.NORMAL));
executeOnLauncher(
launcher -> assertEquals("Still have tasks after dismissing all",
0, getTaskCount(launcher)));
}
}

View File

@@ -104,6 +104,8 @@ public final class TestProtocol {
public static final String REQUEST_GET_ACTIVITIES = "get-activities";
public static final String REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET =
"get-focused-task-height-for-tablet";
public static final String REQUEST_GET_GRID_TASK_SIZE_RECT_FOR_TABLET =
"get-grid-task-size-rect-for-tablet";
public static Long sForcePauseTimeout;
public static final String REQUEST_SET_FORCE_PAUSE_TIMEOUT = "set-force-pause-timeout";

View File

@@ -145,6 +145,16 @@
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts"/>
</activity>
<activity
android:name="com.android.launcher3.testcomponent.OtherBaseTestingActivity"
android:label="OtherLauncherTestApp"
android:exported="true"
android:taskAffinity="com.android.launcher3.testcomponent.Affinity2">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity-alias android:name="Activity2"
android:label="TestActivity2"
android:exported="true"
@@ -208,31 +218,36 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<activity-alias android:name="Activity9"
android:label="TestActivity9"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<activity-alias android:name="Activity9" android:exported="true"
android:label="TestActivity9"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias android:name="Activity10"
android:label="TestActivity10"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<activity-alias android:name="Activity10" android:exported="true"
android:label="TestActivity10"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias android:name="Activity11"
android:label="TestActivity11"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<activity-alias android:name="Activity11" android:exported="true"
android:label="TestActivity11"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias android:name="Activity12" android:exported="true"
android:label="TestActivity12"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2018 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.testcomponent;
/**
* Extension of BaseTestingActivity to help test many activities open at once.
*/
public class OtherBaseTestingActivity extends BaseTestingActivity {}

View File

@@ -25,6 +25,7 @@ import androidx.test.uiautomator.UiObject2;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Common overview panel for both Launcher and fallback recents
@@ -53,14 +54,18 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
}
private void flingForwardImpl() {
flingForwardImpl(0);
}
private void flingForwardImpl(int rightMargin) {
try (LauncherInstrumentation.Closable c =
mLauncher.addContextLayer("want to fling forward in overview")) {
LauncherInstrumentation.log("Overview.flingForward before fling");
final UiObject2 overview = verifyActiveContainer();
final int leftMargin =
mLauncher.getTargetInsets().left + mLauncher.getEdgeSensitivityWidth();
mLauncher.scroll(
overview, Direction.LEFT, new Rect(leftMargin + 1, 0, 0, 0), 20, false);
mLauncher.scroll(overview, Direction.LEFT, new Rect(leftMargin + 1, 0, rightMargin, 0),
20, false);
try (LauncherInstrumentation.Closable c2 =
mLauncher.addContextLayer("flung forwards")) {
verifyActiveContainer();
@@ -86,6 +91,8 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
mLauncher.clickLauncherObject(
mLauncher.waitForObjectInContainer(verifyActiveContainer(), clearAllSelector));
mLauncher.waitUntilLauncherObjectGone(clearAllSelector);
}
}
@@ -110,6 +117,40 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
}
}
/**
* Scrolls the current task via flinging forward until it is off screen.
*
* If only one task is present, it is only partially scrolled off screen and will still be
* the current task.
*/
public void scrollCurrentTaskOffScreen() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to scroll current task off screen in overview")) {
verifyActiveContainer();
OverviewTask task = getCurrentTask();
mLauncher.assertNotNull("current task is null", task);
flingForwardImpl(task.getTaskCenterX());
try (LauncherInstrumentation.Closable c2 =
mLauncher.addContextLayer("scrolled task off screen")) {
verifyActiveContainer();
verifyActionsViewVisibility();
if (getTaskCount() > 1) {
if (mLauncher.isTablet()) {
mLauncher.assertTrue("current task is not grid height",
getCurrentTask().getVisibleHeight() == mLauncher
.getGridTaskRectForTablet().height());
}
mLauncher.assertTrue("Current task not scrolled off screen",
!getCurrentTask().equals(task));
}
}
}
}
/**
* Gets the current task in the carousel, or fails if the carousel is empty.
*
@@ -130,6 +171,20 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
return new OverviewTask(mLauncher, widestTask, this);
}
/**
* Returns a list of all tasks fully visible in the tablet grid overview.
*/
@NonNull
public List<OverviewTask> getCurrentTasksForTablet() {
final List<UiObject2> taskViews = getTasks();
mLauncher.assertNotEquals("Unable to find a task", 0, taskViews.size());
final int gridTaskWidth = mLauncher.getGridTaskRectForTablet().width();
return taskViews.stream().filter(t -> t.getVisibleBounds().width() == gridTaskWidth).map(
t -> new OverviewTask(mLauncher, t, this)).collect(Collectors.toList());
}
@NonNull
private List<UiObject2> getTasks() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
@@ -166,11 +221,18 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
}
}
/**
* Returns if clear all button is visible.
*/
public boolean isClearAllVisible() {
return mLauncher.hasLauncherObject(mLauncher.getOverviewObjectSelector("clear_all"));
}
/* TODO(b/197630182): Once b/188790554 is fixed, remove instanceof check. Currently, when
swiping from app to overview in Fallback Recents, taskbar remains and no action buttons
are visible, so we are only testing Overview for now, not BaseOverview. */
private void verifyActionsViewVisibility() {
if (!(this instanceof Overview)) {
if (!(this instanceof Overview) || !hasTasks()) {
return;
}
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
@@ -198,8 +260,13 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
/**
* Returns Overview focused task if it exists.
*
* @throws IllegalStateException if not run on a tablet device.
*/
UiObject2 getFocusedTaskForTablet() {
if (!mLauncher.isTablet()) {
throw new IllegalStateException("Must be run on tablet device.");
}
final List<UiObject2> taskViews = getTasks();
if (taskViews.size() == 0) {
return null;

View File

@@ -326,6 +326,11 @@ public final class LauncherInstrumentation {
TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
Rect getGridTaskRectForTablet() {
return ((Rect) getTestInfo(TestProtocol.REQUEST_GET_GRID_TASK_SIZE_RECT_FOR_TABLET)
.getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD));
}
float getExactScreenCenterX() {
return getRealDisplaySize().x / 2f;
}

View File

@@ -24,7 +24,9 @@ import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.testing.TestProtocol;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* A recent task in the overview panel carousel.
@@ -47,10 +49,14 @@ public final class OverviewTask {
mOverview.verifyActiveContainer();
}
private int getVisibleHeight() {
int getVisibleHeight() {
return mTask.getVisibleBounds().height();
}
int getTaskCenterX() {
return mTask.getVisibleCenter().x;
}
/**
* Dismisses the task by swiping up.
*/
@@ -68,6 +74,8 @@ public final class OverviewTask {
boolean taskWasFocused = mLauncher.isTablet() && getVisibleHeight() == mLauncher
.getFocusedTaskHeightForTablet();
List<Integer> originalTasksCenterX = getCurrentTasksCenterXList();
boolean isClearAllVisibleBeforeDismiss = mOverview.isClearAllVisible();
dismissBySwipingUp();
@@ -76,6 +84,16 @@ public final class OverviewTask {
mLauncher.assertNotNull("No task became focused",
mOverview.getFocusedTaskForTablet());
}
if (!isClearAllVisibleBeforeDismiss) {
List<Integer> currentTasksCenterX = getCurrentTasksCenterXList();
if (originalTasksCenterX.size() == currentTasksCenterX.size()) {
// Check for the same number of visible tasks before and after to
// avoid asserting on cases of shifting all tasks to close the distance
// between clear all and tasks at the end of the grid.
mLauncher.assertTrue("Task centers not aligned",
originalTasksCenterX.equals(currentTasksCenterX));
}
}
}
}
}
@@ -94,6 +112,14 @@ public final class OverviewTask {
+ centerY, "swiping to dismiss");
}
private List<Integer> getCurrentTasksCenterXList() {
return mLauncher.isTablet()
? mOverview.getCurrentTasksForTablet().stream()
.map(OverviewTask::getTaskCenterX)
.collect(Collectors.toList())
: List.of(mOverview.getCurrentTask().getTaskCenterX());
}
/**
* Clicks at the task.
*/