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