• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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