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

Commit 57a40d9d authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Tweak wakeup time for OneShotTimer to reduce jank" into tm-dev

parents a0292d14 b4ad3600
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -118,17 +118,18 @@ void OneShotTimer::loop() {
        auto triggerTime = mClock->now() + mInterval;
        state = TimerState::WAITING;
        while (true) {
            // Wait until triggerTime time to check if we need to reset or drop into the idle state.
            if (const auto triggerInterval = triggerTime - mClock->now(); triggerInterval > 0ns) {
                mWaiting = true;
            constexpr auto zero = std::chrono::steady_clock::duration::zero();
            // Wait for mInterval time to check if we need to reset or drop into the idle state.
                struct timespec ts;
            calculateTimeoutTime(std::chrono::nanoseconds(mInterval), &ts);
                calculateTimeoutTime(triggerInterval, &ts);
                int result = sem_clockwait(&mSemaphore, CLOCK_MONOTONIC, &ts);
                if (result && errno != ETIMEDOUT && errno != EINTR) {
                    std::stringstream ss;
                    ss << "sem_clockwait failed (" << errno << ")";
                    LOG_ALWAYS_FATAL("%s", ss.str().c_str());
                }
            }

            mWaiting = false;
            state = checkForResetAndStop(state);
@@ -136,7 +137,7 @@ void OneShotTimer::loop() {
                break;
            }

            if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= zero) {
            if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= 0ns) {
                triggerTimeout = true;
                state = TimerState::IDLE;
                break;
+34 −0
Original line number Diff line number Diff line
@@ -130,6 +130,40 @@ TEST_F(OneShotTimerTest, DISABLED_resetBackToBackTest) {
    EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value());
}

// TODO(b/186417847) This test is new and passes locally, but may be flaky
TEST_F(OneShotTimerTest, DISABLED_resetBackToBackSlowAdvanceTest) {
    fake::FakeClock* clock = new fake::FakeClock();
    mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
                                                           mResetTimerCallback.getInvocable(),
                                                           mExpiredTimerCallback.getInvocable(),
                                                           std::unique_ptr<fake::FakeClock>(clock));
    mIdleTimer->start();
    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());

    mIdleTimer->reset();
    EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value());
    EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value());

    clock->advanceTime(200us);
    mIdleTimer->reset();

    // Normally we would check that the timer callbacks weren't invoked here
    // after resetting the timer, but we need to precisely control the timing of
    // this test, and checking that callbacks weren't invoked requires non-zero
    // time.

    clock->advanceTime(1500us);
    EXPECT_TRUE(mExpiredTimerCallback.waitForCall(1100us).has_value());
    mIdleTimer->reset();
    EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());

    mIdleTimer->stop();
    clock->advanceTime(2ms);
    // Final quick check that no more callback were observed.
    EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value());
    EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value());
}

TEST_F(OneShotTimerTest, startNotCalledTest) {
    fake::FakeClock* clock = new fake::FakeClock();
    mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,