• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.common.flicker.subject.surfaceflinger
18 
19 import android.tools.TestComponents
20 import android.tools.assertFail
21 import android.tools.assertThatErrorContainsDebugInfo
22 import android.tools.assertThrows
23 import android.tools.common.Cache
24 import android.tools.common.datatypes.Rect
25 import android.tools.common.datatypes.Region
26 import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject
27 import android.tools.common.flicker.subject.layers.LayersTraceSubject
28 import android.tools.common.traces.component.ComponentNameMatcher
29 import android.tools.common.traces.component.OrComponentMatcher
30 import android.tools.getLayerTraceReaderFromAsset
31 import android.tools.rules.CleanFlickerEnvironmentRule
32 import android.tools.utils.MockLayerBuilder
33 import android.tools.utils.MockLayerTraceEntryBuilder
34 import com.google.common.truth.Truth
35 import org.junit.Before
36 import org.junit.ClassRule
37 import org.junit.FixMethodOrder
38 import org.junit.Test
39 import org.junit.runners.MethodSorters
40 
41 /**
42  * Contains [LayerTraceEntrySubject] tests. To run this test: `atest
43  * FlickerLibTest:LayerTraceEntrySubjectTest`
44  */
45 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
46 class LayerTraceEntrySubjectTest {
47     @Before
beforenull48     fun before() {
49         Cache.clear()
50     }
51 
52     @Test
exceptionContainsDebugInfonull53     fun exceptionContainsDebugInfo() {
54         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
55         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
56         val error =
57             assertThrows<AssertionError> {
58                 LayersTraceSubject(trace, reader).first().visibleRegion(TestComponents.IMAGINARY)
59             }
60         assertThatErrorContainsDebugInfo(error)
61         Truth.assertThat(error).hasMessageThat().contains(TestComponents.IMAGINARY.className)
62     }
63 
64     @Test
testCanInspectBeginningnull65     fun testCanInspectBeginning() {
66         val reader =
67             getLayerTraceReaderFromAsset("layers_trace_launch_split_screen.pb", legacyTrace = true)
68         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
69         LayerTraceEntrySubject(trace.entries.first(), reader)
70             .isVisible(ComponentNameMatcher.NAV_BAR)
71             .notContains(TestComponents.DOCKER_STACK_DIVIDER)
72             .isVisible(TestComponents.LAUNCHER)
73     }
74 
75     @Test
testCanInspectEndnull76     fun testCanInspectEnd() {
77         val reader =
78             getLayerTraceReaderFromAsset("layers_trace_launch_split_screen.pb", legacyTrace = true)
79         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
80         LayerTraceEntrySubject(trace.entries.last(), reader)
81             .isVisible(ComponentNameMatcher.NAV_BAR)
82             .isVisible(TestComponents.DOCKER_STACK_DIVIDER)
83     }
84 
85     // b/75276931
86     @Test
canDetectUncoveredRegionnull87     fun canDetectUncoveredRegion() {
88         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
89         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
90         val expectedRegion = Region.from(0, 0, 1440, 2960)
91         assertFail("SkRegion((0,0,1440,1440)) should cover at least SkRegion((0,0,1440,2960))") {
92             LayersTraceSubject(trace, reader)
93                 .getEntryBySystemUpTime(935346112030, byElapsedTimestamp = true)
94                 .visibleRegion()
95                 .coversAtLeast(expectedRegion)
96         }
97     }
98 
99     // Visible region tests
100     @Test
canTestLayerVisibleRegion_layerDoesNotExistnull101     fun canTestLayerVisibleRegion_layerDoesNotExist() {
102         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
103         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
104         val expectedVisibleRegion = Region.from(0, 0, 1, 1)
105         assertFail(TestComponents.IMAGINARY.toWindowIdentifier()) {
106             LayersTraceSubject(trace, reader)
107                 .getEntryBySystemUpTime(937229257165, byElapsedTimestamp = true)
108                 .visibleRegion(TestComponents.IMAGINARY)
109                 .coversExactly(expectedVisibleRegion)
110         }
111     }
112 
113     @Test
canTestLayerVisibleRegion_layerDoesNotHaveExpectedVisibleRegionnull114     fun canTestLayerVisibleRegion_layerDoesNotHaveExpectedVisibleRegion() {
115         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
116         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
117         val expectedVisibleRegion = Region.from(0, 0, 1, 1)
118         assertFail("[empty] should cover exactly SkRegion((0,0,1,1))") {
119             LayersTraceSubject(trace, reader)
120                 .getEntryBySystemUpTime(937126074082, byElapsedTimestamp = true)
121                 .visibleRegion(TestComponents.DOCKER_STACK_DIVIDER)
122                 .coversExactly(expectedVisibleRegion)
123         }
124     }
125 
126     @Test
canTestLayerVisibleRegion_layerIsHiddenByParentnull127     fun canTestLayerVisibleRegion_layerIsHiddenByParent() {
128         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
129         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
130         val expectedVisibleRegion = Region.from(0, 0, 1, 1)
131         assertFail("[empty] should cover exactly SkRegion((0,0,1,1))") {
132             LayersTraceSubject(trace, reader)
133                 .getEntryBySystemUpTime(935346112030, byElapsedTimestamp = true)
134                 .visibleRegion(TestComponents.SIMPLE_APP)
135                 .coversExactly(expectedVisibleRegion)
136         }
137     }
138 
139     @Test
canTestLayerVisibleRegion_incorrectRegionSizenull140     fun canTestLayerVisibleRegion_incorrectRegionSize() {
141         val reader = getLayerTraceReaderFromAsset("layers_trace_emptyregion.pb", legacyTrace = true)
142         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
143         val expectedVisibleRegion = Region.from(0, 0, 1440, 99)
144         assertFail("SkRegion((0,0,1440,171)) should cover exactly SkRegion((0,0,1440,99))") {
145             LayersTraceSubject(trace, reader)
146                 .getEntryBySystemUpTime(937126074082, byElapsedTimestamp = true)
147                 .visibleRegion(ComponentNameMatcher.STATUS_BAR)
148                 .coversExactly(expectedVisibleRegion)
149         }
150     }
151 
152     @Test
canTestLayerVisibleRegionnull153     fun canTestLayerVisibleRegion() {
154         val reader =
155             getLayerTraceReaderFromAsset("layers_trace_launch_split_screen.pb", legacyTrace = true)
156         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
157         val expectedVisibleRegion = Region.from(0, 0, 1080, 145)
158         LayersTraceSubject(trace, reader)
159             .getEntryBySystemUpTime(90480846872160, byElapsedTimestamp = true)
160             .visibleRegion(ComponentNameMatcher.STATUS_BAR)
161             .coversExactly(expectedVisibleRegion)
162     }
163 
164     @Test
canTestLayerVisibleRegion_layerIsNotVisiblenull165     fun canTestLayerVisibleRegion_layerIsNotVisible() {
166         val reader =
167             getLayerTraceReaderFromAsset(
168                 "layers_trace_invalid_layer_visibility.pb",
169                 legacyTrace = true
170             )
171         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
172         assertFail("Bounds is 0x0") {
173             LayersTraceSubject(trace, reader)
174                 .getEntryBySystemUpTime(252794268378458, byElapsedTimestamp = true)
175                 .isVisible(TestComponents.SIMPLE_APP)
176         }
177     }
178 
179     @Test
orComponentMatcher_visibility_oneVisibleOtherInvisiblenull180     fun orComponentMatcher_visibility_oneVisibleOtherInvisible() {
181         val app1Name = "com.simple.test.app1"
182         val app2Name = "com.simple.test.app2"
183 
184         val layerTraceEntry =
185             MockLayerTraceEntryBuilder()
186                 .addDisplay(
187                     rootLayers =
188                         listOf(
189                             MockLayerBuilder(app1Name)
190                                 .setContainerLayer()
191                                 .addChild(MockLayerBuilder(app1Name).setVisible()),
192                             MockLayerBuilder(app2Name)
193                                 .setContainerLayer()
194                                 .addChild(MockLayerBuilder(app2Name).setInvisible()),
195                         )
196                 )
197                 .build()
198 
199         val subject = LayerTraceEntrySubject(layerTraceEntry)
200         val component =
201             OrComponentMatcher(
202                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
203             )
204 
205         subject.isVisible(ComponentNameMatcher(app1Name))
206         subject.isInvisible(ComponentNameMatcher(app2Name))
207 
208         subject.isInvisible(component)
209         subject.isVisible(component)
210     }
211 
212     @Test
orComponentMatcher_visibility_oneVisibleOtherMissingnull213     fun orComponentMatcher_visibility_oneVisibleOtherMissing() {
214         val app1Name = "com.simple.test.app1"
215         val app2Name = "com.simple.test.app2"
216 
217         val layerTraceEntry =
218             MockLayerTraceEntryBuilder()
219                 .addDisplay(
220                     rootLayers =
221                         listOf(
222                             MockLayerBuilder(app1Name)
223                                 .setContainerLayer()
224                                 .addChild(MockLayerBuilder(app1Name).setVisible())
225                         )
226                 )
227                 .build()
228 
229         val subject = LayerTraceEntrySubject(layerTraceEntry)
230         val component =
231             OrComponentMatcher(
232                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
233             )
234 
235         subject.isVisible(ComponentNameMatcher(app1Name))
236         subject.notContains(ComponentNameMatcher(app2Name))
237 
238         subject.isInvisible(component)
239         subject.isVisible(component)
240     }
241 
242     @Test
canUseOrComponentMatcher_visibility_allVisiblenull243     fun canUseOrComponentMatcher_visibility_allVisible() {
244         val app1Name = "com.simple.test.app1"
245         val app2Name = "com.simple.test.app2"
246 
247         val layerTraceEntry =
248             MockLayerTraceEntryBuilder()
249                 .addDisplay(
250                     rootLayers =
251                         listOf(
252                             MockLayerBuilder(app1Name)
253                                 .setContainerLayer()
254                                 .setAbsoluteBounds(Rect.from(0, 0, 200, 200))
255                                 .addChild(MockLayerBuilder("$app1Name child").setVisible()),
256                             MockLayerBuilder(app2Name)
257                                 .setContainerLayer()
258                                 .setAbsoluteBounds(Rect.from(200, 200, 400, 400))
259                                 .addChild(MockLayerBuilder("$app2Name child").setVisible()),
260                         )
261                 )
262                 .build()
263 
264         val subject = LayerTraceEntrySubject(layerTraceEntry)
265         val component =
266             OrComponentMatcher(
267                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
268             )
269 
270         subject.isVisible(ComponentNameMatcher(app1Name))
271         subject.isVisible(ComponentNameMatcher(app2Name))
272 
273         assertThrows<AssertionError> { subject.isInvisible(component) }
274         subject.isVisible(component)
275     }
276 
277     @Test
canUseOrComponentMatcher_contains_withOneExistsnull278     fun canUseOrComponentMatcher_contains_withOneExists() {
279         val app1Name = "com.simple.test.app1"
280         val app2Name = "com.simple.test.app2"
281 
282         val layerTraceEntry =
283             MockLayerTraceEntryBuilder()
284                 .addDisplay(
285                     rootLayers =
286                         listOf(
287                             MockLayerBuilder(app1Name)
288                                 .setContainerLayer()
289                                 .addChild(MockLayerBuilder(app1Name))
290                         )
291                 )
292                 .build()
293 
294         val subject = LayerTraceEntrySubject(layerTraceEntry)
295         val component =
296             OrComponentMatcher(
297                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
298             )
299 
300         subject.contains(ComponentNameMatcher(app1Name))
301         subject.notContains(ComponentNameMatcher(app2Name))
302 
303         subject.contains(component)
304 
305         assertFail("Found: com.simple.test.app1") { subject.notContains(component) }
306     }
307 
308     @Test
canUseOrComponentMatcher_contains_withNoneExistsnull309     fun canUseOrComponentMatcher_contains_withNoneExists() {
310         val app1Name = "com.simple.test.app1"
311         val app2Name = "com.simple.test.app2"
312 
313         val layerTraceEntry = MockLayerTraceEntryBuilder().addDisplay(rootLayers = listOf()).build()
314 
315         val subject = LayerTraceEntrySubject(layerTraceEntry)
316         val component =
317             OrComponentMatcher(
318                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
319             )
320 
321         subject.notContains(ComponentNameMatcher(app1Name))
322         subject.notContains(ComponentNameMatcher(app2Name))
323 
324         subject.notContains(component)
325         assertThrows<AssertionError> { subject.contains(component) }
326     }
327 
328     @Test
canUseOrComponentMatcher_contains_withBothExistsnull329     fun canUseOrComponentMatcher_contains_withBothExists() {
330         val app1Name = "com.simple.test.app1"
331         val app2Name = "com.simple.test.app2"
332 
333         val layerTraceEntry =
334             MockLayerTraceEntryBuilder()
335                 .addDisplay(
336                     rootLayers =
337                         listOf(
338                             MockLayerBuilder(app1Name)
339                                 .setContainerLayer()
340                                 .addChild(MockLayerBuilder(app1Name)),
341                             MockLayerBuilder(app2Name)
342                                 .setContainerLayer()
343                                 .addChild(MockLayerBuilder(app2Name)),
344                         )
345                 )
346                 .build()
347 
348         val subject = LayerTraceEntrySubject(layerTraceEntry)
349         val component =
350             OrComponentMatcher(
351                 arrayOf(ComponentNameMatcher(app1Name), ComponentNameMatcher(app2Name))
352             )
353 
354         subject.contains(ComponentNameMatcher(app1Name))
355         subject.contains(ComponentNameMatcher(app2Name))
356 
357         assertThrows<AssertionError> { subject.notContains(component) }
358         subject.contains(component)
359     }
360 
361     @Test
detectOccludedLayerBecauseOfRoundedCornersnull362     fun detectOccludedLayerBecauseOfRoundedCorners() {
363         val reader = getLayerTraceReaderFromAsset("layers_trace_rounded_corners.winscope")
364         val trace = reader.readLayersTrace() ?: error("Unable to read layers trace")
365         val entry =
366             LayersTraceSubject(trace, reader)
367                 .getEntryBySystemUpTime(6216612368228, byElapsedTimestamp = true)
368         val defaultPkg = "com.android.server.wm.flicker.testapp"
369         val simpleActivityMatcher =
370             ComponentNameMatcher(defaultPkg, "$defaultPkg.SimpleActivity#66086")
371         val imeActivityMatcher = ComponentNameMatcher(defaultPkg, "$defaultPkg.ImeActivity#66060")
372         val simpleActivitySubject =
373             entry.layer(simpleActivityMatcher) ?: error("Layer should be available")
374         val imeActivitySubject =
375             entry.layer(imeActivityMatcher) ?: error("Layer should be available")
376         val simpleActivityLayer = simpleActivitySubject.layer
377         val imeActivityLayer = imeActivitySubject.layer
378         // both layers have the same region
379         imeActivitySubject.visibleRegion.coversExactly(simpleActivitySubject.visibleRegion.region)
380         // both are visible
381         entry.isInvisible(simpleActivityMatcher)
382         entry.isVisible(imeActivityMatcher)
383         // and simple activity is partially covered by IME activity
384         Truth.assertWithMessage("IME activity has rounded corners")
385             .that(simpleActivityLayer.occludedBy)
386             .asList()
387             .contains(imeActivityLayer)
388         // because IME activity has rounded corners
389         Truth.assertWithMessage("IME activity has rounded corners")
390             .that(imeActivityLayer.cornerRadius)
391             .isGreaterThan(0)
392     }
393 
394     companion object {
395         @ClassRule @JvmField val ENV_CLEANUP = CleanFlickerEnvironmentRule()
396     }
397 }
398