SF: Update vsync timeline validUntil to be exact vsync time.

Introduce Timeline::isWithin function that puts sourced vsync time
source into Unique, Shared and Outside categories.

BUG: 343603085
Test: atest VSyncPredictorTest
Flag: com.android.graphics.surfaceflinger.flags.vrr_bugfix_24q4
Change-Id: I99094e64c8403455158a6e794bd4d2ce32429f93
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 8ce61d8..66a7d71 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -106,6 +106,24 @@
         void shiftVsyncSequence(Duration phase);
         void setRenderRate(std::optional<Fps> renderRateOpt) { mRenderRateOpt = renderRateOpt; }
 
+        enum class VsyncOnTimeline {
+            Unique,  // Within timeline, not shared with next timeline.
+            Shared,  // Within timeline, shared with next timeline.
+            Outside, // Outside of the timeline.
+        };
+        VsyncOnTimeline isWithin(TimePoint vsync) {
+            const auto threshold = mIdealPeriod.ns() / 2;
+            if (!mValidUntil || vsync.ns() < mValidUntil->ns() - threshold) {
+                // if mValidUntil is absent then timeline is not frozen and
+                // vsync should be unique to that timeline.
+                return VsyncOnTimeline::Unique;
+            }
+            if (vsync.ns() > mValidUntil->ns() + threshold) {
+                return VsyncOnTimeline::Outside;
+            }
+            return VsyncOnTimeline::Shared;
+        }
+
     private:
         nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync);
         VsyncSequence getVsyncSequenceLocked(Model, nsecs_t vsync);