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