1 /*
2 * Copyright 2023 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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19
20 #include <gui/SurfaceComposerClient.h>
21 #include "DisplayHardware/Hal.h"
22 #include "DisplayTransactionTestHelpers.h"
23
24 namespace android {
25
26 using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
27 using android::hardware::graphics::composer::hal::Error;
28
29 class NotifyExpectedPresentTest : public DisplayTransactionTest {
30 public:
SetUp()31 void SetUp() override {
32 const auto display = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this).inject();
33 mPhysicalDisplayId = display->getPhysicalId();
34 FakeHwcDisplayInjector(mPhysicalDisplayId, hal::DisplayType::PHYSICAL, /*isPrimary=*/true)
35 .setPowerMode(hal::PowerMode::ON)
36 .inject(&mFlinger, mComposer);
37
38 ASSERT_NO_FATAL_FAILURE(mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId,
39 TimePoint::fromNs(0),
40 kFps60Hz));
41 mCompositor = std::make_unique<Compositor>(mPhysicalDisplayId, mFlinger);
42 }
43
44 protected:
setTransactionState()45 void setTransactionState() {
46 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
47 TransactionInfo transaction;
48 mFlinger.setTransactionState(FrameTimelineInfo{}, transaction.states, transaction.displays,
49 transaction.flags, transaction.applyToken,
50 transaction.inputWindowCommands,
51 TimePoint::now().ns() + s2ns(1), transaction.isAutoTimestamp,
52 transaction.unCachedBuffers,
53 /*HasListenerCallbacks=*/false, transaction.callbacks,
54 transaction.id, transaction.mergedTransactionIds);
55 }
56
57 struct TransactionInfo {
58 Vector<ComposerState> states;
59 Vector<DisplayState> displays;
60 uint32_t flags = 0;
61 sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
62 InputWindowCommands inputWindowCommands;
63 int64_t desiredPresentTime = 0;
64 bool isAutoTimestamp = false;
65 FrameTimelineInfo frameTimelineInfo{};
66 std::vector<client_cache_t> unCachedBuffers;
67 uint64_t id = static_cast<uint64_t>(-1);
68 std::vector<uint64_t> mergedTransactionIds;
69 std::vector<ListenerCallbacks> callbacks;
70 };
71
72 struct Compositor final : ICompositor {
Compositorandroid::NotifyExpectedPresentTest::Compositor73 explicit Compositor(PhysicalDisplayId displayId, TestableSurfaceFlinger& surfaceFlinger)
74 : displayId(displayId), surfaceFlinger(surfaceFlinger) {}
75
sendNotifyExpectedPresentHintandroid::NotifyExpectedPresentTest::Compositor76 void sendNotifyExpectedPresentHint(PhysicalDisplayId id) override {
77 surfaceFlinger.sendNotifyExpectedPresentHint(id);
78 }
79
commitandroid::NotifyExpectedPresentTest::Compositor80 bool commit(PhysicalDisplayId, const scheduler::FrameTargets&) override {
81 return committed;
82 }
83
compositeandroid::NotifyExpectedPresentTest::Compositor84 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
85 const scheduler::FrameTargeters& targeters) override {
86 pacesetterIds.composite = pacesetterId;
87 CompositeResultsPerDisplay results;
88
89 for (const auto& [id, targeter] : targeters) {
90 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
91 surfaceFlinger.resetNotifyExpectedPresentHintState(pacesetterId);
92 results.try_emplace(id,
93 CompositeResult{.compositionCoverage =
94 CompositionCoverage::Hwc});
95 }
96
97 return results;
98 }
99
sampleandroid::NotifyExpectedPresentTest::Compositor100 void sample() override {}
configureandroid::NotifyExpectedPresentTest::Compositor101 void configure() override {}
102
103 struct {
104 PhysicalDisplayId commit;
105 PhysicalDisplayId composite;
106 } pacesetterIds;
107
108 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
109 struct {
110 VsyncIds commit;
111 VsyncIds composite;
112 } vsyncIds;
113
114 bool committed = true;
115 PhysicalDisplayId displayId;
116 TestableSurfaceFlinger& surfaceFlinger;
117 };
118
119 PhysicalDisplayId mPhysicalDisplayId;
120 std::unique_ptr<Compositor> mCompositor;
121 static constexpr hal::HWDisplayId kHwcDisplayId =
122 FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
123 static constexpr Fps kFps60Hz = 60_Hz;
124 static constexpr int32_t kFrameInterval5HzNs = static_cast<Fps>(5_Hz).getPeriodNsecs();
125 static constexpr int32_t kFrameInterval60HzNs = kFps60Hz.getPeriodNsecs();
126 static constexpr int32_t kFrameInterval120HzNs = static_cast<Fps>(120_Hz).getPeriodNsecs();
127 static constexpr Period kVsyncPeriod =
128 Period::fromNs(static_cast<Fps>(240_Hz).getPeriodNsecs());
129 static constexpr Period kTimeoutNs = Period::fromNs(kFrameInterval5HzNs);
130 };
131
TEST_F(NotifyExpectedPresentTest,noNotifyExpectedPresentHintCall_absentTimeout)132 TEST_F(NotifyExpectedPresentTest, noNotifyExpectedPresentHintCall_absentTimeout) {
133 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
134 ASSERT_NO_FATAL_FAILURE(
135 mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId,
136 TimePoint::fromNs(expectedPresentTime),
137 kFps60Hz));
138 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
139 for (int i = 0; i < 5; i++) {
140 expectedPresentTime += 2 * kFrameInterval5HzNs;
141 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
142 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
143 /*timeoutOpt*/ std::nullopt);
144 EXPECT_TRUE(
145 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
146 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
147 }
148 }
149
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentHint_zeroTimeout)150 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) {
151 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
152 {
153 // Very first ExpectedPresent after idle, no previous timestamp.
154 EXPECT_CALL(*mComposer,
155 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
156 .WillOnce(Return(Error::NONE));
157 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
158 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
159 kTimeoutNs);
160 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
161
162 // Present frame
163 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
164 // Present happens and NotifyExpectedPresentHintStatus is start.
165 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
166 }
167 {
168 mCompositor->committed = false;
169 expectedPresentTime += kFrameInterval60HzNs;
170 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
171 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
172 nextAnticipatedVSyncTimeFrom(_, _))
173 .WillRepeatedly(Return(expectedPresentTime));
174 EXPECT_CALL(*mComposer,
175 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
176 .WillOnce(Return(Error::NONE));
177 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
178 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
179 Period::fromNs(0));
180 EXPECT_TRUE(
181 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
182 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
183 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
184 // Hint sent
185 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
186 }
187 {
188 expectedPresentTime += kFrameInterval60HzNs;
189 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
190 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
191 nextAnticipatedVSyncTimeFrom(_, _))
192 .WillRepeatedly(Return(expectedPresentTime));
193 EXPECT_CALL(*mComposer,
194 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
195 .WillOnce(Return(Error::NONE));
196 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
197 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
198 Period::fromNs(0));
199 EXPECT_TRUE(
200 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
201 // Hint is executed
202 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
203 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
204 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
205 }
206 }
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentTimeout)207 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) {
208 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
209 {
210 // Very first ExpectedPresent after idle, no previous timestamp
211 mCompositor->committed = false;
212 EXPECT_CALL(*mComposer,
213 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
214 .WillOnce(Return(Error::NONE));
215 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
216 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
217 kTimeoutNs);
218 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
219 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
220 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
221 }
222 {
223 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
224 expectedPresentTime += 2 * kFrameInterval5HzNs;
225 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
226 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
227 kTimeoutNs);
228 EXPECT_TRUE(
229 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
230 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
231 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
232 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
233 {
234 EXPECT_CALL(*mComposer,
235 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime,
236 kFrameInterval60HzNs))
237 .WillOnce(Return(Error::NONE));
238 // Hint sent with the setTransactionState
239 setTransactionState();
240 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
241 }
242 }
243 {
244 // ExpectedPresentTime is after the timeoutNs
245 mCompositor->committed = true;
246 expectedPresentTime += 2 * kFrameInterval5HzNs;
247 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
248 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
249 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
250 kTimeoutNs);
251 EXPECT_TRUE(
252 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
253 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
254 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
255 // Present happens notifyExpectedPresentHintStatus is Start
256 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
257
258 // Another expectedPresent after timeout
259 expectedPresentTime += 2 * kFrameInterval5HzNs;
260 EXPECT_CALL(*mComposer,
261 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
262 .WillOnce(Return(Error::NONE));
263 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
264 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
265 kTimeoutNs);
266 EXPECT_TRUE(
267 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
268 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
269 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
270 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
271 }
272 {
273 // ExpectedPresent has not changed
274 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
275 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
276 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
277 kTimeoutNs);
278 EXPECT_TRUE(
279 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
280 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
281 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
282 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
283 }
284 {
285 // ExpectedPresent is after the last reported ExpectedPresent and within timeout.
286 expectedPresentTime += kFrameInterval60HzNs;
287 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
288 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
289 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
290 kTimeoutNs);
291 EXPECT_TRUE(
292 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
293 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
294 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
295 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
296 }
297 {
298 // ExpectedPresent is before the last reported ExpectedPresent but after the timeoutNs,
299 // representing we changed our decision and want to present earlier than previously
300 // reported.
301 mCompositor->committed = false;
302 expectedPresentTime -= kFrameInterval120HzNs;
303 EXPECT_CALL(*mComposer,
304 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
305 .WillOnce(Return(Error::NONE));
306 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
307 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
308 kTimeoutNs);
309 EXPECT_TRUE(
310 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
311 ASSERT_TRUE(mFlinger.verifyHintIsScheduledOnPresent(mPhysicalDisplayId));
312 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
313 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
314 }
315 }
316
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentRenderRateChanged)317 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentRenderRateChanged) {
318 const auto now = TimePoint::now().ns();
319 auto expectedPresentTime = now;
320 static constexpr Period kTimeoutNs = Period::fromNs(static_cast<Fps>(1_Hz).getPeriodNsecs());
321
322 ASSERT_NO_FATAL_FAILURE(mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId,
323 TimePoint::fromNs(now),
324 Fps::fromValue(0)));
325 static constexpr int32_t kFrameIntervalNs120Hz = static_cast<Fps>(120_Hz).getPeriodNsecs();
326 static constexpr int32_t kFrameIntervalNs96Hz = static_cast<Fps>(96_Hz).getPeriodNsecs();
327 static constexpr int32_t kFrameIntervalNs80Hz = static_cast<Fps>(80_Hz).getPeriodNsecs();
328 static constexpr int32_t kFrameIntervalNs60Hz = static_cast<Fps>(60_Hz).getPeriodNsecs();
329 static constexpr int32_t kFrameIntervalNs40Hz = static_cast<Fps>(40_Hz).getPeriodNsecs();
330 static constexpr int32_t kFrameIntervalNs30Hz = static_cast<Fps>(30_Hz).getPeriodNsecs();
331 static constexpr int32_t kFrameIntervalNs24Hz = static_cast<Fps>(24_Hz).getPeriodNsecs();
332 static constexpr int32_t kFrameIntervalNs20Hz = static_cast<Fps>(20_Hz).getPeriodNsecs();
333 static constexpr Period kVsyncPeriod =
334 Period::fromNs(static_cast<Fps>(240_Hz).getPeriodNsecs());
335
336 struct FrameRateIntervalTestData {
337 int32_t frameIntervalNs;
338 bool callNotifyExpectedPresentHint;
339 };
340 const std::vector<FrameRateIntervalTestData> frameIntervals = {
341 {kFrameIntervalNs60Hz, true}, {kFrameIntervalNs96Hz, true},
342 {kFrameIntervalNs80Hz, true}, {kFrameIntervalNs120Hz, true},
343 {kFrameIntervalNs80Hz, true}, {kFrameIntervalNs60Hz, true},
344 {kFrameIntervalNs60Hz, false}, {kFrameIntervalNs30Hz, false},
345 {kFrameIntervalNs24Hz, true}, {kFrameIntervalNs40Hz, true},
346 {kFrameIntervalNs20Hz, false}, {kFrameIntervalNs60Hz, true},
347 {kFrameIntervalNs20Hz, false}, {kFrameIntervalNs120Hz, true},
348 };
349
350 for (size_t i = 0; i < frameIntervals.size(); i++) {
351 const auto& [frameIntervalNs, callNotifyExpectedPresentHint] = frameIntervals[i];
352 expectedPresentTime += frameIntervalNs;
353 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
354 TimePoint::fromNs(expectedPresentTime),
355 Fps::fromPeriodNsecs(frameIntervalNs), kTimeoutNs);
356
357 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
358 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
359 nextAnticipatedVSyncTimeFrom(_, _))
360 .WillRepeatedly(Return(expectedPresentTime));
361 if (callNotifyExpectedPresentHint) {
362 mCompositor->committed = false;
363 ASSERT_TRUE(mFlinger.verifyHintIsScheduledOnPresent(mPhysicalDisplayId))
364 << "Hint not scheduled for frameInterval " << frameIntervalNs << " at index "
365 << i;
366 EXPECT_CALL(*mComposer,
367 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
368 .WillOnce(Return(Error::NONE));
369 } else {
370 // Only lastExpectedPresentTime is updated
371 EXPECT_TRUE(
372 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime))
373 << "LastExpectedPresentTime for frameInterval " << frameIntervalNs
374 << "at index " << i << " did not match for frameInterval " << frameIntervalNs;
375 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
376 }
377 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
378
379 if (callNotifyExpectedPresentHint) {
380 // Present resumes the calls to the notifyExpectedPresentHint.
381 mCompositor->committed = true;
382 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
383 }
384 }
385 }
386 } // namespace android