• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.OverviewTask.TASK_START_EVENT;
20 import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
21 import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
22 
23 import android.graphics.Point;
24 import android.os.SystemClock;
25 import android.view.MotionEvent;
26 
27 import androidx.annotation.NonNull;
28 import androidx.test.uiautomator.UiObject2;
29 
30 import com.android.launcher3.testing.TestProtocol;
31 
32 import java.util.regex.Pattern;
33 
34 /**
35  * Indicates the base state with a UI other than Overview running as foreground. It can also
36  * indicate Launcher as long as Launcher is not in Overview state.
37  */
38 public class Background extends LauncherInstrumentation.VisibleContainer {
39     private static final int ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION = 500;
40     private static final Pattern SQUARE_BUTTON_EVENT = Pattern.compile("onOverviewToggle");
41 
Background(LauncherInstrumentation launcher)42     Background(LauncherInstrumentation launcher) {
43         super(launcher);
44     }
45 
46     @Override
getContainerType()47     protected LauncherInstrumentation.ContainerType getContainerType() {
48         return LauncherInstrumentation.ContainerType.BACKGROUND;
49     }
50 
51     /**
52      * Swipes up or presses the square button to switch to Overview.
53      * Returns the base overview, which can be either in Launcher or the fallback recents.
54      *
55      * @return the Overview panel object.
56      */
57     @NonNull
switchToOverview()58     public BaseOverview switchToOverview() {
59         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
60              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
61                      "want to switch from background to overview")) {
62             verifyActiveContainer();
63             goToOverviewUnchecked();
64             return mLauncher.isFallbackOverview() ?
65                     new BaseOverview(mLauncher) : new Overview(mLauncher);
66         }
67     }
68 
zeroButtonToOverviewGestureStartsInLauncher()69     protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
70         return false;
71     }
72 
goToOverviewUnchecked()73     protected void goToOverviewUnchecked() {
74         switch (mLauncher.getNavigationModel()) {
75             case ZERO_BUTTON: {
76                 final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
77                 final int startY = getSwipeStartY();
78                 final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).
79                         getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
80                 final Point start = new Point(centerX, startY);
81                 final Point end =
82                         new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
83 
84                 final long downTime = SystemClock.uptimeMillis();
85                 final LauncherInstrumentation.GestureScope gestureScope =
86                         zeroButtonToOverviewGestureStartsInLauncher()
87                                 ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
88                                 : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
89 
90                 // b/156044202
91                 mLauncher.log("Hierarchy before swiping up to overview:");
92                 mLauncher.dumpViewHierarchy();
93 
94                 mLauncher.sendPointer(
95                         downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
96                 mLauncher.executeAndWaitForEvent(
97                         () -> mLauncher.movePointer(
98                                 downTime,
99                                 downTime,
100                                 ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
101                                 start,
102                                 end,
103                                 gestureScope),
104                         event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(event.getClassName()),
105                         () -> "Pause wasn't detected");
106                 mLauncher.runToState(
107                         () -> mLauncher.sendPointer(
108                                 downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end,
109                                 gestureScope),
110                         OVERVIEW_STATE_ORDINAL);
111                 break;
112             }
113 
114             case TWO_BUTTON: {
115                 final int startX;
116                 final int startY;
117                 final int endX;
118                 final int endY;
119                 final int swipeLength = mLauncher.getTestInfo(getSwipeHeightRequestName()).
120                         getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) + mLauncher.getTouchSlop();
121 
122                 if (mLauncher.getDevice().isNaturalOrientation()) {
123                     startX = endX = mLauncher.getDevice().getDisplayWidth() / 2;
124                     startY = getSwipeStartY();
125                     endY = startY - swipeLength;
126                 } else {
127                     startX = getSwipeStartX();
128                     endX = startX - swipeLength;
129                     startY = endY = mLauncher.getDevice().getDisplayHeight() / 2;
130                 }
131 
132                 mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL,
133                         LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
134                 break;
135             }
136 
137             case THREE_BUTTON:
138                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
139                 mLauncher.runToState(
140                         () -> mLauncher.waitForSystemUiObject("recent_apps").click(),
141                         OVERVIEW_STATE_ORDINAL);
142                 break;
143         }
144         expectSwitchToOverviewEvents();
145     }
146 
expectSwitchToOverviewEvents()147     private void expectSwitchToOverviewEvents() {
148     }
149 
150     /**
151      * Swipes right or double presses the square button to switch to the previous app.
152      */
quickSwitchToPreviousApp()153     public Background quickSwitchToPreviousApp() {
154         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
155              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
156                      "want to quick switch to the previous app")) {
157             verifyActiveContainer();
158             quickSwitchToPreviousApp(getExpectedStateForQuickSwitch());
159             return new Background(mLauncher);
160         }
161     }
162 
getExpectedStateForQuickSwitch()163     protected int getExpectedStateForQuickSwitch() {
164         return BACKGROUND_APP_STATE_ORDINAL;
165     }
166 
quickSwitchToPreviousApp(int expectedState)167     protected void quickSwitchToPreviousApp(int expectedState) {
168         final boolean launcherWasVisible = mLauncher.isLauncherVisible();
169         boolean transposeInLandscape = false;
170         switch (mLauncher.getNavigationModel()) {
171             case TWO_BUTTON:
172                 transposeInLandscape = true;
173                 // Fall through, zero button and two button modes behave the same.
174             case ZERO_BUTTON: {
175                 final int startX;
176                 final int startY;
177                 final int endX;
178                 final int endY;
179                 if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
180                     // Swipe from the bottom left to the bottom right of the screen.
181                     startX = 0;
182                     startY = getSwipeStartY();
183                     endX = mLauncher.getDevice().getDisplayWidth();
184                     endY = startY;
185                 } else {
186                     // Swipe from the bottom right to the top right of the screen.
187                     startX = getSwipeStartX();
188                     startY = mLauncher.getRealDisplaySize().y - 1;
189                     endX = startX;
190                     endY = 0;
191                 }
192                 final boolean isZeroButton = mLauncher.getNavigationModel()
193                         == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
194                 mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState,
195                         launcherWasVisible && isZeroButton
196                                 ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
197                                 : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
198                 break;
199             }
200 
201             case THREE_BUTTON:
202                 // Double press the recents button.
203                 UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
204                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
205                 mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL);
206                 mLauncher.getOverview();
207                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
208                 recentsButton.click();
209                 break;
210         }
211         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
212     }
213     /** Swipes left to switch to the previous app. */
quickSwitchToPreviousAppSwipeLeft()214     public Background quickSwitchToPreviousAppSwipeLeft() {
215         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
216             LauncherInstrumentation.Closable c =
217                 mLauncher.addContextLayer("want to quick switch to the previous app")) {
218             verifyActiveContainer();
219             quickSwitchToPreviousAppSwipeLeft(getExpectedStateForQuickSwitch());
220             return new Background(mLauncher);
221         }
222     }
223 
quickSwitchToPreviousAppSwipeLeft(int expectedState)224     protected void quickSwitchToPreviousAppSwipeLeft(int expectedState) {
225         final boolean launcherWasVisible = mLauncher.isLauncherVisible();
226         boolean transposeInLandscape = false;
227         switch (mLauncher.getNavigationModel()) {
228             case TWO_BUTTON:
229                 transposeInLandscape = true;
230                 // Fall through, zero button and two button modes behave the same.
231             case ZERO_BUTTON: {
232                 final int startX;
233                 final int startY;
234                 final int endX;
235                 final int endY;
236                 if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
237                     // Swipe from the bottom right to the bottom left of the screen.
238                     startX = mLauncher.getDevice().getDisplayWidth();
239                     startY = getSwipeStartY();
240                     endX = 0;
241                     endY = startY;
242                 } else {
243                     // Swipe from the bottom right to the top right of the screen.
244                     startX = getSwipeStartX();
245                     startY = mLauncher.getRealDisplaySize().y - 1;
246                     endX = startX;
247                     endY = 0;
248                 }
249                 final boolean isZeroButton =
250                         mLauncher.getNavigationModel()
251                         == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
252                 mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState,
253                         launcherWasVisible && isZeroButton
254                                 ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
255                                 : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
256                 break;
257             }
258 
259             case THREE_BUTTON:
260                 // Double press the recents button.
261                 UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
262                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
263                 mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL);
264                 mLauncher.getOverview();
265                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
266                 recentsButton.click();
267                 break;
268         }
269         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
270     }
271 
getSwipeHeightRequestName()272     protected String getSwipeHeightRequestName() {
273         return TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT;
274     }
275 
getSwipeStartX()276     protected int getSwipeStartX() {
277         return mLauncher.getRealDisplaySize().x - 1;
278     }
279 
getSwipeStartY()280     protected int getSwipeStartY() {
281         return mLauncher.getRealDisplaySize().y - 1;
282     }
283 }
284