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(std::move(transaction));
49 }
50
51 struct TransactionInfo : public TransactionState {
TransactionInfoandroid::NotifyExpectedPresentTest::TransactionInfo52 TransactionInfo() {
53 mApplyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
54 mIsAutoTimestamp = false;
55 mId = static_cast<uint64_t>(-1);
56 }
57 };
58
59 struct Compositor final : ICompositor {
Compositorandroid::NotifyExpectedPresentTest::Compositor60 explicit Compositor(PhysicalDisplayId displayId, TestableSurfaceFlinger& surfaceFlinger)
61 : displayId(displayId), surfaceFlinger(surfaceFlinger) {}
62
sendNotifyExpectedPresentHintandroid::NotifyExpectedPresentTest::Compositor63 void sendNotifyExpectedPresentHint(PhysicalDisplayId id) override {
64 surfaceFlinger.sendNotifyExpectedPresentHint(id);
65 }
66
commitandroid::NotifyExpectedPresentTest::Compositor67 bool commit(PhysicalDisplayId, const scheduler::FrameTargets&) override {
68 return committed;
69 }
70
compositeandroid::NotifyExpectedPresentTest::Compositor71 CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
72 const scheduler::FrameTargeters& targeters) override {
73 pacesetterIds.composite = pacesetterId;
74 CompositeResultsPerDisplay results;
75
76 for (const auto& [id, targeter] : targeters) {
77 vsyncIds.composite.emplace_back(id, targeter->target().vsyncId());
78 surfaceFlinger.resetNotifyExpectedPresentHintState(pacesetterId);
79 results.try_emplace(id,
80 CompositeResult{.compositionCoverage =
81 CompositionCoverage::Hwc});
82 }
83
84 return results;
85 }
86
sampleandroid::NotifyExpectedPresentTest::Compositor87 void sample() override {}
configureandroid::NotifyExpectedPresentTest::Compositor88 void configure() override {}
89
90 struct {
91 PhysicalDisplayId commit;
92 PhysicalDisplayId composite;
93 } pacesetterIds;
94
95 using VsyncIds = std::vector<std::pair<PhysicalDisplayId, VsyncId>>;
96 struct {
97 VsyncIds commit;
98 VsyncIds composite;
99 } vsyncIds;
100
101 bool committed = true;
102 PhysicalDisplayId displayId;
103 TestableSurfaceFlinger& surfaceFlinger;
104 };
105
106 PhysicalDisplayId mPhysicalDisplayId;
107 std::unique_ptr<Compositor> mCompositor;
108 static constexpr hal::HWDisplayId kHwcDisplayId =
109 FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
110 static constexpr Fps kFps60Hz = 60_Hz;
111 static constexpr int32_t kFrameInterval5HzNs = static_cast<Fps>(5_Hz).getPeriodNsecs();
112 static constexpr int32_t kFrameInterval60HzNs = kFps60Hz.getPeriodNsecs();
113 static constexpr int32_t kFrameInterval120HzNs = static_cast<Fps>(120_Hz).getPeriodNsecs();
114 static constexpr Period kVsyncPeriod =
115 Period::fromNs(static_cast<Fps>(240_Hz).getPeriodNsecs());
116 static constexpr Period kTimeoutNs = Period::fromNs(kFrameInterval5HzNs);
117 };
118
TEST_F(NotifyExpectedPresentTest,noNotifyExpectedPresentHintCall_absentTimeout)119 TEST_F(NotifyExpectedPresentTest, noNotifyExpectedPresentHintCall_absentTimeout) {
120 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
121 ASSERT_NO_FATAL_FAILURE(
122 mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId,
123 TimePoint::fromNs(expectedPresentTime),
124 kFps60Hz));
125 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
126 for (int i = 0; i < 5; i++) {
127 expectedPresentTime += 2 * kFrameInterval5HzNs;
128 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
129 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
130 /*timeoutOpt*/ std::nullopt);
131 EXPECT_TRUE(
132 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
133 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
134 }
135 }
136
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentHint_zeroTimeout)137 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentHint_zeroTimeout) {
138 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
139 {
140 // Very first ExpectedPresent after idle, no previous timestamp.
141 EXPECT_CALL(*mComposer,
142 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
143 .WillOnce(Return(Error::NONE));
144 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
145 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
146 kTimeoutNs);
147 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
148
149 // Present frame
150 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
151 // Present happens and NotifyExpectedPresentHintStatus is start.
152 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
153 }
154 {
155 mCompositor->committed = false;
156 expectedPresentTime += kFrameInterval60HzNs;
157 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
158 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
159 nextAnticipatedVSyncTimeFrom(_, _))
160 .WillRepeatedly(Return(expectedPresentTime));
161 EXPECT_CALL(*mComposer,
162 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
163 .WillOnce(Return(Error::NONE));
164 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
165 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
166 Period::fromNs(0));
167 EXPECT_TRUE(
168 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
169 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
170 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
171 // Hint sent
172 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
173 }
174 {
175 expectedPresentTime += kFrameInterval60HzNs;
176 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
177 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
178 nextAnticipatedVSyncTimeFrom(_, _))
179 .WillRepeatedly(Return(expectedPresentTime));
180 EXPECT_CALL(*mComposer,
181 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
182 .WillOnce(Return(Error::NONE));
183 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
184 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
185 Period::fromNs(0));
186 EXPECT_TRUE(
187 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
188 // Hint is executed
189 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
190 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
191 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
192 }
193 }
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentTimeout)194 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentTimeout) {
195 auto expectedPresentTime = TimePoint::now().ns() + ms2ns(10);
196 {
197 // Very first ExpectedPresent after idle, no previous timestamp
198 mCompositor->committed = false;
199 EXPECT_CALL(*mComposer,
200 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
201 .WillOnce(Return(Error::NONE));
202 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
203 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
204 kTimeoutNs);
205 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
206 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
207 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
208 }
209 {
210 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
211 expectedPresentTime += 2 * kFrameInterval5HzNs;
212 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
213 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
214 kTimeoutNs);
215 EXPECT_TRUE(
216 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
217 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
218 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
219 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
220 {
221 EXPECT_CALL(*mComposer,
222 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime,
223 kFrameInterval60HzNs))
224 .WillOnce(Return(Error::NONE));
225 // Hint sent with the setTransactionState
226 setTransactionState();
227 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
228 }
229 }
230 {
231 // ExpectedPresentTime is after the timeoutNs
232 mCompositor->committed = true;
233 expectedPresentTime += 2 * kFrameInterval5HzNs;
234 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
235 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
236 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
237 kTimeoutNs);
238 EXPECT_TRUE(
239 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
240 ASSERT_TRUE(mFlinger.verifyHintStatusIsScheduledOnTx(mPhysicalDisplayId));
241 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
242 // Present happens notifyExpectedPresentHintStatus is Start
243 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
244
245 // Another expectedPresent after timeout
246 expectedPresentTime += 2 * kFrameInterval5HzNs;
247 EXPECT_CALL(*mComposer,
248 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
249 .WillOnce(Return(Error::NONE));
250 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
251 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
252 kTimeoutNs);
253 EXPECT_TRUE(
254 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
255 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
256 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
257 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
258 }
259 {
260 // ExpectedPresent has not changed
261 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
262 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
263 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
264 kTimeoutNs);
265 EXPECT_TRUE(
266 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
267 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
268 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
269 ASSERT_TRUE(mFlinger.verifyHintStatusIsStart(mPhysicalDisplayId));
270 }
271 {
272 // ExpectedPresent is after the last reported ExpectedPresent and within timeout.
273 expectedPresentTime += kFrameInterval60HzNs;
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 before the last reported ExpectedPresent but after the timeoutNs,
286 // representing we changed our decision and want to present earlier than previously
287 // reported.
288 mCompositor->committed = false;
289 expectedPresentTime -= kFrameInterval120HzNs;
290 EXPECT_CALL(*mComposer,
291 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, kFrameInterval60HzNs))
292 .WillOnce(Return(Error::NONE));
293 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
294 TimePoint::fromNs(expectedPresentTime), kFps60Hz,
295 kTimeoutNs);
296 EXPECT_TRUE(
297 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime));
298 ASSERT_TRUE(mFlinger.verifyHintIsScheduledOnPresent(mPhysicalDisplayId));
299 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
300 ASSERT_TRUE(mFlinger.verifyHintIsSent(mPhysicalDisplayId));
301 }
302 }
303
TEST_F(NotifyExpectedPresentTest,notifyExpectedPresentRenderRateChanged)304 TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentRenderRateChanged) {
305 const auto now = TimePoint::now().ns();
306 auto expectedPresentTime = now;
307 static constexpr Period kTimeoutNs = Period::fromNs(static_cast<Fps>(1_Hz).getPeriodNsecs());
308
309 ASSERT_NO_FATAL_FAILURE(mFlinger.setNotifyExpectedPresentData(mPhysicalDisplayId,
310 TimePoint::fromNs(now),
311 Fps::fromValue(0)));
312 static constexpr int32_t kFrameIntervalNs120Hz = static_cast<Fps>(120_Hz).getPeriodNsecs();
313 static constexpr int32_t kFrameIntervalNs96Hz = static_cast<Fps>(96_Hz).getPeriodNsecs();
314 static constexpr int32_t kFrameIntervalNs80Hz = static_cast<Fps>(80_Hz).getPeriodNsecs();
315 static constexpr int32_t kFrameIntervalNs60Hz = static_cast<Fps>(60_Hz).getPeriodNsecs();
316 static constexpr int32_t kFrameIntervalNs40Hz = static_cast<Fps>(40_Hz).getPeriodNsecs();
317 static constexpr int32_t kFrameIntervalNs30Hz = static_cast<Fps>(30_Hz).getPeriodNsecs();
318 static constexpr int32_t kFrameIntervalNs24Hz = static_cast<Fps>(24_Hz).getPeriodNsecs();
319 static constexpr int32_t kFrameIntervalNs20Hz = static_cast<Fps>(20_Hz).getPeriodNsecs();
320 static constexpr Period kVsyncPeriod =
321 Period::fromNs(static_cast<Fps>(240_Hz).getPeriodNsecs());
322
323 struct FrameRateIntervalTestData {
324 int32_t frameIntervalNs;
325 bool callNotifyExpectedPresentHint;
326 };
327 const std::vector<FrameRateIntervalTestData> frameIntervals = {
328 {kFrameIntervalNs60Hz, true}, {kFrameIntervalNs96Hz, true},
329 {kFrameIntervalNs80Hz, true}, {kFrameIntervalNs120Hz, true},
330 {kFrameIntervalNs80Hz, true}, {kFrameIntervalNs60Hz, true},
331 {kFrameIntervalNs60Hz, false}, {kFrameIntervalNs30Hz, false},
332 {kFrameIntervalNs24Hz, true}, {kFrameIntervalNs40Hz, true},
333 {kFrameIntervalNs20Hz, false}, {kFrameIntervalNs60Hz, true},
334 {kFrameIntervalNs20Hz, false}, {kFrameIntervalNs120Hz, true},
335 };
336
337 for (size_t i = 0; i < frameIntervals.size(); i++) {
338 const auto& [frameIntervalNs, callNotifyExpectedPresentHint] = frameIntervals[i];
339 expectedPresentTime += frameIntervalNs;
340 mFlinger.notifyExpectedPresentIfRequired(mPhysicalDisplayId, kVsyncPeriod,
341 TimePoint::fromNs(expectedPresentTime),
342 Fps::fromPeriodNsecs(frameIntervalNs), kTimeoutNs);
343
344 EXPECT_CALL(static_cast<mock::VSyncTracker&>(
345 mFlinger.scheduler()->getVsyncSchedule()->getTracker()),
346 nextAnticipatedVSyncTimeFrom(_, _))
347 .WillRepeatedly(Return(expectedPresentTime));
348 if (callNotifyExpectedPresentHint) {
349 mCompositor->committed = false;
350 ASSERT_TRUE(mFlinger.verifyHintIsScheduledOnPresent(mPhysicalDisplayId))
351 << "Hint not scheduled for frameInterval " << frameIntervalNs << " at index "
352 << i;
353 EXPECT_CALL(*mComposer,
354 notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
355 .WillOnce(Return(Error::NONE));
356 } else {
357 // Only lastExpectedPresentTime is updated
358 EXPECT_TRUE(
359 mFlinger.verifyLastExpectedPresentTime(mPhysicalDisplayId, expectedPresentTime))
360 << "LastExpectedPresentTime for frameInterval " << frameIntervalNs
361 << "at index " << i << " did not match for frameInterval " << frameIntervalNs;
362 EXPECT_CALL(*mComposer, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
363 }
364 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
365
366 if (callNotifyExpectedPresentHint) {
367 // Present resumes the calls to the notifyExpectedPresentHint.
368 mCompositor->committed = true;
369 mFlinger.scheduler()->doFrameSignal(*mCompositor, VsyncId{42});
370 }
371 }
372 }
373 } // namespace android
374