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