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