1 /*
2  * Copyright (C) 2023 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 android.tools.flicker.subject.wm
18 
19 import android.tools.PlatformConsts
20 import android.tools.Rotation
21 import android.tools.traces.component.IComponentMatcher
22 import android.tools.traces.wm.Activity
23 import android.tools.traces.wm.DisplayContent
24 import android.tools.traces.wm.WindowState
25 
26 /** Base interface for WM trace and state assertions */
27 interface IWindowManagerSubject<WMSubjectType, RegionSubjectType> {
28     /** Asserts the current WindowManager state doesn't contain [WindowState]s */
isEmptynull29     fun isEmpty(): WMSubjectType
30 
31     /** Asserts the current WindowManager state contains [WindowState]s */
32     fun isNotEmpty(): WMSubjectType
33 
34     /**
35      * Obtains the region occupied by all windows matching [componentMatcher]
36      *
37      * @param componentMatcher Components to search
38      */
39     fun visibleRegion(componentMatcher: IComponentMatcher? = null): RegionSubjectType
40 
41     /**
42      * Asserts the state contains a [WindowState] matching [componentMatcher] above the app windows
43      *
44      * @param componentMatcher Component to search
45      */
46     fun containsAboveAppWindow(componentMatcher: IComponentMatcher): WMSubjectType
47 
48     /**
49      * Asserts the state contains a [WindowState] matching [componentMatcher] below the app windows
50      *
51      * @param componentMatcher Component to search
52      */
53     fun containsBelowAppWindow(componentMatcher: IComponentMatcher): WMSubjectType
54 
55     /**
56      * Asserts the state contains [WindowState]s matching [aboveWindowComponentMatcher] and
57      * [belowWindowComponentMatcher], and that [aboveWindowComponentMatcher] is above
58      * [belowWindowComponentMatcher]
59      *
60      * This assertion can be used, for example, to assert that a PIP window is shown above other
61      * apps.
62      *
63      * @param aboveWindowComponentMatcher name of the window that should be above
64      * @param belowWindowComponentMatcher name of the window that should be below
65      */
66     fun isAboveWindow(
67         aboveWindowComponentMatcher: IComponentMatcher,
68         belowWindowComponentMatcher: IComponentMatcher
69     ): WMSubjectType
70 
71     /**
72      * Asserts the state contains a non-app [WindowState] matching [componentMatcher]
73      *
74      * @param componentMatcher Component to search
75      */
76     fun containsNonAppWindow(componentMatcher: IComponentMatcher): WMSubjectType
77 
78     /**
79      * Asserts the top visible app window in the state matches [componentMatcher]
80      *
81      * @param componentMatcher Component to search
82      */
83     fun isAppWindowOnTop(componentMatcher: IComponentMatcher): WMSubjectType
84 
85     /**
86      * Asserts the top visible app window in the state doesn't match [componentMatcher]
87      *
88      * @param componentMatcher Component to search
89      */
90     fun isAppWindowNotOnTop(componentMatcher: IComponentMatcher): WMSubjectType
91 
92     /**
93      * Asserts the bounds of the [WindowState] matching [componentMatcher] don't overlap.
94      *
95      * @param componentMatcher Component to search
96      */
97     fun doNotOverlap(vararg componentMatcher: IComponentMatcher): WMSubjectType
98 
99     /**
100      * Asserts the state contains an app [WindowState] matching [componentMatcher]
101      *
102      * @param componentMatcher Component to search
103      */
104     fun containsAppWindow(componentMatcher: IComponentMatcher): WMSubjectType
105 
106     /**
107      * Asserts the display with id [displayId] has rotation [rotation]
108      *
109      * @param rotation to assert
110      * @param displayId of the target display
111      */
112     fun hasRotation(
113         rotation: Rotation,
114         displayId: Int = PlatformConsts.DEFAULT_DISPLAY
115     ): WMSubjectType
116 
117     /**
118      * Asserts the state contains a [WindowState] matching [componentMatcher].
119      *
120      * @param componentMatcher Components to search
121      */
122     fun contains(componentMatcher: IComponentMatcher): WMSubjectType
123 
124     /**
125      * Asserts the state doesn't contain a [WindowState] nor an [Activity] matching
126      * [componentMatcher].
127      *
128      * @param componentMatcher Components to search
129      */
130     fun notContainsAppWindow(componentMatcher: IComponentMatcher): WMSubjectType
131 
132     /**
133      * Asserts the state doesn't contain a [WindowState] matching [componentMatcher].
134      *
135      * @param componentMatcher Components to search
136      */
137     fun notContains(componentMatcher: IComponentMatcher): WMSubjectType
138 
139     fun isRecentsActivityVisible(): WMSubjectType
140 
141     fun isRecentsActivityInvisible(): WMSubjectType
142 
143     /**
144      * Asserts the state is valid, that is, if it has:
145      * - a resumed activity
146      * - a focused activity
147      * - a focused window
148      * - a front window
149      * - a focused app
150      */
151     fun isValid(): WMSubjectType
152 
153     /**
154      * Asserts the state contains a visible [WindowState] matching [componentMatcher].
155      *
156      * Also, if [componentMatcher] has a package name (i.e., is not a system component), also checks
157      * that it contains a visible [Activity] matching [componentMatcher].
158      *
159      * @param componentMatcher Components to search
160      */
161     fun isNonAppWindowVisible(componentMatcher: IComponentMatcher): WMSubjectType
162 
163     /**
164      * Asserts the state contains a visible [WindowState] matching [componentMatcher].
165      *
166      * Also, if [componentMatcher] has a package name (i.e., is not a system component), also checks
167      * that it contains a visible [Activity] matching [componentMatcher].
168      *
169      * @param componentMatcher Components to search
170      */
171     fun isAppWindowVisible(componentMatcher: IComponentMatcher): WMSubjectType
172 
173     /** Asserts the state contains no visible app windows. */
174     fun hasNoVisibleAppWindow(): WMSubjectType
175 
176     /** Asserts the state contains no visible app windows. */
177     fun isKeyguardShowing(): WMSubjectType
178 
179     /**
180      * Asserts the state contains an invisible window [WindowState] matching [componentMatcher].
181      *
182      * Also, if [componentMatcher] has a package name (i.e., is not a system component), also checks
183      * that it contains an invisible [Activity] matching [componentMatcher].
184      *
185      * @param componentMatcher Components to search
186      */
187     fun isAppWindowInvisible(componentMatcher: IComponentMatcher): WMSubjectType
188 
189     /**
190      * Asserts the state contains an invisible window matching [componentMatcher].
191      *
192      * Also, if [componentMatcher] has a package name (i.e., is not a system component), also checks
193      * that it contains an invisible [Activity] matching [componentMatcher].
194      *
195      * @param componentMatcher Components to search
196      */
197     fun isNonAppWindowInvisible(componentMatcher: IComponentMatcher): WMSubjectType
198 
199     /** Asserts the state home activity is visible */
200     fun isHomeActivityVisible(): WMSubjectType
201 
202     /** Asserts the state home activity is invisible */
203     fun isHomeActivityInvisible(): WMSubjectType
204 
205     /**
206      * Asserts that [app] is the focused app
207      *
208      * @param app App to check
209      */
210     fun isFocusedApp(app: String): WMSubjectType
211 
212     /**
213      * Asserts that [app] is not the focused app
214      *
215      * @param app App to check
216      */
217     fun isNotFocusedApp(app: String): WMSubjectType
218 
219     /**
220      * Asserts that [componentMatcher] exists and is pinned (in PIP mode)
221      *
222      * @param componentMatcher Components to search
223      */
224     fun isPinned(componentMatcher: IComponentMatcher): WMSubjectType
225 
226     /**
227      * Asserts that [componentMatcher] exists and is not pinned (not in PIP mode)
228      *
229      * @param componentMatcher Components to search
230      */
231     fun isNotPinned(componentMatcher: IComponentMatcher): WMSubjectType
232 
233     /**
234      * Checks if the activity with matching [componentMatcher] is visible
235      *
236      * In the case that an app is stopped in the background (e.g. OS stopped it to release memory)
237      * the app window will not be immediately visible when switching back to the app. Checking if a
238      * snapshotStartingWindow is present for that app instead can decrease flakiness levels of the
239      * assertion.
240      *
241      * @param componentMatcher Component to search
242      */
243     fun isAppSnapshotStartingWindowVisibleFor(componentMatcher: IComponentMatcher): WMSubjectType
244 
245     /**
246      * Checks if the non-app window matching [componentMatcher] exists above the app windows and is
247      * visible
248      *
249      * @param componentMatcher Components to search
250      */
251     fun isAboveAppWindowVisible(componentMatcher: IComponentMatcher): WMSubjectType
252 
253     /**
254      * Checks if the non-app window matching [componentMatcher] exists above the app windows and is
255      * invisible
256      *
257      * @param componentMatcher Components to search
258      */
259     fun isAboveAppWindowInvisible(componentMatcher: IComponentMatcher): WMSubjectType
260 
261     /**
262      * Checks if the non-app window matching [componentMatcher] exists below the app windows and is
263      * visible
264      *
265      * @param componentMatcher Components to search
266      */
267     fun isBelowAppWindowVisible(componentMatcher: IComponentMatcher): WMSubjectType
268 
269     /**
270      * Checks if the non-app window matching [componentMatcher] exists below the app windows and is
271      * invisible
272      *
273      * @param componentMatcher Components to search
274      */
275     fun isBelowAppWindowInvisible(componentMatcher: IComponentMatcher): WMSubjectType
276 
277     /** Checks if the state contains at least one [DisplayContent] */
278     fun containsAtLeastOneDisplay(): WMSubjectType
279 }
280