• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package com.android.launcher3.tapl;
18 
19 import static com.android.launcher3.tapl.LauncherInstrumentation.DEFAULT_POLL_INTERVAL;
20 import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID;
21 import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
22 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT;
23 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
24 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT;
25 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
26 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_SHELL_DRAG_READY;
27 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
28 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_SCALE;
29 
30 import android.graphics.Point;
31 import android.graphics.Rect;
32 import android.os.SystemClock;
33 import android.view.InputDevice;
34 import android.view.MotionEvent;
35 import android.view.ViewConfiguration;
36 
37 import androidx.test.uiautomator.By;
38 import androidx.test.uiautomator.Condition;
39 import androidx.test.uiautomator.UiDevice;
40 
41 import com.android.launcher3.testing.shared.ResourceUtils;
42 import com.android.launcher3.testing.shared.TestProtocol;
43 
44 /**
45  * Background state operations specific to when an app has been launched.
46  */
47 public final class LaunchedAppState extends Background {
48 
49     // More drag steps than Launchables to give the window manager time to register the drag.
50     private static final int DEFAULT_DRAG_STEPS = 35;
51 
52     // UNSTASHED_TASKBAR_HANDLE_HINT_SCALE value from TaskbarStashController.
53     private static final float UNSTASHED_TASKBAR_HANDLE_HINT_SCALE = 1.1f;
54 
55     private static final int STASHED_TASKBAR_BOTTOM_EDGE_DP = 1;
56 
57     private final Condition<UiDevice, Boolean> mStashedTaskbarHintScaleCondition =
58             device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat(
59                     TestProtocol.TEST_INFO_RESPONSE_FIELD) - UNSTASHED_TASKBAR_HANDLE_HINT_SCALE
60                     < 0.00001f;
61 
62     private final Condition<UiDevice, Boolean> mStashedTaskbarDefaultScaleCondition =
63             device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat(
64                     TestProtocol.TEST_INFO_RESPONSE_FIELD) - 1f < 0.00001f;
65 
66     LaunchedAppState(LauncherInstrumentation launcher) {
67         super(launcher);
68     }
69 
70     @Override
71     protected LauncherInstrumentation.ContainerType getContainerType() {
72         return LauncherInstrumentation.ContainerType.LAUNCHED_APP;
73     }
74 
75     /**
76      * Returns the taskbar.
77      *
78      * The taskbar must already be visible when calling this method.
79      */
80     public Taskbar getTaskbar() {
81         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
82                 "want to get the taskbar")) {
83             mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
84 
85             return new Taskbar(mLauncher);
86         }
87     }
88 
89     /**
90      * Waits for the taskbar to be hidden, or fails.
91      */
92     public void assertTaskbarHidden() {
93         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
94                 "waiting for taskbar to be hidden")) {
95             mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
96         }
97     }
98 
99     /**
100      * Waits for the taskbar to be visible, or fails.
101      */
102     public void assertTaskbarVisible() {
103         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
104                 "waiting for taskbar to be visible")) {
105             mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
106         }
107     }
108 
109     /**
110      * Returns the Taskbar in a visible state.
111      *
112      * The taskbar must already be hidden when calling this method.
113      */
114     public Taskbar showTaskbar() {
115         mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
116         mLauncher.getTestInfo(REQUEST_ENABLE_BLOCK_TIMEOUT);
117 
118         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
119              LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
120                      "want to show the taskbar")) {
121             mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
122 
123             final long downTime = SystemClock.uptimeMillis();
124             final int unstashTargetY = mLauncher.getRealDisplaySize().y
125                     - (mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_HEIGHT)
126                             .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) / 2);
127             final Point unstashTarget = new Point(
128                     mLauncher.getRealDisplaySize().x / 2, unstashTargetY);
129 
130             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget,
131                     LauncherInstrumentation.GestureScope.EXPECT_PILFER);
132             LauncherInstrumentation.log("showTaskbar: sent down");
133 
134             try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
135                 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
136                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
137                         LauncherInstrumentation.GestureScope.EXPECT_PILFER);
138 
139                 return new Taskbar(mLauncher);
140             }
141         } finally {
142             mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
143             mLauncher.getTestInfo(REQUEST_DISABLE_BLOCK_TIMEOUT);
144         }
145     }
146 
147     static void dragToSplitscreen(
148             LauncherInstrumentation launcher,
149             Launchable launchable,
150             String expectedNewPackageName,
151             String expectedExistingPackageName) {
152         try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer(
153                 "want to drag taskbar item to splitscreen")) {
154             final Point displaySize = launcher.getRealDisplaySize();
155             // Drag to the center of the top-left quadrant of the screen, this point will work in
156             // both portrait and landscape.
157             final Point endPoint = new Point(displaySize.x / 4, displaySize.y / 4);
158             final long downTime = SystemClock.uptimeMillis();
159             // Use mObject before starting drag since the system drag and drop moves the original
160             // view.
161             Point itemVisibleCenter = launchable.mObject.getVisibleCenter();
162             Rect itemVisibleBounds = launcher.getVisibleBounds(launchable.mObject);
163             String itemLabel = launchable.mObject.getText();
164 
165             Point dragStart = launchable.startDrag(
166                     downTime,
167                     launchable::addExpectedEventsForLongClick,
168                     /* runToSpringLoadedState= */ false);
169 
170             try (LauncherInstrumentation.Closable c2 = launcher.addContextLayer(
171                     "started item drag")) {
172                 launcher.assertTrue("Shell drag not marked as ready", launcher.waitAndGet(() -> {
173                     LauncherInstrumentation.log("Checking shell drag ready");
174                     return launcher.getTestInfo(REQUEST_SHELL_DRAG_READY)
175                             .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, false);
176                 }, WAIT_TIME_MS, DEFAULT_POLL_INTERVAL));
177 
launcher.movePointer( dragStart, endPoint, DEFAULT_DRAG_STEPS, true, downTime, SystemClock.uptimeMillis(), false, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER)178                 launcher.movePointer(
179                         dragStart,
180                         endPoint,
181                         DEFAULT_DRAG_STEPS,
182                         /* isDecelerating= */ true,
183                         downTime,
184                         SystemClock.uptimeMillis(),
185                         /* slowDown= */ false,
186                         LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
187 
try(LauncherInstrumentation.Closable c3 = launcher.addContextLayer( "moved pointer to drop point"))188                 try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
189                         "moved pointer to drop point")) {
190                     LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
191                             + "before drop " + itemVisibleCenter + " in " + itemVisibleBounds);
192                     launcher.sendPointer(
193                             downTime,
194                             SystemClock.uptimeMillis(),
195                             MotionEvent.ACTION_UP,
196                             endPoint,
197                             LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
198                     LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
199                             + "after drop");
200 
201                     try (LauncherInstrumentation.Closable c4 = launcher.addContextLayer(
202                             "dropped item")) {
203                         launchable.assertAppLaunched(By.pkg(expectedNewPackageName));
204                         launchable.assertAppLaunched(By.pkg(expectedExistingPackageName));
205                     }
206                 }
207             }
208         }
209     }
210 
211     /**
212      * Emulate the cursor hovering the screen edge to unstash the taskbar.
213      *
214      * <p>This unstashing occurs when not actively hovering the taskbar.
215      */
216     public Taskbar hoverScreenBottomEdgeToUnstashTaskbar() {
217         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
218              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
219                      "cursor hover entering screen edge to unstash taskbar")) {
220             mLauncher.getDevice().wait(mStashedTaskbarDefaultScaleCondition,
221                     ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT);
222 
223             long downTime = SystemClock.uptimeMillis();
224             int leftEdge = 10;
225             Point taskbarUnstashArea = new Point(leftEdge, mLauncher.getRealDisplaySize().y - 1);
226             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
227                     new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
228                     InputDevice.SOURCE_MOUSE);
229 
230             mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
231 
232             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
233                     new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
234                     InputDevice.SOURCE_MOUSE);
235 
236             return new Taskbar(mLauncher);
237         }
238     }
239 
240     /**
241      * Emulate the cursor hovering the taskbar to get unstash hint, then hovering below to unstash.
242      */
243     public Taskbar hoverBelowHintedTaskbarToUnstash() {
244         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
245              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
246                      "cursor hover entering stashed taskbar")) {
247             long downTime = SystemClock.uptimeMillis();
248             Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
249                     mLauncher.getRealDisplaySize().y - 1);
250             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
251                     new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null,
252                     InputDevice.SOURCE_MOUSE);
253 
254             mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
255                     LauncherInstrumentation.WAIT_TIME_MS);
256 
257             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
258                          "cursor hover enter below taskbar to unstash")) {
259                 downTime = SystemClock.uptimeMillis();
260                 Point taskbarUnstashArea = new Point(mLauncher.getRealDisplaySize().x / 2,
261                         mLauncher.getRealDisplaySize().y - 1);
262                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
263                         new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
264                         InputDevice.SOURCE_MOUSE);
265 
266                 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
267                 return new Taskbar(mLauncher);
268             }
269         }
270     }
271 
272     /**
273      * Emulate the cursor entering and exiting a hover over the taskbar.
274      */
275     public void hoverToShowTaskbarUnstashHint() {
276         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
277              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
278                      "cursor hover entering stashed taskbar")) {
279             long downTime = SystemClock.uptimeMillis();
280             Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
281                     mLauncher.getRealDisplaySize().y - 1);
282             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
283                     new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null);
284 
285             mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
286                     LauncherInstrumentation.WAIT_TIME_MS);
287 
288             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
289                          "cursor hover exiting stashed taskbar")) {
290                 Point outsideStashedTaskbarHintArea = new Point(
291                         mLauncher.getRealDisplaySize().x / 2,
292                         mLauncher.getRealDisplaySize().y - 500);
293                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
294                         new Point(outsideStashedTaskbarHintArea.x, outsideStashedTaskbarHintArea.y),
295                         null);
296 
297                 mLauncher.getDevice().wait(mStashedTaskbarDefaultScaleCondition,
298                         LauncherInstrumentation.WAIT_TIME_MS);
299             }
300         }
301     }
302 
303     /**
304      * Emulate the cursor clicking the stashed taskbar to go home.
305      */
306     public Workspace clickStashedTaskbarToGoHome() {
307         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
308              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
309                      "cursor hover entering stashed taskbar")) {
310             long downTime = SystemClock.uptimeMillis();
311             int stashedTaskbarBottomEdge = ResourceUtils.pxFromDp(STASHED_TASKBAR_BOTTOM_EDGE_DP,
312                     mLauncher.getResources().getDisplayMetrics());
313             Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
314                     mLauncher.getRealDisplaySize().y - stashedTaskbarBottomEdge - 1);
315             mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
316                     new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null,
317                     InputDevice.SOURCE_MOUSE);
318 
319             mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
320                     LauncherInstrumentation.WAIT_TIME_MS);
321 
322             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
323                     "cursor clicking stashed taskbar to go home")) {
324                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
325                         new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
326                         null, InputDevice.SOURCE_MOUSE);
327                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
328                         new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
329                         LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
330                         InputDevice.SOURCE_MOUSE);
331                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_PRESS,
332                         new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
333                         null, InputDevice.SOURCE_MOUSE);
334                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_RELEASE,
335                         new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
336                         null, InputDevice.SOURCE_MOUSE);
337                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP,
338                         new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
339                         LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
340                         InputDevice.SOURCE_MOUSE);
341 
342                 return mLauncher.getWorkspace();
343             }
344         }
345     }
346 }
347