1 /*
2 * Copyright (C) 2019 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20
21 #include "LayerTransactionTest.h"
22
23 namespace android {
24
25 using android::hardware::graphics::common::V1_1::BufferUsage;
26
27 ::testing::Environment* const binderEnv =
28 ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
29
30 class RelativeZTest : public LayerTransactionTest {
31 protected:
SetUp()32 virtual void SetUp() {
33 LayerTransactionTest::SetUp();
34 ASSERT_EQ(NO_ERROR, mClient->initCheck());
35
36 const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
37 ASSERT_FALSE(ids.empty());
38 const auto display = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
39 ASSERT_FALSE(display == nullptr);
40
41 // Back layer
42 mBackgroundLayer = createColorLayer("Background layer", Color::RED);
43
44 // Front layer
45 mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
46
47 asTransaction([&](Transaction& t) {
48 t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
49 t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
50 t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
51 });
52 }
53
TearDown()54 virtual void TearDown() {
55 LayerTransactionTest::TearDown();
56 mBackgroundLayer = 0;
57 mForegroundLayer = 0;
58 }
59
60 sp<SurfaceControl> mBackgroundLayer;
61 sp<SurfaceControl> mForegroundLayer;
62 };
63
64 // When a layer is reparented offscreen, remove relative z order if the relative parent
65 // is still onscreen so that the layer is not drawn.
TEST_F(RelativeZTest,LayerRemoved)66 TEST_F(RelativeZTest, LayerRemoved) {
67 std::unique_ptr<ScreenCapture> sc;
68
69 // Background layer (RED)
70 // Child layer (WHITE) (relative to foregroud layer)
71 // Foregroud layer (GREEN)
72 sp<SurfaceControl> childLayer =
73 createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
74
75 Transaction{}.setRelativeLayer(childLayer, mForegroundLayer, 1).show(childLayer).apply();
76
77 {
78 // The childLayer should be in front of the FG control.
79 ScreenCapture::captureScreen(&sc);
80 sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
81 }
82
83 // Background layer (RED)
84 // Foregroud layer (GREEN)
85 Transaction{}.reparent(childLayer, nullptr).apply();
86
87 // Background layer (RED)
88 // Child layer (WHITE)
89 // Foregroud layer (GREEN)
90 Transaction{}.reparent(childLayer, mBackgroundLayer).apply();
91
92 {
93 // The relative z info for child layer should be reset, leaving FG control on top.
94 ScreenCapture::captureScreen(&sc);
95 sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
96 }
97 }
98
99 // When a layer is reparented offscreen, preseve relative z order if the relative parent
100 // is also offscreen. Regression test b/132613412
TEST_F(RelativeZTest,LayerRemovedOffscreenRelativeParent)101 TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
102 std::unique_ptr<ScreenCapture> sc;
103
104 // Background layer (RED)
105 // Foregroud layer (GREEN)
106 // child level 1 (WHITE)
107 // child level 2a (BLUE)
108 // child level 3 (GREEN) (relative to child level 2b)
109 // child level 2b (BLACK)
110 sp<SurfaceControl> childLevel1 =
111 createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
112 sp<SurfaceControl> childLevel2a =
113 createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
114 sp<SurfaceControl> childLevel2b =
115 createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
116 sp<SurfaceControl> childLevel3 =
117 createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
118
119 Transaction{}
120 .setRelativeLayer(childLevel3, childLevel2b, 1)
121 .show(childLevel2a)
122 .show(childLevel2b)
123 .show(childLevel3)
124 .apply();
125
126 {
127 // The childLevel3 should be in front of childLevel2b.
128 ScreenCapture::captureScreen(&sc);
129 sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
130 }
131
132 // Background layer (RED)
133 // Foregroud layer (GREEN)
134 Transaction{}.reparent(childLevel1, nullptr).apply();
135
136 // Background layer (RED)
137 // Foregroud layer (GREEN)
138 // child level 1 (WHITE)
139 // child level 2 back (BLUE)
140 // child level 3 (GREEN) (relative to child level 2b)
141 // child level 2 front (BLACK)
142 Transaction{}.reparent(childLevel1, mForegroundLayer).apply();
143
144 {
145 // Nothing should change at this point since relative z info was preserved.
146 ScreenCapture::captureScreen(&sc);
147 sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
148 }
149 }
150
TEST_F(RelativeZTest,LayerAndRelativeRemoved)151 TEST_F(RelativeZTest, LayerAndRelativeRemoved) {
152 std::unique_ptr<ScreenCapture> sc;
153
154 // Background layer (RED)
155 // Foregroud layer (GREEN)
156 // Child layer (BLUE) (relative to relativeToLayer layer)
157 // Relative layer (WHITE)
158 sp<SurfaceControl> childLayer =
159 createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get());
160 sp<SurfaceControl> relativeToLayer =
161 createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get());
162
163 Transaction{}
164 .setRelativeLayer(childLayer, relativeToLayer, 1)
165 .show(childLayer)
166 .show(relativeToLayer)
167 .apply();
168
169 {
170 // The childLayer should be in front of relativeToLayer.
171 ScreenCapture::captureScreen(&sc);
172 sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
173 }
174
175 // Remove layer that childLayer is relative to
176 // Background layer (RED)
177 // Foregroud layer (GREEN)
178 // Child layer (BLUE) (relative to relativeToLayer layer)
179 Transaction{}.reparent(relativeToLayer, nullptr).apply();
180 relativeToLayer = 0;
181
182 {
183 // The child layer is relative to an deleted layer so it won't be drawn.
184 ScreenCapture::captureScreen(&sc);
185 sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
186 }
187
188 // Background layer (RED)
189 // Foregroud layer (GREEN)
190 Transaction{}.reparent(childLayer, nullptr).apply();
191
192 {
193 // The child layer is offscreen, so it won't be drawn.
194 ScreenCapture::captureScreen(&sc);
195 sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
196 }
197
198 // Background layer (RED)
199 // Foregroud layer (GREEN)
200 // Child layer (BLUE)
201 Transaction{}.reparent(childLayer, mForegroundLayer).apply();
202
203 {
204 // The relative z info for child layer should be reset, leaving the child layer on top.
205 ScreenCapture::captureScreen(&sc);
206 sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
207 }
208 }
209
210 // Preserve the relative z order when a layer is reparented to a layer that's already offscreen
TEST_F(RelativeZTest,LayerWithRelativeReparentedToOffscreen)211 TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) {
212 std::unique_ptr<ScreenCapture> sc;
213
214 Color testLayerColor = {255, 100, 0, 255};
215
216 // Background layer (RED)
217 // Foregroud layer (GREEN)
218 // child level 1a (testLayerColor) (relative to child level 2b)
219 // child level 1b (WHITE)
220 // child level 2a (BLUE)
221 // child level 2b (BLACK)
222 sp<SurfaceControl> childLevel1a =
223 createColorLayer("child level 1a", testLayerColor, mForegroundLayer.get());
224 sp<SurfaceControl> childLevel1b =
225 createColorLayer("child level 1b", Color::WHITE, mForegroundLayer.get());
226 sp<SurfaceControl> childLevel2a =
227 createColorLayer("child level 2a", Color::BLUE, childLevel1b.get());
228 sp<SurfaceControl> childLevel2b =
229 createColorLayer("child level 2b", Color::BLACK, childLevel1b.get());
230
231 Transaction{}
232 .setRelativeLayer(childLevel1a, childLevel2b, 1)
233 .show(childLevel1a)
234 .show(childLevel1b)
235 .show(childLevel2a)
236 .show(childLevel2b)
237 .apply();
238
239 {
240 // The childLevel1a should be in front of childLevel2b.
241 ScreenCapture::captureScreen(&sc);
242 sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor);
243 }
244
245 // Background layer (RED)
246 // Foregroud layer (GREEN)
247 // child level 1a (testLayerColor) (relative to child level 2b)
248 Transaction{}.reparent(childLevel1b, nullptr).apply();
249
250 // // Background layer (RED)
251 // // Foregroud layer (GREEN)
252 Transaction{}.reparent(childLevel1a, childLevel2a).apply();
253
254 {
255 // The childLevel1a and childLevel1b are no longer on screen
256 ScreenCapture::captureScreen(&sc);
257 sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::GREEN);
258 }
259
260 // Background layer (RED)
261 // Foregroud layer (GREEN)
262 // child level 1b (WHITE)
263 // child level 2a (BLUE)
264 // child level 1a (testLayerColor) (relative to child level 2b)
265 // child level 2b (BLACK)
266 Transaction{}.reparent(childLevel1b, mForegroundLayer).apply();
267
268 {
269 // Nothing should change at this point since relative z info was preserved.
270 ScreenCapture::captureScreen(&sc);
271 sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor);
272 }
273 }
274 } // namespace android
275
276 // TODO(b/129481165): remove the #pragma below and fix conversion issues
277 #pragma clang diagnostic pop // ignored "-Wconversion"
278