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