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