Merge "updates to libarect_headers to include in media apex modules" into tm-dev
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
index 9c6e56d..3c8dc64 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -118,16 +118,17 @@
         auto triggerTime = mClock->now() + mInterval;
         state = TimerState::WAITING;
         while (true) {
-            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);
-            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());
+            // 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;
+                struct timespec 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;
@@ -136,7 +137,7 @@
                 break;
             }
 
-            if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= zero) {
+            if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= 0ns) {
                 triggerTimeout = true;
                 state = TimerState::IDLE;
                 break;
diff --git a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index 597e5e7..aafc323 100644
--- a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -130,6 +130,40 @@
     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,