From a518e034f708357e90de41be8fa5de2f48b3089b Mon Sep 17 00:00:00 2001 From: Chilun Huang Date: Thu, 19 May 2022 16:45:29 +0800 Subject: [PATCH] Add TAPL API for adding app icon to hotseat Please refer to go/tapl-add-icon-to-hotseat for more details. Bug: 231400119 Test: atest NexusLauncherTests:TaplTestsQuickstep#testAddDeleteShortcutOnHotseat Change-Id: I8cadecbe742413e3ce35ff269c0f78057331532c --- .../testing/HotseatCellCenterRequest.java | 99 +++++++++++++++++++ .../testing/TestInformationHandler.java | 18 +++- .../launcher3/testing/TestProtocol.java | 2 + .../launcher3/ui/TaplTestsLauncher3.java | 12 +++ .../android/launcher3/tapl/HomeAppIcon.java | 39 ++++++++ .../com/android/launcher3/tapl/Workspace.java | 43 ++++++++ 6 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/com/android/launcher3/testing/HotseatCellCenterRequest.java diff --git a/src/com/android/launcher3/testing/HotseatCellCenterRequest.java b/src/com/android/launcher3/testing/HotseatCellCenterRequest.java new file mode 100644 index 0000000000..cbb847e3f8 --- /dev/null +++ b/src/com/android/launcher3/testing/HotseatCellCenterRequest.java @@ -0,0 +1,99 @@ +/* + * 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.testing; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Request object for querying a hotseat cell region in Rect. + */ +public class HotseatCellCenterRequest implements TestInformationRequest { + public final int cellInd; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(cellInd); + } + + @Override + public String getRequestName() { + return TestProtocol.REQUEST_HOTSEAT_CELL_CENTER; + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + + @Override + public HotseatCellCenterRequest createFromParcel(Parcel source) { + return new HotseatCellCenterRequest(source); + } + + @Override + public HotseatCellCenterRequest[] newArray(int size) { + return new HotseatCellCenterRequest[size]; + } + }; + + private HotseatCellCenterRequest(int cellInd) { + this.cellInd = cellInd; + } + + private HotseatCellCenterRequest(Parcel in) { + this(in.readInt()); + } + + /** + * Create a builder for HotseatCellCenterRequest. + * + * @return HotseatCellCenterRequest builder. + */ + public static HotseatCellCenterRequest.Builder builder() { + return new HotseatCellCenterRequest.Builder(); + } + + /** + * HotseatCellCenterRequest Builder. + */ + public static final class Builder { + private int mCellInd; + + private Builder() { + mCellInd = 0; + } + + /** + * Set the index of hotseat cells. + */ + public HotseatCellCenterRequest.Builder setCellInd(int i) { + this.mCellInd = i; + return this; + } + + /** + * build the HotseatCellCenterRequest. + */ + public HotseatCellCenterRequest build() { + return new HotseatCellCenterRequest(mCellInd); + } + } +} diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index 242d2d423c..af4fb26699 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -33,6 +33,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Hotseat; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; @@ -185,7 +186,7 @@ public class TestInformationHandler implements ResourceBasedOverride { return new int[]{cellLayout.getCountX(), cellLayout.getCountY()}; }); - case TestProtocol.REQUEST_WORKSPACE_CELL_CENTER: + case TestProtocol.REQUEST_WORKSPACE_CELL_CENTER: { final WorkspaceCellCenterRequest request = extra.getParcelable( TestProtocol.TEST_INFO_REQUEST_FIELD); return getLauncherUIProperty(Bundle::putParcelable, launcher -> { @@ -197,6 +198,21 @@ public class TestInformationHandler implements ResourceBasedOverride { cellLayout, request.cellX, request.cellY, request.spanX, request.spanY); return new Point(cellRect.centerX(), cellRect.centerY()); }); + } + + case TestProtocol.REQUEST_HOTSEAT_CELL_CENTER: { + final HotseatCellCenterRequest request = extra.getParcelable( + TestProtocol.TEST_INFO_REQUEST_FIELD); + return getLauncherUIProperty(Bundle::putParcelable, launcher -> { + final Hotseat hotseat = launcher.getHotseat(); + final Rect cellRect = getDescendantRectRelativeToDragLayerForCell(launcher, + hotseat, request.cellInd, /* cellY= */ 0, + /* spanX= */ 1, /* spanY= */ 1); + // TODO(b/234322284): return the real center point. + return new Point(cellRect.left + (cellRect.right - cellRect.left) / 3, + cellRect.centerY()); + }); + } case TestProtocol.REQUEST_HAS_TIS: { response.putBoolean( diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 3a030a8b87..980b7d7ec8 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -115,6 +115,8 @@ 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_HOTSEAT_CELL_CENTER = "hotseat-cell-center"; + 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 = diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 0f29abc3d2..b3a241226a 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -540,6 +540,18 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { } } + @Test + @PortraitLandscape + public void testAddDeleteShortcutOnHotseat() { + mLauncher.getWorkspace() + .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0)) + .switchToAllApps() + .getAppIcon(APP_NAME) + .dragToHotseat(0); + mLauncher.getWorkspace().deleteAppIcon( + mLauncher.getWorkspace().getHotseatAppIcon(APP_NAME)); + } + /** * @return List of workspace grid coordinates. Those are not pixels. See {@link * Workspace#getIconGridDimensions()} diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java index 75465046d5..693baa02c5 100644 --- a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java +++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java @@ -22,6 +22,8 @@ import android.graphics.Rect; import androidx.annotation.NonNull; import androidx.test.uiautomator.UiObject2; +import java.util.function.Supplier; + /** * App icon on the workspace or all apps. */ @@ -100,9 +102,46 @@ public abstract class HomeAppIcon extends AppIcon implements FolderDragTarget, W } } + /** + * Drag an object to the given cell in hotseat. The target cell should be expected to be empty. + * + * @param cellInd zero based index number of the hotseat cells. + * @return the workspace app icon. + */ + @NonNull + public WorkspaceAppIcon dragToHotseat(int cellInd) { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + String.format("want to drag the icon to hotseat cell %d", cellInd)) + ) { + final Supplier dest = () -> Workspace.getHotseatCellCenter(mLauncher, cellInd); + + Workspace.dragIconToHotseat( + mLauncher, + this, + dest, + () -> addExpectedEventsForLongClick(), + /*expectDropEvents= */ null); + try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) { + WorkspaceAppIcon appIcon = + (WorkspaceAppIcon) mLauncher.getWorkspace().getHotseatAppIcon(mAppName); + mLauncher.assertTrue( + String.format("The %s icon should be in the hotseat cell %d.", mAppName, + cellInd), + appIcon.isInHotseatCell(cellInd)); + return appIcon; + } + } + } + /** This method requires public access, however should not be called in tests. */ @Override public Launchable getLaunchable() { return this; } + + boolean isInHotseatCell(int cellInd) { + final Point center = Workspace.getHotseatCellCenter(mLauncher, cellInd); + return mObject.getVisibleBounds().contains(center.x, center.y); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 42ba18c36d..5e5fdecaea 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -39,6 +39,7 @@ import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; +import com.android.launcher3.testing.HotseatCellCenterRequest; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.testing.WorkspaceCellCenterRequest; @@ -250,6 +251,24 @@ public final class Workspace extends Home { mHotseat, AppIcon.getAppIconSelector(appName, mLauncher))); } + /** + * Returns an icon for the given cell; fails if the icon doesn't exist. + * + * @param cellInd zero based index number of the hotseat cells. + * @return app icon. + */ + @NonNull + public HomeAppIcon getHotseatAppIcon(int cellInd) { + List icons = mHotseat.findObjects(AppIcon.getAnyAppIconSelector()); + final Point center = getHotseatCellCenter(mLauncher, cellInd); + return icons.stream() + .filter(icon -> icon.getVisibleBounds().contains(center.x, center.y)) + .findFirst() + .map(icon -> new WorkspaceAppIcon(mLauncher, icon)) + .orElseThrow(() -> + new AssertionError("Unable to get a hotseat icon on " + cellInd)); + } + /** * @return map of text -> center of the view. In case of icons with the same name, the one with * lower x coordinate is selected. @@ -360,6 +379,11 @@ public final class Workspace extends Home { TestProtocol.TEST_INFO_RESPONSE_FIELD); } + static Point getHotseatCellCenter(LauncherInstrumentation launcher, int cellInd) { + return launcher.getTestInfo(HotseatCellCenterRequest.builder() + .setCellInd(cellInd).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + /** * Finds folder icons in the current workspace. * @@ -471,6 +495,25 @@ public final class Workspace extends Home { () -> "Page scroll didn't happen", "Scrolling page"); } + static void dragIconToHotseat( + LauncherInstrumentation launcher, + Launchable launchable, + Supplier dest, + Runnable expectLongClickEvents, + @Nullable Runnable expectDropEvents) { + final long downTime = SystemClock.uptimeMillis(); + Point dragStart = launchable.startDrag( + downTime, + expectLongClickEvents, + /* runToSpringLoadedState= */ true); + Point targetDest = dest.get(); + + launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, true, + downTime, SystemClock.uptimeMillis(), false, + LauncherInstrumentation.GestureScope.INSIDE); + dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents); + } + /** * Flings to get to screens on the right. Waits for scrolling and a possible overscroll * recoil to complete.