diff --git a/Android.bp b/Android.bp index c980a2e50f..78db2f1cd1 100644 --- a/Android.bp +++ b/Android.bp @@ -210,6 +210,8 @@ filegroup { srcs: [ "ext_tests/src/**/*.java", "ext_tests/src/**/*.kt", + "quickstep/ext_tests/src/**/*.java", + "quickstep/ext_tests/src/**/*.kt", ], } diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java index 02206c0dc9..d16e12c9b8 100644 --- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java +++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java @@ -29,8 +29,10 @@ import android.view.View; import androidx.annotation.Keep; import androidx.annotation.Nullable; +import com.android.launcher3.BubbleTextView; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.ShortcutAndWidgetContainer; import java.util.ArrayList; import java.util.Collection; @@ -205,6 +207,32 @@ public class DebugTestInformationHandler extends TestInformationHandler { } } + case TestProtocol.REQUEST_USE_TEST_WORKSPACE_LAYOUT: { + useTestWorkspaceLayout(true); + return response; + } + + case TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT: { + useTestWorkspaceLayout(false); + return response; + } + + case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: { + return getLauncherUIProperty(Bundle::putStringArrayList, l -> { + ShortcutAndWidgetContainer hotseatIconsContainer = + l.getHotseat().getShortcutsAndWidgets(); + ArrayList hotseatIconNames = new ArrayList<>(); + + for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) { + // Use unchecked cast to catch changes in hotseat layout + BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i); + hotseatIconNames.add((String) icon.getText()); + } + + return hotseatIconNames; + }); + } + case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: { response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount); return response; @@ -223,4 +251,15 @@ public class DebugTestInformationHandler extends TestInformationHandler { return super.call(method, arg, extras); } } + + private void useTestWorkspaceLayout(boolean useTestWorkspaceLayout) { + final long identity = Binder.clearCallingIdentity(); + try { + LauncherSettings.Settings.call(mContext.getContentResolver(), useTestWorkspaceLayout + ? LauncherSettings.Settings.METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG + : LauncherSettings.Settings.METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG); + } finally { + Binder.restoreCallingIdentity(identity); + } + } } diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java new file mode 100644 index 0000000000..e5f0295ff6 --- /dev/null +++ b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java @@ -0,0 +1,120 @@ +/* + * 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.quickstep; + +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; + +import android.content.Context; +import android.content.res.Resources; +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import com.android.launcher3.BaseQuickstepLauncher; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.taskbar.LauncherTaskbarUIController; +import com.android.launcher3.testing.DebugTestInformationHandler; +import com.android.launcher3.testing.TestProtocol; + +import java.util.concurrent.ExecutionException; + +/** + * Class to handle requests from tests, including debug ones, to Quickstep Launcher builds. + */ +public abstract class DebugQuickstepTestInformationHandler extends QuickstepTestInformationHandler { + + private final DebugTestInformationHandler mDebugTestInformationHandler; + + public DebugQuickstepTestInformationHandler(Context context) { + super(context); + mDebugTestInformationHandler = new DebugTestInformationHandler(context); + } + + @Override + public Bundle call(String method, String arg, @Nullable Bundle extras) { + Bundle response = new Bundle(); + switch (method) { + case TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING: + runOnUIThread(l -> { + enableManualTaskbarStashing(l, true); + }); + return response; + + case TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING: + runOnUIThread(l -> { + enableManualTaskbarStashing(l, false); + }); + return response; + + case TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED: + runOnUIThread(l -> { + enableManualTaskbarStashing(l, true); + + BaseQuickstepLauncher quickstepLauncher = (BaseQuickstepLauncher) l; + LauncherTaskbarUIController taskbarUIController = + quickstepLauncher.getTaskbarUIController(); + + // Allow null-pointer to catch illegal states. + taskbarUIController.unstashTaskbarIfStashed(); + + enableManualTaskbarStashing(l, false); + }); + return response; + + case TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT: { + final Resources resources = mContext.getResources(); + response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, + resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size)); + return response; + } + + default: + response = super.call(method, arg, extras); + if (response != null) return response; + return mDebugTestInformationHandler.call(method, arg, extras); + } + } + + private void enableManualTaskbarStashing(Launcher launcher, boolean enable) { + BaseQuickstepLauncher quickstepLauncher = (BaseQuickstepLauncher) launcher; + LauncherTaskbarUIController taskbarUIController = + quickstepLauncher.getTaskbarUIController(); + + // Allow null-pointer to catch illegal states. + taskbarUIController.enableManualStashingForTests(enable); + } + + /** + * Runs the given command on the UI thread. + */ + private static void runOnUIThread(UIThreadCommand command) { + try { + MAIN_EXECUTOR.submit(() -> { + command.execute(Launcher.ACTIVITY_TRACKER.getCreatedActivity()); + return null; + }).get(); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + private interface UIThreadCommand { + + void execute(Launcher launcher); + } +} + diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 768a348613..793d98704c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -27,6 +27,7 @@ import android.view.TaskTransitionSpec; import android.view.WindowManagerGlobal; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; @@ -117,6 +118,24 @@ public class LauncherTaskbarUIController extends TaskbarUIController { shouldDelayLauncherStateAnim); } + /** + * Enables manual taskbar stashing. This method should only be used for tests that need to + * stash/unstash the taskbar. + */ + @VisibleForTesting + public void enableManualStashingForTests(boolean enableManualStashing) { + mControllers.taskbarStashController.enableManualStashingForTests(enableManualStashing); + } + + /** + * Unstashes the Taskbar if it is stashed. This method should only be used to unstash the + * taskbar at the end of a test. + */ + @VisibleForTesting + public void unstashTaskbarIfStashed() { + mControllers.taskbarStashController.onLongPressToUnstashTaskbar(); + } + /** * Should be called from onResume() and onPause(), and animates the Taskbar accordingly. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 5387b1ac83..6c74ae379b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -71,6 +71,8 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController; +import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.NavigationMode; @@ -646,12 +648,16 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show(); } else if (info.isPromise()) { + TestLogging.recordEvent( + TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon"); intent = new PackageManagerHelper(this) .getMarketIntent(info.getTargetPackage()) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) { + TestLogging.recordEvent( + TestProtocol.SEQUENCE_MAIN, "start: taskbarDeepShortcut"); String id = info.getDeepShortcutId(); String packageName = intent.getPackage(); getSystemService(LauncherApps.class) @@ -680,6 +686,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Intent intent = new Intent(info.getIntent()) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon"); if (info.user.equals(Process.myUserHandle())) { // TODO(b/216683257): Use startActivityForResult for search results that require it. startActivity(intent); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index af98b7f224..e2ab4435ad 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -63,6 +63,8 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; +import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; import com.android.systemui.shared.recents.model.Task; @@ -128,7 +130,7 @@ public class TaskbarDragController extends DragController im if (!(view instanceof BubbleTextView)) { return false; } - + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); BubbleTextView btv = (BubbleTextView) view; mActivity.onDragStart(); btv.post(() -> { @@ -164,24 +166,7 @@ public class TaskbarDragController extends DragController im dragLayerY += dragRect.top; DragOptions dragOptions = new DragOptions(); - dragOptions.preDragCondition = new DragOptions.PreDragCondition() { - private DragView mDragView; - - @Override - public boolean shouldStartDrag(double distanceDragged) { - return mDragView != null && mDragView.isAnimationFinished(); - } - - @Override - public void onPreDragStart(DropTarget.DragObject dragObject) { - mDragView = dragObject.dragView; - } - - @Override - public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) { - mDragView = null; - } - }; + dragOptions.preDragCondition = null; if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) { PopupContainerWithArrow popupContainer = mControllers.taskbarPopupController.showForIcon(btv); @@ -189,6 +174,32 @@ public class TaskbarDragController extends DragController im dragOptions.preDragCondition = popupContainer.createPreDragCondition(false); } } + if (dragOptions.preDragCondition == null) { + dragOptions.preDragCondition = new DragOptions.PreDragCondition() { + private DragView mDragView; + + @Override + public boolean shouldStartDrag(double distanceDragged) { + return mDragView != null && mDragView.isAnimationFinished(); + } + + @Override + public void onPreDragStart(DropTarget.DragObject dragObject) { + mDragView = dragObject.dragView; + + if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get() + && !shouldStartDrag(0)) { + // Immediately close the popup menu. + mDragView.setOnAnimationEndCallback(() -> callOnDragStart()); + } + } + + @Override + public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) { + mDragView = null; + } + }; + } return startDrag( drawable, diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index ea4fe34fea..f9c806262a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -145,6 +145,7 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba }); // TODO (b/198438631): configure for taskbar/context container.setPopupItemDragHandler(new TaskbarPopupItemDragHandler()); + mControllers.taskbarDragController.addDragListener(container); container.populateAndShow(icon, mPopupDataProvider.getShortcutCountForItem(item), diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 473be9ea7e..f9a282b561 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -136,6 +136,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private boolean mIsSystemGestureInProgress; private boolean mIsImeShowing; + private boolean mEnableManualStashingForTests = false; + // Evaluate whether the handle should be stashed private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder( flags -> { @@ -199,12 +201,15 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba */ protected boolean supportsManualStashing() { return supportsVisualStashing() - && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || supportsStashingForTests()); + && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingForTests); } - private boolean supportsStashingForTests() { - // TODO: enable this for tests that specifically check stash/unstash behavior. - return false; + /** + * Enables support for manual stashing. This should only be used to add this functionality + * to Launcher specific tests. + */ + public void enableManualStashingForTests(boolean enableManualStashing) { + mEnableManualStashingForTests = enableManualStashing; } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java index a67ca7089b..579b5d7d0e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java @@ -24,6 +24,7 @@ import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsI import android.content.Context; import android.graphics.Insets; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.WindowInsets; @@ -38,6 +39,8 @@ import com.android.launcher3.taskbar.BaseTaskbarContext; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.launcher3.taskbar.TaskbarDragController; import com.android.launcher3.taskbar.TaskbarStashController; +import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; @@ -180,6 +183,12 @@ class TaskbarAllAppsContext extends BaseTaskbarContext { mControllers = new TouchController[]{mActivity.mDragController}; } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev); + return super.dispatchTouchEvent(ev); + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) { diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java new file mode 100644 index 0000000000..ba93975089 --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java @@ -0,0 +1,155 @@ +/* + * 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.quickstep; + +import static androidx.test.InstrumentationRegistry.getInstrumentation; + +import static junit.framework.TestCase.assertEquals; + +import android.content.Intent; + +import androidx.test.filters.LargeTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.launcher3.tapl.Taskbar; +import com.android.launcher3.ui.TaplTestsLauncher3; + +import org.junit.After; +import org.junit.Assume; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class TaplTestsTaskbar extends AbstractQuickStepTest { + + private static final String TEST_APP_NAME = "LauncherTestApp"; + private static final String TEST_APP_PACKAGE = + getInstrumentation().getContext().getPackageName(); + private static final String CALCULATOR_APP_PACKAGE = + resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR); + + @Override + public void setUp() throws Exception { + Assume.assumeTrue(mLauncher.isTablet()); + super.setUp(); + mLauncher.useTestWorkspaceLayoutOnReload(); + TaplTestsLauncher3.initialize(this); + + startAppFast(CALCULATOR_APP_PACKAGE); + mLauncher.showTaskbarIfHidden(); + } + + @After + public void tearDown() { + mLauncher.useDefaultWorkspaceLayoutOnReload(); + } + + @Test + public void testHideShowTaskbar() { + getTaskbar().hide(); + mLauncher.getLaunchedAppState().showTaskbar(); + } + + @Test + public void testLaunchApp() throws Exception { + getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE); + } + + @Test + public void testOpenMenu() throws Exception { + getTaskbar().getAppIcon(TEST_APP_NAME).openMenu(); + } + + @Test + public void testLaunchShortcut() throws Exception { + getTaskbar().getAppIcon(TEST_APP_NAME) + .openDeepShortcutMenu() + .getMenuItem("Shortcut 1") + .launch(TEST_APP_PACKAGE); + } + + @Test + @PortraitLandscape + public void testLaunchAppInSplitscreen() throws Exception { + getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen( + TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE); + } + + @Test + @PortraitLandscape + public void testLaunchShortcutInSplitscreen() throws Exception { + getTaskbar().getAppIcon(TEST_APP_NAME) + .openDeepShortcutMenu() + .getMenuItem("Shortcut 1") + .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE); + } + + @Test + public void testLaunchApp_FromTaskbarAllApps() throws Exception { + getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE); + } + + @Test + public void testOpenMenu_FromTaskbarAllApps() throws Exception { + getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu(); + } + + @Test + public void testLaunchShortcut_FromTaskbarAllApps() throws Exception { + getTaskbar().openAllApps() + .getAppIcon(TEST_APP_NAME) + .openDeepShortcutMenu() + .getMenuItem("Shortcut 1") + .launch(TEST_APP_PACKAGE); + } + + @Test + @PortraitLandscape + public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception { + getTaskbar().openAllApps() + .getAppIcon(TEST_APP_NAME) + .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE); + } + + @Test + @PortraitLandscape + public void testLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception { + getTaskbar().openAllApps() + .getAppIcon(TEST_APP_NAME) + .openDeepShortcutMenu() + .getMenuItem("Shortcut 1") + .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE); + } + + private Taskbar getTaskbar() { + Taskbar taskbar = mLauncher.getLaunchedAppState().getTaskbar(); + List taskbarIconNames = taskbar.getIconNames(); + List hotseatIconNames = mLauncher.getHotseatIconNames(); + + assertEquals("Taskbar and hotseat icon counts do not match", + taskbarIconNames.size(), hotseatIconNames.size()); + + for (int i = 0; i < taskbarIconNames.size(); i++) { + assertEquals("Taskbar and Hotseat icons do not match", + taskbarIconNames, hotseatIconNames); + } + + return taskbar; + } +} diff --git a/res/xml/default_test_workspace.xml b/res/xml/default_test_workspace.xml new file mode 100644 index 0000000000..bd718b3b14 --- /dev/null +++ b/res/xml/default_test_workspace.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index e004a4b240..85ee8bc184 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -102,6 +102,8 @@ public class LauncherProvider extends ContentProvider { public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings"; public static final String KEY_LAYOUT_PROVIDER_AUTHORITY = "KEY_LAYOUT_PROVIDER_AUTHORITY"; + private static final int TEST_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test_workspace; + static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED"; protected DatabaseHelper mOpenHelper; @@ -109,6 +111,8 @@ public class LauncherProvider extends ContentProvider { private long mLastRestoreTimestamp = 0L; + private boolean mUseTestWorkspaceLayout; + /** * $ adb shell dumpsys activity provider com.android.launcher3 */ @@ -390,6 +394,14 @@ public class LauncherProvider extends ContentProvider { mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase()); return null; } + case LauncherSettings.Settings.METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG: { + mUseTestWorkspaceLayout = true; + return null; + } + case LauncherSettings.Settings.METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG: { + mUseTestWorkspaceLayout = false; + return null; + } case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: { loadDefaultFavoritesIfNecessary(); return null; @@ -609,7 +621,8 @@ public class LauncherProvider extends ContentProvider { private DefaultLayoutParser getDefaultLayoutParser(AppWidgetHost widgetHost) { InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext()); - int defaultLayout = idp.defaultLayoutId; + int defaultLayout = mUseTestWorkspaceLayout + ? TEST_WORKSPACE_LAYOUT_RES_XML : idp.defaultLayoutId; if (getContext().getSystemService(UserManager.class).isDemoUser() && idp.demoModeLayoutId != 0) { diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 048aaaa3bf..66195f3a1d 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -374,6 +374,12 @@ public class LauncherSettings { public static final String METHOD_CREATE_EMPTY_DB = "create_empty_db"; + public static final String METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG = + "set_use_test_workspace_layout_flag"; + + public static final String METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG = + "clear_use_test_workspace_layout_flag"; + public static final String METHOD_LOAD_DEFAULT_FAVORITES = "load_default_favorites"; public static final String METHOD_REMOVE_GHOST_WIDGETS = "remove_ghost_widgets"; diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java index b914ae2dac..a3945fdba8 100644 --- a/src/com/android/launcher3/dragndrop/DragView.java +++ b/src/com/android/launcher3/dragndrop/DragView.java @@ -98,6 +98,7 @@ public abstract class DragView extends Fram final ValueAnimator mAnim; // Whether mAnim has started. Unlike mAnim.isStarted(), this is true even after mAnim ends. private boolean mAnimStarted; + private Runnable mOnAnimEndCallback = null; private int mLastTouchX; private int mLastTouchY; @@ -180,6 +181,14 @@ public abstract class DragView extends Fram public void onAnimationStart(Animator animation) { mAnimStarted = true; } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (mOnAnimEndCallback != null) { + mOnAnimEndCallback.run(); + } + } }); setDragRegion(new Rect(0, 0, width, height)); @@ -199,6 +208,10 @@ public abstract class DragView extends Fram setWillNotDraw(false); } + public void setOnAnimationEndCallback(Runnable callback) { + mOnAnimEndCallback = callback; + } + /** * Initialize {@code #mIconDrawable} if the item can be represented using * an {@link AdaptiveIconDrawable} or {@link FolderAdaptiveIcon}. diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 05fe182fa7..b04110dfb4 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -82,6 +82,10 @@ public final class TestProtocol { public static final String REQUEST_IS_LAUNCHER_INITIALIZED = "is-launcher-initialized"; public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list"; public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list"; + public static final String REQUEST_ENABLE_MANUAL_TASKBAR_STASHING = "enable-taskbar-stashing"; + public static final String REQUEST_DISABLE_MANUAL_TASKBAR_STASHING = "disable-taskbar-stashing"; + public static final String REQUEST_UNSTASH_TASKBAR_IF_STASHED = "unstash-taskbar-if-stashed"; + public static final String REQUEST_STASHED_TASKBAR_HEIGHT = "stashed-taskbar-height"; public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags"; public static final String REQUEST_APPS_LIST_SCROLL_Y = "apps-list-scroll-y"; public static final String REQUEST_WIDGETS_SCROLL_Y = "widgets-scroll-y"; @@ -96,6 +100,10 @@ public final class TestProtocol { public static final String REQUEST_GET_HAD_NONTEST_EVENTS = "get-had-nontest-events"; public static final String REQUEST_STOP_EVENT_LOGGING = "stop-event-logging"; public static final String REQUEST_CLEAR_DATA = "clear-data"; + public static final String REQUEST_USE_TEST_WORKSPACE_LAYOUT = "use-test-workspace-layout"; + public static final String REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT = + "use-default-workspace-layout"; + public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names"; public static final String REQUEST_IS_TABLET = "is-tablet"; public static final String REQUEST_IS_TWO_PANELS = "is-two-panel"; public static final String REQUEST_START_DRAG_THRESHOLD = "start-drag-threshold"; diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml index b4cd773435..9cc3aeda1f 100644 --- a/tests/AndroidManifest-common.xml +++ b/tests/AndroidManifest-common.xml @@ -94,7 +94,6 @@ - @@ -138,6 +137,7 @@ + diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index c99c4f1bac..136f115650 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -567,6 +567,7 @@ public abstract class AbstractLauncherUiTest { ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL); break; } + case TASKBAR_ALL_APPS: case LAUNCHED_APP: { assertTrue("Launcher is resumed in state: " + expectedContainerType, !isResumed); @@ -580,9 +581,10 @@ public abstract class AbstractLauncherUiTest { } } else { assertTrue( - "Container type is not LAUNCHED_APP or FALLBACK_OVERVIEW: " - + expectedContainerType, + "Container type is not LAUNCHED_APP, TASKBAR_ALL_APPS " + + "or FALLBACK_OVERVIEW: " + expectedContainerType, expectedContainerType == ContainerType.LAUNCHED_APP + || expectedContainerType == ContainerType.TASKBAR_ALL_APPS || expectedContainerType == ContainerType.FALLBACK_OVERVIEW); } } diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 3658f41d70..bfb115d1b8 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -74,7 +74,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.log("hasClickableIcon: icon has insufficient height"); return false; } - if (iconCenterInSearchBox(allAppsContainer, icon)) { + if (hasSearchBox() && iconCenterInSearchBox(allAppsContainer, icon)) { LauncherInstrumentation.log("hasClickableIcon: icon center is under search box"); return false; } @@ -107,7 +107,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { final UiObject2 allAppsContainer = verifyActiveContainer(); final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, "apps_list_view"); - final UiObject2 searchBox = getSearchBox(allAppsContainer); + final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; int deviceHeight = mLauncher.getRealDisplaySize().y; int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen(); @@ -128,8 +128,10 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { mLauncher.getVisibleBounds(icon).top < bottomGestureStartOnScreen) .collect(Collectors.toList()), - mLauncher.getVisibleBounds(searchBox).bottom - - mLauncher.getVisibleBounds(allAppsContainer).top); + hasSearchBox() + ? mLauncher.getVisibleBounds(searchBox).bottom + - mLauncher.getVisibleBounds(allAppsContainer).top + : 0); verifyActiveContainer(); final int newScroll = getAllAppsScroll(); mLauncher.assertTrue( @@ -173,18 +175,21 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { return appIcon; } + @NonNull protected abstract AppIcon createAppIcon(UiObject2 icon); + protected abstract boolean hasSearchBox(); + private void scrollBackToBeginning() { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to scroll back in all apps")) { LauncherInstrumentation.log("Scrolling to the beginning"); final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 searchBox = getSearchBox(allAppsContainer); + final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; int attempts = 0; - final Rect margins = - new Rect(0, mLauncher.getVisibleBounds(searchBox).bottom + 1, 0, 5); + final Rect margins = new Rect( + 0, hasSearchBox() ? mLauncher.getVisibleBounds(searchBox).bottom + 1 : 0, 0, 5); for (int scroll = getAllAppsScroll(); scroll != 0; @@ -196,7 +201,11 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { ++attempts <= MAX_SCROLL_ATTEMPTS); mLauncher.scroll( - allAppsContainer, Direction.UP, margins, 12, false); + allAppsContainer, + Direction.UP, + margins, + /* steps= */ 12, + /* slowDown= */ false); } try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) { @@ -225,7 +234,11 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { final UiObject2 allAppsContainer = verifyActiveContainer(); // Start the gesture in the center to avoid starting at elements near the top. mLauncher.scroll( - allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10, false); + allAppsContainer, + Direction.DOWN, + new Rect(0, 0, 0, mHeight / 2), + /* steps= */ 10, + /* slowDown= */ false); verifyActiveContainer(); } } @@ -240,7 +253,11 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { final UiObject2 allAppsContainer = verifyActiveContainer(); // Start the gesture in the center, for symmetry with forward. mLauncher.scroll( - allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10, false); + allAppsContainer, + Direction.UP, + new Rect(0, mHeight / 2, 0, 0), + /* steps= */ 10, + /*slowDown= */ false); verifyActiveContainer(); } } diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java new file mode 100644 index 0000000000..516402563d --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java @@ -0,0 +1,51 @@ +/* + * 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.tapl; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiObject2; + +/** + * Operations on AllApps opened from the Taskbar. + */ +public class AllAppsFromTaskbar extends AllApps { + + AllAppsFromTaskbar(LauncherInstrumentation launcher) { + super(launcher); + } + + @Override + protected LauncherInstrumentation.ContainerType getContainerType() { + return LauncherInstrumentation.ContainerType.TASKBAR_ALL_APPS; + } + + @NonNull + @Override + public TaskbarAppIcon getAppIcon(String appName) { + return (TaskbarAppIcon) super.getAppIcon(appName); + } + + @NonNull + @Override + protected TaskbarAppIcon createAppIcon(UiObject2 icon) { + return new TaskbarAppIcon(mLauncher, icon); + } + + @Override + protected boolean hasSearchBox() { + return false; + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java index bef242ca6e..e28f0af1bc 100644 --- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java +++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java @@ -51,7 +51,7 @@ public abstract class AppIcon extends Launchable { public AppIconMenu openMenu() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { return createMenu(mLauncher.clickAndGet( - mObject, "popup_container", getLongClickEvent())); + mObject, /* resName= */ "popup_container", getLongClickEvent())); } } @@ -61,7 +61,7 @@ public abstract class AppIcon extends Launchable { public AppIconMenu openDeepShortcutMenu() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { return createMenu(mLauncher.clickAndGet( - mObject, "deep_shortcuts_container", getLongClickEvent())); + mObject, /* resName= */ "deep_shortcuts_container", getLongClickEvent())); } } @@ -73,8 +73,8 @@ public abstract class AppIcon extends Launchable { } @Override - protected String getLongPressIndicator() { - return "popup_container"; + protected void waitForLongPressConfirmation() { + mLauncher.waitForLauncherObject("popup_container"); } @Override diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java index a6a1531805..5cf5abab0b 100644 --- a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java +++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java @@ -41,8 +41,8 @@ public abstract class AppIconMenuItem extends Launchable { } @Override - protected String getLongPressIndicator() { - return "drop_target_bar"; + protected void waitForLongPressConfirmation() { + mLauncher.waitForLauncherObject("drop_target_bar"); } @Override diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java index 2e00d5967e..c275f3b320 100644 --- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java @@ -35,8 +35,14 @@ public class HomeAllApps extends AllApps { return (AllAppsAppIcon) super.getAppIcon(appName); } + @NonNull @Override protected HomeAppIcon createAppIcon(UiObject2 icon) { return new AllAppsAppIcon(mLauncher, icon); } + + @Override + protected boolean hasSearchBox() { + return true; + } } diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java index baabe12688..71d8ba9a41 100644 --- a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java +++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java @@ -51,8 +51,7 @@ public abstract class HomeAppIcon extends AppIcon implements FolderDragTarget, W () -> { final Rect bounds = target.getDropLocationBounds(); return new Point(bounds.centerX(), bounds.centerY()); - }, - getLongPressIndicator()); + }); FolderIcon result = target.getTargetFolder(dropBounds); mLauncher.assertTrue("Can't find the target folder.", result != null); return result; @@ -115,8 +114,12 @@ public abstract class HomeAppIcon extends AppIcon implements FolderDragTarget, W String.format("want to drag the icon to cell(%d, %d)", cellX, cellY)) ) { final Supplier dest = () -> Workspace.getCellCenter(mLauncher, cellX, cellY); - Workspace.dragIconToWorkspace(mLauncher, this, dest, getLongPressIndicator(), - () -> addExpectedEventsForLongClick(), null); + Workspace.dragIconToWorkspace( + mLauncher, + /* launchable= */ this, + dest, + () -> addExpectedEventsForLongClick(), + /*expectDropEvents= */ null); try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) { WorkspaceAppIcon appIcon = (WorkspaceAppIcon) mLauncher.getWorkspace().getWorkspaceAppIcon(mAppName); diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java index a28eac6bad..45a01968ed 100644 --- a/tests/tapl/com/android/launcher3/tapl/Launchable.java +++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java @@ -97,8 +97,7 @@ abstract class Launchable { return new LaunchedAppState(mLauncher); } - Point startDrag(long downTime, String longPressIndicator, - Runnable expectLongClickEvents, boolean runToSpringLoadedState) { + Point startDrag(long downTime, Runnable expectLongClickEvents, boolean runToSpringLoadedState) { final Point iconCenter = getObject().getVisibleCenter(); final Point dragStartCenter = new Point(iconCenter.x, iconCenter.y - getStartDragThreshold()); @@ -108,7 +107,6 @@ abstract class Launchable { downTime, iconCenter, dragStartCenter, - longPressIndicator, expectLongClickEvents), SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start"); } else { @@ -116,7 +114,6 @@ abstract class Launchable { downTime, iconCenter, dragStartCenter, - longPressIndicator, expectLongClickEvents); } @@ -124,22 +121,44 @@ abstract class Launchable { return dragStartCenter; } + /** + * Waits for a confirmation that a long press has successfully been triggered. + * + * This method waits for a view to either appear or disappear to confirm that the long press + * has been triggered and fails if no confirmation is received before the default timeout. + */ + protected abstract void waitForLongPressConfirmation(); + /** * Drags this Launchable a short distance before starting a full drag. * * This is necessary for shortcuts, which require being dragged beyond a threshold to close * their container and start drag callbacks. */ - private void movePointerForStartDrag(long downTime, Point iconCenter, Point dragStartCenter, - String longPressIndicator, Runnable expectLongClickEvents) { - mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, - iconCenter, LauncherInstrumentation.GestureScope.INSIDE); + private void movePointerForStartDrag( + long downTime, + Point iconCenter, + Point dragStartCenter, + Runnable expectLongClickEvents) { + mLauncher.sendPointer( + downTime, + downTime, + MotionEvent.ACTION_DOWN, + iconCenter, + LauncherInstrumentation.GestureScope.INSIDE); LauncherInstrumentation.log("movePointerForStartDrag: sent down"); expectLongClickEvents.run(); - mLauncher.waitForLauncherObject(longPressIndicator); + waitForLongPressConfirmation(); LauncherInstrumentation.log("movePointerForStartDrag: indicator"); - mLauncher.movePointer(iconCenter, dragStartCenter, DEFAULT_DRAG_STEPS, false, - downTime, downTime, true, LauncherInstrumentation.GestureScope.INSIDE); + mLauncher.movePointer( + iconCenter, + dragStartCenter, + DEFAULT_DRAG_STEPS, + /* isDecelerating= */ false, + downTime, + downTime, + /* slowDown= */ true, + LauncherInstrumentation.GestureScope.INSIDE); } private int getStartDragThreshold() { @@ -148,6 +167,4 @@ abstract class Launchable { } protected abstract void addExpectedEventsForLongClick(); - - protected abstract String getLongPressIndicator(); } diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java index 3f1be8021e..2033a42798 100644 --- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java +++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java @@ -16,11 +16,27 @@ package com.android.launcher3.tapl; +import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING; +import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING; +import static com.android.launcher3.testing.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT; + +import android.graphics.Point; +import android.graphics.Rect; +import android.os.SystemClock; +import android.view.MotionEvent; + +import androidx.test.uiautomator.By; + +import com.android.launcher3.testing.TestProtocol; + /** * Background state operations specific to when an app has been launched. */ public final class LaunchedAppState extends Background { + // More drag steps than Launchables to give the window manager time to register the drag. + private static final int DEFAULT_DRAG_STEPS = 35; + LaunchedAppState(LauncherInstrumentation launcher) { super(launcher); } @@ -29,4 +45,126 @@ public final class LaunchedAppState extends Background { protected LauncherInstrumentation.ContainerType getContainerType() { return LauncherInstrumentation.ContainerType.LAUNCHED_APP; } + + /** + * Returns the taskbar. + * + * The taskbar must already be visible when calling this method. + */ + public Taskbar getTaskbar() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get the taskbar")) { + mLauncher.waitForLauncherObject("taskbar_view"); + + return new Taskbar(mLauncher); + } + } + + /** + * Returns the Taskbar in a visible state. + * + * The taskbar must already be hidden when calling this method. + */ + public Taskbar showTaskbar() { + mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING); + + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "want to show the taskbar")) { + mLauncher.waitUntilLauncherObjectGone("taskbar_view"); + + final long downTime = SystemClock.uptimeMillis(); + final int unstashTargetY = mLauncher.getRealDisplaySize().y + - (mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_HEIGHT) + .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) / 2); + final Point unstashTarget = new Point( + mLauncher.getRealDisplaySize().x / 2, unstashTargetY); + + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget, + LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER); + LauncherInstrumentation.log("showTaskbar: sent down"); + + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) { + mLauncher.waitForLauncherObject("taskbar_view"); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget, + LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER); + + return new Taskbar(mLauncher); + } + } finally { + mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING); + } + } + + static void dragToSplitscreen( + LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName, + String expectedExistingPackageName) { + try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer( + "want to drag taskbar item to splitscreen")) { + final Point displaySize = launcher.getRealDisplaySize(); + final Point endPoint = new Point(displaySize.x / 4, 3 * displaySize.y / 4); + final long downTime = SystemClock.uptimeMillis(); + // Use mObject before starting drag since the system drag and drop moves the original + // view. + Point itemVisibleCenter = launchable.mObject.getVisibleCenter(); + Rect itemVisibleBounds = launcher.getVisibleBounds(launchable.mObject); + String itemLabel = launchable.mObject.getText(); + + Point dragStart = launchable.startDrag( + downTime, + launchable::addExpectedEventsForLongClick, + /* runToSpringLoadedState= */ false); + + try (LauncherInstrumentation.Closable c2 = launcher.addContextLayer( + "started item drag")) { + launcher.movePointer( + dragStart, + endPoint, + DEFAULT_DRAG_STEPS, + /* isDecelerating= */ true, + downTime, + SystemClock.uptimeMillis(), + /* slowDown= */ false, + LauncherInstrumentation.GestureScope.INSIDE); + + try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer( + "moved pointer to drop point")) { + dropDraggedItem( + launcher, + launchable, + expectedNewPackageName, + endPoint, downTime, + itemVisibleCenter, + itemVisibleBounds, + itemLabel, + expectedExistingPackageName); + } + } + } + } + + private static void dropDraggedItem( + LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName, + Point endPoint, long downTime, Point itemVisibleCenter, Rect itemVisibleBounds, + String itemLabel, String expectedExistingPackageName) { + LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen before drop " + + itemVisibleCenter + " in " + itemVisibleBounds); + + launchable.executeAndWaitForWindowChange(() -> { + launcher.sendPointer( + downTime, + SystemClock.uptimeMillis(), + MotionEvent.ACTION_UP, + endPoint, + LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER); + LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: after " + + "drop"); + }, itemLabel, "dropping taskbar item"); + + try (LauncherInstrumentation.Closable c = launcher.addContextLayer("dropped item")) { + launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName)); + launcher.checkPackagesVisible( + new String[] {expectedNewPackageName, expectedExistingPackageName}); + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index bbfbc550d0..1e3b078136 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -84,6 +84,7 @@ import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; @@ -123,7 +124,8 @@ public final class LauncherInstrumentation { // Types for launcher containers that the user is interacting with. "Background" is a // pseudo-container corresponding to inactive launcher covered by another app. public enum ContainerType { - WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP + WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP, + TASKBAR_ALL_APPS } public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON} @@ -167,6 +169,7 @@ public final class LauncherInstrumentation { private static final String OVERVIEW_RES_ID = "overview_panel"; private static final String WIDGETS_RES_ID = "primary_widgets_list_view"; private static final String CONTEXT_MENU_RES_ID = "popup_container"; + private static final String TASKBAR_RES_ID = "taskbar_view"; public static final int WAIT_TIME_MS = 60000; private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; private static final String ANDROID_PACKAGE = "android"; @@ -500,6 +503,16 @@ public final class LauncherInstrumentation { } } + void checkPackagesVisible(String[] expectedVisiblePackages) { + Set actualVisiblePackages = + getVisiblePackagesStream().collect(Collectors.toSet()); + + for (String expectedVisible : expectedVisiblePackages) { + assertTrue("Expected package not visible: " + expectedVisible, + actualVisiblePackages.contains(expectedVisible)); + } + } + private String getVisiblePackages() { final String apps = getVisiblePackagesStream().collect(Collectors.joining(", ")); return !apps.isEmpty() @@ -722,27 +735,41 @@ public final class LauncherInstrumentation { waitUntilLauncherObjectGone(APPS_RES_ID); waitUntilLauncherObjectGone(OVERVIEW_RES_ID); waitUntilLauncherObjectGone(WIDGETS_RES_ID); + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + return waitForLauncherObject(WORKSPACE_RES_ID); } case WIDGETS: { waitUntilLauncherObjectGone(WORKSPACE_RES_ID); waitUntilLauncherObjectGone(APPS_RES_ID); waitUntilLauncherObjectGone(OVERVIEW_RES_ID); + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + return waitForLauncherObject(WIDGETS_RES_ID); } + case TASKBAR_ALL_APPS: case HOME_ALL_APPS: { waitUntilLauncherObjectGone(WORKSPACE_RES_ID); waitUntilLauncherObjectGone(OVERVIEW_RES_ID); waitUntilLauncherObjectGone(WIDGETS_RES_ID); + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + return waitForLauncherObject(APPS_RES_ID); } case OVERVIEW: { waitUntilLauncherObjectGone(APPS_RES_ID); waitUntilLauncherObjectGone(WORKSPACE_RES_ID); waitUntilLauncherObjectGone(WIDGETS_RES_ID); + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + return waitForLauncherObject(OVERVIEW_RES_ID); } case FALLBACK_OVERVIEW: { + waitUntilLauncherObjectGone(APPS_RES_ID); + waitUntilLauncherObjectGone(WORKSPACE_RES_ID); + waitUntilLauncherObjectGone(WIDGETS_RES_ID); + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + return waitForFallbackLauncherObject(OVERVIEW_RES_ID); } case LAUNCHED_APP: { @@ -750,6 +777,12 @@ public final class LauncherInstrumentation { waitUntilLauncherObjectGone(APPS_RES_ID); waitUntilLauncherObjectGone(OVERVIEW_RES_ID); waitUntilLauncherObjectGone(WIDGETS_RES_ID); + + if (isTablet() && !isFallbackOverview()) { + waitForLauncherObject(TASKBAR_RES_ID); + } else { + waitUntilLauncherObjectGone(TASKBAR_RES_ID); + } return null; } default: @@ -863,8 +896,13 @@ public final class LauncherInstrumentation { setForcePauseTimeout(FORCE_PAUSE_TIMEOUT_MS); final Point displaySize = getRealDisplaySize(); + // The swipe up to home gesture starts from inside the launcher when the user is + // already home. Otherwise, the gesture can start inside the launcher process if the + // taskbar is visible. boolean gestureStartFromLauncher = isTablet() - ? !isLauncher3() || hasLauncherObject(WORKSPACE_RES_ID) + ? !isLauncher3() + || hasLauncherObject(WORKSPACE_RES_ID) + || hasLauncherObject(TASKBAR_RES_ID) : isLauncherVisible(); // CLose floating views before going back to home. @@ -1301,9 +1339,7 @@ public final class LauncherInstrumentation { } void scrollToLastVisibleRow( - UiObject2 container, - Collection items, - int topPaddingInContainer) { + UiObject2 container, Collection items, int topPaddingInContainer) { final UiObject2 lowestItem = Collections.max(items, (i1, i2) -> Integer.compare(getVisibleBounds(i1).top, getVisibleBounds(i2).top)); @@ -1326,8 +1362,8 @@ public final class LauncherInstrumentation { containerRect.height() - distance - bottomGestureMarginInContainer, 0, bottomGestureMarginInContainer), - 10, - true); + /* steps= */ 10, + /* slowDown= */ true); } void scrollLeftByDistance(UiObject2 container, int distance) { @@ -1650,6 +1686,29 @@ public final class LauncherInstrumentation { getTestInfo(TestProtocol.REQUEST_CLEAR_DATA); } + /** + * Reloads the workspace with a test layout that includes the Test Activity app icon on the + * hotseat. + */ + public void useTestWorkspaceLayoutOnReload() { + getTestInfo(TestProtocol.REQUEST_USE_TEST_WORKSPACE_LAYOUT); + } + + /** Reloads the workspace with the default layout defined by the user's grid size selection. */ + public void useDefaultWorkspaceLayoutOnReload() { + getTestInfo(TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT); + } + + /** Shows the taskbar if it is hidden, otherwise does nothing. */ + public void showTaskbarIfHidden() { + getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED); + } + + public List getHotseatIconNames() { + return getTestInfo(TestProtocol.REQUEST_HOTSEAT_ICON_NAMES) + .getStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + private String[] getActivities() { return getTestInfo(TestProtocol.REQUEST_GET_ACTIVITIES) .getStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD); diff --git a/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java new file mode 100644 index 0000000000..ce1c3c0e9d --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java @@ -0,0 +1,39 @@ +/* + * 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.tapl; + +/** Launchable that can serve as a source for dragging and dropping to splitscreen. */ +interface SplitscreenDragSource { + + /** + * Drags this app icon to the left (landscape) or bottom (portrait) of the screen, launching it + * in splitscreen. + * + * @param expectedNewPackageName package name of the app being dragged + * @param expectedExistingPackageName package name of the already-launched app + */ + default void dragToSplitscreen( + String expectedNewPackageName, String expectedExistingPackageName) { + Launchable launchable = getLaunchable(); + LauncherInstrumentation launcher = launchable.mLauncher; + try (LauncherInstrumentation.Closable e = launcher.eventsCheck()) { + LaunchedAppState.dragToSplitscreen( + launcher, launchable, expectedNewPackageName, expectedExistingPackageName); + } + } + + Launchable getLaunchable(); +} diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java new file mode 100644 index 0000000000..b5a08c3ba6 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java @@ -0,0 +1,123 @@ +/* + * 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.tapl; + +import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING; +import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING; + +import android.graphics.Point; +import android.os.SystemClock; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiObject2; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Operations on the Taskbar from LaunchedApp. + */ +public final class Taskbar { + + private final LauncherInstrumentation mLauncher; + + Taskbar(LauncherInstrumentation launcher) { + mLauncher = launcher; + } + + /** + * Returns an app icon with the given name. This fails if the icon is not found. + */ + @NonNull + public TaskbarAppIcon getAppIcon(String appName) { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get a taskbar icon")) { + return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer( + mLauncher.waitForLauncherObject("taskbar_view"), + AppIcon.getAppIconSelector(appName, mLauncher))); + } + } + + /** + * Hides this taskbar. + * + * The taskbar must already be visible when calling this method. + */ + public void hide() { + mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING); + + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to hide the taskbar"); + LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { + mLauncher.waitForLauncherObject("taskbar_view"); + + final long downTime = SystemClock.uptimeMillis(); + Point stashTarget = new Point( + mLauncher.getRealDisplaySize().x - 1, mLauncher.getRealDisplaySize().y - 1); + + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, stashTarget, + LauncherInstrumentation.GestureScope.INSIDE); + LauncherInstrumentation.log("hideTaskbar: sent down"); + + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) { + mLauncher.waitUntilLauncherObjectGone("taskbar_view"); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget, + LauncherInstrumentation.GestureScope.INSIDE); + } + } finally { + mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING); + } + } + + /** + * Opens the Taskbar all apps page. + */ + public AllAppsFromTaskbar openAllApps() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to open taskbar all apps"); + LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { + + mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer( + mLauncher.waitForLauncherObject("taskbar_view"), getAllAppsButtonSelector())); + + return new AllAppsFromTaskbar(mLauncher); + } + } + + /** Returns a list of app icon names on the Taskbar */ + public List getIconNames() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get all taskbar icons")) { + return mLauncher.waitForObjectsInContainer( + mLauncher.waitForLauncherObject("taskbar_view"), + AppIcon.getAnyAppIconSelector()) + .stream() + .map(UiObject2::getText) + .filter(text -> !TextUtils.isEmpty(text)) // Filter out the all apps button + .collect(Collectors.toList()); + } + } + + private static BySelector getAllAppsButtonSelector() { + // Look for an icon with no text + return By.clazz(TextView.class).text(""); + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java new file mode 100644 index 0000000000..099acd4716 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java @@ -0,0 +1,52 @@ +/* + * 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.tapl; + +import androidx.test.uiautomator.UiObject2; + +import java.util.regex.Pattern; + +/** + * App icon specifically on the Taskbar. + */ +public final class TaskbarAppIcon extends AppIcon implements SplitscreenDragSource { + + private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick"); + + TaskbarAppIcon(LauncherInstrumentation launcher, UiObject2 icon) { + super(launcher, icon); + } + + @Override + protected Pattern getLongClickEvent() { + return LONG_CLICK_EVENT; + } + + @Override + public TaskbarAppIconMenu openDeepShortcutMenu() { + return (TaskbarAppIconMenu) super.openDeepShortcutMenu(); + } + + @Override + protected TaskbarAppIconMenu createMenu(UiObject2 menu) { + return new TaskbarAppIconMenu(mLauncher, menu); + } + + @Override + public Launchable getLaunchable() { + return this; + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java new file mode 100644 index 0000000000..1f137c5406 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java @@ -0,0 +1,38 @@ +/* + * 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.tapl; + +import androidx.test.uiautomator.UiObject2; + +/** + * Context menu of a Taskbar app icon. + */ +public final class TaskbarAppIconMenu extends AppIconMenu { + + TaskbarAppIconMenu(LauncherInstrumentation launcher, UiObject2 deepShortcutsContainer) { + super(launcher, deepShortcutsContainer); + } + + @Override + public TaskbarAppIconMenuItem getMenuItem(String shortcutText) { + return (TaskbarAppIconMenuItem) super.getMenuItem(shortcutText); + } + + @Override + protected TaskbarAppIconMenuItem createMenuItem(UiObject2 menuItem) { + return new TaskbarAppIconMenuItem(mLauncher, menuItem); + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java new file mode 100644 index 0000000000..69a8a08800 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java @@ -0,0 +1,57 @@ +/* + * 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.tapl; + +import androidx.test.uiautomator.UiObject2; + +import com.android.launcher3.testing.TestProtocol; + +import java.util.regex.Pattern; + +/** + * Menu item in a Taskbar app icon menu. + */ +public final class TaskbarAppIconMenuItem extends AppIconMenuItem implements SplitscreenDragSource { + + private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick"); + + TaskbarAppIconMenuItem( + LauncherInstrumentation launcher, UiObject2 shortcut) { + super(launcher, shortcut); + } + + @Override + protected void addExpectedEventsForLongClick() { + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT); + } + + @Override + protected void waitForLongPressConfirmation() { + // On long-press, the popup container closes and the system drag-and-drop begins. This + // only leaves launcher views that were previously visible. + mLauncher.waitUntilLauncherObjectGone("popup_container"); + } + + @Override + protected String launchableType() { + return "taskbar app icon menu item"; + } + + @Override + public Launchable getLaunchable() { + return this; + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java index 73e983013e..2346249564 100644 --- a/tests/tapl/com/android/launcher3/tapl/Widget.java +++ b/tests/tapl/com/android/launcher3/tapl/Widget.java @@ -39,8 +39,8 @@ public final class Widget extends Launchable implements WorkspaceDragSource { } @Override - protected String getLongPressIndicator() { - return "drop_target_bar"; + protected void waitForLongPressConfirmation() { + mLauncher.waitForLauncherObject("drop_target_bar"); } @Override diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 3bc53893ff..fee449011d 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -205,7 +205,6 @@ public final class Workspace extends Home { mLauncher, homeAppIcon, new Point(targetX, mLauncher.getVisibleBounds(workspace).centerY()), - "popup_container", false, false, () -> mLauncher.expectEvent( @@ -244,11 +243,11 @@ public final class Workspace extends Home { LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "removing app icon from workspace")) { dragIconToWorkspace( - mLauncher, homeAppIcon, + mLauncher, + homeAppIcon, () -> getDropPointFromDropTargetBar(mLauncher, DELETE_TARGET_TEXT_ID), - homeAppIcon.getLongPressIndicator(), () -> mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), - null); + /* expectDropEvents= */ null); try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( "dragged the app to the drop bar")) { @@ -274,11 +273,11 @@ public final class Workspace extends Home { try (LauncherInstrumentation.Closable c = launcher.addContextLayer( "uninstalling app icon")) { dragIconToWorkspace( - launcher, homeAppIcon, + launcher, + homeAppIcon, () -> getDropPointFromDropTargetBar(launcher, UNINSTALL_TARGET_TEXT_ID), - homeAppIcon.getLongPressIndicator(), expectLongClickEvents, - null); + /* expectDropEvents= */null); launcher.waitUntilLauncherObjectGone(DROP_BAR_RES_ID); @@ -345,15 +344,15 @@ public final class Workspace extends Home { } static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable, - Point dest, String longPressIndicator, boolean startsActivity, boolean isWidgetShortcut, + Point dest, boolean startsActivity, boolean isWidgetShortcut, Runnable expectLongClickEvents) { Runnable expectDropEvents = null; if (startsActivity || isWidgetShortcut) { expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START); } - dragIconToWorkspace(launcher, launchable, () -> dest, longPressIndicator, - expectLongClickEvents, expectDropEvents); + dragIconToWorkspace( + launcher, launchable, () -> dest, expectLongClickEvents, expectDropEvents); } /** @@ -361,22 +360,27 @@ public final class Workspace extends Home { * (There is no slow down time before drop event) * This function expects the launchable is inside the workspace and there is no drop event. */ - static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable, - Supplier destSupplier, String longPressIndicator) { - dragIconToWorkspace(launcher, launchable, destSupplier, longPressIndicator, - () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), null); + static void dragIconToWorkspace( + LauncherInstrumentation launcher, Launchable launchable, Supplier destSupplier) { + dragIconToWorkspace( + launcher, + launchable, + destSupplier, + () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), + /* expectDropEvents= */ null); } static void dragIconToWorkspace( - LauncherInstrumentation launcher, Launchable launchable, Supplier dest, - String longPressIndicator, Runnable expectLongClickEvents, + LauncherInstrumentation launcher, + Launchable launchable, + Supplier dest, + Runnable expectLongClickEvents, @Nullable Runnable expectDropEvents) { try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer( "want to drag icon to workspace")) { final long downTime = SystemClock.uptimeMillis(); Point dragStart = launchable.startDrag( downTime, - longPressIndicator, expectLongClickEvents, /* runToSpringLoadedState= */ true); Point targetDest = dest.get(); diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java index 93c2213db0..d8d4420005 100644 --- a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java +++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java @@ -41,7 +41,6 @@ interface WorkspaceDragSource { ? launchableCenter.x - width / 2 : launchableCenter.x + width / 2, displaySize.y / 2), - launchable.getLongPressIndicator(), startsActivity, isWidgetShortcut, launchable::addExpectedEventsForLongClick);