Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82363132 authored by Sebastián Franco's avatar Sebastián Franco Committed by Android (Google) Code Review
Browse files

Merge "Adding support to add icons in the workspace for tests" into tm-qpr-dev

parents 37bcfadd 314bbf1c
Loading
Loading
Loading
Loading
+102 −24
Original line number Diff line number Diff line
@@ -30,39 +30,117 @@ import java.util.Set;

public class CellLayoutBoard {

    public static class CellType {
        // The cells marked by this will be filled by 1x1 widgets and will be ignored when
        // validating
        public static final char IGNORE = 'x';
        // The cells marked by this will be filled by app icons
        public static final char ICON = 'i';
        // Empty space
        public static final char EMPTY = '-';
        // Widget that will be saved as "main widget" for easier retrieval
        public static final char MAIN_WIDGET = 'm';
        // Everything else will be consider a widget
    }

    public static class WidgetRect {
        public char mType;
        public Rect mBounds;

        WidgetRect(char type, Rect bounds) {
            this.mType = type;
            this.mBounds = bounds;
        }

        int getSpanX() {
            return mBounds.right - mBounds.left + 1;
        }

        int getSpanY() {
            return mBounds.top - mBounds.bottom + 1;
        }

        int getCellX() {
            return mBounds.left;
        }

        int getCellY() {
            return mBounds.bottom;
        }

        boolean shouldIgnore() {
            return this.mType == CellType.IGNORE;
        }

        @Override
        public String toString() {
            return "WidgetRect type = " + mType + " bounds = " + mBounds.toString();
        }
    }

    public static class IconPoint {
        public Point coord;
        public char mType;

        public IconPoint(Point coord, char type) {
            this.coord = coord;
            mType = type;
        }

        public char getType() {
            return mType;
        }

        public void setType(char type) {
            mType = type;
        }

        public Point getCoord() {
            return coord;
        }

        public void setCoord(Point coord) {
            this.coord = coord;
        }
    }

    static final int INFINITE = 99999;

    char[][] mBoard = new char[30][30];
    char[][] mWidget = new char[30][30];

    List<TestBoardWidget> mWidgetsRects = new ArrayList<>();
    Map<Character, TestBoardWidget> mWidgetsMap = new HashMap<>();
    List<WidgetRect> mWidgetsRects = new ArrayList<>();
    Map<Character, WidgetRect> mWidgetsMap = new HashMap<>();

    List<TestBoardAppIcon> mIconPoints = new ArrayList<>();
    Map<Character, TestBoardAppIcon> mIconsMap = new HashMap<>();
    List<IconPoint> mIconPoints = new ArrayList<>();
    Map<Character, IconPoint> mIconsMap = new HashMap<>();

    Point mMain = new Point();

