1 /*
2  * Copyright (C) 2020 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.wm.shell.flicker.pip
18 
19 import android.platform.test.annotations.Presubmit
20 import android.view.Surface
21 import androidx.test.filters.FlakyTest
22 import androidx.test.filters.RequiresDevice
23 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
24 import com.android.server.wm.flicker.FlickerTestParameter
25 import com.android.server.wm.flicker.FlickerTestParameterFactory
26 import com.android.server.wm.flicker.annotation.Group4
27 import com.android.server.wm.flicker.dsl.FlickerBuilder
28 import com.android.server.wm.flicker.endRotation
29 import com.android.server.wm.flicker.entireScreenCovered
30 import com.android.server.wm.flicker.helpers.WindowUtils
31 import com.android.server.wm.flicker.helpers.setRotation
32 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
33 import com.android.server.wm.flicker.startRotation
34 import com.android.server.wm.flicker.statusBarLayerRotatesScales
35 import com.android.wm.shell.flicker.helpers.FixedAppHelper
36 import org.junit.FixMethodOrder
37 import org.junit.Test
38 import org.junit.runner.RunWith
39 import org.junit.runners.MethodSorters
40 import org.junit.runners.Parameterized
41 
42 /**
43  * Test Pip Stack in bounds after rotations.
44  *
45  * To run this test: `atest WMShellFlickerTests:PipRotationTest`
46  *
47  * Actions:
48  *     Launch a [pipApp] in pip mode
49  *     Launch another app [fixedApp] (appears below pip)
50  *     Rotate the screen from [testSpec.config.startRotation] to [testSpec.config.endRotation]
51  *     (usually, 0->90 and 90->0)
52  *
53  * Notes:
54  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
55  *        are inherited from [PipTransition]
56  *     2. Part of the test setup occurs automatically via
57  *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
58  *        including configuring navigation mode, initial orientation and ensuring no
59  *        apps are running before setup
60  */
61 @RequiresDevice
62 @RunWith(Parameterized::class)
63 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
64 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
65 @Group4
66 class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
67     private val fixedApp = FixedAppHelper(instrumentation)
68     private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
69     private val screenBoundsEnd = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
70 
71     override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
72         get() = buildTransition(eachRun = false) { configuration ->
73             setup {
74                 test {
75                     fixedApp.launchViaIntent(wmHelper)
76                 }
77                 eachRun {
78                     setRotation(configuration.startRotation)
79                 }
80             }
81             transitions {
82                 setRotation(configuration.endRotation)
83             }
84         }
85 
86     /**
87      * Checks that all parts of the screen are covered at the start and end of the transition
88      */
89     @Presubmit
90     @Test
91     override fun entireScreenCovered() = testSpec.entireScreenCovered()
92 
93     /**
94      * Checks the position of the navigation bar at the start and end of the transition
95      */
96     @FlakyTest
97     @Test
98     override fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
99 
100     /**
101      * Checks the position of the status bar at the start and end of the transition
102      */
103     @Presubmit
104     @Test
105     override fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
106 
107     /**
108      * Checks that [fixedApp] layer is within [screenBoundsStart] at the start of the transition
109      */
110     @Presubmit
111     @Test
112     fun appLayerRotates_StartingBounds() {
113         testSpec.assertLayersStart {
114             visibleRegion(fixedApp.component).coversExactly(screenBoundsStart)
115         }
116     }
117 
118     /**
119      * Checks that [fixedApp] layer is within [screenBoundsEnd] at the end of the transition
120      */
121     @Presubmit
122     @Test
123     fun appLayerRotates_EndingBounds() {
124         testSpec.assertLayersEnd {
125             visibleRegion(fixedApp.component).coversExactly(screenBoundsEnd)
126         }
127     }
128 
129     /**
130      * Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition
131      */
132     @Presubmit
133     @Test
134     fun pipLayerRotates_StartingBounds() {
135         testSpec.assertLayersStart {
136             visibleRegion(pipApp.component).coversAtMost(screenBoundsStart)
137         }
138     }
139 
140     /**
141      * Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition
142      */
143     @Presubmit
144     @Test
145     fun pipLayerRotates_EndingBounds() {
146         testSpec.assertLayersEnd {
147             visibleRegion(pipApp.component).coversAtMost(screenBoundsEnd)
148         }
149     }
150 
151     /**
152      * Ensure that the [pipApp] window does not obscure the [fixedApp] at the start of the
153      * transition
154      */
155     @Presubmit
156     @Test
157     fun pipIsAboveFixedAppWindow_Start() {
158         testSpec.assertWmStart {
159             isAboveWindow(pipApp.component, fixedApp.component)
160         }
161     }
162 
163     /**
164      * Ensure that the [pipApp] window does not obscure the [fixedApp] at the end of the
165      * transition
166      */
167     @Presubmit
168     @Test
169     fun pipIsAboveFixedAppWindow_End() {
170         testSpec.assertWmEnd {
171             isAboveWindow(pipApp.component, fixedApp.component)
172         }
173     }
174 
175     companion object {
176         /**
177          * Creates the test configurations.
178          *
179          * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
180          * repetitions, screen orientation and navigation modes.
181          */
182         @Parameterized.Parameters(name = "{0}")
183         @JvmStatic
184         fun getParams(): Collection<FlickerTestParameter> {
185             return FlickerTestParameterFactory.getInstance().getConfigRotationTests(
186                 supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
187                 repetitions = 5)
188         }
189     }
190 }
191