xref: /aosp_15_r20/frameworks/native/include/input/Resampler.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /**
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2024 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <array>
20*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
21*38e8c45fSAndroid Build Coastguard Worker #include <iterator>
22*38e8c45fSAndroid Build Coastguard Worker #include <map>
23*38e8c45fSAndroid Build Coastguard Worker #include <optional>
24*38e8c45fSAndroid Build Coastguard Worker #include <vector>
25*38e8c45fSAndroid Build Coastguard Worker 
26*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ftl/mixins.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <input/CoordinateFilter.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <input/Input.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <input/InputTransport.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <input/RingBuffer.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h>
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker namespace android {
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker /**
37*38e8c45fSAndroid Build Coastguard Worker  * Resampler is an interface for resampling MotionEvents. Every resampling implementation
38*38e8c45fSAndroid Build Coastguard Worker  * must use this interface to enable resampling inside InputConsumer's logic.
39*38e8c45fSAndroid Build Coastguard Worker  */
40*38e8c45fSAndroid Build Coastguard Worker struct Resampler {
41*38e8c45fSAndroid Build Coastguard Worker     virtual ~Resampler() = default;
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker     /**
44*38e8c45fSAndroid Build Coastguard Worker      * Tries to resample motionEvent at frameTime. The provided frameTime must be greater than
45*38e8c45fSAndroid Build Coastguard Worker      * the latest sample time of motionEvent. It is not guaranteed that resampling occurs at
46*38e8c45fSAndroid Build Coastguard Worker      * frameTime. Interpolation may occur is futureSample is available. Otherwise, motionEvent
47*38e8c45fSAndroid Build Coastguard Worker      * may be resampled by another method, or not resampled at all. Furthermore, it is the
48*38e8c45fSAndroid Build Coastguard Worker      * implementer's responsibility to guarantee the following:
49*38e8c45fSAndroid Build Coastguard Worker      * - If resampling occurs, a single additional sample should be added to motionEvent. That is,
50*38e8c45fSAndroid Build Coastguard Worker      * if motionEvent had N samples before being passed to Resampler, then it will have N + 1
51*38e8c45fSAndroid Build Coastguard Worker      * samples by the end of the resampling. No other field of motionEvent should be modified.
52*38e8c45fSAndroid Build Coastguard Worker      * - If resampling does not occur, then motionEvent must not be modified in any way.
53*38e8c45fSAndroid Build Coastguard Worker      */
54*38e8c45fSAndroid Build Coastguard Worker     virtual void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent,
55*38e8c45fSAndroid Build Coastguard Worker                                      const InputMessage* futureSample) = 0;
56*38e8c45fSAndroid Build Coastguard Worker 
57*38e8c45fSAndroid Build Coastguard Worker     /**
58*38e8c45fSAndroid Build Coastguard Worker      * Returns resample latency. Resample latency is the time difference between frame time and
59*38e8c45fSAndroid Build Coastguard Worker      * resample time. More precisely, let frameTime and resampleTime be two timestamps, and
60*38e8c45fSAndroid Build Coastguard Worker      * frameTime > resampleTime. Resample latency is defined as frameTime - resampleTime.
61*38e8c45fSAndroid Build Coastguard Worker      */
62*38e8c45fSAndroid Build Coastguard Worker     virtual std::chrono::nanoseconds getResampleLatency() const = 0;
63*38e8c45fSAndroid Build Coastguard Worker };
64*38e8c45fSAndroid Build Coastguard Worker 
65*38e8c45fSAndroid Build Coastguard Worker class LegacyResampler final : public Resampler {
66*38e8c45fSAndroid Build Coastguard Worker public:
67*38e8c45fSAndroid Build Coastguard Worker     /**
68*38e8c45fSAndroid Build Coastguard Worker      * Tries to resample `motionEvent` at `frameTime` by adding a resampled sample at the end of
69*38e8c45fSAndroid Build Coastguard Worker      * `motionEvent` with eventTime equal to `resampleTime` and pointer coordinates determined by
70*38e8c45fSAndroid Build Coastguard Worker      * linear interpolation or linear extrapolation. An earlier `resampleTime` will be used if
71*38e8c45fSAndroid Build Coastguard Worker      * extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is
72*38e8c45fSAndroid Build Coastguard Worker      * not null, interpolation will occur. If `futureSample` is null and there is enough historical
73*38e8c45fSAndroid Build Coastguard Worker      * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and
74*38e8c45fSAndroid Build Coastguard Worker      * `motionEvent` is unmodified. Furthermore, motionEvent is not resampled if resampleTime equals
75*38e8c45fSAndroid Build Coastguard Worker      * the last sample eventTime of motionEvent.
76*38e8c45fSAndroid Build Coastguard Worker      */
77*38e8c45fSAndroid Build Coastguard Worker     void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent,
78*38e8c45fSAndroid Build Coastguard Worker                              const InputMessage* futureSample) override;
79*38e8c45fSAndroid Build Coastguard Worker 
80*38e8c45fSAndroid Build Coastguard Worker     std::chrono::nanoseconds getResampleLatency() const override;
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker private:
83*38e8c45fSAndroid Build Coastguard Worker     struct Pointer {
84*38e8c45fSAndroid Build Coastguard Worker         PointerProperties properties;
85*38e8c45fSAndroid Build Coastguard Worker         PointerCoords coords;
86*38e8c45fSAndroid Build Coastguard Worker     };
87*38e8c45fSAndroid Build Coastguard Worker 
88*38e8c45fSAndroid Build Coastguard Worker     /**
89*38e8c45fSAndroid Build Coastguard Worker      * Container that stores pointers as an associative array, supporting O(1) lookup by pointer id,
90*38e8c45fSAndroid Build Coastguard Worker      * as well as forward iteration in the order in which the pointer or pointers were inserted in
91*38e8c45fSAndroid Build Coastguard Worker      * the container. PointerMap has a maximum capacity equal to MAX_POINTERS.
92*38e8c45fSAndroid Build Coastguard Worker      */
93*38e8c45fSAndroid Build Coastguard Worker     class PointerMap {
94*38e8c45fSAndroid Build Coastguard Worker     public:
95*38e8c45fSAndroid Build Coastguard Worker         struct PointerId : ftl::DefaultConstructible<PointerId, int32_t>,
96*38e8c45fSAndroid Build Coastguard Worker                            ftl::Equatable<PointerId> {
97*38e8c45fSAndroid Build Coastguard Worker             using DefaultConstructible::DefaultConstructible;
98*38e8c45fSAndroid Build Coastguard Worker         };
99*38e8c45fSAndroid Build Coastguard Worker 
100*38e8c45fSAndroid Build Coastguard Worker         /**
101*38e8c45fSAndroid Build Coastguard Worker          * Custom iterator to enable use of range-based for loops.
102*38e8c45fSAndroid Build Coastguard Worker          */
103*38e8c45fSAndroid Build Coastguard Worker         template <typename T>
104*38e8c45fSAndroid Build Coastguard Worker         class iterator {
105*38e8c45fSAndroid Build Coastguard Worker         public:
106*38e8c45fSAndroid Build Coastguard Worker             using iterator_category = std::forward_iterator_tag;
107*38e8c45fSAndroid Build Coastguard Worker             using value_type = T;
108*38e8c45fSAndroid Build Coastguard Worker             using difference_type = std::ptrdiff_t;
109*38e8c45fSAndroid Build Coastguard Worker             using pointer = T*;
110*38e8c45fSAndroid Build Coastguard Worker             using reference = T&;
111*38e8c45fSAndroid Build Coastguard Worker 
iterator(pointer element)112*38e8c45fSAndroid Build Coastguard Worker             explicit iterator(pointer element) : mElement{element} {}
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker             friend bool operator==(const iterator& lhs, const iterator& rhs) {
115*38e8c45fSAndroid Build Coastguard Worker                 return lhs.mElement == rhs.mElement;
116*38e8c45fSAndroid Build Coastguard Worker             }
117*38e8c45fSAndroid Build Coastguard Worker 
118*38e8c45fSAndroid Build Coastguard Worker             friend bool operator!=(const iterator& lhs, const iterator& rhs) {
119*38e8c45fSAndroid Build Coastguard Worker                 return !(lhs == rhs);
120*38e8c45fSAndroid Build Coastguard Worker             }
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker             iterator operator++() {
123*38e8c45fSAndroid Build Coastguard Worker                 ++mElement;
124*38e8c45fSAndroid Build Coastguard Worker                 return *this;
125*38e8c45fSAndroid Build Coastguard Worker             }
126*38e8c45fSAndroid Build Coastguard Worker 
127*38e8c45fSAndroid Build Coastguard Worker             reference operator*() const { return *mElement; }
128*38e8c45fSAndroid Build Coastguard Worker 
129*38e8c45fSAndroid Build Coastguard Worker         private:
130*38e8c45fSAndroid Build Coastguard Worker             pointer mElement;
131*38e8c45fSAndroid Build Coastguard Worker         };
132*38e8c45fSAndroid Build Coastguard Worker 
PointerMap()133*38e8c45fSAndroid Build Coastguard Worker         PointerMap() {
134*38e8c45fSAndroid Build Coastguard Worker             idToIndex.fill(std::nullopt);
135*38e8c45fSAndroid Build Coastguard Worker             for (Pointer& pointer : pointers) {
136*38e8c45fSAndroid Build Coastguard Worker                 pointer.properties.clear();
137*38e8c45fSAndroid Build Coastguard Worker                 pointer.coords.clear();
138*38e8c45fSAndroid Build Coastguard Worker             }
139*38e8c45fSAndroid Build Coastguard Worker         }
140*38e8c45fSAndroid Build Coastguard Worker 
141*38e8c45fSAndroid Build Coastguard Worker         /**
142*38e8c45fSAndroid Build Coastguard Worker          * Forward iterators to traverse the pointers in `pointers`. The order of the pointers is
143*38e8c45fSAndroid Build Coastguard Worker          * determined by the order in which they were inserted (not by id).
144*38e8c45fSAndroid Build Coastguard Worker          */
begin()145*38e8c45fSAndroid Build Coastguard Worker         iterator<Pointer> begin() { return iterator<Pointer>{&pointers[0]}; }
146*38e8c45fSAndroid Build Coastguard Worker 
begin()147*38e8c45fSAndroid Build Coastguard Worker         iterator<const Pointer> begin() const { return iterator<const Pointer>{&pointers[0]}; }
148*38e8c45fSAndroid Build Coastguard Worker 
end()149*38e8c45fSAndroid Build Coastguard Worker         iterator<Pointer> end() { return iterator<Pointer>{&pointers[nextPointerIndex]}; }
150*38e8c45fSAndroid Build Coastguard Worker 
end()151*38e8c45fSAndroid Build Coastguard Worker         iterator<const Pointer> end() const {
152*38e8c45fSAndroid Build Coastguard Worker             return iterator<const Pointer>{&pointers[nextPointerIndex]};
153*38e8c45fSAndroid Build Coastguard Worker         }
154*38e8c45fSAndroid Build Coastguard Worker 
155*38e8c45fSAndroid Build Coastguard Worker         /**
156*38e8c45fSAndroid Build Coastguard Worker          * Inserts the given pointer into the PointerMap. Precondition: The current number of
157*38e8c45fSAndroid Build Coastguard Worker          * contained pointers must be less than MAX_POINTERS when this function is called. It
158*38e8c45fSAndroid Build Coastguard Worker          * fatally logs if the user tries to insert more than MAX_POINTERS, or if pointer id is out
159*38e8c45fSAndroid Build Coastguard Worker          * of bounds.
160*38e8c45fSAndroid Build Coastguard Worker          */
insert(const Pointer & pointer)161*38e8c45fSAndroid Build Coastguard Worker         void insert(const Pointer& pointer) {
162*38e8c45fSAndroid Build Coastguard Worker             LOG_IF(FATAL, nextPointerIndex >= pointers.size())
163*38e8c45fSAndroid Build Coastguard Worker                     << "Cannot insert more than " << MAX_POINTERS << " in PointerMap.";
164*38e8c45fSAndroid Build Coastguard Worker             LOG_IF(FATAL, (pointer.properties.id < 0) || (pointer.properties.id > MAX_POINTER_ID))
165*38e8c45fSAndroid Build Coastguard Worker                     << "Invalid pointer id.";
166*38e8c45fSAndroid Build Coastguard Worker             idToIndex[pointer.properties.id] = std::optional<size_t>{nextPointerIndex};
167*38e8c45fSAndroid Build Coastguard Worker             pointers[nextPointerIndex] = pointer;
168*38e8c45fSAndroid Build Coastguard Worker             ++nextPointerIndex;
169*38e8c45fSAndroid Build Coastguard Worker         }
170*38e8c45fSAndroid Build Coastguard Worker 
171*38e8c45fSAndroid Build Coastguard Worker         /**
172*38e8c45fSAndroid Build Coastguard Worker          * Returns the pointer associated with the provided id if it exists.
173*38e8c45fSAndroid Build Coastguard Worker          * Otherwise, std::nullopt is returned.
174*38e8c45fSAndroid Build Coastguard Worker          */
find(PointerId id)175*38e8c45fSAndroid Build Coastguard Worker         std::optional<Pointer> find(PointerId id) const {
176*38e8c45fSAndroid Build Coastguard Worker             const int32_t idValue = ftl::to_underlying(id);
177*38e8c45fSAndroid Build Coastguard Worker             LOG_IF(FATAL, (idValue < 0) || (idValue > MAX_POINTER_ID)) << "Invalid pointer id.";
178*38e8c45fSAndroid Build Coastguard Worker             const std::optional<size_t> index = idToIndex[idValue];
179*38e8c45fSAndroid Build Coastguard Worker             return index.has_value() ? std::optional{pointers[*index]} : std::nullopt;
180*38e8c45fSAndroid Build Coastguard Worker         }
181*38e8c45fSAndroid Build Coastguard Worker 
182*38e8c45fSAndroid Build Coastguard Worker     private:
183*38e8c45fSAndroid Build Coastguard Worker         /**
184*38e8c45fSAndroid Build Coastguard Worker          * The index at which a pointer is inserted in `pointers`. Likewise, it represents the
185*38e8c45fSAndroid Build Coastguard Worker          * number of pointers in PointerMap.
186*38e8c45fSAndroid Build Coastguard Worker          */
187*38e8c45fSAndroid Build Coastguard Worker         size_t nextPointerIndex{0};
188*38e8c45fSAndroid Build Coastguard Worker 
189*38e8c45fSAndroid Build Coastguard Worker         /**
190*38e8c45fSAndroid Build Coastguard Worker          * Sequentially stores pointers. Each pointer's position is determined by the value of
191*38e8c45fSAndroid Build Coastguard Worker          * nextPointerIndex at insertion time.
192*38e8c45fSAndroid Build Coastguard Worker          */
193*38e8c45fSAndroid Build Coastguard Worker         std::array<Pointer, MAX_POINTERS + 1> pointers;
194*38e8c45fSAndroid Build Coastguard Worker 
195*38e8c45fSAndroid Build Coastguard Worker         /**
196*38e8c45fSAndroid Build Coastguard Worker          * Maps each pointer id to its associated index in pointers. If no pointer with the id
197*38e8c45fSAndroid Build Coastguard Worker          * exists in pointers, the mapped value is std::nullopt.
198*38e8c45fSAndroid Build Coastguard Worker          */
199*38e8c45fSAndroid Build Coastguard Worker         std::array<std::optional<size_t>, MAX_POINTER_ID + 1> idToIndex;
200*38e8c45fSAndroid Build Coastguard Worker     };
201*38e8c45fSAndroid Build Coastguard Worker 
202*38e8c45fSAndroid Build Coastguard Worker     struct Sample {
203*38e8c45fSAndroid Build Coastguard Worker         std::chrono::nanoseconds eventTime;
204*38e8c45fSAndroid Build Coastguard Worker         PointerMap pointerMap;
205*38e8c45fSAndroid Build Coastguard Worker 
asPointerCoordsSample206*38e8c45fSAndroid Build Coastguard Worker         std::vector<PointerCoords> asPointerCoords() const {
207*38e8c45fSAndroid Build Coastguard Worker             std::vector<PointerCoords> pointersCoords;
208*38e8c45fSAndroid Build Coastguard Worker             for (const Pointer& pointer : pointerMap) {
209*38e8c45fSAndroid Build Coastguard Worker                 pointersCoords.push_back(pointer.coords);
210*38e8c45fSAndroid Build Coastguard Worker             }
211*38e8c45fSAndroid Build Coastguard Worker             return pointersCoords;
212*38e8c45fSAndroid Build Coastguard Worker         }
213*38e8c45fSAndroid Build Coastguard Worker     };
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     /**
216*38e8c45fSAndroid Build Coastguard Worker      * Up to two latest samples from MotionEvent. Updated every time resampleMotionEvent is called.
217*38e8c45fSAndroid Build Coastguard Worker      * Note: We store up to two samples in order to simplify the implementation. Although,
218*38e8c45fSAndroid Build Coastguard Worker      * calculations are possible with only one previous sample.
219*38e8c45fSAndroid Build Coastguard Worker      */
220*38e8c45fSAndroid Build Coastguard Worker     RingBuffer<Sample> mLatestSamples{/*capacity=*/2};
221*38e8c45fSAndroid Build Coastguard Worker 
222*38e8c45fSAndroid Build Coastguard Worker     /**
223*38e8c45fSAndroid Build Coastguard Worker      * Latest sample in mLatestSamples after resampling motion event.
224*38e8c45fSAndroid Build Coastguard Worker      */
225*38e8c45fSAndroid Build Coastguard Worker     std::optional<Sample> mLastRealSample;
226*38e8c45fSAndroid Build Coastguard Worker 
227*38e8c45fSAndroid Build Coastguard Worker     /**
228*38e8c45fSAndroid Build Coastguard Worker      * Latest prediction. That is, the latest extrapolated sample.
229*38e8c45fSAndroid Build Coastguard Worker      */
230*38e8c45fSAndroid Build Coastguard Worker     std::optional<Sample> mPreviousPrediction;
231*38e8c45fSAndroid Build Coastguard Worker 
232*38e8c45fSAndroid Build Coastguard Worker     /**
233*38e8c45fSAndroid Build Coastguard Worker      * Adds up to mLatestSamples.capacity() of motionEvent's latest samples to mLatestSamples. If
234*38e8c45fSAndroid Build Coastguard Worker      * motionEvent has fewer samples than mLatestSamples.capacity(), then the available samples are
235*38e8c45fSAndroid Build Coastguard Worker      * added to mLatestSamples.
236*38e8c45fSAndroid Build Coastguard Worker      */
237*38e8c45fSAndroid Build Coastguard Worker     void updateLatestSamples(const MotionEvent& motionEvent);
238*38e8c45fSAndroid Build Coastguard Worker 
239*38e8c45fSAndroid Build Coastguard Worker     static Sample messageToSample(const InputMessage& message);
240*38e8c45fSAndroid Build Coastguard Worker 
241*38e8c45fSAndroid Build Coastguard Worker     /**
242*38e8c45fSAndroid Build Coastguard Worker      * Checks if auxiliary sample has the same pointer properties of target sample. That is,
243*38e8c45fSAndroid Build Coastguard Worker      * auxiliary pointer IDs must appear in the same order as target pointer IDs, their toolType
244*38e8c45fSAndroid Build Coastguard Worker      * must match and be resampleable.
245*38e8c45fSAndroid Build Coastguard Worker      */
246*38e8c45fSAndroid Build Coastguard Worker     static bool pointerPropertiesResampleable(const Sample& target, const Sample& auxiliary);
247*38e8c45fSAndroid Build Coastguard Worker 
248*38e8c45fSAndroid Build Coastguard Worker     /**
249*38e8c45fSAndroid Build Coastguard Worker      * Checks if there are necessary conditions to interpolate. For example, interpolation cannot
250*38e8c45fSAndroid Build Coastguard Worker      * take place if samples are too far apart in time. mLatestSamples must have at least one sample
251*38e8c45fSAndroid Build Coastguard Worker      * when canInterpolate is invoked.
252*38e8c45fSAndroid Build Coastguard Worker      */
253*38e8c45fSAndroid Build Coastguard Worker     bool canInterpolate(const InputMessage& futureSample) const;
254*38e8c45fSAndroid Build Coastguard Worker 
255*38e8c45fSAndroid Build Coastguard Worker     /**
256*38e8c45fSAndroid Build Coastguard Worker      * Returns a sample interpolated between the latest sample of mLatestSamples and futureMessage,
257*38e8c45fSAndroid Build Coastguard Worker      * if the conditions from canInterpolate are satisfied. Otherwise, returns nullopt.
258*38e8c45fSAndroid Build Coastguard Worker      * mLatestSamples must have at least one sample when attemptInterpolation is called.
259*38e8c45fSAndroid Build Coastguard Worker      */
260*38e8c45fSAndroid Build Coastguard Worker     std::optional<Sample> attemptInterpolation(std::chrono::nanoseconds resampleTime,
261*38e8c45fSAndroid Build Coastguard Worker                                                const InputMessage& futureMessage) const;
262*38e8c45fSAndroid Build Coastguard Worker 
263*38e8c45fSAndroid Build Coastguard Worker     /**
264*38e8c45fSAndroid Build Coastguard Worker      * Checks if there are necessary conditions to extrapolate. That is, there are at least two
265*38e8c45fSAndroid Build Coastguard Worker      * samples in mLatestSamples, and delta is bounded within a time interval.
266*38e8c45fSAndroid Build Coastguard Worker      */
267*38e8c45fSAndroid Build Coastguard Worker     bool canExtrapolate() const;
268*38e8c45fSAndroid Build Coastguard Worker 
269*38e8c45fSAndroid Build Coastguard Worker     /**
270*38e8c45fSAndroid Build Coastguard Worker      * Returns a sample extrapolated from the two samples of mLatestSamples, if the conditions from
271*38e8c45fSAndroid Build Coastguard Worker      * canExtrapolate are satisfied. The returned sample either has eventTime equal to resampleTime,
272*38e8c45fSAndroid Build Coastguard Worker      * or an earlier time if resampleTime is too far in the future. If canExtrapolate returns false,
273*38e8c45fSAndroid Build Coastguard Worker      * this function returns nullopt.
274*38e8c45fSAndroid Build Coastguard Worker      */
275*38e8c45fSAndroid Build Coastguard Worker     std::optional<Sample> attemptExtrapolation(std::chrono::nanoseconds resampleTime) const;
276*38e8c45fSAndroid Build Coastguard Worker 
277*38e8c45fSAndroid Build Coastguard Worker     /**
278*38e8c45fSAndroid Build Coastguard Worker      * Iterates through motion event samples, and replaces real coordinates with resampled
279*38e8c45fSAndroid Build Coastguard Worker      * coordinates to avoid jerkiness in certain conditions.
280*38e8c45fSAndroid Build Coastguard Worker      */
281*38e8c45fSAndroid Build Coastguard Worker     void overwriteMotionEventSamples(MotionEvent& motionEvent) const;
282*38e8c45fSAndroid Build Coastguard Worker 
283*38e8c45fSAndroid Build Coastguard Worker     /**
284*38e8c45fSAndroid Build Coastguard Worker      * Overwrites with resampled data the pointer coordinates that did not move between motion event
285*38e8c45fSAndroid Build Coastguard Worker      * samples, that is, both x and y values are identical to mLastRealSample.
286*38e8c45fSAndroid Build Coastguard Worker      */
287*38e8c45fSAndroid Build Coastguard Worker     void overwriteStillPointers(MotionEvent& motionEvent, size_t sampleIndex) const;
288*38e8c45fSAndroid Build Coastguard Worker 
289*38e8c45fSAndroid Build Coastguard Worker     /**
290*38e8c45fSAndroid Build Coastguard Worker      * Overwrites the pointer coordinates of a sample with event time older than
291*38e8c45fSAndroid Build Coastguard Worker      * that of mPreviousPrediction.
292*38e8c45fSAndroid Build Coastguard Worker      */
293*38e8c45fSAndroid Build Coastguard Worker     void overwriteOldPointers(MotionEvent& motionEvent, size_t sampleIndex) const;
294*38e8c45fSAndroid Build Coastguard Worker 
295*38e8c45fSAndroid Build Coastguard Worker     inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
296*38e8c45fSAndroid Build Coastguard Worker };
297*38e8c45fSAndroid Build Coastguard Worker 
298*38e8c45fSAndroid Build Coastguard Worker /**
299*38e8c45fSAndroid Build Coastguard Worker  * Resampler that first applies the LegacyResampler resampling algorithm, then independently filters
300*38e8c45fSAndroid Build Coastguard Worker  * the X and Y coordinates with a pair of One Euro filters.
301*38e8c45fSAndroid Build Coastguard Worker  */
302*38e8c45fSAndroid Build Coastguard Worker class FilteredLegacyResampler final : public Resampler {
303*38e8c45fSAndroid Build Coastguard Worker public:
304*38e8c45fSAndroid Build Coastguard Worker     /**
305*38e8c45fSAndroid Build Coastguard Worker      * Creates a resampler, using the given minCutoffFreq and beta to instantiate its One Euro
306*38e8c45fSAndroid Build Coastguard Worker      * filters.
307*38e8c45fSAndroid Build Coastguard Worker      */
308*38e8c45fSAndroid Build Coastguard Worker     explicit FilteredLegacyResampler(float minCutoffFreq, float beta);
309*38e8c45fSAndroid Build Coastguard Worker 
310*38e8c45fSAndroid Build Coastguard Worker     void resampleMotionEvent(std::chrono::nanoseconds requestedFrameTime, MotionEvent& motionEvent,
311*38e8c45fSAndroid Build Coastguard Worker                              const InputMessage* futureMessage) override;
312*38e8c45fSAndroid Build Coastguard Worker 
313*38e8c45fSAndroid Build Coastguard Worker     std::chrono::nanoseconds getResampleLatency() const override;
314*38e8c45fSAndroid Build Coastguard Worker 
315*38e8c45fSAndroid Build Coastguard Worker private:
316*38e8c45fSAndroid Build Coastguard Worker     LegacyResampler mResampler;
317*38e8c45fSAndroid Build Coastguard Worker 
318*38e8c45fSAndroid Build Coastguard Worker     /**
319*38e8c45fSAndroid Build Coastguard Worker      * Minimum cutoff frequency of the value's low pass filter. Refer to OneEuroFilter class for a
320*38e8c45fSAndroid Build Coastguard Worker      * more detailed explanation.
321*38e8c45fSAndroid Build Coastguard Worker      */
322*38e8c45fSAndroid Build Coastguard Worker     const float mMinCutoffFreq;
323*38e8c45fSAndroid Build Coastguard Worker 
324*38e8c45fSAndroid Build Coastguard Worker     /**
325*38e8c45fSAndroid Build Coastguard Worker      * Scaling factor of the adaptive cutoff frequency criterion. Refer to OneEuroFilter class for a
326*38e8c45fSAndroid Build Coastguard Worker      * more detailed explanation.
327*38e8c45fSAndroid Build Coastguard Worker      */
328*38e8c45fSAndroid Build Coastguard Worker     const float mBeta;
329*38e8c45fSAndroid Build Coastguard Worker 
330*38e8c45fSAndroid Build Coastguard Worker     /*
331*38e8c45fSAndroid Build Coastguard Worker      * Note: an associative array with constant insertion and lookup times would be more efficient.
332*38e8c45fSAndroid Build Coastguard Worker      * When this was implemented, there was no container with these properties.
333*38e8c45fSAndroid Build Coastguard Worker      */
334*38e8c45fSAndroid Build Coastguard Worker     std::map<int32_t /*pointerId*/, CoordinateFilter> mFilteredPointers;
335*38e8c45fSAndroid Build Coastguard Worker };
336*38e8c45fSAndroid Build Coastguard Worker 
337*38e8c45fSAndroid Build Coastguard Worker } // namespace android
338