    CellLayoutBoard() {
        for (int x = 0; x < mBoard.length; x++) {
            for (int y = 0; y < mBoard[0].length; y++) {
                mBoard[x][y] = '-';
        for (int x = 0; x < mWidget.length; x++) {
            for (int y = 0; y < mWidget[0].length; y++) {
                mWidget[x][y] = CellType.EMPTY;
            }
        }
    }

    public List<TestBoardWidget> getWidgets() {
    public List<WidgetRect> getWidgets() {
        return mWidgetsRects;
    }

    public List<IconPoint> getIcons() {
        return mIconPoints;
    }

    public Point getMain() {
        return mMain;
    }

    public TestBoardWidget getWidgetRect(char c) {
    public WidgetRect getWidgetRect(char c) {
        return mWidgetsMap.get(c);
    }

    public static TestBoardWidget getWidgetRect(int x, int y, Set<Point> used, char[][] board) {
    public static WidgetRect getWidgetRect(int x, int y, Set<Point> used, char[][] board) {
        char type = board[x][y];
        Queue<Point> search = new ArrayDeque<Point>();
        Point current = new Point(x, y);
@@ -91,20 +169,20 @@ public class CellLayoutBoard {
                }
            }
        }
        return new TestBoardWidget(type, widgetRect);
        return new WidgetRect(type, widgetRect);
    }

    public static boolean isWidget(char type) {
        return type != 'i' && type != '-';
        return type != CellType.ICON && type != CellType.EMPTY;
    }

    public static boolean isIcon(char type) {
        return type == 'i';
        return type == CellType.ICON;
    }

    private static List<TestBoardWidget> getRects(char[][] board) {
    private static List<WidgetRect> getRects(char[][] board) {
        Set<Point> used = new HashSet<>();
        List<TestBoardWidget> widgetsRects = new ArrayList<>();
        List<WidgetRect> widgetsRects = new ArrayList<>();
        for (int x = 0; x < board.length; x++) {
            for (int y = 0; y < board[0].length; y++) {
                if (!used.contains(new Point(x, y)) && isWidget(board[x][y])) {
@@ -115,12 +193,12 @@ public class CellLayoutBoard {
        return widgetsRects;
    }

    private static List<TestBoardAppIcon> getIconPoints(char[][] board) {
        List<TestBoardAppIcon> iconPoints = new ArrayList<>();
    private static List<IconPoint> getIconPoints(char[][] board) {
        List<IconPoint> iconPoints = new ArrayList<>();
        for (int x = 0; x < board.length; x++) {
            for (int y = 0; y < board[0].length; y++) {
                if (isIcon(board[x][y])) {
                    iconPoints.add(new TestBoardAppIcon(new Point(x, y), board[x][y]));
                    iconPoints.add(new IconPoint(new Point(x, y), board[x][y]));
                }
            }
        }
@@ -135,18 +213,18 @@ public class CellLayoutBoard {
            String line = lines[y];
            for (int x = 0; x < line.length(); x++) {
                char c = line.charAt(x);
                if (c == 'm') {
                if (c == CellType.MAIN_WIDGET) {
                    board.mMain = new Point(x, y);
                }
                if (c != '-') {
                    board.mBoard[x][y] = line.charAt(x);
                if (c != CellType.EMPTY) {
                    board.mWidget[x][y] = line.charAt(x);
                }
            }
        }
        board.mWidgetsRects = getRects(board.mBoard);
        board.mWidgetsRects = getRects(board.mWidget);
        board.mWidgetsRects.forEach(
                widgetRect -> board.mWidgetsMap.put(widgetRect.mType, widgetRect));
        board.mIconPoints = getIconPoints(board.mBoard);
        board.mIconPoints = getIconPoints(board.mWidget);
        return board;
    }
}
+24 −57
Original line number Diff line number Diff line
@@ -15,16 +15,13 @@
 */
package com.android.launcher3.celllayout;

import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

@@ -34,13 +31,14 @@ import com.android.launcher3.celllayout.testcases.MoveOutReorderCase;
import com.android.launcher3.celllayout.testcases.PushReorderCase;
import com.android.launcher3.celllayout.testcases.ReorderTestCase;
import com.android.launcher3.celllayout.testcases.SimpleReorderCase;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.views.DoubleShadowBubbleTextView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;

import org.junit.Assume;
import org.junit.Before;
@@ -60,6 +58,8 @@ public class ReorderWidgets extends AbstractLauncherUiTest {

    private static final String TAG = ReorderWidgets.class.getSimpleName();

    TestWorkspaceBuilder mBoardBuilder;

    private View getViewAt(int cellX, int cellY) {
        return getFromLauncher(l -> l.getWorkspace().getScreenWithId(
                l.getWorkspace().getScreenIdForPageIndex(0)).getChildAt(cellX, cellY));
@@ -76,6 +76,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest {

    @Before
    public void setup() throws Throwable {
        mBoardBuilder = new TestWorkspaceBuilder(this);
        TaplTestsLauncher3.initialize(this);
        clearHomescreen();
    }
@@ -86,78 +87,44 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
    private boolean validateBoard(CellLayoutBoard board) {
        boolean match = true;
        Point cellDimensions = getCellDimensions();
        for (TestBoardWidget widgetRect: board.getWidgets()) {
        for (CellLayoutBoard.WidgetRect widgetRect: board.getWidgets()) {
            if (widgetRect.shouldIgnore()) {
                continue;
            }
            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;
        }
        return match;
    }

    /**
     * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
     */
    private void fillWithWidgets(TestBoardWidget widgetRect) {
        int initX = widgetRect.getCellX();
        int initY = widgetRect.getCellY();
        for (int x = 0; x < widgetRect.getSpanX(); x++) {
            for (int y = 0; y < widgetRect.getSpanY(); y++) {
                int auxX = initX + x;
                int auxY = initY + y;
                try {
                    // this widgets are filling, we don't care if we can't place them
                    addWidgetInCell(
                            new TestBoardWidget('x',
                                    new Rect(auxX, auxY, auxX, auxY))
                    );
                } catch (Exception e) {
                    Log.d(TAG, "Unable to place filling widget at " + auxX + "," + auxY);
                }
            }
        }
    }

    private void addWidgetInCell(TestBoardWidget widgetRect) {
        LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
        LauncherAppWidgetInfo item = createWidgetInfo(info,
                ApplicationProvider.getApplicationContext(), true);
        item.cellX = widgetRect.getCellX();
        item.cellY = widgetRect.getCellY();

        item.spanX = widgetRect.getSpanX();
        item.spanY = widgetRect.getSpanY();
        addItemToScreen(item);
    }

    private void addCorrespondingWidgetRect(TestBoardWidget widgetRect) {
        if (widgetRect.mType == 'x') {
            fillWithWidgets(widgetRect);
        } else {
            addWidgetInCell(widgetRect);
        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 match;
    }

    private void runTestCase(ReorderTestCase testCase) {
        Point mainWidgetCellPos = testCase.mStart.getMain();

        testCase.mStart.getWidgets().forEach(this::addCorrespondingWidgetRect);
        mBoardBuilder.buildBoard(testCase.mStart);

        mLauncher.getWorkspace()
                .getWidgetAtCell(mainWidgetCellPos.x, mainWidgetCellPos.y)
                .dragWidgetToWorkspace(testCase.moveMainTo.x, testCase.moveMainTo.y)
                .dismiss(); // dismiss resize frame
        Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x,
                mainWidgetCellPos.y);
        assertNotNull(widget);
        WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x,
                testCase.moveMainTo.y);
        resizeFrame.dismiss();

        boolean isValid = false;
        for (CellLayoutBoard board : testCase.mEnd) {
            isValid |= validateBoard(board);
        }
        assertTrue("None of the valid boards match with the current state", isValid);
        assertTrue("Non of the valid boards match with the current state", isValid);
    }

    /**
+110 −0
Original line number Diff line number Diff line
/*
 * 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;

import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;

import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;

import androidx.test.core.app.ApplicationProvider;

import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;

public class TestWorkspaceBuilder {

    private static final ComponentName APP_COMPONENT_NAME = new ComponentName(
            "com.google.android.calculator", "com.android.calculator2.Calculator");

    public AbstractLauncherUiTest mTest;

    private UserHandle mMyUser;

    public TestWorkspaceBuilder(AbstractLauncherUiTest test) {
        mTest = test;
        mMyUser = Process.myUserHandle();
    }

    private static final String TAG = "CellLayoutBoardBuilder";

    /**
     * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
     */
    private void fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect) {
        int initX = widgetRect.getCellX();
        int initY = widgetRect.getCellY();
        for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
            for (int y = initY; y < initY + widgetRect.getSpanY(); y++) {
                try {
                    // this widgets are filling, we don't care if we can't place them
                    addWidgetInCell(
                            new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
                                    new Rect(x, y, x, y))
                    );
                } catch (Exception e) {
                    Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
                }
            }
        }
    }

    private void addWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) {
        LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false);
        LauncherAppWidgetInfo item = createWidgetInfo(info,
                ApplicationProvider.getApplicationContext(), true);

        item.cellX = widgetRect.getCellX();
        item.cellY = widgetRect.getCellY();
        item.spanX = widgetRect.getSpanX();
        item.spanY = widgetRect.getSpanY();
        mTest.addItemToScreen(item);
    }

    private void addIconInCell(CellLayoutBoard.IconPoint iconPoint) {
        AppInfo appInfo = new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser,
                AppInfo.makeLaunchIntent(APP_COMPONENT_NAME));

        appInfo.cellX = iconPoint.getCoord().x;
        appInfo.cellY = iconPoint.getCoord().y;
        appInfo.minSpanY = appInfo.minSpanX = appInfo.spanX = appInfo.spanY = 1;
        appInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
        appInfo.componentName = APP_COMPONENT_NAME;

        mTest.addItemToScreen(new WorkspaceItemInfo(appInfo));
    }

    private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect) {
        if (widgetRect.mType == 'x') {
            fillWithWidgets(widgetRect);
        } else {
            addWidgetInCell(widgetRect);
        }
    }

    public void buildBoard(CellLayoutBoard board) {
        board.getWidgets().forEach(this::addCorrespondingWidgetRect);
        board.getIcons().forEach(this::addIconInCell);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ 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 FullReorderCase {

    /** 5x5 Test
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ 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 MoveOutReorderCase {

    /** 5x5 Test
Loading