Refactor resampler logic to constrain MotionEvent mutation

Refactored resampler logic to constrain the functions where MotionEvent
can mutate.

Bug: 297226446
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="ResamplerTest*"
Change-Id: I4b9c9140b73cd45f866dc51931b03cdf2883e5a3
diff --git a/include/input/Resampler.h b/include/input/Resampler.h
index ff9c4b0..5980d5d 100644
--- a/include/input/Resampler.h
+++ b/include/input/Resampler.h
@@ -44,7 +44,7 @@
      * samples by the end of the resampling. No other field of motionEvent should be modified.
      * - If resampling does not occur, then motionEvent must not be modified in any way.
      */
-    virtual void resampleMotionEvent(const std::chrono::nanoseconds resampleTime,
+    virtual void resampleMotionEvent(std::chrono::nanoseconds resampleTime,
                                      MotionEvent& motionEvent,
                                      const InputMessage* futureSample) = 0;
 };
@@ -60,7 +60,7 @@
      * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and
      * `motionEvent` is unmodified.
      */
-    void resampleMotionEvent(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
+    void resampleMotionEvent(std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
                              const InputMessage* futureSample) override;
 
 private:
@@ -72,10 +72,6 @@
     struct Sample {
         std::chrono::nanoseconds eventTime;
         Pointer pointer;
-
-        Sample(const std::chrono::nanoseconds eventTime, const PointerProperties& properties,
-               const PointerCoords& coords)
-              : eventTime{eventTime}, pointer{properties, coords} {}
     };
 
     /**
@@ -99,17 +95,34 @@
     void updateLatestSamples(const MotionEvent& motionEvent);
 
     /**
-     * May add a sample at the end of motionEvent with eventTime equal to resampleTime, and
-     * interpolated coordinates between the latest motionEvent sample and futureSample.
+     * Checks if there are necessary conditions to interpolate. For example, interpolation cannot
+     * take place if samples are too far apart in time. mLatestSamples must have at least one sample
+     * when canInterpolate is invoked.
      */
-    void interpolate(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
-                     const InputMessage& futureSample) const;
+    bool canInterpolate(const InputMessage& futureSample) const;
 
     /**
-     * May add a sample at the end of motionEvent by extrapolating from the latest two samples. The
-     * added sample either has eventTime equal to resampleTime, or an earlier time if resampleTime
-     * is too far in the future.
+     * Returns a sample interpolated between the latest sample of mLatestSamples and futureSample,
+     * if the conditions from canInterpolate are satisfied. Otherwise, returns nullopt.
+     * mLatestSamples must have at least one sample when attemptInterpolation is called.
      */
-    void extrapolate(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent) const;
+    std::optional<Sample> attemptInterpolation(std::chrono::nanoseconds resampleTime,
+                                               const InputMessage& futureSample) const;
+
+    /**
+     * Checks if there are necessary conditions to extrapolate. That is, there are at least two
+     * samples in mLatestSamples, and delta is bounded within a time interval.
+     */
+    bool canExtrapolate() const;
+
+    /**
+     * Returns a sample extrapolated from the two samples of mLatestSamples, if the conditions from
+     * canExtrapolate are satisfied. The returned sample either has eventTime equal to resampleTime,
+     * or an earlier time if resampleTime is too far in the future. If canExtrapolate returns false,
+     * this function returns nullopt.
+     */
+    std::optional<Sample> attemptExtrapolation(std::chrono::nanoseconds resampleTime) const;
+
+    inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
 };
 } // namespace android
\ No newline at end of file