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