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.assertors.assertions
18 
19 import android.graphics.Region
20 import android.tools.flicker.ScenarioInstance
21 import android.tools.flicker.assertions.FlickerTest
22 import android.tools.flicker.assertors.ComponentTemplate
23 import android.tools.flicker.config.splitscreen.Components.SPLIT_SCREEN_DIVIDER
24 import android.tools.flicker.subject.layers.LayerTraceEntrySubject
25 import android.tools.flicker.subject.layers.LayersTraceSubject
26 import android.tools.traces.component.IComponentMatcher
27 
28 class SplitAppLayerBoundsBecomesVisible(
29     private val component: ComponentTemplate,
30     val isPrimaryApp: Boolean
31 ) : AssertionTemplateWithComponent(component) {
doEvaluatenull32     override fun doEvaluate(scenarioInstance: ScenarioInstance, flicker: FlickerTest) {
33         val splitScreenDivider = SPLIT_SCREEN_DIVIDER.build(scenarioInstance)
34         val app = component.build(scenarioInstance)
35 
36         val landscapePosLeft: Boolean
37         val portraitPosTop: Boolean
38         if (isPrimaryApp) {
39             landscapePosLeft = false
40             portraitPosTop = false
41         } else {
42             // secondaryApp
43             landscapePosLeft = true
44             portraitPosTop = true
45         }
46 
47         flicker.assertLayers {
48             notContains(splitScreenDivider.or(app), isOptional = true)
49                 .then()
50                 .isInvisible(splitScreenDivider.or(app))
51                 .then()
52                 .splitAppLayerBoundsSnapToDivider(
53                     app,
54                     splitScreenDivider,
55                     landscapePosLeft,
56                     portraitPosTop
57                 )
58         }
59     }
60 
61     companion object {
splitAppLayerBoundsSnapToDividernull62         fun LayersTraceSubject.splitAppLayerBoundsSnapToDivider(
63             component: IComponentMatcher,
64             splitScreenDivider: IComponentMatcher,
65             landscapePosLeft: Boolean,
66             portraitPosTop: Boolean
67         ): LayersTraceSubject {
68             return invoke("splitAppLayerBoundsSnapToDivider") {
69                 it.splitAppLayerBoundsSnapToDivider(
70                     component,
71                     splitScreenDivider,
72                     landscapePosLeft,
73                     portraitPosTop
74                 )
75             }
76         }
77 
LayerTraceEntrySubjectnull78         private fun LayerTraceEntrySubject.splitAppLayerBoundsSnapToDivider(
79             component: IComponentMatcher,
80             splitScreenDivider: IComponentMatcher,
81             landscapePosLeft: Boolean,
82             portraitPosTop: Boolean
83         ): LayerTraceEntrySubject {
84             val activeDisplay =
85                 this.entry.displays.firstOrNull { it.isOn && !it.isVirtual }
86                     ?: error("No non-virtual and on display found")
87 
88             return invoke {
89                 val dividerRegion =
90                     layer(splitScreenDivider)?.visibleRegion?.region
91                         ?: error("$splitScreenDivider component not found")
92                 visibleRegion(component)
93                     .coversAtMost(
94                         if (
95                             activeDisplay.layerStackSpace.width() >
96                                 activeDisplay.layerStackSpace.height()
97                         ) {
98                             if (landscapePosLeft) {
99                                 Region(
100                                     0,
101                                     0,
102                                     (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
103                                     activeDisplay.layerStackSpace.bottom
104                                 )
105                             } else {
106                                 Region(
107                                     (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
108                                     0,
109                                     activeDisplay.layerStackSpace.right,
110                                     activeDisplay.layerStackSpace.bottom
111                                 )
112                             }
113                         } else {
114                             if (portraitPosTop) {
115                                 Region(
116                                     0,
117                                     0,
118                                     activeDisplay.layerStackSpace.right,
119                                     (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2
120                                 )
121                             } else {
122                                 Region(
123                                     0,
124                                     (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2,
125                                     activeDisplay.layerStackSpace.right,
126                                     activeDisplay.layerStackSpace.bottom
127                                 )
128                             }
129                         }
130                     )
131             }
132         }
133     }
134 }
135