1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.dragging;
17 
18 import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
19 import static com.android.launcher3.util.TestConstants.AppNames.GMAIL_APP_NAME;
20 import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME;
21 import static com.android.launcher3.util.TestConstants.AppNames.PHOTOS_APP_NAME;
22 import static com.android.launcher3.util.TestConstants.AppNames.STORE_APP_NAME;
23 import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
24 
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertTrue;
28 
29 import android.graphics.Point;
30 import android.os.SystemClock;
31 import android.platform.test.annotations.PlatinumTest;
32 import android.util.Log;
33 
34 import com.android.launcher3.Launcher;
35 import com.android.launcher3.tapl.Folder;
36 import com.android.launcher3.tapl.FolderIcon;
37 import com.android.launcher3.tapl.HomeAllApps;
38 import com.android.launcher3.tapl.HomeAppIcon;
39 import com.android.launcher3.tapl.HomeAppIconMenuItem;
40 import com.android.launcher3.tapl.Workspace;
41 import com.android.launcher3.ui.AbstractLauncherUiTest;
42 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
43 import com.android.launcher3.util.TestUtil;
44 import com.android.launcher3.util.rule.ScreenRecordRule;
45 
46 import org.junit.Test;
47 
48 /**
49  * This test run in both Out of process (Oop) and in-process (Ipc).
50  * Tests multiple facets of the drag interaction in the Launcher:
51  *    * Can create a folder by dragging items.
52  *    * Can create a shortcut by dragging it to Workspace.
53  *    * Can create shortcuts in multiple spaces in the Workspace.
54  *    * Can cancel a drag icon to workspace by dragging outside of the Workspace.
55  *    * Can drag an icon from AllApps into the workspace
56  *    * Can drag an icon on the Workspace to other positions of the Workspace.
57  */
58 public class TaplDragTest extends AbstractLauncherUiTest<Launcher> {
59 
60     /**
61      * Adds two icons to the Workspace and combines them into a folder, then makes sure the icons
62      * are no longer in the Workspace then adds a third one to test adding an icon to an existing
63      * folder instead of creating one and drags it to the folder.
64      */
65     @Test
66     @PortraitLandscape
67     @PlatinumTest(focusArea = "launcher")
testDragToFolder()68     public void testDragToFolder() {
69         // TODO: add the use case to drag an icon to an existing folder. Currently it either fails
70         // on tablets or phones due to difference in resolution.
71         final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1);
72         final HomeAppIcon photosIcon = createShortcutInCenterIfNotExist(PHOTOS_APP_NAME);
73 
74         FolderIcon folderIcon = photosIcon.dragToIcon(playStoreIcon);
75         Folder folder = folderIcon.open();
76         folder.getAppIcon(STORE_APP_NAME);
77         folder.getAppIcon(PHOTOS_APP_NAME);
78         Workspace workspace = folder.close();
79 
80         workspace.verifyWorkspaceAppIconIsGone(STORE_APP_NAME + " should be moved to a folder.",
81                 STORE_APP_NAME);
82         workspace.verifyWorkspaceAppIconIsGone(PHOTOS_APP_NAME + " should be moved to a folder.",
83                 PHOTOS_APP_NAME);
84 
85         final HomeAppIcon mapIcon = createShortcutInCenterIfNotExist(MAPS_APP_NAME);
86         folder = mapIcon.dragToFolder(folderIcon);
87         folder.getAppIcon(MAPS_APP_NAME);
88         workspace = folder.close();
89 
90         workspace.verifyWorkspaceAppIconIsGone(MAPS_APP_NAME + " should be moved to a folder.",
91                 MAPS_APP_NAME);
92     }
93 
94     /**
95      * Adds two icons to the Workspace and combines them into a folder, then makes sure we are able
96      * to remove an icon from the folder and that the folder ceases to exist since it only has one
97      * icon left.
98      */
99     @Test
testDragOutOfFolder()100     public void testDragOutOfFolder() {
101         final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1);
102         final HomeAppIcon photosIcon = createShortcutInCenterIfNotExist(PHOTOS_APP_NAME);
103         FolderIcon folderIcon = photosIcon.dragToIcon(playStoreIcon);
104         Folder folder = folderIcon.open();
105         folder.getAppIcon(STORE_APP_NAME).internalDragToWorkspace(false, false);
106         assertNotNull(mLauncher.getWorkspace().tryGetWorkspaceAppIcon(STORE_APP_NAME));
107         assertNotNull(mLauncher.getWorkspace().tryGetWorkspaceAppIcon(PHOTOS_APP_NAME));
108     }
109 
110     /** Drags a shortcut from a long press menu into the workspace.
111      * 1. Open all apps and wait for load complete.
112      * 2. Find the app and long press it to show shortcuts.
113      * 3. Press icon center until shortcuts appear
114      * 4. Drags shortcut to any free space in the Workspace.
115      */
116     @Test
117     @PortraitLandscape
118     @PlatinumTest(focusArea = "launcher")
testDragShortcut()119     public void testDragShortcut() {
120 
121         final HomeAllApps allApps = mLauncher
122                 .getWorkspace()
123                 .switchToAllApps();
124         allApps.freeze();
125         try {
126             final HomeAppIconMenuItem menuItem = allApps
127                     .getAppIcon(TEST_APP_NAME)
128                     .openDeepShortcutMenu()
129                     .getMenuItem(0);
130             final String actualShortcutName = menuItem.getText();
131             final String expectedShortcutName = "Shortcut 1";
132 
133             assertEquals(expectedShortcutName, actualShortcutName);
134             menuItem.dragToWorkspace(false, false);
135             mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName)
136                     .launch(getAppPackageName());
137         } finally {
138             allApps.unfreeze();
139         }
140     }
141 
142     /**
143      * Similar to testDragShortcut but it adds shortcuts to multiple positions of the Workspace
144      * namely the corners and the center.
145      */
146     @Test
147     @PortraitLandscape
148     @PlatinumTest(focusArea = "launcher")
testDragShortcutToMultipleWorkspaceCells()149     public void testDragShortcutToMultipleWorkspaceCells() {
150         Point[] targets = TestUtil.getCornersAndCenterPositions(mLauncher);
151 
152         for (Point target : targets) {
153             final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
154             allApps.freeze();
155             try {
156                 allApps.getAppIcon(TEST_APP_NAME)
157                         .openDeepShortcutMenu()
158                         .getMenuItem(0)
159                         .dragToWorkspace(target.x, target.y);
160             } finally {
161                 allApps.unfreeze();
162             }
163         }
164     }
165 
166     /**
167      * Drags an icon to the workspace but instead of submitting it, it gets dragged outside of the
168      * Workspace to cancel it.
169      */
170 
171     @Test
172     @PortraitLandscape
173     @PlatinumTest(focusArea = "launcher")
testDragAndCancelAppIcon()174     public void testDragAndCancelAppIcon() {
175         final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
176         Point positionBeforeDrag =
177                 mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
178         assertNotNull("App not found in Workspace before dragging.", positionBeforeDrag);
179 
180         mLauncher.getWorkspace().dragAndCancelAppIcon(homeAppIcon);
181 
182         Point positionAfterDrag =
183                 mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
184         assertNotNull("App not found in Workspace after dragging.", positionAfterDrag);
185         assertEquals("App not returned to same position in Workspace after drag & cancel",
186                 positionBeforeDrag, positionAfterDrag);
187     }
188 
189     /**
190      * Drags app icon from AllApps into the Workspace.
191      * 1. Open all apps and wait for load complete.
192      * 2. Drag icon to homescreen.
193      * 3. Verify that the icon works on homescreen.
194      */
195     @PlatinumTest(focusArea = "launcher")
196     @Test
197     @PortraitLandscape
198     @ScreenRecordRule.ScreenRecord // b/343953783
testDragAppIcon()199     public void testDragAppIcon() {
200 
201         final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
202         allApps.freeze();
203         try {
204             allApps.getAppIcon(TEST_APP_NAME).dragToWorkspace(false, false);
205             mLauncher.getWorkspace().getWorkspaceAppIcon(TEST_APP_NAME).launch(getAppPackageName());
206         } finally {
207             allApps.unfreeze();
208         }
209         executeOnLauncher(launcher -> assertTrue(
210                 "Launcher activity is the top activity; expecting another activity to be the top "
211                         + "one",
212                 isInLaunchedApp(launcher)));
213     }
214 
215     /**
216      * Similar start to testDragAppIcon but after dragging the icon to the workspace, it drags the
217      * icon inside of the workspace to different positions.
218      * @throws Exception
219      */
220     @Test
221     @PortraitLandscape
222     @PlatinumTest(focusArea = "launcher")
testDragAppIconToMultipleWorkspaceCells()223     public void testDragAppIconToMultipleWorkspaceCells() throws Exception {
224         long startTime, endTime, elapsedTime;
225         Point[] targets = TestUtil.getCornersAndCenterPositions(mLauncher);
226         reinitializeLauncherData(true);
227         // test to move a shortcut to other cell.
228         final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(TEST_APP_NAME);
229         for (Point target : targets) {
230             startTime = SystemClock.uptimeMillis();
231             Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
232                     "TaplDragTest.java.testDragAppIconToMultipleWorkspaceCells: shortcut name: "
233                             + launcherTestAppIcon.getIconName()
234                             + " | target cell coordinates: (" + target.x + ", " + target.y
235                             + ") | start time: " + startTime);
236             launcherTestAppIcon.dragToWorkspace(target.x, target.y);
237             endTime = SystemClock.uptimeMillis();
238             elapsedTime = endTime - startTime;
239             Log.d("testDragAppIconToWorkspaceCellTime",
240                     "Milliseconds taken to move shortcut to other cell: " + elapsedTime);
241         }
242     }
243 }
244