diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index acb7eb38a2..9a34478918 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -201,6 +201,13 @@ public class TestInformationHandler implements ResourceBasedOverride { }); } + case TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS: { + return getLauncherUIProperty(Bundle::putParcelable, launcher -> new Point( + InvariantDeviceProfile.INSTANCE.get(mContext).numColumns, + InvariantDeviceProfile.INSTANCE.get(mContext).numRows) + ); + } + case TestProtocol.REQUEST_HOTSEAT_CELL_CENTER: { final HotseatCellCenterRequest request = extra.getParcelable( TestProtocol.TEST_INFO_REQUEST_FIELD); diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java index f5ee91b297..9b2ce9a67f 100644 --- a/src/com/android/launcher3/testing/shared/TestProtocol.java +++ b/src/com/android/launcher3/testing/shared/TestProtocol.java @@ -123,6 +123,7 @@ public final class TestProtocol { public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size"; public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center"; + public static final String REQUEST_WORKSPACE_COLUMNS_ROWS = "workspace-columns-rows"; public static final String REQUEST_HOTSEAT_CELL_CENTER = "hotseat-cell-center"; diff --git a/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java b/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java index 80dbef86b9..e2cd8ea965 100644 --- a/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java +++ b/src/com/android/launcher3/testing/shared/WorkspaceCellCenterRequest.java @@ -124,7 +124,7 @@ public class WorkspaceCellCenterRequest implements TestInformationRequest { * Set span Height in cells */ public WorkspaceCellCenterRequest.Builder setSpanY(int y) { - this.mCellY = y; + this.mSpanY = y; return this; } diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java index 469d79f74e..6d75180f8c 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java @@ -29,7 +29,73 @@ import java.util.Set; import java.util.stream.Collectors; -public class CellLayoutBoard { +public class CellLayoutBoard implements Comparable { + + private boolean intersects(Rect r1, Rect r2) { + // If one rectangle is on left side of other + if (r1.left > r2.right || r2.left > r1.right) { + return false; + } + + // If one rectangle is above other + if (r1.bottom > r2.top || r2.bottom > r1.top) { + return false; + } + + return true; + } + + private boolean overlapsWithIgnored(Set ignoredRectangles, Rect rect) { + for (Rect ignoredRect : ignoredRectangles) { + // Using the built in intersects doesn't work because it doesn't account for area 0 + if (intersects(ignoredRect, rect)) { + return true; + } + } + return false; + } + + @Override + public int compareTo(CellLayoutBoard cellLayoutBoard) { + // to be equal they need to have the same number of widgets and the same dimensions + // their order can be different + Set widgetsSet = new HashSet<>(); + Set ignoredRectangles = new HashSet<>(); + for (WidgetRect rect : mWidgetsRects) { + if (rect.shouldIgnore()) { + ignoredRectangles.add(rect.mBounds); + } else { + widgetsSet.add(rect.mBounds); + } + } + for (WidgetRect rect : cellLayoutBoard.mWidgetsRects) { + // ignore rectangles overlapping with the area marked by x + if (overlapsWithIgnored(ignoredRectangles, rect.mBounds)) { + continue; + } + if (!widgetsSet.contains(rect.mBounds)) { + return -1; + } + widgetsSet.remove(rect.mBounds); + } + if (!widgetsSet.isEmpty()) { + return 1; + } + + // to be equal they need to have the same number of icons their order can be different + Set iconsSet = new HashSet<>(); + mIconPoints.forEach(icon -> iconsSet.add(icon.getCoord())); + for (IconPoint icon : cellLayoutBoard.mIconPoints) { + if (!iconsSet.contains(icon.getCoord())) { + return -1; + } + iconsSet.remove(icon.getCoord()); + } + if (!iconsSet.isEmpty()) { + return 1; + } + return 0; + } public static class CellType { // The cells marked by this will be filled by 1x1 widgets and will be ignored when @@ -115,7 +181,7 @@ public class CellLayoutBoard { List mIconPoints = new ArrayList<>(); Map mIconsMap = new HashMap<>(); - Point mMain = new Point(); + WidgetRect mMain = null; CellLayoutBoard() { for (int x = 0; x < mWidget.length; x++) { @@ -133,7 +199,7 @@ public class CellLayoutBoard { return mIconPoints; } - public Point getMain() { + public WidgetRect getMain() { return mMain; } @@ -273,6 +339,16 @@ public class CellLayoutBoard { return iconPoints; } + public static WidgetRect getMainFromList(List boards) { + for (CellLayoutBoard board : boards) { + WidgetRect main = board.getMain(); + if (main != null) { + return main; + } + } + return null; + } + public static CellLayoutBoard boardFromString(String boardStr) { String[] lines = boardStr.split("\n"); CellLayoutBoard board = new CellLayoutBoard(); @@ -281,17 +357,18 @@ public class CellLayoutBoard { String line = lines[y]; for (int x = 0; x < line.length(); x++) { char c = line.charAt(x); - if (c == CellType.MAIN_WIDGET) { - board.mMain = new Point(x, y); - } if (c != CellType.EMPTY) { board.mWidget[x][y] = line.charAt(x); } } } board.mWidgetsRects = getRects(board.mWidget); - board.mWidgetsRects.forEach( - widgetRect -> board.mWidgetsMap.put(widgetRect.mType, widgetRect)); + board.mWidgetsRects.forEach(widgetRect -> { + if (widgetRect.mType == CellType.MAIN_WIDGET) { + board.mMain = widgetRect; + } + board.mWidgetsMap.put(widgetRect.mType, widgetRect); + }); board.mIconPoints = getIconPoints(board.mWidget); return board; } @@ -308,4 +385,24 @@ public class CellLayoutBoard { } return s.toString(); } + + public static List boardListFromString(String boardsStr) { + String[] lines = boardsStr.split("\n"); + ArrayList individualBoards = new ArrayList<>(); + ArrayList boards = new ArrayList<>(); + for (String line : lines) { + String[] boardSegment = line.split("\\|"); + for (int i = 0; i < boardSegment.length; i++) { + if (i >= individualBoards.size()) { + individualBoards.add(boardSegment[i]); + } else { + individualBoards.set(i, individualBoards.get(i) + "\n" + boardSegment[i]); + } + } + } + for (String board : individualBoards) { + boards.add(CellLayoutBoard.boardFromString(board)); + } + return boards; + } } diff --git a/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java b/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java new file mode 100644 index 0000000000..9b52fe826c --- /dev/null +++ b/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java @@ -0,0 +1,88 @@ +/* + * 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.celllayout.testcases; + +import android.graphics.Point; + +import java.util.Map; + +/** + * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character + * in the board mean refer to {@code CellType} + */ +public class MultipleCellLayoutsSimpleReorder { + + /** 5x5 Test + **/ + private static final String START_BOARD_STR_5x5 = "" + + "xxxxx|-----\n" + + "--mm-|-----\n" + + "--mm-|-----\n" + + "-----|-----\n" + + "-----|-----"; + private static final Point MOVE_TO_5x5 = new Point(8, 3); + private static final String END_BOARD_STR_5x5 = "" + + "xxxxx|-----\n" + + "-----|-----\n" + + "-----|-----\n" + + "-----|---mm\n" + + "-----|---mm"; + private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5, + MOVE_TO_5x5, + END_BOARD_STR_5x5); + + /** 4x4 Test + **/ + private static final String START_BOARD_STR_4x4 = "" + + "xxxx|----\n" + + "--mm|----\n" + + "--mm|----\n" + + "----|----"; + private static final Point MOVE_TO_4x4 = new Point(5, 3); + private static final String END_BOARD_STR_4x4 = "" + + "xxxx|----\n" + + "----|----\n" + + "----|-mm-\n" + + "----|-mm-"; + private static final ReorderTestCase TEST_CASE_4x4 = new ReorderTestCase(START_BOARD_STR_4x4, + MOVE_TO_4x4, + END_BOARD_STR_4x4); + + + /** 6x5 Test + **/ + private static final String START_BOARD_STR_6x5 = "" + + "xxxxxx|------\n" + + "--m---|------\n" + + "------|------\n" + + "------|------\n" + + "------|------"; + private static final Point MOVE_TO_6x5 = new Point(10, 4); + private static final String END_BOARD_STR_6x5 = "" + + "xxxxxx|------\n" + + "------|------\n" + + "------|------\n" + + "------|------\n" + + "------|----m-"; + private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5, + MOVE_TO_6x5, + END_BOARD_STR_6x5); + + public static final Map TEST_BY_GRID_SIZE = + Map.of(new Point(5, 5), TEST_CASE_5x5, + new Point(4, 4), TEST_CASE_4x4, + new Point(6, 5), TEST_CASE_6x5); +} diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 7b38ed6900..35f6cbc462 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -29,6 +29,7 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.celllayout.testcases.FullReorderCase; import com.android.launcher3.celllayout.testcases.MoveOutReorderCase; +import com.android.launcher3.celllayout.testcases.MultipleCellLayoutsSimpleReorder; import com.android.launcher3.celllayout.testcases.PushReorderCase; import com.android.launcher3.celllayout.testcases.ReorderTestCase; import com.android.launcher3.celllayout.testcases.SimpleReorderCase; @@ -38,7 +39,6 @@ import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.ui.TaplTestsLauncher3; import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.views.DoubleShadowBubbleTextView; -import com.android.launcher3.widget.LauncherAppWidgetHostView; import org.junit.Assume; import org.junit.Before; @@ -48,6 +48,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -62,20 +63,6 @@ public class ReorderWidgets extends AbstractLauncherUiTest { TestWorkspaceBuilder mWorkspaceBuilder; - private View getViewAt(int cellX, int cellY) { - return getFromLauncher(l -> l.getWorkspace().getScreenWithId( - l.getWorkspace().getScreenIdForPageIndex(0)).getChildAt(cellX, cellY)); - } - - private Point getCellDimensions() { - return getFromLauncher(l -> { - CellLayout cellLayout = l.getWorkspace().getScreenWithId( - l.getWorkspace().getScreenIdForPageIndex(0)); - return new Point(cellLayout.getWidth() / cellLayout.getCountX(), - cellLayout.getHeight() / cellLayout.getCountY()); - }); - } - @Before public void setup() throws Throwable { mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext); @@ -86,28 +73,26 @@ public class ReorderWidgets extends AbstractLauncherUiTest { /** * Validate if the given board represent the current CellLayout **/ - private boolean validateBoard(CellLayoutBoard board) { - boolean match = true; - Point cellDimensions = getCellDimensions(); - for (CellLayoutBoard.WidgetRect widgetRect : board.getWidgets()) { - if (widgetRect.shouldIgnore()) { - continue; + private boolean validateBoard(List testBoards) { + ArrayList workspaceBoards = workspaceToBoards(); + if (workspaceBoards.size() < testBoards.size()) { + return false; + } + for (int i = 0; i < testBoards.size(); i++) { + if (testBoards.get(i).compareTo(workspaceBoards.get(i)) != 0) { + return false; } - View widget = getViewAt(widgetRect.getCellX(), widgetRect.getCellY()); - assertTrue("The view selected at " + board + " is not a widget", - widget instanceof LauncherAppWidgetHostView); - match &= widgetRect.getSpanX() - == Math.round(widget.getWidth() / (float) cellDimensions.x); - match &= widgetRect.getSpanY() - == Math.round(widget.getHeight() / (float) cellDimensions.y); - if (!match) return match; } - for (CellLayoutBoard.IconPoint iconPoint : board.getIcons()) { - View icon = getViewAt(iconPoint.getCoord().x, iconPoint.getCoord().y); - assertTrue("The view selected at " + iconPoint.coord + " is not an Icon", - icon instanceof DoubleShadowBubbleTextView); + return true; + } + + private FavoriteItemsTransaction buildWorkspaceFromBoards(List boards, + FavoriteItemsTransaction transaction) { + for (int i = 0; i < boards.size(); i++) { + CellLayoutBoard board = boards.get(i); + mWorkspaceBuilder.buildFromBoard(board, transaction, i); } - return match; + return transaction; } private void printCurrentWorkspace() { @@ -148,22 +133,25 @@ public class ReorderWidgets extends AbstractLauncherUiTest { private void runTestCase(ReorderTestCase testCase) throws ExecutionException, InterruptedException { - Point mainWidgetCellPos = testCase.mStart.getMain(); + CellLayoutBoard.WidgetRect mainWidgetCellPos = CellLayoutBoard.getMainFromList( + testCase.mStart); FavoriteItemsTransaction transaction = new FavoriteItemsTransaction(mTargetContext, this); - mWorkspaceBuilder.buildFromBoard(testCase.mStart, transaction).commit(); + transaction = buildWorkspaceFromBoards(testCase.mStart, transaction); + transaction.commit(); waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading()); - Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x, - mainWidgetCellPos.y); + Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(), + mainWidgetCellPos.getCellY()); assertNotNull(widget); WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x, - testCase.moveMainTo.y); + testCase.moveMainTo.y, mainWidgetCellPos.getSpanX(), mainWidgetCellPos.getSpanY()); resizeFrame.dismiss(); boolean isValid = false; - for (CellLayoutBoard board : testCase.mEnd) { - isValid |= validateBoard(board); + for (List boards : testCase.mEnd) { + isValid |= validateBoard(boards); + if (isValid) break; } printCurrentWorkspace(); assertTrue("Non of the valid boards match with the current state", isValid); @@ -207,4 +195,11 @@ public class ReorderWidgets extends AbstractLauncherUiTest { runTestCaseMap(MoveOutReorderCase.TEST_BY_GRID_SIZE, MoveOutReorderCase.class.getSimpleName()); } + + @Test + public void multipleCellLayoutsSimpleReorder() throws ExecutionException, InterruptedException { + Assume.assumeTrue("Test doesn't support foldables", !mLauncher.isTwoPanels()); + runTestCaseMap(MultipleCellLayoutsSimpleReorder.TEST_BY_GRID_SIZE, + MultipleCellLayoutsSimpleReorder.class.getSimpleName()); + } } diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java index 7e3588b944..5945605daf 100644 --- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java +++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.celllayout; -import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID; import static com.android.launcher3.util.WidgetUtils.createWidgetInfo; import android.content.ComponentName; @@ -62,7 +61,7 @@ public class TestWorkspaceBuilder { * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. */ private FavoriteItemsTransaction fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect, - FavoriteItemsTransaction transaction) { + FavoriteItemsTransaction transaction, int screenId) { int initX = widgetRect.getCellX(); int initY = widgetRect.getCellY(); for (int x = initX; x < initX + widgetRect.getSpanX(); x++) { @@ -71,8 +70,7 @@ public class TestWorkspaceBuilder { // this widgets are filling, we don't care if we can't place them ItemInfo item = createWidgetInCell( new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE, - new Rect(x, y, x, y)) - ); + new Rect(x, y, x, y)), screenId); transaction.addItem(item); } catch (Exception e) { Log.d(TAG, "Unable to place filling widget at " + x + "," + y); @@ -94,11 +92,11 @@ public class TestWorkspaceBuilder { } private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect, - FavoriteItemsTransaction transaction) { + FavoriteItemsTransaction transaction, int screenId) { if (widgetRect.mType == 'x') { - fillWithWidgets(widgetRect, transaction); + fillWithWidgets(widgetRect, transaction, screenId); } else { - transaction.addItem(createWidgetInCell(widgetRect)); + transaction.addItem(createWidgetInCell(widgetRect, screenId)); } } @@ -106,11 +104,11 @@ public class TestWorkspaceBuilder { * Builds the given board into the transaction */ public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board, - FavoriteItemsTransaction transaction) { + FavoriteItemsTransaction transaction, final int screenId) { board.getWidgets().forEach( - (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction)); + (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId)); board.getIcons().forEach((iconPoint) -> - transaction.addItem(createIconInCell(iconPoint)) + transaction.addItem(createIconInCell(iconPoint, screenId)) ); return transaction; } @@ -127,7 +125,7 @@ public class TestWorkspaceBuilder { return transaction; } - private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) { + private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect, int screenId) { LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false); LauncherAppWidgetInfo item = createWidgetInfo(info, ApplicationProvider.getApplicationContext(), true); @@ -136,14 +134,14 @@ public class TestWorkspaceBuilder { item.cellY = widgetRect.getCellY(); item.spanX = widgetRect.getSpanX(); item.spanY = widgetRect.getSpanY(); - item.screenId = FIRST_SCREEN_ID; + item.screenId = screenId; return item; } - private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint) { + private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) { WorkspaceItemInfo item = new WorkspaceItemInfo(getApp()); item.id = getID(); - item.screenId = FIRST_SCREEN_ID; + item.screenId = screenId; item.cellX = iconPoint.getCoord().x; item.cellY = iconPoint.getCoord().y; item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1; diff --git a/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java b/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java index 0a28668d96..1689e47834 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/ReorderTestCase.java @@ -24,23 +24,23 @@ import java.util.List; import java.util.stream.Collectors; public class ReorderTestCase { - public CellLayoutBoard mStart; + public List mStart; public Point moveMainTo; - public List mEnd; + public List> mEnd; - ReorderTestCase(CellLayoutBoard start, Point moveMainTo, CellLayoutBoard ... end) { + ReorderTestCase(List start, Point moveMainTo, List ... end) { mStart = start; this.moveMainTo = moveMainTo; mEnd = Arrays.asList(end); } ReorderTestCase(String start, Point moveMainTo, String ... end) { - mStart = CellLayoutBoard.boardFromString(start); + mStart = CellLayoutBoard.boardListFromString(start); this.moveMainTo = moveMainTo; mEnd = Arrays .asList(end) .stream() - .map(CellLayoutBoard::boardFromString) + .map(CellLayoutBoard::boardListFromString) .collect(Collectors.toList()); } } diff --git a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java index 546c48bccb..c9f6849854 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java @@ -33,13 +33,13 @@ public class SimpleReorderCase { + "--mm-\n" + "-----\n" + "-----"; - private static final Point MOVE_TO_5x5 = new Point(4, 4); + private static final Point MOVE_TO_5x5 = new Point(0, 4); private static final String END_BOARD_STR_5x5 = "" + "xxxxx\n" + "-----\n" + "-----\n" - + "---mm\n" - + "---mm"; + + "mm---\n" + + "mm---"; private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5, MOVE_TO_5x5, END_BOARD_STR_5x5); @@ -61,7 +61,27 @@ public class SimpleReorderCase { MOVE_TO_4x4, END_BOARD_STR_4x4); + /** 6x5 Test + **/ + private static final String START_BOARD_STR_6x5 = "" + + "xxxxxx\n" + + "-mm---\n" + + "-mm---\n" + + "------\n" + + "------"; + private static final Point MOVE_TO_6x5 = new Point(4, 3); + private static final String END_BOARD_STR_6x5 = "" + + "xxxxxx\n" + + "------\n" + + "------\n" + + "----mm\n" + + "----mm"; + private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5, + MOVE_TO_6x5, + END_BOARD_STR_6x5); + public static final Map TEST_BY_GRID_SIZE = Map.of(new Point(5, 5), TEST_CASE_5x5, - new Point(4, 4), TEST_CASE_4x4); + new Point(4, 4), TEST_CASE_4x4, + new Point(6, 5), TEST_CASE_6x5); } diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java index 046308b595..d440903eb6 100644 --- a/tests/tapl/com/android/launcher3/tapl/Widget.java +++ b/tests/tapl/com/android/launcher3/tapl/Widget.java @@ -71,7 +71,7 @@ public final class Widget extends Launchable implements WorkspaceDragSource { public WidgetResizeFrame dragWidgetToWorkspace() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false, -1, - -1); + -1, 1, 1); } } @@ -80,12 +80,12 @@ public final class Widget extends Launchable implements WorkspaceDragSource { * cellY and returns the resize frame that is shown after the widget is added. */ @NonNull - public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY) { + public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY, int spanX, int spanY) { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "Dragging widget to workspace cell " + cellX + "," + cellY)) { return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false, - cellX, cellY); + cellX, cellY, spanX, spanY); } } @@ -98,7 +98,7 @@ public final class Widget extends Launchable implements WorkspaceDragSource { public WidgetResizeFrame dragConfigWidgetToWorkspace(boolean acceptsConfig) { // TODO(b/239438337, fransebas) add correct event checking for this case //try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { - return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1); + return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1, 1, 1); //} } @@ -110,18 +110,17 @@ public final class Widget extends Launchable implements WorkspaceDragSource { * @param cellX X position in the CellLayout * @param cellY Y position in the CellLayout */ - private void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut, int cellX, - int cellY) { + private void dragToWorkspaceCellPosition(boolean startsActivity, boolean isWidgetShortcut, + int cellX, int cellY, int spanX, int spanY) { Launchable launchable = getLaunchable(); LauncherInstrumentation launcher = launchable.mLauncher; - Workspace.dragIconToWorkspace( + Workspace.dragIconToWorkspaceCellPosition( launcher, launchable, - () -> Workspace.getCellCenter(launchable.mLauncher, cellX, cellY), + cellX, cellY, spanX, spanY, startsActivity, isWidgetShortcut, launchable::addExpectedEventsForLongClick); - } /** @@ -144,13 +143,13 @@ public final class Widget extends Launchable implements WorkspaceDragSource { */ @Nullable private WidgetResizeFrame dragWidgetToWorkspace(boolean configurable, boolean acceptsConfig, - int cellX, int cellY) { + int cellX, int cellY, int spanX, int spanY) { if (cellX == -1 || cellY == -1) { internalDragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */ false); } else { - dragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */ false, - cellX, cellY); + dragToWorkspaceCellPosition(/* startsActivity= */ configurable, /* isWidgetShortcut= */ + false, cellX, cellY, spanX, spanY); } if (configurable) { diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 388955c6ab..62665dea89 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -409,9 +409,15 @@ public final class Workspace extends Home { } static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY) { - return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX( - cellX).setCellY(cellY).build()).getParcelable( - TestProtocol.TEST_INFO_RESPONSE_FIELD); + return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX).setCellY( + cellY).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + + static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY, int spanX, + int spanY) { + return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX) + .setCellY(cellY).setSpanX(spanX).setSpanY(spanY).build()) + .getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD); } static Point getHotseatCellCenter(LauncherInstrumentation launcher, int cellInd) { @@ -419,6 +425,12 @@ public final class Workspace extends Home { .setCellInd(cellInd).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD); } + /** Returns the number of rows and columns in the workspace */ + public Point getRowsAndCols() { + return mLauncher.getTestInfo(TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS).getParcelable( + TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + /** * Finds folder icons in the current workspace. * @@ -457,6 +469,19 @@ public final class Workspace extends Home { launcher, launchable, dest, expectLongClickEvents, expectDropEvents); } + static void dragIconToWorkspaceCellPosition(LauncherInstrumentation launcher, + Launchable launchable, int cellX, int cellY, int spanX, int spanY, + boolean startsActivity, boolean isWidgetShortcut, Runnable expectLongClickEvents) { + Runnable expectDropEvents = null; + if (startsActivity || isWidgetShortcut) { + expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, + LauncherInstrumentation.EVENT_START); + } + dragIconToWorkspaceCellPosition( + launcher, launchable, cellX, cellY, spanX, spanY, true, expectLongClickEvents, + expectDropEvents); + } + /** * Drag icon in workspace to else where and drop it immediately. * (There is no slow down time before drop event) @@ -526,6 +551,51 @@ public final class Workspace extends Home { } } + static void dragIconToWorkspaceCellPosition( + LauncherInstrumentation launcher, + Launchable launchable, + int cellX, int cellY, int spanX, int spanY, + boolean isDecelerating, + Runnable expectLongClickEvents, + @Nullable Runnable expectDropEvents) { + try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer( + "want to drag icon to workspace")) { + Point rowsAndCols = launcher.getWorkspace().getRowsAndCols(); + int destinationWorkspace = cellX / rowsAndCols.x; + cellX = cellX % rowsAndCols.x; + + final long downTime = SystemClock.uptimeMillis(); + Point dragStart = launchable.startDrag( + downTime, + expectLongClickEvents, + /* runToSpringLoadedState= */ true); + Point targetDest = getCellCenter(launcher, cellX, cellY, spanX, spanY); + int displayX = launcher.getRealDisplaySize().x; + + // Since the destination can be on another page, we need to drag to the edge first + // until we reach the target page + for (int i = 0; i < destinationWorkspace; i++) { + // Don't drag all the way to the edge to prevent touch events from getting out of + //screen bounds. + Point screenEdge = new Point(displayX - 1, targetDest.y); + Point finalDragStart = dragStart; + executeAndWaitForPageScroll(launcher, + () -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS, + true, downTime, downTime, true, + LauncherInstrumentation.GestureScope.INSIDE)); + dragStart = screenEdge; + } + + // targetDest.x is now between 0 and displayX so we found the target page, + // we just have to put move the icon to the destination and drop it + launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating, + downTime, SystemClock.uptimeMillis(), false, + LauncherInstrumentation.GestureScope.INSIDE); + launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP); + dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents); + } + } + private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher, Runnable command) { launcher.executeAndWaitForEvent(command,