blob: b6c2fe2d55fe657cf0f4585af1a5a39e1f33c712 [file] [log] [blame]
chaviw5e1e8f22020-07-10 12:46:21 -07001/*
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#pragma clang diagnostic push
18#pragma clang diagnostic ignored "-Wconversion"
19
20#include "LayerTransactionTest.h"
21
22namespace android {
23
24class DetachChildren : public LayerTransactionTest {
25protected:
26 virtual void SetUp() {
27 LayerTransactionTest::SetUp();
28
29 mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
30 mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
31
32 ASSERT_TRUE(mMainSurface != nullptr);
33 ASSERT_TRUE(mMainSurface->isValid());
34
35 TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
36
37 asTransaction([&](Transaction& t) {
38 t.setLayer(mMainSurface, INT32_MAX - 1)
39 .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
40 .show(mMainSurface);
41 });
42 }
43
44 virtual void TearDown() {
45 LayerTransactionTest::TearDown();
46 mMainSurface = 0;
47 }
48
49 sp<SurfaceControl> mMainSurface;
50 Color mMainSurfaceColor = {195, 63, 63, 255};
51 Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
52 std::unique_ptr<ScreenCapture> mCapture;
53};
54
55TEST_F(DetachChildren, RelativesAreNotDetached) {
56 Color relativeColor = {10, 10, 10, 255};
57 Rect relBounds = Rect(64, 64, 74, 74);
58
59 sp<SurfaceControl> relative =
60 createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
61 TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
62
63 Transaction{}
64 .setRelativeLayer(relative, mMainSurface->getHandle(), 1)
65 .setPosition(relative, relBounds.left, relBounds.top)
66 .apply();
67
68 {
69 // The relative should be on top of the FG control.
70 mCapture = screenshot();
71 mCapture->expectColor(relBounds, relativeColor);
72 }
73 Transaction{}.detachChildren(mMainSurface).apply();
74
75 {
76 // Nothing should change at this point.
77 mCapture = screenshot();
78 mCapture->expectColor(relBounds, relativeColor);
79 }
80
81 Transaction{}.hide(relative).apply();
82
83 {
84 // Ensure that the relative was actually hidden, rather than
85 // being left in the detached but visible state.
86 mCapture = screenshot();
87 mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
88 }
89}
90
91TEST_F(DetachChildren, DetachChildrenSameClient) {
92 Color childColor = {200, 200, 200, 255};
93 Rect childBounds = Rect(74, 74, 84, 84);
94 sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
95 childBounds.height(), 0, mMainSurface.get());
96 ASSERT_TRUE(child->isValid());
97
98 TransactionUtils::fillSurfaceRGBA8(child, childColor);
99
100 asTransaction([&](Transaction& t) {
101 t.show(child);
102 t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
103 childBounds.top - mMainSurfaceBounds.top);
104 });
105
106 {
107 mCapture = screenshot();
108 // Expect main color around the child surface
109 mCapture->expectBorder(childBounds, mMainSurfaceColor);
110 mCapture->expectColor(childBounds, childColor);
111 }
112
113 asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
114
115 asTransaction([&](Transaction& t) { t.hide(child); });
116
117 // Since the child has the same client as the parent, it will not get
118 // detached and will be hidden.
119 {
120 mCapture = screenshot();
121 mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
122 }
123}
124
125TEST_F(DetachChildren, DetachChildrenDifferentClient) {
126 Color childColor = {200, 200, 200, 255};
127 Rect childBounds = Rect(74, 74, 84, 84);
128
129 sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
130 sp<SurfaceControl> childNewClient =
131 createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
132 childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
133 ASSERT_TRUE(childNewClient->isValid());
134
135 TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
136
137 asTransaction([&](Transaction& t) {
138 t.show(childNewClient);
139 t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
140 childBounds.top - mMainSurfaceBounds.top);
141 });
142
143 {
144 mCapture = screenshot();
145 // Expect main color around the child surface
146 mCapture->expectBorder(childBounds, mMainSurfaceColor);
147 mCapture->expectColor(childBounds, childColor);
148 }
149
150 asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
151
152 asTransaction([&](Transaction& t) { t.hide(childNewClient); });
153
154 // Nothing should have changed.
155 {
156 mCapture = screenshot();
157 mCapture->expectBorder(childBounds, mMainSurfaceColor);
158 mCapture->expectColor(childBounds, childColor);
159 }
160}
161
162TEST_F(DetachChildren, DetachChildrenThenAttach) {
163 Color childColor = {200, 200, 200, 255};
164 Rect childBounds = Rect(74, 74, 84, 84);
165
166 sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
167 sp<SurfaceControl> childNewClient =
168 createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
169 childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
170 ASSERT_TRUE(childNewClient->isValid());
171
172 TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
173
174 Transaction()
175 .show(childNewClient)
176 .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
177 childBounds.top - mMainSurfaceBounds.top)
178 .apply();
179
180 {
181 mCapture = screenshot();
182 // Expect main color around the child surface
183 mCapture->expectBorder(childBounds, mMainSurfaceColor);
184 mCapture->expectColor(childBounds, childColor);
185 }
186
187 Transaction().detachChildren(mMainSurface).apply();
188 Transaction().hide(childNewClient).apply();
189
190 // Nothing should have changed.
191 {
192 mCapture = screenshot();
193 mCapture->expectBorder(childBounds, mMainSurfaceColor);
194 mCapture->expectColor(childBounds, childColor);
195 }
196
197 Color newParentColor = Color::RED;
198 Rect newParentBounds = Rect(20, 20, 52, 52);
199 sp<SurfaceControl> newParentSurface =
200 createLayer(String8("New Parent Surface"), newParentBounds.width(),
201 newParentBounds.height(), 0);
202 TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
203 Transaction()
204 .setLayer(newParentSurface, INT32_MAX - 1)
205 .show(newParentSurface)
206 .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
207 .reparent(childNewClient, newParentSurface->getHandle())
208 .apply();
209 {
210 mCapture = screenshot();
211 // Child is now hidden.
212 mCapture->expectColor(newParentBounds, newParentColor);
213 }
214}
215
216TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
217 Color childColor = {200, 200, 200, 255};
218 Rect childBounds = Rect(74, 74, 84, 84);
219
220 sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
221 sp<SurfaceControl> childNewClient =
222 createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
223 childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
224 ASSERT_TRUE(childNewClient->isValid());
225
226 TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
227
228 Transaction()
229 .show(childNewClient)
230 .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
231 childBounds.top - mMainSurfaceBounds.top)
232 .apply();
233
234 {
235 mCapture = screenshot();
236 mCapture->expectBorder(childBounds, mMainSurfaceColor);
237 mCapture->expectColor(childBounds, childColor);
238 }
239
240 Transaction()
241 .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(),
242 mMainSurface->getSurface()->getNextFrameNumber())
243 .apply();
244 Transaction().detachChildren(mMainSurface).apply();
245 ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
246 mMainSurfaceBounds.width(),
247 mMainSurfaceBounds.height()));
248
249 // BufferLayer can still dequeue buffers even though there's a detached layer with a
250 // deferred transaction.
251 {
252 SCOPED_TRACE("new buffer");
253 mCapture = screenshot();
254 mCapture->expectBorder(childBounds, Color::RED);
255 mCapture->expectColor(childBounds, childColor);
256 }
257}
258
259TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
260 Color childColor = {200, 200, 200, 255};
261 Rect childBounds = Rect(74, 74, 94, 94);
262 Color grandchildColor = Color::RED;
263 Rect grandchildBounds = Rect(80, 80, 90, 90);
264
265 sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
266 sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
267
268 sp<SurfaceControl> childSurface =
269 createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
270 PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
271 sp<SurfaceControl> grandchildSurface =
272 createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
273 grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
274
275 TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
276 TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
277
278 Transaction()
279 .show(childSurface)
280 .show(grandchildSurface)
281 .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
282 childBounds.top - mMainSurfaceBounds.top)
283 .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
284 grandchildBounds.top - childBounds.top)
285 .apply();
286
287 {
288 mCapture = screenshot();
289 mCapture->expectBorder(childBounds, mMainSurfaceColor);
290 mCapture->expectBorder(grandchildBounds, childColor);
291 mCapture->expectColor(grandchildBounds, grandchildColor);
292 }
293
294 Transaction().detachChildren(childSurface).apply();
295
296 // Remove main surface offscreen
297 Transaction().reparent(mMainSurface, nullptr).apply();
298 {
299 mCapture = screenshot();
300 mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
301 }
302
303 Transaction().reparent(mMainSurface, mBlackBgSurface->getHandle()).apply();
304 {
305 mCapture = screenshot();
306 mCapture->expectBorder(childBounds, mMainSurfaceColor);
307 mCapture->expectBorder(grandchildBounds, childColor);
308 mCapture->expectColor(grandchildBounds, grandchildColor);
309 }
310
311 Transaction().hide(grandchildSurface).apply();
312
313 // grandchild is still detached so it will not hide
314 {
315 mCapture = screenshot();
316 mCapture->expectBorder(childBounds, mMainSurfaceColor);
317 mCapture->expectBorder(grandchildBounds, childColor);
318 mCapture->expectColor(grandchildBounds, grandchildColor);
319 }
320}
321
322} // namespace android