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