Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 027d3655 authored by Dan Stoza's avatar Dan Stoza
Browse files

SF: Reconfirm all period changes, ignore HWC

This change includes two separate fixes to make waking up from idle more
robust when using a kernel idle timer:

  1) Always reconfirm the refresh rate when we resync to hardware vsync.
     This is because if the kernel idle timer is enabled, we may not
     immediately be in the refresh rate we expect to be.
  2) Ignore the refresh rate reported by the hardware vsync callbacks,
     since that refresh rate may not reflect the actual refresh rate
     when the kernel idle timer is in effect.

Bug: 154303580
Test: systrace
Test: libsurfaceflinger_unittest
Change-Id: I79c66faeaed262acd9c5925fe2202a9fb3f10b7b
parent 9b5bf0f4
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@

namespace android {

std::unique_ptr<DispSync> createDispSync() {
std::unique_ptr<DispSync> createDispSync(bool supportKernelTimer) {
    // TODO (140302863) remove this and use the vsync_reactor system.
    if (property_get_bool("debug.sf.vsync_reactor", true)) {
        // TODO (144707443) tune Predictor tunables.
@@ -90,7 +90,7 @@ std::unique_ptr<DispSync> createDispSync() {
        static constexpr size_t pendingFenceLimit = 20;
        return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
                                                         std::move(dispatch), std::move(tracker),
                                                         pendingFenceLimit);
                                                         pendingFenceLimit, supportKernelTimer);
    } else {
        return std::make_unique<impl::DispSync>("SchedulerDispSync",
                                                sysprop::running_without_sync_framework(true));
@@ -101,9 +101,9 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                     const scheduler::RefreshRateConfigs& refreshRateConfig,
                     ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
                     bool useContentDetection)
      : mPrimaryDispSync(createDispSync()),
      : mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
        mPrimaryDispSync(createDispSync(mSupportKernelTimer)),
        mEventControlThread(new impl::EventControlThread(std::move(function))),
        mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(refreshRateConfig),
        mUseContentDetection(useContentDetection),
@@ -151,9 +151,9 @@ Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
                     const scheduler::RefreshRateConfigs& configs,
                     ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
                     bool useContentDetection)
      : mPrimaryDispSync(std::move(primaryDispSync)),
      : mSupportKernelTimer(false),
        mPrimaryDispSync(std::move(primaryDispSync)),
        mEventControlThread(std::move(eventControlThread)),
        mSupportKernelTimer(false),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(configs),
        mUseContentDetection(useContentDetection),
+3 −3
Original line number Diff line number Diff line
@@ -205,15 +205,15 @@ private:

    std::atomic<nsecs_t> mLastResyncTime = 0;

    // Whether to use idle timer callbacks that support the kernel timer.
    const bool mSupportKernelTimer;

    std::unique_ptr<DispSync> mPrimaryDispSync;
    std::unique_ptr<EventControlThread> mEventControlThread;

    // Used to choose refresh rate if content detection is enabled.
    std::unique_ptr<scheduler::LayerHistory> mLayerHistory;

    // Whether to use idle timer callbacks that support the kernel timer.
    const bool mSupportKernelTimer;

    // Timer that records time between requests for next vsync.
    std::optional<scheduler::OneShotTimer> mIdleTimer;
    // Timer used to monitor touch events.
+11 −3
Original line number Diff line number Diff line
@@ -56,14 +56,16 @@ private:
};

VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
                           std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit)
                           std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
                           bool supportKernelIdleTimer)
      : mClock(std::move(clock)),
        mTracker(std::move(tracker)),
        mDispatch(std::move(dispatch)),
        mPendingLimit(pendingFenceLimit),
        mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
                                      ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
                                      : nullptr) {}
                                      : nullptr),
        mSupportKernelIdleTimer(supportKernelIdleTimer) {}

VSyncReactor::~VSyncReactor() = default;

@@ -249,7 +251,8 @@ void VSyncReactor::setPeriod(nsecs_t period) {
    ATRACE_INT64("VSR-setPeriod", period);
    std::lock_guard lk(mMutex);
    mLastHwVsync.reset();
    if (period == getPeriod()) {

    if (!mSupportKernelIdleTimer && period == getPeriod()) {
        endPeriodTransition();
    } else {
        startPeriodTransition(period);
@@ -275,6 +278,11 @@ bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp, std::optional<nsecs_
        return false;
    }

    if (mSupportKernelIdleTimer) {
        // Clear out the Composer-provided period and use the allowance logic below
        HwcVsyncPeriod = {};
    }

    auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : getPeriod();
    static constexpr int allowancePercent = 10;
    static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio;
+3 −1
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ class PredictedVsyncTracer;
class VSyncReactor : public android::DispSync {
public:
    VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
                 std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit);
                 std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
                 bool supportKernelIdleTimer);
    ~VSyncReactor();

    bool addPresentFence(const std::shared_ptr<FenceTime>& fence) final;
@@ -89,6 +90,7 @@ private:
            GUARDED_BY(mMutex);

    const std::unique_ptr<PredictedVsyncTracer> mPredictedVsyncTracer;
    const bool mSupportKernelIdleTimer = false;
};

class SystemClock : public Clock {
+24 −1
Original line number Diff line number Diff line
@@ -157,7 +157,8 @@ protected:
            mMockClock(std::make_shared<NiceMock<MockClock>>()),
            mReactor(std::make_unique<ClockWrapper>(mMockClock),
                     std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
                     std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit) {
                     std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit,
                     false /* supportKernelIdleTimer */) {
        ON_CALL(*mMockClock, now()).WillByDefault(Return(mFakeNow));
        ON_CALL(*mMockTracker, currentPeriod()).WillByDefault(Return(period));
    }
@@ -663,6 +664,28 @@ TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {
    EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}

TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
    // Create a reactor which supports the kernel idle timer
    auto idleReactor = VSyncReactor(std::make_unique<ClockWrapper>(mMockClock),
                                    std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
                                    std::make_unique<VSyncTrackerWrapper>(mMockTracker),
                                    kPendingLimit, true /* supportKernelIdleTimer */);

    bool periodFlushed = true;
    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
    idleReactor.setIgnorePresentFences(true);

    nsecs_t const newPeriod = 5000;
    idleReactor.setPeriod(newPeriod);

    EXPECT_TRUE(idleReactor.addResyncSample(0, 0, &periodFlushed));
    EXPECT_FALSE(periodFlushed);
    EXPECT_FALSE(idleReactor.addResyncSample(newPeriod, 0, &periodFlushed));
    EXPECT_TRUE(periodFlushed);

    EXPECT_TRUE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}

using VSyncReactorDeathTest = VSyncReactorTest;
TEST_F(VSyncReactorDeathTest, invalidRemoval) {
    mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);