SurfaceFlinger: use TFD_TIMER_ABSTIME for VSP timer
Using the semantics of alarmIn in VSP timer may lead to lag
if the thread is getting preempted. For example:
Time 0: t1 calls to alarmIn(5)
-- t1 gets preempted for 2ms --
Time 2: t1 calls to timerfd_settime(5)
Time 7: timer wakes up t1, results in 2ms lag
Switching to alarmAt semantics and using TFD_TIMER_ABSTIME to
schedule the timer solves this problem:
Time 0: t1 calls to alarmAt(5)
-- t1 gets preempted for 2ms --
Time 2: t1 calls to timerfd_settime(5)
Time 5: timer wakes up t1
Bug: 159884130
Test: bouncy ball with simulated scheduling delays
Change-Id: I3d727530c2dd47c1a8d1d6a66114d654d7261d87
diff --git a/services/surfaceflinger/tests/unittests/TimerTest.cpp b/services/surfaceflinger/tests/unittests/TimerTest.cpp
new file mode 100644
index 0000000..cda6bbf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TimerTest.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AsyncCallRecorder.h"
+#include "Scheduler/TimeKeeper.h"
+#include "Scheduler/Timer.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace testing;
+using namespace std::literals;
+
+namespace android::scheduler {
+
+struct TimerTest : testing::Test {
+ static constexpr int mIterations = 20;
+
+ AsyncCallRecorder<void (*)()> mCallbackRecorder;
+ Timer mTimer;
+
+ void timerCallback() { mCallbackRecorder.recordCall(); }
+};
+
+TEST_F(TimerTest, callsCallbackIfScheduledInPast) {
+ for (int i = 0; i < mIterations; i++) {
+ mTimer.alarmAt(std::bind(&TimerTest::timerCallback, this), systemTime() - 10'000'00);
+ EXPECT_TRUE(mCallbackRecorder.waitForCall().has_value());
+ EXPECT_FALSE(mCallbackRecorder.waitForUnexpectedCall().has_value());
+ }
+}
+} // namespace android::scheduler