• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 #include <compositionengine/impl/OutputCompositionState.h>
18 #include <compositionengine/impl/planner/CachedSet.h>
19 #include <compositionengine/impl/planner/LayerState.h>
20 #include <compositionengine/mock/LayerFE.h>
21 #include <compositionengine/mock/OutputLayer.h>
22 #include <gmock/gmock-actions.h>
23 #include <gtest/gtest.h>
24 #include <renderengine/ExternalTexture.h>
25 #include <renderengine/mock/RenderEngine.h>
26 #include <ui/GraphicTypes.h>
27 #include <utils/Errors.h>
28 #include <memory>
29 
30 namespace android::compositionengine {
31 using namespace std::chrono_literals;
32 
33 using testing::_;
34 using testing::DoAll;
35 using testing::Invoke;
36 using testing::Return;
37 using testing::ReturnRef;
38 using testing::SetArgPointee;
39 
40 using impl::planner::CachedSet;
41 using impl::planner::LayerState;
42 using impl::planner::LayerStateField;
43 using impl::planner::TexturePool;
44 
45 namespace {
46 
47 MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
48     *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
49     *result_listener << "expected " << expectedBlurSetting << "\n";
50     *result_listener << "actual " << arg.blurSetting << "\n";
51 
52     return expectedBlurSetting == arg.blurSetting;
53 }
54 
55 MATCHER_P(ClientCompositionTargetSettingsSecureEq, expectedSecureSetting, "") {
56     *result_listener << "ClientCompositionTargetSettings' SecureSettings aren't equal \n";
57     *result_listener << "expected " << expectedSecureSetting << "\n";
58     *result_listener << "actual " << arg.isSecure << "\n";
59 
60     return expectedSecureSetting == arg.isSecure;
61 }
62 
63 static const ui::Size kOutputSize = ui::Size(1, 1);
64 
65 class CachedSetTest : public testing::Test {
66 public:
67     CachedSetTest() = default;
68     void SetUp() override;
69     void TearDown() override;
70 
71 protected:
72     const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
73 
74     struct TestLayer {
75         mock::OutputLayer outputLayer;
76         impl::OutputLayerCompositionState outputLayerCompositionState;
77         // LayerFE inherits from RefBase and must be held by an sp<>
78         sp<mock::LayerFE> layerFE;
79         LayerFECompositionState layerFECompositionState;
80 
81         std::unique_ptr<LayerState> layerState;
82         std::unique_ptr<CachedSet::Layer> cachedSetLayer;
83     };
84 
85     static constexpr size_t kNumLayers = 5;
86     std::vector<std::unique_ptr<TestLayer>> mTestLayers;
87     impl::OutputCompositionState mOutputState;
88 
89     android::renderengine::mock::RenderEngine mRenderEngine;
90     TexturePool mTexturePool = TexturePool(mRenderEngine);
91 };
92 
SetUp()93 void CachedSetTest::SetUp() {
94     mTexturePool.setDisplaySize(kOutputSize);
95     for (size_t i = 0; i < kNumLayers; i++) {
96         auto testLayer = std::make_unique<TestLayer>();
97         auto pos = static_cast<int32_t>(i);
98         testLayer->outputLayerCompositionState.displayFrame = Rect(pos, pos, pos + 1, pos + 1);
99         testLayer->outputLayerCompositionState.visibleRegion =
100                 Region(Rect(pos + 1, pos + 1, pos + 2, pos + 2));
101 
102         testLayer->layerFE = sp<mock::LayerFE>::make();
103 
104         EXPECT_CALL(*testLayer->layerFE, getSequence)
105                 .WillRepeatedly(Return(static_cast<int32_t>(i)));
106         EXPECT_CALL(*testLayer->layerFE, getDebugName).WillRepeatedly(Return("testLayer"));
107         EXPECT_CALL(*testLayer->layerFE, getCompositionState)
108                 .WillRepeatedly(Return(&testLayer->layerFECompositionState));
109         EXPECT_CALL(testLayer->outputLayer, getLayerFE)
110                 .WillRepeatedly(ReturnRef(*testLayer->layerFE));
111         EXPECT_CALL(testLayer->outputLayer, getState)
112                 .WillRepeatedly(ReturnRef(testLayer->outputLayerCompositionState));
113 
114         testLayer->layerState = std::make_unique<LayerState>(&testLayer->outputLayer);
115         testLayer->layerState->incrementFramesSinceBufferUpdate();
116         testLayer->cachedSetLayer =
117                 std::make_unique<CachedSet::Layer>(testLayer->layerState.get(), kStartTime);
118 
119         mTestLayers.emplace_back(std::move(testLayer));
120 
121         // set up minimium params needed for rendering
122         mOutputState.dataspace = ui::Dataspace::SRGB;
123         mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5));
124         mOutputState.framebufferSpace.orientation = ui::ROTATION_90;
125         mOutputState.layerStackSpace = ProjectionSpace(ui::Size(20, 10), Rect(5, 10));
126     }
127 }
128 
TearDown()129 void CachedSetTest::TearDown() {
130     mTestLayers.clear();
131 }
132 
expectEqual(const CachedSet & cachedSet,const CachedSet::Layer & layer)133 void expectEqual(const CachedSet& cachedSet, const CachedSet::Layer& layer) {
134     EXPECT_EQ(layer.getLastUpdate(), cachedSet.getLastUpdate());
135     EXPECT_EQ(layer.getDisplayFrame(), cachedSet.getBounds());
136     EXPECT_TRUE(layer.getVisibleRegion().hasSameRects(cachedSet.getVisibleRegion()));
137     EXPECT_EQ(1u, cachedSet.getLayerCount());
138     EXPECT_EQ(layer.getState(), cachedSet.getFirstLayer().getState());
139     EXPECT_EQ(0u, cachedSet.getAge());
140     EXPECT_EQ(layer.getHash(), cachedSet.getNonBufferHash());
141 }
142 
expectEqual(const CachedSet & cachedSet,const LayerState & layerState,std::chrono::steady_clock::time_point lastUpdate)143 void expectEqual(const CachedSet& cachedSet, const LayerState& layerState,
144                  std::chrono::steady_clock::time_point lastUpdate) {
145     CachedSet::Layer layer(&layerState, lastUpdate);
146     expectEqual(cachedSet, layer);
147 }
148 
expectNoBuffer(const CachedSet & cachedSet)149 void expectNoBuffer(const CachedSet& cachedSet) {
150     EXPECT_EQ(nullptr, cachedSet.getBuffer());
151     EXPECT_EQ(nullptr, cachedSet.getDrawFence());
152     EXPECT_FALSE(cachedSet.hasReadyBuffer());
153 }
154 
expectReadyBuffer(const CachedSet & cachedSet)155 void expectReadyBuffer(const CachedSet& cachedSet) {
156     EXPECT_NE(nullptr, cachedSet.getBuffer());
157     EXPECT_NE(nullptr, cachedSet.getDrawFence());
158     EXPECT_TRUE(cachedSet.hasReadyBuffer());
159     EXPECT_TRUE(cachedSet.hasRenderedBuffer());
160 }
161 
TEST_F(CachedSetTest,createFromLayer)162 TEST_F(CachedSetTest, createFromLayer) {
163     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
164     CachedSet cachedSet(layer);
165     expectEqual(cachedSet, layer);
166     expectNoBuffer(cachedSet);
167 }
168 
TEST_F(CachedSetTest,createFromLayerState)169 TEST_F(CachedSetTest, createFromLayerState) {
170     LayerState& layerState = *mTestLayers[0]->layerState.get();
171     CachedSet cachedSet(&layerState, kStartTime);
172     expectEqual(cachedSet, layerState, kStartTime);
173     expectNoBuffer(cachedSet);
174 }
175 
TEST_F(CachedSetTest,addLayer)176 TEST_F(CachedSetTest, addLayer) {
177     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
178     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
179 
180     CachedSet cachedSet(layer1);
181     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
182 
183     EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
184     EXPECT_EQ(Rect(0, 0, 2, 2), cachedSet.getBounds());
185     Region expectedRegion;
186     expectedRegion.orSelf(Rect(1, 1, 2, 2));
187     expectedRegion.orSelf(Rect(2, 2, 3, 3));
188     EXPECT_TRUE(cachedSet.getVisibleRegion().hasSameRects(expectedRegion));
189     EXPECT_EQ(2u, cachedSet.getLayerCount());
190     EXPECT_EQ(0u, cachedSet.getAge());
191     expectNoBuffer(cachedSet);
192     // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
193     // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
194     // cachedSet.getNonBufferHash());
195 }
196 
TEST_F(CachedSetTest,decompose)197 TEST_F(CachedSetTest, decompose) {
198     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
199     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
200     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
201 
202     CachedSet cachedSet(layer1);
203     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
204     cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
205 
206     std::vector<CachedSet> decomposed = cachedSet.decompose();
207     EXPECT_EQ(3u, decomposed.size());
208     expectEqual(decomposed[0], *layer1.getState(), kStartTime);
209     expectNoBuffer(decomposed[0]);
210 
211     expectEqual(decomposed[1], *layer2.getState(), kStartTime + 10ms);
212     expectNoBuffer(decomposed[1]);
213 
214     expectEqual(decomposed[2], *layer3.getState(), kStartTime + 20ms);
215     expectNoBuffer(decomposed[2]);
216 }
217 
TEST_F(CachedSetTest,setLastUpdate)218 TEST_F(CachedSetTest, setLastUpdate) {
219     LayerState& layerState = *mTestLayers[0]->layerState.get();
220     CachedSet cachedSet(&layerState, kStartTime);
221     cachedSet.setLastUpdate(kStartTime + 10ms);
222     expectEqual(cachedSet, layerState, kStartTime + 10ms);
223 }
224 
TEST_F(CachedSetTest,incrementAge)225 TEST_F(CachedSetTest, incrementAge) {
226     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
227     CachedSet cachedSet(layer);
228     EXPECT_EQ(0u, cachedSet.getAge());
229     cachedSet.incrementAge();
230     EXPECT_EQ(1u, cachedSet.getAge());
231     cachedSet.incrementAge();
232     EXPECT_EQ(2u, cachedSet.getAge());
233 }
234 
TEST_F(CachedSetTest,incrementSkipCount)235 TEST_F(CachedSetTest, incrementSkipCount) {
236     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
237     CachedSet cachedSet(layer);
238     EXPECT_EQ(0u, cachedSet.getSkipCount());
239     cachedSet.incrementSkipCount();
240     EXPECT_EQ(1u, cachedSet.getSkipCount());
241     cachedSet.incrementSkipCount();
242     EXPECT_EQ(2u, cachedSet.getSkipCount());
243 }
244 
TEST_F(CachedSetTest,hasBufferUpdate_NoUpdate)245 TEST_F(CachedSetTest, hasBufferUpdate_NoUpdate) {
246     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
247     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
248     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
249 
250     CachedSet cachedSet(layer1);
251     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
252     cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
253 
254     EXPECT_FALSE(cachedSet.hasBufferUpdate());
255 }
256 
TEST_F(CachedSetTest,hasBufferUpdate_BufferUpdate)257 TEST_F(CachedSetTest, hasBufferUpdate_BufferUpdate) {
258     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
259     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
260     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
261 
262     CachedSet cachedSet(layer1);
263     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
264     cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
265 
266     mTestLayers[1]->layerState->resetFramesSinceBufferUpdate();
267 
268     EXPECT_TRUE(cachedSet.hasBufferUpdate());
269 }
270 
TEST_F(CachedSetTest,append)271 TEST_F(CachedSetTest, append) {
272     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
273     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
274     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
275 
276     CachedSet cachedSet1(layer1);
277     CachedSet cachedSet2(layer2);
278     cachedSet1.addLayer(layer3.getState(), kStartTime + 10ms);
279     cachedSet1.incrementSkipCount();
280     EXPECT_EQ(1u, cachedSet1.getSkipCount());
281     cachedSet1.append(cachedSet2);
282 
283     EXPECT_EQ(kStartTime, cachedSet1.getLastUpdate());
284     EXPECT_EQ(Rect(0, 0, 3, 3), cachedSet1.getBounds());
285     Region expectedRegion;
286     expectedRegion.orSelf(Rect(1, 1, 2, 2));
287     expectedRegion.orSelf(Rect(2, 2, 3, 3));
288     expectedRegion.orSelf(Rect(3, 3, 4, 4));
289     EXPECT_TRUE(cachedSet1.getVisibleRegion().hasSameRects(expectedRegion));
290     EXPECT_EQ(3u, cachedSet1.getLayerCount());
291     EXPECT_EQ(0u, cachedSet1.getAge());
292     EXPECT_EQ(0u, cachedSet1.getSkipCount());
293 
294     expectNoBuffer(cachedSet1);
295     // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
296     // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
297     // cachedSet1.getNonBufferHash());
298 }
299 
TEST_F(CachedSetTest,updateAge_NoUpdate)300 TEST_F(CachedSetTest, updateAge_NoUpdate) {
301     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
302 
303     CachedSet cachedSet(layer);
304     cachedSet.incrementAge();
305     EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
306     EXPECT_EQ(1u, cachedSet.getAge());
307 
308     cachedSet.updateAge(kStartTime + 10ms);
309     EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
310     EXPECT_EQ(1u, cachedSet.getAge());
311 }
312 
TEST_F(CachedSetTest,updateAge_BufferUpdate)313 TEST_F(CachedSetTest, updateAge_BufferUpdate) {
314     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
315     mTestLayers[0]->layerState->resetFramesSinceBufferUpdate();
316 
317     CachedSet cachedSet(layer);
318     cachedSet.incrementAge();
319     EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
320     EXPECT_EQ(1u, cachedSet.getAge());
321 
322     cachedSet.updateAge(kStartTime + 10ms);
323     EXPECT_EQ(kStartTime + 10ms, cachedSet.getLastUpdate());
324     EXPECT_EQ(0u, cachedSet.getAge());
325 }
326 
TEST_F(CachedSetTest,renderUnsecureOutput)327 TEST_F(CachedSetTest, renderUnsecureOutput) {
328     // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
329     CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
330     sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
331     CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
332     sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
333 
334     CachedSet cachedSet(layer1);
335     cachedSet.append(CachedSet(layer2));
336 
337     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
338     clientCompList1.push_back({});
339     clientCompList1[0].alpha = 0.5f;
340 
341     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
342     clientCompList2.push_back({});
343     clientCompList2[0].alpha = 0.75f;
344 
345     const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
346                                 const std::vector<const renderengine::LayerSettings*>& layers,
347                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
348                                 base::unique_fd&&, base::unique_fd*) -> size_t {
349         EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay);
350         EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
351         EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
352                   displaySettings.orientation);
353         EXPECT_EQ(0.5f, layers[0]->alpha);
354         EXPECT_EQ(0.75f, layers[1]->alpha);
355         EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
356 
357         return NO_ERROR;
358     };
359 
360     EXPECT_CALL(*layerFE1,
361                 prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false)))
362             .WillOnce(Return(clientCompList1));
363     EXPECT_CALL(*layerFE2,
364                 prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false)))
365             .WillOnce(Return(clientCompList2));
366     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
367     mOutputState.isSecure = false;
368     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
369     expectReadyBuffer(cachedSet);
370 
371     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
372     EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
373 
374     // Now check that appending a new cached set properly cleans up RenderEngine resources.
375     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
376     cachedSet.append(CachedSet(layer3));
377 }
378 
TEST_F(CachedSetTest,renderSecureOutput)379 TEST_F(CachedSetTest, renderSecureOutput) {
380     // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
381     CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
382     sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
383     CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
384     sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
385 
386     CachedSet cachedSet(layer1);
387     cachedSet.append(CachedSet(layer2));
388 
389     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
390     clientCompList1.push_back({});
391     clientCompList1[0].alpha = 0.5f;
392 
393     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
394     clientCompList2.push_back({});
395     clientCompList2[0].alpha = 0.75f;
396 
397     const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
398                                 const std::vector<const renderengine::LayerSettings*>& layers,
399                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
400                                 base::unique_fd&&, base::unique_fd*) -> size_t {
401         EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay);
402         EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
403         EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
404                   displaySettings.orientation);
405         EXPECT_EQ(0.5f, layers[0]->alpha);
406         EXPECT_EQ(0.75f, layers[1]->alpha);
407         EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
408 
409         return NO_ERROR;
410     };
411 
412     EXPECT_CALL(*layerFE1,
413                 prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true)))
414             .WillOnce(Return(clientCompList1));
415     EXPECT_CALL(*layerFE2,
416                 prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true)))
417             .WillOnce(Return(clientCompList2));
418     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
419     mOutputState.isSecure = true;
420     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
421     expectReadyBuffer(cachedSet);
422 
423     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
424     EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
425 
426     // Now check that appending a new cached set properly cleans up RenderEngine resources.
427     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
428     cachedSet.append(CachedSet(layer3));
429 }
430 
TEST_F(CachedSetTest,rendersWithOffsetFramebufferContent)431 TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) {
432     // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
433     CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
434     sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
435     CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
436     sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
437 
438     CachedSet cachedSet(layer1);
439     cachedSet.append(CachedSet(layer2));
440 
441     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
442     clientCompList1.push_back({});
443     clientCompList1[0].alpha = 0.5f;
444 
445     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
446     clientCompList2.push_back({});
447     clientCompList2[0].alpha = 0.75f;
448 
449     mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5));
450 
451     const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
452                                 const std::vector<const renderengine::LayerSettings*>& layers,
453                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
454                                 base::unique_fd&&, base::unique_fd*) -> size_t {
455         EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay);
456         EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
457         EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
458                   displaySettings.orientation);
459         EXPECT_EQ(0.5f, layers[0]->alpha);
460         EXPECT_EQ(0.75f, layers[1]->alpha);
461         EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
462 
463         return NO_ERROR;
464     };
465 
466     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
467     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
468     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
469     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
470     expectReadyBuffer(cachedSet);
471 
472     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
473 
474     // Now check that appending a new cached set properly cleans up RenderEngine resources.
475     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
476     cachedSet.append(CachedSet(layer3));
477 }
478 
TEST_F(CachedSetTest,holePunch_requiresBuffer)479 TEST_F(CachedSetTest, holePunch_requiresBuffer) {
480     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
481     sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
482 
483     CachedSet cachedSet(layer1);
484     EXPECT_CALL(*layerFE1, hasRoundedCorners()).WillRepeatedly(Return(true));
485 
486     EXPECT_FALSE(cachedSet.requiresHolePunch());
487 }
488 
TEST_F(CachedSetTest,holePunch_requiresRoundedCorners)489 TEST_F(CachedSetTest, holePunch_requiresRoundedCorners) {
490     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
491     mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
492 
493     CachedSet cachedSet(layer1);
494 
495     EXPECT_FALSE(cachedSet.requiresHolePunch());
496 }
497 
TEST_F(CachedSetTest,holePunch_requiresSingleLayer)498 TEST_F(CachedSetTest, holePunch_requiresSingleLayer) {
499     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
500     mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
501     sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
502     EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
503 
504     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
505 
506     CachedSet cachedSet(layer1);
507     cachedSet.append(layer2);
508 
509     EXPECT_FALSE(cachedSet.requiresHolePunch());
510 }
511 
TEST_F(CachedSetTest,holePunch_requiresNonHdr)512 TEST_F(CachedSetTest, holePunch_requiresNonHdr) {
513     mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ;
514     mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
515 
516     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
517     mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
518     sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
519 
520     CachedSet cachedSet(layer);
521     EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
522 
523     EXPECT_FALSE(cachedSet.requiresHolePunch());
524 }
525 
TEST_F(CachedSetTest,holePunch_requiresNonBT601_625)526 TEST_F(CachedSetTest, holePunch_requiresNonBT601_625) {
527     mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625;
528     mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
529 
530     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
531     mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
532     sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
533 
534     CachedSet cachedSet(layer);
535     EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
536 
537     EXPECT_FALSE(cachedSet.requiresHolePunch());
538 }
539 
TEST_F(CachedSetTest,requiresHolePunch)540 TEST_F(CachedSetTest, requiresHolePunch) {
541     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
542     mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
543     sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
544 
545     CachedSet cachedSet(layer);
546     EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
547 
548     EXPECT_TRUE(cachedSet.requiresHolePunch());
549 }
550 
TEST_F(CachedSetTest,holePunch_requiresDeviceComposition)551 TEST_F(CachedSetTest, holePunch_requiresDeviceComposition) {
552     CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
553     sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
554     auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
555     layerFECompositionState.buffer = sp<GraphicBuffer>::make();
556     layerFECompositionState.forceClientComposition = true;
557 
558     CachedSet cachedSet(layer);
559     EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
560 
561     EXPECT_FALSE(cachedSet.requiresHolePunch());
562 }
563 
TEST_F(CachedSetTest,addHolePunch_requiresOverlap)564 TEST_F(CachedSetTest, addHolePunch_requiresOverlap) {
565     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
566     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
567     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
568 
569     CachedSet cachedSet(layer1);
570     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
571 
572     cachedSet.addHolePunchLayerIfFeasible(layer3, true);
573 
574     ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
575 }
576 
TEST_F(CachedSetTest,addHolePunch_requiresOpaque)577 TEST_F(CachedSetTest, addHolePunch_requiresOpaque) {
578     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
579     mTestLayers[0]->layerFECompositionState.isOpaque = false;
580     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
581     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
582     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
583 
584     CachedSet cachedSet(layer1);
585     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
586 
587     cachedSet.addHolePunchLayerIfFeasible(layer3, false);
588 
589     ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
590 }
591 
TEST_F(CachedSetTest,addHolePunch_opaque)592 TEST_F(CachedSetTest, addHolePunch_opaque) {
593     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
594     mTestLayers[0]->layerFECompositionState.isOpaque = true;
595     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
596     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
597     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
598 
599     CachedSet cachedSet(layer1);
600     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
601 
602     cachedSet.addHolePunchLayerIfFeasible(layer3, false);
603 
604     ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
605 }
606 
TEST_F(CachedSetTest,addHolePunch_firstLayer)607 TEST_F(CachedSetTest, addHolePunch_firstLayer) {
608     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
609     mTestLayers[0]->layerFECompositionState.isOpaque = false;
610     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
611     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
612     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
613 
614     CachedSet cachedSet(layer1);
615     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
616 
617     cachedSet.addHolePunchLayerIfFeasible(layer3, true);
618 
619     ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
620 }
621 
TEST_F(CachedSetTest,addHolePunch)622 TEST_F(CachedSetTest, addHolePunch) {
623     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
624     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
625     sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
626 
627     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
628     sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
629 
630     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
631     sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
632 
633     CachedSet cachedSet(layer1);
634     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
635 
636     cachedSet.addHolePunchLayerIfFeasible(layer3, true);
637 
638     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
639     clientCompList1.push_back({});
640     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
641     clientCompList2.push_back({});
642     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
643     clientCompList3.push_back({});
644 
645     clientCompList3[0].source.buffer.buffer = std::make_shared<
646             renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
647                                            renderengine::ExternalTexture::READABLE);
648 
649     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
650     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
651     EXPECT_CALL(*layerFE3, prepareClientCompositionList(_)).WillOnce(Return(clientCompList3));
652 
653     const auto drawLayers = [&](const renderengine::DisplaySettings&,
654                                 const std::vector<const renderengine::LayerSettings*>& layers,
655                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
656                                 base::unique_fd&&, base::unique_fd*) -> size_t {
657         // If the highlight layer is enabled, it will increase the size by 1.
658         // We're interested in the third layer either way.
659         EXPECT_GE(layers.size(), 4u);
660         {
661             const auto* holePunchSettings = layers[3];
662             EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer);
663             EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor);
664             EXPECT_TRUE(holePunchSettings->disableBlending);
665             EXPECT_EQ(0.0f, holePunchSettings->alpha);
666         }
667 
668         {
669             const auto* holePunchBackgroundSettings = layers[0];
670             EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer);
671             EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor);
672             EXPECT_FALSE(holePunchBackgroundSettings->disableBlending);
673             EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha);
674         }
675 
676         return NO_ERROR;
677     };
678 
679     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
680     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
681 }
682 
TEST_F(CachedSetTest,addHolePunch_noBuffer)683 TEST_F(CachedSetTest, addHolePunch_noBuffer) {
684     // Same as addHolePunch, except that clientCompList3 does not contain a
685     // buffer. This imitates the case where the buffer had protected content, so
686     // BufferLayer did not add it to the LayerSettings. This should not assert.
687     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
688     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
689     sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
690 
691     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
692     sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
693 
694     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
695     sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
696 
697     CachedSet cachedSet(layer1);
698     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
699 
700     cachedSet.addHolePunchLayerIfFeasible(layer3, true);
701 
702     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
703     clientCompList1.push_back({});
704     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
705     clientCompList2.push_back({});
706     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
707     clientCompList3.push_back({});
708 
709     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
710     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
711     EXPECT_CALL(*layerFE3, prepareClientCompositionList(_)).WillOnce(Return(clientCompList3));
712 
713     const auto drawLayers = [&](const renderengine::DisplaySettings&,
714                                 const std::vector<const renderengine::LayerSettings*>& layers,
715                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
716                                 base::unique_fd&&, base::unique_fd*) -> size_t {
717         // If the highlight layer is enabled, it will increase the size by 1.
718         // We're interested in the third layer either way.
719         EXPECT_GE(layers.size(), 4u);
720 
721         {
722             const auto* holePunchSettings = layers[3];
723             EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer);
724             EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor);
725             EXPECT_TRUE(holePunchSettings->disableBlending);
726             EXPECT_EQ(0.0f, holePunchSettings->alpha);
727         }
728 
729         {
730             const auto* holePunchBackgroundSettings = layers[0];
731             EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer);
732             EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor);
733             EXPECT_FALSE(holePunchBackgroundSettings->disableBlending);
734             EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha);
735         }
736 
737         return NO_ERROR;
738     };
739 
740     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
741     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
742 }
743 
TEST_F(CachedSetTest,append_removesHolePunch)744 TEST_F(CachedSetTest, append_removesHolePunch) {
745     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
746     mTestLayers[0]->layerFECompositionState.isOpaque = true;
747     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
748     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
749     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
750 
751     CachedSet cachedSet(layer1);
752     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
753 
754     cachedSet.addHolePunchLayerIfFeasible(layer3, false);
755 
756     ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
757 
758     CachedSet cachedSet3(layer3);
759     cachedSet.append(cachedSet3);
760     ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
761 }
762 
TEST_F(CachedSetTest,decompose_removesHolePunch)763 TEST_F(CachedSetTest, decompose_removesHolePunch) {
764     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
765     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
766     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
767     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
768 
769     CachedSet cachedSet(layer1);
770     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
771 
772     cachedSet.addHolePunchLayerIfFeasible(layer3, true);
773 
774     ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
775 
776     std::vector<CachedSet> decomposed = cachedSet.decompose();
777     EXPECT_EQ(2u, decomposed.size());
778     for (const auto& set : decomposed) {
779         EXPECT_EQ(nullptr, set.getHolePunchLayer());
780     }
781 }
782 
TEST_F(CachedSetTest,hasBlurBehind)783 TEST_F(CachedSetTest, hasBlurBehind) {
784     mTestLayers[1]->layerFECompositionState.backgroundBlurRadius = 1;
785     mTestLayers[1]->layerState->update(&mTestLayers[1]->outputLayer);
786     mTestLayers[2]->layerFECompositionState.blurRegions.push_back(
787             BlurRegion{1, 0, 0, 0, 0, 0, 0, 0, 0, 0});
788     mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
789 
790     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
791     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
792     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
793 
794     CachedSet cachedSet1(layer1);
795     CachedSet cachedSet2(layer2);
796     CachedSet cachedSet3(layer3);
797 
798     // Cached set 4 will consist of layers 1 and 2, which will contain a blur behind
799     CachedSet cachedSet4(layer1);
800     cachedSet4.addLayer(layer2.getState(), kStartTime);
801 
802     EXPECT_FALSE(cachedSet1.hasBlurBehind());
803     EXPECT_TRUE(cachedSet2.hasBlurBehind());
804     EXPECT_TRUE(cachedSet3.hasBlurBehind());
805     EXPECT_TRUE(cachedSet4.hasBlurBehind());
806 }
807 
TEST_F(CachedSetTest,addBackgroundBlurLayer)808 TEST_F(CachedSetTest, addBackgroundBlurLayer) {
809     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
810     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
811     CachedSet cachedSet(layer1);
812 
813     EXPECT_EQ(nullptr, cachedSet.getBlurLayer());
814 
815     cachedSet.addBackgroundBlurLayer(layer2);
816     EXPECT_EQ(layer2.getState()->getOutputLayer(), cachedSet.getBlurLayer());
817 }
818 
TEST_F(CachedSetTest,addBlur)819 TEST_F(CachedSetTest, addBlur) {
820     mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
821     CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
822     sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
823 
824     CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
825     sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
826 
827     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
828     sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
829 
830     CachedSet cachedSet(layer1);
831     cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
832 
833     cachedSet.addBackgroundBlurLayer(layer3);
834 
835     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
836     clientCompList1.push_back({});
837     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
838     clientCompList2.push_back({});
839     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
840     clientCompList3.push_back({});
841 
842     clientCompList3[0].source.buffer.buffer = std::make_shared<
843             renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
844                                            renderengine::ExternalTexture::READABLE);
845 
846     EXPECT_CALL(*layerFE1,
847                 prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
848                         compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
849                                 Enabled)))
850             .WillOnce(Return(clientCompList1));
851     EXPECT_CALL(*layerFE2,
852                 prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
853                         compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
854                                 Enabled)))
855             .WillOnce(Return(clientCompList2));
856     EXPECT_CALL(*layerFE3,
857                 prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
858                         compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
859                                 BackgroundBlurOnly)))
860             .WillOnce(Return(clientCompList3));
861 
862     const auto drawLayers = [&](const renderengine::DisplaySettings&,
863                                 const std::vector<const renderengine::LayerSettings*>& layers,
864                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
865                                 base::unique_fd&&, base::unique_fd*) -> int32_t {
866         // If the highlight layer is enabled, it will increase the size by 1.
867         // We're interested in the third layer either way.
868         EXPECT_GE(layers.size(), 3u);
869         const auto* blurSettings = layers[2];
870         EXPECT_TRUE(blurSettings->skipContentDraw);
871         EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor);
872         EXPECT_EQ(0.0f, blurSettings->alpha);
873 
874         return NO_ERROR;
875     };
876 
877     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
878     cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
879 }
880 
881 } // namespace
882 } // namespace android::compositionengine
883