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