From f34f35fddbf098bf79dd036fb79669e812970ad5 Mon Sep 17 00:00:00 2001 From: Sebastian Franco Date: Thu, 8 Dec 2022 11:08:00 -0800 Subject: [PATCH] Printing the workspace items to improve flake investigation. Recording the screen to investigates flakes on ReorderWidgets is really useful but it requires changing the code for that and storing the video and most of the time the useful information is just the end state so by logging the end state makes resolving flakes easier Fix: 261877803 Test: atest ReorderWidgets Change-Id: If5d9745ebb57826a55b5df9d3599eed56c48298f --- src/com/android/launcher3/Workspace.java | 5 +- .../launcher3/celllayout/CellLayoutBoard.java | 81 +++++++++++++++++++ .../launcher3/celllayout/ReorderWidgets.java | 39 +++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 483309d1cf..2b9c1359b7 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -62,6 +62,7 @@ import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.accessibility.AccessibleDragListenerAdapter; import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper; @@ -161,7 +162,9 @@ public class Workspace extends PagedView protected ShortcutAndWidgetContainer mDragSourceInternal; - @Thunk final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + @Thunk public final IntSparseArrayMap mWorkspaceScreens = new IntSparseArrayMap<>(); + @Thunk final IntArray mScreenOrder = new IntArray(); @Thunk boolean mDeferRemoveExtraEmptyScreen = false; diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java index a32ce3c558..469d79f74e 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; +import java.util.stream.Collectors; public class CellLayoutBoard { @@ -140,6 +141,73 @@ public class CellLayoutBoard { return mWidgetsMap.get(c); } + private void removeWidgetFromBoard(WidgetRect widget) { + for (int xi = widget.mBounds.left; xi < widget.mBounds.right; xi++) { + for (int yi = widget.mBounds.top; yi < widget.mBounds.bottom; yi++) { + mWidget[xi][yi] = '-'; + } + } + } + + private void removeOverlappingItems(Rect rect) { + // Remove overlapping widgets and remove them from the board + mWidgetsRects = mWidgetsRects.stream().filter(widget -> { + if (rect.intersect(widget.mBounds)) { + removeWidgetFromBoard(widget); + return false; + } + return true; + }).collect(Collectors.toList()); + // Remove overlapping icons and remove them from the board + mIconPoints = mIconPoints.stream().filter(iconPoint -> { + int x = iconPoint.coord.x; + int y = iconPoint.coord.y; + if (rect.contains(x, y)) { + mWidget[x][y] = '-'; + return false; + } + return true; + }).collect(Collectors.toList()); + } + + private void removeOverlappingItems(Point p) { + // Remove overlapping widgets and remove them from the board + mWidgetsRects = mWidgetsRects.stream().filter(widget -> { + if (widget.mBounds.contains(p.x, p.y)) { + removeWidgetFromBoard(widget); + return false; + } + return true; + }).collect(Collectors.toList()); + // Remove overlapping icons and remove them from the board + mIconPoints = mIconPoints.stream().filter(iconPoint -> { + int x = iconPoint.coord.x; + int y = iconPoint.coord.y; + if (p.x == x && p.y == y) { + mWidget[x][y] = '-'; + return false; + } + return true; + }).collect(Collectors.toList()); + } + + public void addWidget(int x, int y, int spanX, int spanY, char type) { + Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y); + removeOverlappingItems(rect); + WidgetRect widgetRect = new WidgetRect(type, rect); + mWidgetsRects.add(widgetRect); + for (int xi = rect.left; xi < rect.right + 1; xi++) { + for (int yi = rect.bottom; yi < rect.top + 1; yi++) { + mWidget[xi][yi] = type; + } + } + } + + public void addIcon(int x, int y) { + removeOverlappingItems(new Point(x, y)); + mWidget[x][y] = 'i'; + } + public static WidgetRect getWidgetRect(int x, int y, Set used, char[][] board) { char type = board[x][y]; Queue search = new ArrayDeque(); @@ -227,4 +295,17 @@ public class CellLayoutBoard { board.mIconPoints = getIconPoints(board.mWidget); return board; } + + public String toString(int maxX, int maxY) { + StringBuilder s = new StringBuilder(); + maxX = Math.min(maxX, mWidget.length); + maxY = Math.min(maxY, mWidget[0].length); + for (int y = 0; y < maxY; y++) { + for (int x = 0; x < maxX; x++) { + s.append(mWidget[x][y]); + } + s.append('\n'); + } + return s.toString(); + } } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 9da7e0f39b..843f0112ba 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -26,6 +26,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; 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.PushReorderCase; @@ -46,6 +47,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -108,6 +110,42 @@ public class ReorderWidgets extends AbstractLauncherUiTest { return match; } + private void printCurrentWorkspace() { + InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext); + ArrayList boards = workspaceToBoards(); + for (int i = 0; i < boards.size(); i++) { + Log.d(TAG, "Screen number " + i); + Log.d(TAG, ".\n" + boards.get(i).toString(idp.numColumns, idp.numRows)); + } + } + + private ArrayList workspaceToBoards() { + return getFromLauncher(l -> { + ArrayList boards = new ArrayList<>(); + int widgetCount = 0; + for (CellLayout cellLayout : l.getWorkspace().mWorkspaceScreens) { + CellLayoutBoard board = new CellLayoutBoard(); + int count = cellLayout.getShortcutsAndWidgets().getChildCount(); + for (int i = 0; i < count; i++) { + View callView = cellLayout.getShortcutsAndWidgets().getChildAt(i); + CellLayoutLayoutParams params = + (CellLayoutLayoutParams) callView.getLayoutParams(); + // is icon + if (callView instanceof DoubleShadowBubbleTextView) { + board.addIcon(params.cellX, params.cellY); + } else { + // is widget + board.addWidget(params.cellX, params.cellY, params.cellHSpan, + params.cellVSpan, (char) ('A' + widgetCount)); + widgetCount++; + } + } + boards.add(board); + } + return boards; + }); + } + private void runTestCase(ReorderTestCase testCase) throws ExecutionException, InterruptedException { Point mainWidgetCellPos = testCase.mStart.getMain(); @@ -127,6 +165,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest { for (CellLayoutBoard board : testCase.mEnd) { isValid |= validateBoard(board); } + printCurrentWorkspace(); assertTrue("Non of the valid boards match with the current state", isValid); }