SF: avoid updating queue if schedule() is called.
Avoids a rarish race condition where a callback is scheduled in the
interim time between the TimerDispatch starting to run and the callback
for that scheduled callback is invoked. In this condition, the code will
now have the next callback pend until the timer queue processes the when
to wakeup next.
Bug: 154303580
Test: 3 new unit tests
Test: boot to home, check some animations
Test: overnight dogfood with patch.
Change-Id: I0e7e2e3698ed6d1765082db20d9cf25f6e6c2db2
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
index 26a8ec0..957c0d1 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
@@ -64,6 +64,13 @@
// This moves the state from armed->running.
// Store the timestamp that this was intended for as the last called timestamp.
nsecs_t executing();
+
+ // Adds a pending upload of the earliestVSync and workDuration that will be applied on the next
+ // call to update()
+ void addPendingWorkloadUpdate(nsecs_t workDuration, nsecs_t earliestVsync);
+
+ // Checks if there is a pending update to the workload, returning true if so.
+ bool hasPendingWorkloadUpdate() const;
// End: functions that are not threadsafe.
// Invoke the callback with the two given timestamps, moving the state from running->disarmed.
@@ -88,6 +95,12 @@
std::optional<ArmingInfo> mArmedInfo;
std::optional<nsecs_t> mLastDispatchTime;
+ struct WorkloadUpdateInfo {
+ nsecs_t duration;
+ nsecs_t earliestVsync;
+ };
+ std::optional<WorkloadUpdateInfo> mWorkloadUpdateInfo;
+
mutable std::mutex mRunningMutex;
std::condition_variable mCv;
bool mRunning GUARDED_BY(mRunningMutex) = false;