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 com.android.server.wm.flicker.activityembedding.layoutchange
18 
19 import android.platform.test.annotations.Presubmit
20 import android.tools.common.datatypes.Rect
21 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
22 import android.tools.device.flicker.legacy.FlickerBuilder
23 import android.tools.device.flicker.legacy.LegacyFlickerTest
24 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
25 import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
26 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
27 import androidx.test.filters.RequiresDevice
28 import org.junit.FixMethodOrder
29 import org.junit.Test
30 import org.junit.runner.RunWith
31 import org.junit.runners.MethodSorters
32 import org.junit.runners.Parameterized
33 
34 /**
35  * Test changing split ratio at runtime on a horizona split.
36  *
37  * Setup: Launch A|B in horizontal split with B being the secondary activity, by default A and B
38  * windows are equal in size. B is on the top and A is on the bottom.
39  * Transitions:
40  * Change the split ratio to A:B=0.7:0.3, expect bounds change for both A and B.
41  *
42  * To run this test: `atest FlickerTestsOther:HorizontalSplitChangeRatioTest`
43  */
44 @RequiresDevice
45 @RunWith(Parameterized::class)
46 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
47 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
48 class HorizontalSplitChangeRatioTest(flicker: LegacyFlickerTest) :
49         ActivityEmbeddingTestBase(flicker) {
50     /** {@inheritDoc} */
51     override val transition: FlickerBuilder.() -> Unit = {
52         setup {
53             tapl.setExpectedRotationCheckEnabled(false)
54             testApp.launchViaIntent(wmHelper)
55             testApp.launchSecondaryActivityHorizontally(wmHelper)
56             startDisplayBounds =
57                     wmHelper.currentState.layerState.physicalDisplayBounds
58                             ?: error("Display not found")
59         }
60         transitions {
61             testApp.changeSecondaryActivityRatio(wmHelper)
62         }
63         teardown {
64             tapl.goHome()
65             testApp.exit(wmHelper)
66         }
67     }
68 
69     /** Assert the Main activity window is always visible. */
70     @Presubmit
71     @Test
72     fun mainActivityWindowIsAlwaysVisible() {
73         flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
74     }
75 
76     /** Assert the Main activity window is always visible. */
77     @Presubmit
78     @Test
79     fun mainActivityLayerIsAlwaysVisible() {
80         flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
81     }
82 
83     /** Assert the Secondary activity window is always visible. */
84     @Presubmit
85     @Test
86     fun secondaryActivityWindowIsAlwaysVisible() {
87         flicker.assertWm {
88             isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) }
89     }
90 
91     /** Assert the Secondary activity window is always visible. */
92     @Presubmit
93     @Test
94     fun secondaryActivityLayerIsAlwaysVisible() {
95         flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) }
96     }
97 
98     /** Assert the Main and Secondary activity change height during the transition. */
99     @Presubmit
100     @Test
101     fun secondaryActivityAdjustsHeightRuntime() {
102         flicker.assertLayersStart {
103             val topLayerRegion =
104                     this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
105             val bottomLayerRegion =
106                     this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
107             // Compare dimensions of two splits, given we're using default split attributes,
108             // both activities take up the same visible size on the display.
109             check { "height" }
110                     .that(topLayerRegion.region.height).isEqual(bottomLayerRegion.region.height)
111             check { "width" }
112                     .that(topLayerRegion.region.width).isEqual(bottomLayerRegion.region.width)
113             topLayerRegion.notOverlaps(bottomLayerRegion.region)
114             // Layers of two activities sum to be fullscreen size on display.
115             topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
116         }
117 
118         flicker.assertLayersEnd {
119             val topLayerRegion =
120                     this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
121             val bottomLayerRegion =
122                     this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
123             // Compare dimensions of two splits, given we're using default split attributes,
124             // both activities take up the same visible size on the display.
125             check { "height" }
126                     .that(topLayerRegion.region.height).isLower(bottomLayerRegion.region.height)
127             check { "height" }
128                     .that(
129                             topLayerRegion.region.height / 0.3f -
130                                     bottomLayerRegion.region.height / 0.7f)
131                     .isLower(0.1f)
132             check { "width" }
133                     .that(topLayerRegion.region.width).isEqual(bottomLayerRegion.region.width)
134             topLayerRegion.notOverlaps(bottomLayerRegion.region)
135             // Layers of two activities sum to be fullscreen size on display.
136             topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
137         }
138     }
139 
140     companion object {
141         /** {@inheritDoc} */
142         private var startDisplayBounds = Rect.EMPTY
143         /**
144          * Creates the test configurations.
145          *
146          * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
147          * navigation modes.
148          */
149         @Parameterized.Parameters(name = "{0}")
150         @JvmStatic
151         fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
152     }
153 }