• Home
  • History
  • Annotate
  • 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.quickstep;
18 
19 import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
20 import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
21 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assume.assumeFalse;
28 import static org.junit.Assume.assumeTrue;
29 
30 import android.content.Intent;
31 import android.content.res.Configuration;
32 
33 import androidx.test.filters.LargeTest;
34 import androidx.test.platform.app.InstrumentationRegistry;
35 import androidx.test.runner.AndroidJUnit4;
36 import androidx.test.uiautomator.By;
37 import androidx.test.uiautomator.Until;
38 
39 import com.android.launcher3.Launcher;
40 import com.android.launcher3.LauncherState;
41 import com.android.launcher3.tapl.BaseOverview;
42 import com.android.launcher3.tapl.LaunchedAppState;
43 import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
44 import com.android.launcher3.tapl.Overview;
45 import com.android.launcher3.tapl.OverviewActions;
46 import com.android.launcher3.tapl.OverviewTask;
47 import com.android.launcher3.tapl.SelectModeButtons;
48 import com.android.launcher3.tapl.Workspace;
49 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
50 import com.android.launcher3.util.Wait;
51 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
52 import com.android.launcher3.util.rule.TestStabilityRule;
53 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
54 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
55 import com.android.quickstep.views.RecentsView;
56 
57 import org.junit.After;
58 import org.junit.Before;
59 import org.junit.Ignore;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 
63 @LargeTest
64 @RunWith(AndroidJUnit4.class)
65 public class TaplTestsQuickstep extends AbstractQuickStepTest {
66 
67     private static final String CALCULATOR_APP_PACKAGE =
68             resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
69     private static final String READ_DEVICE_CONFIG_PERMISSION =
70             "android.permission.READ_DEVICE_CONFIG";
71 
72     @Before
setUp()73     public void setUp() throws Exception {
74         super.setUp();
75         executeOnLauncher(launcher -> {
76             RecentsView recentsView = launcher.getOverviewPanel();
77             recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(true);
78         });
79     }
80 
81     @After
tearDown()82     public void tearDown() {
83         executeOnLauncherInTearDown(launcher -> {
84             RecentsView recentsView = launcher.getOverviewPanel();
85             recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(false);
86         });
87     }
88 
startTestApps()89     public static void startTestApps() throws Exception {
90         startAppFast(getAppPackageName());
91         startAppFast(CALCULATOR_APP_PACKAGE);
92         startTestActivity(2);
93     }
94 
startTestAppsWithCheck()95     private void startTestAppsWithCheck() throws Exception {
96         startTestApps();
97         executeOnLauncher(launcher -> assertTrue(
98                 "Launcher activity is the top activity; expecting another activity to be the top "
99                         + "one",
100                 isInLaunchedApp(launcher)));
101     }
102 
103     @Test
104     @NavigationModeSwitch
105     @PortraitLandscape
testWorkspaceSwitchToAllApps()106     public void testWorkspaceSwitchToAllApps() {
107         assertNotNull("switchToAllApps() returned null",
108                 mLauncher.getWorkspace().switchToAllApps());
109         assertTrue("Launcher internal state is not All Apps",
110                 isInState(() -> LauncherState.ALL_APPS));
111     }
112 
113     @Test
114     @PortraitLandscape
testOverview()115     public void testOverview() throws Exception {
116         startTestAppsWithCheck();
117         // mLauncher.pressHome() also tests an important case of pressing home while in background.
118         Overview overview = mLauncher.goHome().switchToOverview();
119         assertTrue("Launcher internal state didn't switch to Overview",
120                 isInState(() -> LauncherState.OVERVIEW));
121         executeOnLauncher(
122                 launcher -> assertTrue("Don't have at least 3 tasks", getTaskCount(launcher) >= 3));
123 
124         // Test flinging forward and backward.
125         executeOnLauncher(launcher -> assertEquals("Current task in Overview is not 0",
126                 0, getCurrentOverviewPage(launcher)));
127 
128         overview.flingForward();
129         assertTrue("Launcher internal state is not Overview",
130                 isInState(() -> LauncherState.OVERVIEW));
131         final Integer currentTaskAfterFlingForward = getFromLauncher(
132                 launcher -> getCurrentOverviewPage(launcher));
133         executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
134                 currentTaskAfterFlingForward > 0));
135 
136         overview.flingBackward();
137         assertTrue("Launcher internal state is not Overview",
138                 isInState(() -> LauncherState.OVERVIEW));
139         executeOnLauncher(launcher -> assertTrue("Flinging back in Overview did nothing",
140                 getCurrentOverviewPage(launcher) < currentTaskAfterFlingForward));
141 
142         // Test opening a task.
143         OverviewTask task = mLauncher.goHome().switchToOverview().getCurrentTask();
144         assertNotNull("overview.getCurrentTask() returned null (1)", task);
145         assertNotNull("OverviewTask.open returned null", task.open());
146         assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
147                         By.pkg(getAppPackageName()).text("TestActivity2")),
148                 DEFAULT_UI_TIMEOUT));
149         executeOnLauncher(launcher -> assertTrue(
150                 "Launcher activity is the top activity; expecting another activity to be the top "
151                         + "one",
152                 isInLaunchedApp(launcher)));
153 
154         // Test dismissing a task.
155         overview = mLauncher.goHome().switchToOverview();
156         assertTrue("Launcher internal state didn't switch to Overview",
157                 isInState(() -> LauncherState.OVERVIEW));
158         final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher));
159         task = overview.getCurrentTask();
160         assertNotNull("overview.getCurrentTask() returned null (2)", task);
161         task.dismiss();
162         executeOnLauncher(
163                 launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
164                         numTasks - 1, getTaskCount(launcher)));
165 
166         // Test dismissing all tasks.
167         mLauncher.goHome().switchToOverview().dismissAllTasks();
168         assertTrue("Launcher internal state is not Home",
169                 isInState(() -> LauncherState.NORMAL));
170         executeOnLauncher(
171                 launcher -> assertEquals("Still have tasks after dismissing all",
172                         0, getTaskCount(launcher)));
173     }
174 
175     /**
176      * Smoke test for action buttons: Presses all the buttons and makes sure no crashes occur.
177      */
178     @Test
179     @NavigationModeSwitch
180     @PortraitLandscape
testOverviewActions()181     public void testOverviewActions() throws Exception {
182         assumeFalse("Skipping Overview Actions tests for grid only overview",
183                 mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled());
184         startTestAppsWithCheck();
185         OverviewActions actionsView =
186                 mLauncher.goHome().switchToOverview().getOverviewActions();
187         actionsView.clickAndDismissScreenshot();
188     }
189 
190     @Test
testDismissOverviewWithEscKey()191     public void testDismissOverviewWithEscKey() throws Exception {
192         startTestAppsWithCheck();
193         final Overview overview = mLauncher.goHome().switchToOverview();
194         assertTrue("Launcher internal state is not Overview",
195                 isInState(() -> LauncherState.OVERVIEW));
196 
197         overview.dismissByEscKey();
198         assertTrue("Launcher internal state is not Home",
199                 isInState(() -> LauncherState.NORMAL));
200     }
201 
202     @Test
testDismissModalTaskAndOverviewWithEscKey()203     public void testDismissModalTaskAndOverviewWithEscKey() throws Exception {
204         startTestAppsWithCheck();
205         final Overview overview = mLauncher.goHome().switchToOverview();
206 
207         final SelectModeButtons selectModeButtons;
208 
209         if (mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled()) {
210             selectModeButtons = overview.getCurrentTask().tapMenu().tapSelectMenuItem();
211         } else {
212             selectModeButtons = overview.getOverviewActions().clickSelect();
213         }
214 
215         assertTrue("Launcher internal state is not Overview Modal Task",
216                 isInState(() -> LauncherState.OVERVIEW_MODAL_TASK));
217 
218         selectModeButtons.dismissByEscKey();
219 
220         assertTrue("Launcher internal state is not Overview",
221                 isInState(() -> LauncherState.OVERVIEW));
222         overview.dismissByEscKey();
223         assertTrue("Launcher internal state is not Home",
224                 isInState(() -> LauncherState.NORMAL));
225     }
226 
227     @Test
testOpenOverviewWithActionPlusTabKeys()228     public void testOpenOverviewWithActionPlusTabKeys() throws Exception {
229         startTestAppsWithCheck();
230         startAppFast(CALCULATOR_APP_PACKAGE); // Ensure Calculator is last opened app.
231         Workspace home = mLauncher.goHome();
232         assertTrue("Launcher state is not Home", isInState(() -> LauncherState.NORMAL));
233 
234         Overview overview = home.openOverviewFromActionPlusTabKeyboardShortcut();
235 
236         assertTrue("Launcher state is not Overview", isInState(() -> LauncherState.OVERVIEW));
237         overview.launchFocusedTaskByEnterKey(CALCULATOR_APP_PACKAGE); // Assert app is focused.
238     }
239 
240     @Test
testOpenOverviewWithRecentsKey()241     public void testOpenOverviewWithRecentsKey() throws Exception {
242         startTestAppsWithCheck();
243         startAppFast(CALCULATOR_APP_PACKAGE); // Ensure Calculator is last opened app.
244         Workspace home = mLauncher.goHome();
245         assertTrue("Launcher state is not Home", isInState(() -> LauncherState.NORMAL));
246 
247         Overview overview = home.openOverviewFromRecentsKeyboardShortcut();
248 
249         assertTrue("Launcher state is not Overview", isInState(() -> LauncherState.OVERVIEW));
250         overview.launchFocusedTaskByEnterKey(CALCULATOR_APP_PACKAGE); // Assert app is focused.
251     }
252 
getCurrentOverviewPage(Launcher launcher)253     private int getCurrentOverviewPage(Launcher launcher) {
254         return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
255     }
256 
getTaskCount(Launcher launcher)257     private int getTaskCount(Launcher launcher) {
258         return launcher.<RecentsView>getOverviewPanel().getTaskViewCount();
259     }
260 
getTopRowTaskCountForTablet(Launcher launcher)261     private int getTopRowTaskCountForTablet(Launcher launcher) {
262         return launcher.<RecentsView>getOverviewPanel().getTopRowTaskCountForTablet();
263     }
264 
getBottomRowTaskCountForTablet(Launcher launcher)265     private int getBottomRowTaskCountForTablet(Launcher launcher) {
266         return launcher.<RecentsView>getOverviewPanel().getBottomRowTaskCountForTablet();
267     }
268 
269     // Staging; will be promoted to presubmit if stable
270     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
271 
272     @Test
273     @NavigationModeSwitch
274     @PortraitLandscape
testSwitchToOverview()275     public void testSwitchToOverview() throws Exception {
276         startTestAppsWithCheck();
277         assertNotNull("Workspace.switchToOverview() returned null",
278                 mLauncher.goHome().switchToOverview());
279         assertTrue("Launcher internal state didn't switch to Overview",
280                 isInState(() -> LauncherState.OVERVIEW));
281     }
282 
283     @Test
284     @TaskbarModeSwitch(mode = TRANSIENT)
testSwitchToOverviewWithStashedTaskbar()285     public void testSwitchToOverviewWithStashedTaskbar() throws Exception {
286         try {
287             startTestAppsWithCheck();
288             // Set ignoreTaskbarVisibility, as transient taskbar will be stashed after app launch.
289             mLauncher.setIgnoreTaskbarVisibility(true);
290             mLauncher.getLaunchedAppState().switchToOverview();
291         } finally {
292             mLauncher.setIgnoreTaskbarVisibility(false);
293         }
294     }
295 
296     // Staging; will be promoted to presubmit if stable
297     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
298 
299     @Test
300     @NavigationModeSwitch
301     @PortraitLandscape
testBackground()302     public void testBackground() throws Exception {
303         startAppFast(CALCULATOR_APP_PACKAGE);
304         final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
305 
306         assertNotNull("Background.switchToOverview() returned null",
307                 launchedAppState.switchToOverview());
308         assertTrue("Launcher internal state didn't switch to Overview",
309                 isInState(() -> LauncherState.OVERVIEW));
310     }
311 
quickSwitchToPreviousAppAndAssert(boolean toRight)312     private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
313         final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
314         if (toRight) {
315             launchedAppState.quickSwitchToPreviousApp();
316         } else {
317             launchedAppState.quickSwitchToPreviousAppSwipeLeft();
318         }
319 
320         // While enable shell transition, Launcher can be resumed due to transient launch.
321         waitForLauncherCondition("Launcher shouldn't stay in resume forever",
322                 this::isInLaunchedApp, 3000 /* timeout */);
323     }
324 
325     @Test
326     @NavigationModeSwitch
327     @PortraitLandscape
328     @ScreenRecord // b/313464374
329     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/325659406
testQuickSwitchFromApp()330     public void testQuickSwitchFromApp() throws Exception {
331         startTestActivity(2);
332         startTestActivity(3);
333         startTestActivity(4);
334 
335         quickSwitchToPreviousAppAndAssert(true /* toRight */);
336         assertTestActivityIsRunning(3,
337                 "The first app we should have quick switched to is not running");
338 
339         quickSwitchToPreviousAppAndAssert(true /* toRight */);
340         if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
341             // 3-button mode toggles between 2 apps, rather than going back further.
342             assertTestActivityIsRunning(4,
343                     "Second quick switch should have returned to the first app.");
344         } else {
345             assertTestActivityIsRunning(2,
346                     "The second app we should have quick switched to is not running");
347         }
348 
349         quickSwitchToPreviousAppAndAssert(false /* toRight */);
350         assertTestActivityIsRunning(3,
351                 "The 2nd app we should have quick switched to is not running");
352 
353         final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
354         launchedAppState.switchToOverview();
355     }
356 
357     @Test
358     @TaskbarModeSwitch
testQuickSwitchToPreviousAppForTablet()359     public void testQuickSwitchToPreviousAppForTablet() throws Exception {
360         assumeTrue(mLauncher.isTablet());
361         startTestActivity(2);
362         startImeTestActivity();
363 
364         // Set ignoreTaskbarVisibility to true to verify the task bar visibility explicitly.
365         mLauncher.setIgnoreTaskbarVisibility(true);
366 
367 
368         try {
369             boolean isTransientTaskbar = mLauncher.isTransientTaskbar();
370             // Expect task bar invisible when the launched app was the IME activity.
371             LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
372             if (!isTransientTaskbar && isHardwareKeyboard() && !mLauncher.isImeDocked()) {
373                 launchedAppState.assertTaskbarVisible();
374             } else {
375                 launchedAppState.assertTaskbarHidden();
376             }
377 
378             // Quick-switch to the test app with swiping to right.
379             quickSwitchToPreviousAppAndAssert(true /* toRight */);
380 
381             assertTestActivityIsRunning(2,
382                     "The first app we should have quick switched to is not running");
383             launchedAppState = getAndAssertLaunchedApp();
384             if (isTransientTaskbar) {
385                 launchedAppState.assertTaskbarHidden();
386             } else {
387                 // Expect taskbar visible when the launched app was the test activity.
388                 launchedAppState.assertTaskbarVisible();
389             }
390         } finally {
391             // Reset ignoreTaskbarVisibility to ensure other tests still verify it.
392             mLauncher.setIgnoreTaskbarVisibility(false);
393         }
394     }
395 
isHardwareKeyboard()396     private boolean isHardwareKeyboard() {
397         return Configuration.KEYBOARD_QWERTY
398                 == mTargetContext.getResources().getConfiguration().keyboard;
399     }
400 
401     @Test
402     @NavigationModeSwitch
403     @PortraitLandscape
testQuickSwitchFromHome()404     public void testQuickSwitchFromHome() throws Exception {
405         startTestActivity(2);
406         mLauncher.goHome().quickSwitchToPreviousApp();
407         assertTestActivityIsRunning(2,
408                 "The most recent task is not running after quick switching from home");
409         getAndAssertLaunchedApp();
410     }
411 
412     @Test
413     @PortraitLandscape
414     @NavigationModeSwitch
testPressBack()415     public void testPressBack() throws Exception {
416         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
417                 READ_DEVICE_CONFIG_PERMISSION);
418         // Debug if we need to goHome to prevent wrong previous state b/315525621
419         mLauncher.goHome();
420         mLauncher.getWorkspace().switchToAllApps().pressBackToWorkspace();
421         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
422 
423         startAppFast(CALCULATOR_APP_PACKAGE);
424         mLauncher.getLaunchedAppState().pressBackToWorkspace();
425         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
426     }
427 
428     @Test
429     @PortraitLandscape
430     @TaskbarModeSwitch()
431     @Ignore("b/315376057")
testOverviewForTablet()432     public void testOverviewForTablet() throws Exception {
433         assumeTrue(mLauncher.isTablet());
434 
435         for (int i = 2; i <= 14; i++) {
436             startTestActivity(i);
437         }
438 
439         Overview overview = mLauncher.goHome().switchToOverview();
440         executeOnLauncher(
441                 launcher -> assertTrue("Don't have at least 13 tasks",
442                         getTaskCount(launcher) >= 13));
443 
444         // Test scroll the first task off screen
445         overview.scrollCurrentTaskOffScreen();
446         assertTrue("Launcher internal state is not Overview",
447                 isInState(() -> LauncherState.OVERVIEW));
448         executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
449                 getCurrentOverviewPage(launcher) > 0));
450 
451         // Test opening the task.
452         overview.getCurrentTask().open();
453         assertTrue("Test activity didn't open from Overview",
454                 mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text(
455                                 mLauncher.isGridOnlyOverviewEnabled() ? "TestActivity12"
456                                         : "TestActivity13")),
457                         DEFAULT_UI_TIMEOUT));
458 
459         // Scroll the task offscreen as it is now first
460         overview = mLauncher.goHome().switchToOverview();
461         overview.scrollCurrentTaskOffScreen();
462         assertTrue("Launcher internal state is not Overview",
463                 isInState(() -> LauncherState.OVERVIEW));
464         executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0",
465                 getCurrentOverviewPage(launcher) > 0));
466 
467         // Test dismissing the later task.
468         final Integer numTasks = getFromLauncher(this::getTaskCount);
469         overview.getCurrentTask().dismiss();
470         executeOnLauncher(
471                 launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
472                         numTasks - 1, getTaskCount(launcher)));
473         executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after dismissal",
474                 (Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
475                         launcher)) <= 1)));
476 
477         // TODO(b/308841019): Re-enable after fixing Overview jank when dismiss
478 //        // Test dismissing more tasks.
479 //        assertTrue("Launcher internal state didn't remain in Overview",
480 //                isInState(() -> LauncherState.OVERVIEW));
481 //        overview.getCurrentTask().dismiss();
482 //        assertTrue("Launcher internal state didn't remain in Overview",
483 //                isInState(() -> LauncherState.OVERVIEW));
484 //        overview.getCurrentTask().dismiss();
485 //        executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after multiple dismissals",
486 //                (Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
487 //                        launcher)) <= 1)));
488 
489         // Test dismissing all tasks.
490         mLauncher.goHome().switchToOverview().dismissAllTasks();
491         assertTrue("Launcher internal state is not Home",
492                 isInState(() -> LauncherState.NORMAL));
493         executeOnLauncher(
494                 launcher -> assertEquals("Still have tasks after dismissing all",
495                         0, getTaskCount(launcher)));
496     }
497 
498     @Test
499     @PortraitLandscape
testOverviewDeadzones()500     public void testOverviewDeadzones() throws Exception {
501         startTestAppsWithCheck();
502 
503         Overview overview = mLauncher.goHome().switchToOverview();
504         assertTrue("Launcher internal state should be Overview",
505                 isInState(() -> LauncherState.OVERVIEW));
506         executeOnLauncher(
507                 launcher -> assertTrue("Should have at least 3 tasks",
508                         getTaskCount(launcher) >= 3));
509 
510         // It should not dismiss overview when tapping between tasks
511         overview.touchBetweenTasks();
512         overview = mLauncher.getOverview();
513         assertTrue("Launcher internal state should be Overview",
514                 isInState(() -> LauncherState.OVERVIEW));
515 
516         // Dismiss when tapping to the right of the focused task
517         overview.touchOutsideFirstTask();
518         assertTrue("Launcher internal state should be Home",
519                 isInState(() -> LauncherState.NORMAL));
520     }
521 
522     @Test
523     @PortraitLandscape
524     @TaskbarModeSwitch
testTaskbarDeadzonesForTablet()525     public void testTaskbarDeadzonesForTablet() throws Exception {
526         assumeTrue(mLauncher.isTablet());
527 
528         startTestAppsWithCheck();
529 
530         Overview overview = mLauncher.goHome().switchToOverview();
531         assertTrue("Launcher internal state should be Overview",
532                 isInState(() -> LauncherState.OVERVIEW));
533         executeOnLauncher(
534                 launcher -> assertTrue("Should have at least 3 tasks",
535                         getTaskCount(launcher) >= 3));
536 
537         if (mLauncher.isTransientTaskbar()) {
538             // On transient taskbar, it should dismiss when tapping outside taskbar bounds.
539             overview.touchTaskbarBottomCorner(/* tapRight= */ false);
540             assertTrue("Launcher internal state should be Normal",
541                     isInState(() -> LauncherState.NORMAL));
542 
543             overview = mLauncher.getWorkspace().switchToOverview();
544 
545             // On transient taskbar, it should dismiss when tapping outside taskbar bounds.
546             overview.touchTaskbarBottomCorner(/* tapRight= */ true);
547             assertTrue("Launcher internal state should be Normal",
548                     isInState(() -> LauncherState.NORMAL));
549         } else {
550             // On persistent taskbar, it should not dismiss when tapping the taskbar
551             overview.touchTaskbarBottomCorner(/* tapRight= */ false);
552             assertTrue("Launcher internal state should be Overview",
553                     isInState(() -> LauncherState.OVERVIEW));
554 
555             // On persistent taskbar, it should not dismiss when tapping the taskbar
556             overview.touchTaskbarBottomCorner(/* tapRight= */ true);
557             assertTrue("Launcher internal state should be Overview",
558                     isInState(() -> LauncherState.OVERVIEW));
559         }
560     }
561 
562     @Test
testDisableRotationCheckForPhone()563     public void testDisableRotationCheckForPhone() throws Exception {
564         assumeFalse(mLauncher.isTablet());
565         try {
566             mLauncher.setExpectedRotationCheckEnabled(false);
567             mLauncher.setEnableRotation(false);
568             mLauncher.getDevice().setOrientationLeft();
569             startTestActivity(7);
570             Wait.atMost("Device should not be in natural orientation",
571                     () -> !mDevice.isNaturalOrientation(), DEFAULT_UI_TIMEOUT, mLauncher);
572             mLauncher.goHome();
573         } finally {
574             mLauncher.setExpectedRotationCheckEnabled(true);
575             mLauncher.setEnableRotation(true);
576             mLauncher.getDevice().setOrientationNatural();
577         }
578     }
579 
580     @Test
testExcludeFromRecents()581     public void testExcludeFromRecents() throws Exception {
582         startExcludeFromRecentsTestActivity();
583         OverviewTask currentTask = getAndAssertLaunchedApp().switchToOverview().getCurrentTask();
584         // TODO(b/326565120): the expected content description shouldn't be null but for now there
585         // is a bug that causes it to sometimes be for excludeForRecents tasks.
586         assertTrue("Can't find ExcludeFromRecentsTestActivity after entering Overview from it",
587                 currentTask.containsContentDescription("ExcludeFromRecents")
588                         || currentTask.containsContentDescription(null));
589         // Going home should clear out the excludeFromRecents task.
590         BaseOverview overview = mLauncher.goHome().switchToOverview();
591         if (overview.hasTasks()) {
592             currentTask = overview.getCurrentTask();
593             assertFalse("Found ExcludeFromRecentsTestActivity after entering Overview from Home",
594                     currentTask.containsContentDescription("ExcludeFromRecents")
595                             || currentTask.containsContentDescription(null));
596         } else {
597             // Presumably the test started with 0 tasks and remains that way after going home.
598         }
599     }
600 }
601