• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.quickstep
17 
18 import android.platform.test.rule.AllowedDevices
19 import android.platform.test.rule.DeviceProduct
20 import android.platform.test.rule.IgnoreLimit
21 import androidx.test.uiautomator.By
22 import androidx.test.uiautomator.Until
23 import com.android.launcher3.BuildConfig
24 import com.android.launcher3.tapl.LaunchedAppState
25 import com.android.launcher3.tapl.OverviewTask
26 import com.android.launcher3.ui.AbstractLauncherUiTest
27 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape
28 import com.android.launcher3.uioverrides.QuickstepLauncher
29 import com.android.launcher3.util.TestUtil
30 import com.google.common.truth.Truth.assertWithMessage
31 import org.junit.Before
32 import org.junit.Test
33 
34 /** Test Desktop windowing in Overview. */
35 @AllowedDevices(allowed = [DeviceProduct.CF_TABLET, DeviceProduct.TANGORPRO])
36 @IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD)
37 class TaplTestsOverviewDesktop : AbstractLauncherUiTest<QuickstepLauncher?>() {
38     @Before
39     fun setup() {
40         val overview = mLauncher.goHome().switchToOverview()
41         if (overview.hasTasks()) {
42             overview.dismissAllTasks()
43         }
44         startTestAppsWithCheck()
45         mLauncher.goHome()
46     }
47 
48     @Test
49     @PortraitLandscape
50     fun enterDesktopViaOverviewMenu() {
51         mLauncher.workspace.switchToOverview()
52         moveTaskToDesktop(TEST_ACTIVITY_2) // Move last launched TEST_ACTIVITY_2 into Desktop
53 
54         // Scroll back to TEST_ACTIVITY_1, then move it into Desktop
55         mLauncher
56             .goHome()
57             .switchToOverview()
58             .apply { flingForward() }
59             .also { moveTaskToDesktop(TEST_ACTIVITY_1) }
60         TEST_ACTIVITIES.forEach { assertTestAppLaunched(it) }
61 
62         // Launch static DesktopTaskView without live tile in Overview
63         val desktopTask =
64             mLauncher.goHome().switchToOverview().getTestActivityTask(TEST_ACTIVITIES).open()
65         TEST_ACTIVITIES.forEach { assertTestAppLaunched(it) }
66 
67         // Launch live-tile DesktopTaskView
68         desktopTask.switchToOverview().getTestActivityTask(TEST_ACTIVITIES).open()
69         TEST_ACTIVITIES.forEach { assertTestAppLaunched(it) }
70 
71         // Launch static DesktopTaskView with live tile in Overview
72         mLauncher.goHome()
73         startTestActivity(TEST_ACTIVITY_EXTRA)
74         mLauncher.launchedAppState
75             .switchToOverview()
76             .apply { flingBackward() }
77             .getTestActivityTask(TEST_ACTIVITIES)
78             .open()
79         TEST_ACTIVITIES.forEach { assertTestAppLaunched(it) }
80     }
81 
82     @Test
83     @PortraitLandscape
84     fun dismissFocusedTasks_thenDesktopIsCentered() {
85         // Create DesktopTaskView
86         mLauncher.goHome().switchToOverview()
87         moveTaskToDesktop(TEST_ACTIVITY_2)
88 
89         // Create a new task activity to be the focused task
90         mLauncher.goHome()
91         startTestActivity(TEST_ACTIVITY_EXTRA)
92 
93         val overview = mLauncher.goHome().switchToOverview()
94 
95         // Dismiss focused task
96         val focusedTask1 = overview.currentTask
97         assertTaskContentDescription(focusedTask1, TEST_ACTIVITY_EXTRA)
98         focusedTask1.dismiss()
99 
100         // Dismiss new focused task
101         val focusedTask2 = overview.currentTask
102         assertTaskContentDescription(focusedTask2, TEST_ACTIVITY_1)
103         focusedTask2.dismiss()
104 
105         // Dismiss DesktopTaskView
106         val desktopTask = overview.currentTask
107         assertWithMessage("The current task is not a Desktop.").that(desktopTask.isDesktop).isTrue()
108         desktopTask.dismiss()
109 
110         assertWithMessage("Still have tasks after dismissing all the tasks")
111             .that(mLauncher.workspace.switchToOverview().hasTasks())
112             .isFalse()
113     }
114 
115     @Test
116     @PortraitLandscape
117     fun dismissTasks_whenDesktopTask_IsInTheCenter() {
118         // Create extra activity to be DesktopTaskView
119         startTestActivity(TEST_ACTIVITY_EXTRA)
120         mLauncher.goHome().switchToOverview()
121 
122         val desktop = moveTaskToDesktop(TEST_ACTIVITY_EXTRA)
123         var overview = desktop.switchToOverview()
124 
125         // Open first fullscreen task and go back to Overview to validate whether it has adjacent
126         // tasks in its both sides (grid task on left and desktop tasks at its right side)
127         val firstFullscreenTaskOpened = overview.getTestActivityTask(TEST_ACTIVITY_2).open()
128 
129         // Fling to desktop task and dismiss the first fullscreen task to check repositioning of
130         // grid tasks.
131         overview = firstFullscreenTaskOpened.switchToOverview().apply { flingBackward() }
132         val desktopTask = overview.currentTask
133         assertWithMessage("The current task is not a Desktop.").that(desktopTask.isDesktop).isTrue()
134 
135         // Get first fullscreen task (previously opened task) then dismiss this task
136         val firstFullscreenTaskInOverview = overview.getTestActivityTask(TEST_ACTIVITY_2)
137         assertTaskContentDescription(firstFullscreenTaskInOverview, TEST_ACTIVITY_2)
138         firstFullscreenTaskInOverview.dismiss()
139 
140         // Dismiss DesktopTask to validate whether the new task will take its position
141         desktopTask.dismiss()
142 
143         // Dismiss last fullscreen task
144         val lastFocusedTask = overview.currentTask
145         assertTaskContentDescription(lastFocusedTask, TEST_ACTIVITY_1)
146         lastFocusedTask.dismiss()
147 
148         assertWithMessage("Still have tasks after dismissing all the tasks")
149             .that(mLauncher.workspace.switchToOverview().hasTasks())
150             .isFalse()
151     }
152 
153     private fun assertTaskContentDescription(task: OverviewTask, activityIndex: Int) {
154         assertWithMessage("The current task content description is not TestActivity$activityIndex.")
155             .that(task.containsContentDescription("TestActivity$activityIndex"))
156             .isTrue()
157     }
158 
159     private fun moveTaskToDesktop(activityIndex: Int): LaunchedAppState {
160         return mLauncher.overview
161             .getTestActivityTask(activityIndex)
162             .tapMenu()
163             .tapDesktopMenuItem()
164             .also { assertTestAppLaunched(activityIndex) }
165     }
166 
167     private fun startTestAppsWithCheck() {
168         TEST_ACTIVITIES.forEach {
169             startTestActivity(it)
170             executeOnLauncher { launcher ->
171                 assertWithMessage(
172                         "Launcher activity is the top activity; expecting TestActivity$it"
173                     )
174                     .that(isInLaunchedApp(launcher))
175                     .isTrue()
176             }
177         }
178     }
179 
180     private fun assertTestAppLaunched(index: Int) {
181         assertWithMessage("TestActivity$index not opened in Desktop")
182             .that(
183                 mDevice.wait(
184                     Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity$index")),
185                     TestUtil.DEFAULT_UI_TIMEOUT,
186                 )
187             )
188             .isTrue()
189     }
190 
191     companion object {
192         const val TEST_ACTIVITY_1 = 2
193         const val TEST_ACTIVITY_2 = 3
194         const val TEST_ACTIVITY_EXTRA = 4
195         val TEST_ACTIVITIES = listOf(TEST_ACTIVITY_1, TEST_ACTIVITY_2)
196     }
197 }
198