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 "DisplayHardware/Hal.h"
18 #undef LOG_TAG
19 #define LOG_TAG "PredictorTest"
20 
21 #include <common/include/common/test/FlagUtils.h>
22 #include "com_android_graphics_surfaceflinger_flags.h"
23 
24 #include <compositionengine/impl/planner/Predictor.h>
25 #include <compositionengine/mock/LayerFE.h>
26 #include <compositionengine/mock/OutputLayer.h>
27 #include <gtest/gtest.h>
28 #include <log/log.h>
29 
30 #include <aidl/android/hardware/graphics/composer3/Composition.h>
31 
32 using aidl::android::hardware::graphics::composer3::Composition;
33 
34 namespace android::compositionengine::impl::planner {
35 namespace {
36 
37 const FloatRect sFloatRectOne = FloatRect(100.f, 200.f, 300.f, 400.f);
38 const FloatRect sFloatRectTwo = FloatRect(400.f, 300.f, 200.f, 100.f);
39 const Rect sRectOne = Rect(1, 2, 3, 4);
40 const Rect sRectTwo = Rect(4, 3, 2, 1);
41 const constexpr float sAlphaOne = 0.25f;
42 const constexpr float sAlphaTwo = 0.5f;
43 const Region sRegionOne = Region(sRectOne);
44 const Region sRegionTwo = Region(sRectTwo);
45 const mat4 sMat4One = mat4::scale(vec4(2.f, 3.f, 1.f, 1.f));
46 
47 using testing::Return;
48 using testing::ReturnRef;
49 
50 const std::string sDebugName = std::string("Test LayerFE");
51 const constexpr int32_t sSequenceId = 12345;
52 
setupMocksForLayer(mock::OutputLayer & layer,mock::LayerFE & layerFE,const OutputLayerCompositionState & outputLayerState,const LayerFECompositionState & layerFEState)53 void setupMocksForLayer(mock::OutputLayer& layer, mock::LayerFE& layerFE,
54                         const OutputLayerCompositionState& outputLayerState,
55                         const LayerFECompositionState& layerFEState) {
56     EXPECT_CALL(layer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
57     EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
58     EXPECT_CALL(layerFE, getSequence()).WillRepeatedly(Return(sSequenceId));
59     EXPECT_CALL(layerFE, getDebugName()).WillRepeatedly(Return(sDebugName.c_str()));
60     EXPECT_CALL(layerFE, getCompositionState()).WillRepeatedly(Return(&layerFEState));
61 }
62 
63 struct LayerStackTest : public testing::Test {
LayerStackTestandroid::compositionengine::impl::planner::__anondcd1064e0111::LayerStackTest64     LayerStackTest() {
65         const ::testing::TestInfo* const test_info =
66                 ::testing::UnitTest::GetInstance()->current_test_info();
67         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
68     }
69 
~LayerStackTestandroid::compositionengine::impl::planner::__anondcd1064e0111::LayerStackTest70     ~LayerStackTest() {
71         const ::testing::TestInfo* const test_info =
72                 ::testing::UnitTest::GetInstance()->current_test_info();
73         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
74     }
75 };
76 
TEST_F(LayerStackTest,getApproximateMatch_doesNotMatchSizeDifferences)77 TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchSizeDifferences) {
78     mock::OutputLayer outputLayerOne;
79     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
80     OutputLayerCompositionState outputLayerCompositionStateOne;
81     LayerFECompositionState layerFECompositionStateOne;
82     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
83                        layerFECompositionStateOne);
84     LayerState layerStateOne(&outputLayerOne);
85 
86     mock::OutputLayer outputLayerTwo;
87     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
88     OutputLayerCompositionState outputLayerCompositionStateTwo;
89     LayerFECompositionState layerFECompositionStateTwo;
90     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
91                        layerFECompositionStateTwo);
92     LayerState layerStateTwo(&outputLayerTwo);
93 
94     mock::OutputLayer outputLayerThree;
95     sp<mock::LayerFE> layerFEThree = sp<mock::LayerFE>::make();
96     OutputLayerCompositionState outputLayerCompositionStateThree;
97     LayerFECompositionState layerFECompositionStateThree;
98     setupMocksForLayer(outputLayerThree, *layerFEThree, outputLayerCompositionStateThree,
99                        layerFECompositionStateThree);
100     LayerState layerStateThree(&outputLayerThree);
101 
102     LayerStack stack({&layerStateOne});
103 
104     EXPECT_FALSE(stack.getApproximateMatch({}));
105     EXPECT_FALSE(stack.getApproximateMatch({&layerStateOne, &layerStateThree}));
106 }
107 
TEST_F(LayerStackTest,getApproximateMatch_doesNotMatchDifferentCompositionTypes)108 TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchDifferentCompositionTypes) {
109     mock::OutputLayer outputLayerOne;
110     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
111     OutputLayerCompositionState outputLayerCompositionStateOne;
112     LayerFECompositionState layerFECompositionStateOne;
113     layerFECompositionStateOne.compositionType = Composition::DEVICE;
114     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
115                        layerFECompositionStateOne);
116     LayerState layerStateOne(&outputLayerOne);
117 
118     mock::OutputLayer outputLayerTwo;
119     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
120     OutputLayerCompositionState outputLayerCompositionStateTwo;
121     LayerFECompositionState layerFECompositionStateTwo;
122     layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
123     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
124                        layerFECompositionStateTwo);
125     LayerState layerStateTwo(&outputLayerTwo);
126 
127     LayerStack stack({&layerStateOne});
128 
129     EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo}));
130 }
131 
TEST_F(LayerStackTest,getApproximateMatch_matchesSingleDifferenceInSingleLayer)132 TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInSingleLayer) {
133     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
134                               cache_when_source_crop_layer_only_moved,
135                       false);
136     mock::OutputLayer outputLayerOne;
137     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
138     OutputLayerCompositionState outputLayerCompositionStateOne{
139             .sourceCrop = sFloatRectOne,
140     };
141     LayerFECompositionState layerFECompositionStateOne;
142     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
143                        layerFECompositionStateOne);
144     LayerState layerStateOne(&outputLayerOne);
145 
146     mock::OutputLayer outputLayerTwo;
147     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
148     OutputLayerCompositionState outputLayerCompositionStateTwo{
149             .sourceCrop = sFloatRectTwo,
150     };
151     LayerFECompositionState layerFECompositionStateTwo;
152     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
153                        layerFECompositionStateTwo);
154     LayerState layerStateTwo(&outputLayerTwo);
155 
156     LayerStack stack({&layerStateOne});
157 
158     const auto match = stack.getApproximateMatch({&layerStateTwo});
159     EXPECT_TRUE(match);
160     LayerStack::ApproximateMatch expectedMatch;
161     expectedMatch.differingIndex = 0;
162     expectedMatch.differingFields = LayerStateField::SourceCrop;
163     EXPECT_EQ(expectedMatch, *match);
164 }
165 
TEST_F(LayerStackTest,getApproximateMatch_matchesSingleDifferenceInMultiLayerStack)166 TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInMultiLayerStack) {
167     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
168                               cache_when_source_crop_layer_only_moved,
169                       false);
170     mock::OutputLayer outputLayerOne;
171     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
172     OutputLayerCompositionState outputLayerCompositionStateOne{
173             .sourceCrop = sFloatRectOne,
174     };
175     LayerFECompositionState layerFECompositionStateOne;
176     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
177                        layerFECompositionStateOne);
178     LayerState layerStateOne(&outputLayerOne);
179 
180     mock::OutputLayer outputLayerTwo;
181     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
182     OutputLayerCompositionState outputLayerCompositionStateTwo{
183             .sourceCrop = sFloatRectTwo,
184     };
185     LayerFECompositionState layerFECompositionStateTwo;
186     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
187                        layerFECompositionStateTwo);
188     LayerState layerStateTwo(&outputLayerTwo);
189 
190     LayerStack stack({&layerStateOne, &layerStateOne});
191 
192     const auto match = stack.getApproximateMatch({&layerStateOne, &layerStateTwo});
193     EXPECT_TRUE(match);
194     LayerStack::ApproximateMatch expectedMatch;
195     expectedMatch.differingIndex = 1;
196     expectedMatch.differingFields = LayerStateField::SourceCrop;
197     EXPECT_EQ(expectedMatch, *match);
198 }
199 
TEST_F(LayerStackTest,getApproximateMatch_doesNotMatchManyDifferences)200 TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchManyDifferences) {
201     mock::OutputLayer outputLayerOne;
202     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
203     OutputLayerCompositionState outputLayerCompositionStateOne{
204             .visibleRegion = sRegionOne,
205             .displayFrame = sRectOne,
206             .sourceCrop = sFloatRectOne,
207             .dataspace = ui::Dataspace::SRGB,
208     };
209     LayerFECompositionState layerFECompositionStateOne;
210     layerFECompositionStateOne.alpha = sAlphaOne;
211     layerFECompositionStateOne.colorTransformIsIdentity = true;
212     layerFECompositionStateOne.blendMode = hal::BlendMode::NONE;
213     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
214                        layerFECompositionStateOne);
215     LayerState layerStateOne(&outputLayerOne);
216 
217     mock::OutputLayer outputLayerTwo;
218     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
219     OutputLayerCompositionState outputLayerCompositionStateTwo{
220             .visibleRegion = sRegionTwo,
221             .displayFrame = sRectTwo,
222             .sourceCrop = sFloatRectTwo,
223             .dataspace = ui::Dataspace::DISPLAY_P3,
224     };
225     LayerFECompositionState layerFECompositionStateTwo;
226     layerFECompositionStateTwo.alpha = sAlphaTwo;
227     layerFECompositionStateTwo.colorTransformIsIdentity = false;
228     layerFECompositionStateTwo.colorTransform = sMat4One;
229     layerFECompositionStateTwo.blendMode = hal::BlendMode::PREMULTIPLIED;
230     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
231                        layerFECompositionStateTwo);
232     LayerState layerStateTwo(&outputLayerTwo);
233 
234     LayerStack stack({&layerStateOne});
235 
236     EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo}));
237 }
238 
TEST_F(LayerStackTest,getApproximateMatch_exactMatchesSameBuffer)239 TEST_F(LayerStackTest, getApproximateMatch_exactMatchesSameBuffer) {
240     sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make();
241     mock::OutputLayer outputLayerOne;
242     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
243     OutputLayerCompositionState outputLayerCompositionStateOne;
244     LayerFECompositionState layerFECompositionStateOne;
245     layerFECompositionStateOne.buffer = buffer;
246     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
247                        layerFECompositionStateOne);
248     LayerState layerStateOne(&outputLayerOne);
249 
250     mock::OutputLayer outputLayerTwo;
251     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
252     OutputLayerCompositionState outputLayerCompositionStateTwo;
253     LayerFECompositionState layerFECompositionStateTwo;
254     layerFECompositionStateTwo.buffer = buffer;
255     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
256                        layerFECompositionStateTwo);
257     LayerState layerStateTwo(&outputLayerTwo);
258 
259     LayerStack stack({&layerStateOne});
260 
261     const auto match = stack.getApproximateMatch({&layerStateTwo});
262     EXPECT_TRUE(match);
263     LayerStack::ApproximateMatch expectedMatch;
264     expectedMatch.differingIndex = 0;
265     expectedMatch.differingFields = LayerStateField::None;
266     EXPECT_EQ(expectedMatch, *match);
267 }
268 
TEST_F(LayerStackTest,getApproximateMatch_alwaysMatchesClientComposition)269 TEST_F(LayerStackTest, getApproximateMatch_alwaysMatchesClientComposition) {
270     mock::OutputLayer outputLayerOne;
271     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
272     OutputLayerCompositionState outputLayerCompositionStateOne{
273             .visibleRegion = sRegionOne,
274             .forceClientComposition = true,
275             .displayFrame = sRectOne,
276             .sourceCrop = sFloatRectOne,
277             .dataspace = ui::Dataspace::SRGB,
278     };
279     LayerFECompositionState layerFECompositionStateOne;
280     layerFECompositionStateOne.buffer = sp<GraphicBuffer>::make();
281     layerFECompositionStateOne.alpha = sAlphaOne;
282     layerFECompositionStateOne.colorTransformIsIdentity = true;
283     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
284                        layerFECompositionStateOne);
285     LayerState layerStateOne(&outputLayerOne);
286 
287     mock::OutputLayer outputLayerTwo;
288     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
289     OutputLayerCompositionState outputLayerCompositionStateTwo{
290             .visibleRegion = sRegionTwo,
291             .forceClientComposition = true,
292             .displayFrame = sRectTwo,
293             .sourceCrop = sFloatRectTwo,
294             .dataspace = ui::Dataspace::DISPLAY_P3,
295     };
296     LayerFECompositionState layerFECompositionStateTwo;
297     layerFECompositionStateTwo.buffer = sp<GraphicBuffer>::make();
298     layerFECompositionStateTwo.alpha = sAlphaTwo;
299     layerFECompositionStateTwo.colorTransformIsIdentity = false;
300     layerFECompositionStateTwo.colorTransform = sMat4One;
301     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
302                        layerFECompositionStateTwo);
303     LayerState layerStateTwo(&outputLayerTwo);
304 
305     LayerStack stack({&layerStateOne});
306 
307     const auto match = stack.getApproximateMatch({&layerStateTwo});
308     EXPECT_TRUE(match);
309     LayerStack::ApproximateMatch expectedMatch;
310     expectedMatch.differingIndex = 0;
311     expectedMatch.differingFields = LayerStateField::None;
312     EXPECT_EQ(expectedMatch, *match);
313 }
314 
TEST_F(LayerStackTest,getApproximateMatch_doesNotMatchMultipleApproximations)315 TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchMultipleApproximations) {
316     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
317                               cache_when_source_crop_layer_only_moved,
318                       false);
319     mock::OutputLayer outputLayerOne;
320     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
321     OutputLayerCompositionState outputLayerCompositionStateOne{
322             .sourceCrop = sFloatRectOne,
323     };
324     LayerFECompositionState layerFECompositionStateOne;
325     layerFECompositionStateOne.buffer = sp<GraphicBuffer>::make();
326     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
327                        layerFECompositionStateOne);
328     LayerState layerStateOne(&outputLayerOne);
329 
330     mock::OutputLayer outputLayerTwo;
331     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
332     OutputLayerCompositionState outputLayerCompositionStateTwo{
333             .sourceCrop = sFloatRectTwo,
334     };
335     LayerFECompositionState layerFECompositionStateTwo;
336     layerFECompositionStateTwo.buffer = sp<GraphicBuffer>::make();
337     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
338                        layerFECompositionStateTwo);
339     LayerState layerStateTwo(&outputLayerTwo);
340 
341     EXPECT_TRUE(LayerStack({&layerStateOne}).getApproximateMatch({&layerStateTwo}));
342 
343     LayerStack stack({&layerStateOne, &layerStateOne});
344     EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo, &layerStateTwo}));
345 }
346 
347 struct PredictionTest : public testing::Test {
PredictionTestandroid::compositionengine::impl::planner::__anondcd1064e0111::PredictionTest348     PredictionTest() {
349         const ::testing::TestInfo* const test_info =
350                 ::testing::UnitTest::GetInstance()->current_test_info();
351         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
352     }
353 
~PredictionTestandroid::compositionengine::impl::planner::__anondcd1064e0111::PredictionTest354     ~PredictionTest() {
355         const ::testing::TestInfo* const test_info =
356                 ::testing::UnitTest::GetInstance()->current_test_info();
357         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
358     }
359 };
360 
TEST_F(LayerStackTest,reorderingChangesNonBufferHash)361 TEST_F(LayerStackTest, reorderingChangesNonBufferHash) {
362     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
363                               cache_when_source_crop_layer_only_moved,
364                       false);
365     mock::OutputLayer outputLayerOne;
366     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
367     OutputLayerCompositionState outputLayerCompositionStateOne{
368             .sourceCrop = sFloatRectOne,
369     };
370     LayerFECompositionState layerFECompositionStateOne;
371     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
372                        layerFECompositionStateOne);
373     LayerState layerStateOne(&outputLayerOne);
374 
375     mock::OutputLayer outputLayerTwo;
376     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
377     OutputLayerCompositionState outputLayerCompositionStateTwo{
378             .sourceCrop = sFloatRectTwo,
379     };
380     LayerFECompositionState layerFECompositionStateTwo;
381     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
382                        layerFECompositionStateTwo);
383     LayerState layerStateTwo(&outputLayerTwo);
384 
385     NonBufferHash hash = getNonBufferHash({&layerStateOne, &layerStateTwo});
386     NonBufferHash hashReverse = getNonBufferHash({&layerStateTwo, &layerStateOne});
387     EXPECT_NE(hash, hashReverse);
388 }
389 
TEST_F(PredictionTest,constructPrediction)390 TEST_F(PredictionTest, constructPrediction) {
391     Plan plan;
392     plan.addLayerType(Composition::DEVICE);
393 
394     Prediction prediction({}, plan);
395 
396     EXPECT_EQ(plan, prediction.getPlan());
397 
398     // check that dump doesn't crash
399     std::string result;
400     prediction.dump(result);
401 }
402 
TEST_F(PredictionTest,recordHits)403 TEST_F(PredictionTest, recordHits) {
404     Prediction prediction({}, {});
405 
406     const constexpr uint32_t kExactMatches = 2;
407     for (uint32_t i = 0; i < kExactMatches; i++) {
408         prediction.recordHit(Prediction::Type::Exact);
409     }
410 
411     const constexpr uint32_t kApproximateMatches = 3;
412     for (uint32_t i = 0; i < kApproximateMatches; i++) {
413         prediction.recordHit(Prediction::Type::Approximate);
414     }
415 
416     EXPECT_EQ(kExactMatches, prediction.getHitCount(Prediction::Type::Exact));
417     EXPECT_EQ(kApproximateMatches, prediction.getHitCount(Prediction::Type::Approximate));
418     EXPECT_EQ(kExactMatches + kApproximateMatches, prediction.getHitCount(Prediction::Type::Total));
419 }
420 
TEST_F(PredictionTest,recordMisses)421 TEST_F(PredictionTest, recordMisses) {
422     Prediction prediction({}, {});
423 
424     const constexpr uint32_t kExactMatches = 2;
425     for (uint32_t i = 0; i < kExactMatches; i++) {
426         prediction.recordMiss(Prediction::Type::Exact);
427     }
428 
429     const constexpr uint32_t kApproximateMatches = 3;
430     for (uint32_t i = 0; i < kApproximateMatches; i++) {
431         prediction.recordMiss(Prediction::Type::Approximate);
432     }
433 
434     EXPECT_EQ(kExactMatches, prediction.getMissCount(Prediction::Type::Exact));
435     EXPECT_EQ(kApproximateMatches, prediction.getMissCount(Prediction::Type::Approximate));
436     EXPECT_EQ(kExactMatches + kApproximateMatches,
437               prediction.getMissCount(Prediction::Type::Total));
438 }
439 
440 struct PredictorTest : public testing::Test {
PredictorTestandroid::compositionengine::impl::planner::__anondcd1064e0111::PredictorTest441     PredictorTest() {
442         const ::testing::TestInfo* const test_info =
443                 ::testing::UnitTest::GetInstance()->current_test_info();
444         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
445     }
446 
~PredictorTestandroid::compositionengine::impl::planner::__anondcd1064e0111::PredictorTest447     ~PredictorTest() {
448         const ::testing::TestInfo* const test_info =
449                 ::testing::UnitTest::GetInstance()->current_test_info();
450         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
451     }
452 };
453 
TEST_F(PredictorTest,getPredictedPlan_emptyLayersWithoutExactMatch_returnsNullopt)454 TEST_F(PredictorTest, getPredictedPlan_emptyLayersWithoutExactMatch_returnsNullopt) {
455     Predictor predictor;
456     EXPECT_FALSE(predictor.getPredictedPlan({}, 0));
457 }
458 
TEST_F(PredictorTest,getPredictedPlan_recordCandidateAndRetrieveExactMatch)459 TEST_F(PredictorTest, getPredictedPlan_recordCandidateAndRetrieveExactMatch) {
460     mock::OutputLayer outputLayerOne;
461     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
462     OutputLayerCompositionState outputLayerCompositionStateOne;
463     LayerFECompositionState layerFECompositionStateOne;
464     layerFECompositionStateOne.compositionType = Composition::DEVICE;
465     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
466                        layerFECompositionStateOne);
467     LayerState layerStateOne(&outputLayerOne);
468 
469     Plan plan;
470     plan.addLayerType(Composition::DEVICE);
471 
472     Predictor predictor;
473 
474     NonBufferHash hash = getNonBufferHash({&layerStateOne});
475 
476     predictor.recordResult(std::nullopt, hash, {&layerStateOne}, false, plan);
477 
478     auto predictedPlan = predictor.getPredictedPlan({}, hash);
479     EXPECT_TRUE(predictedPlan);
480     Predictor::PredictedPlan expectedPlan{hash, plan, Prediction::Type::Exact};
481     EXPECT_EQ(expectedPlan, predictedPlan);
482 }
483 
TEST_F(PredictorTest,getPredictedPlan_recordCandidateAndRetrieveApproximateMatch)484 TEST_F(PredictorTest, getPredictedPlan_recordCandidateAndRetrieveApproximateMatch) {
485     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
486                               cache_when_source_crop_layer_only_moved,
487                       false);
488     mock::OutputLayer outputLayerOne;
489     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
490     OutputLayerCompositionState outputLayerCompositionStateOne{
491             .sourceCrop = sFloatRectOne,
492     };
493     LayerFECompositionState layerFECompositionStateOne;
494     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
495                        layerFECompositionStateOne);
496     LayerState layerStateOne(&outputLayerOne);
497 
498     mock::OutputLayer outputLayerTwo;
499     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
500     OutputLayerCompositionState outputLayerCompositionStateTwo{
501             .sourceCrop = sFloatRectTwo,
502     };
503     LayerFECompositionState layerFECompositionStateTwo;
504     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
505                        layerFECompositionStateTwo);
506     LayerState layerStateTwo(&outputLayerTwo);
507 
508     Plan plan;
509     plan.addLayerType(Composition::DEVICE);
510 
511     Predictor predictor;
512 
513     NonBufferHash hashOne = getNonBufferHash({&layerStateOne});
514     NonBufferHash hashTwo = getNonBufferHash({&layerStateTwo});
515 
516     predictor.recordResult(std::nullopt, hashOne, {&layerStateOne}, false, plan);
517 
518     auto predictedPlan = predictor.getPredictedPlan({&layerStateTwo}, hashTwo);
519     EXPECT_TRUE(predictedPlan);
520     Predictor::PredictedPlan expectedPlan{hashOne, plan, Prediction::Type::Approximate};
521     EXPECT_EQ(expectedPlan, predictedPlan);
522 }
523 
TEST_F(PredictorTest,recordMissedPlan_skipsApproximateMatch)524 TEST_F(PredictorTest, recordMissedPlan_skipsApproximateMatch) {
525     SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
526                               cache_when_source_crop_layer_only_moved,
527                       false);
528     mock::OutputLayer outputLayerOne;
529     sp<mock::LayerFE> layerFEOne = sp<mock::LayerFE>::make();
530     OutputLayerCompositionState outputLayerCompositionStateOne{
531             .sourceCrop = sFloatRectOne,
532     };
533     LayerFECompositionState layerFECompositionStateOne;
534     setupMocksForLayer(outputLayerOne, *layerFEOne, outputLayerCompositionStateOne,
535                        layerFECompositionStateOne);
536     LayerState layerStateOne(&outputLayerOne);
537 
538     mock::OutputLayer outputLayerTwo;
539     sp<mock::LayerFE> layerFETwo = sp<mock::LayerFE>::make();
540     OutputLayerCompositionState outputLayerCompositionStateTwo{
541             .sourceCrop = sFloatRectTwo,
542     };
543     LayerFECompositionState layerFECompositionStateTwo;
544     setupMocksForLayer(outputLayerTwo, *layerFETwo, outputLayerCompositionStateTwo,
545                        layerFECompositionStateTwo);
546     LayerState layerStateTwo(&outputLayerTwo);
547 
548     Plan plan;
549     plan.addLayerType(Composition::DEVICE);
550 
551     Predictor predictor;
552 
553     NonBufferHash hashOne = getNonBufferHash({&layerStateOne});
554     NonBufferHash hashTwo = getNonBufferHash({&layerStateTwo});
555 
556     predictor.recordResult(std::nullopt, hashOne, {&layerStateOne}, false, plan);
557 
558     auto predictedPlan = predictor.getPredictedPlan({&layerStateTwo}, hashTwo);
559     ASSERT_TRUE(predictedPlan);
560     EXPECT_EQ(Prediction::Type::Approximate, predictedPlan->type);
561 
562     Plan planTwo;
563     planTwo.addLayerType(Composition::CLIENT);
564     predictor.recordResult(predictedPlan, hashTwo, {&layerStateTwo}, false, planTwo);
565     // Now trying to retrieve the predicted plan again returns a nullopt instead.
566     // TODO(b/158790260): Even though this is enforced in this test, we might want to reassess this.
567     // One of the implications around this implementation is that if we miss a prediction then we
568     // can never actually correct our mistake if we see the same layer stack again, which doesn't
569     // seem robust.
570     auto predictedPlanTwo = predictor.getPredictedPlan({&layerStateTwo}, hashTwo);
571     EXPECT_FALSE(predictedPlanTwo);
572 }
573 
574 } // namespace
575 } // namespace android::compositionengine::impl::planner
576