xref: /aosp_15_r20/frameworks/native/include/input/InputConsumer.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 /*
20*38e8c45fSAndroid Build Coastguard Worker  * Native input transport.
21*38e8c45fSAndroid Build Coastguard Worker  *
22*38e8c45fSAndroid Build Coastguard Worker  * The InputConsumer is used by the application to receive events from the input dispatcher.
23*38e8c45fSAndroid Build Coastguard Worker  */
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include "InputTransport.h"
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker namespace android {
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker /*
30*38e8c45fSAndroid Build Coastguard Worker  * Consumes input events from an input channel.
31*38e8c45fSAndroid Build Coastguard Worker  */
32*38e8c45fSAndroid Build Coastguard Worker class InputConsumer {
33*38e8c45fSAndroid Build Coastguard Worker public:
34*38e8c45fSAndroid Build Coastguard Worker     /* Create a consumer associated with an input channel. */
35*38e8c45fSAndroid Build Coastguard Worker     explicit InputConsumer(const std::shared_ptr<InputChannel>& channel);
36*38e8c45fSAndroid Build Coastguard Worker     /* Create a consumer associated with an input channel, override resampling system property */
37*38e8c45fSAndroid Build Coastguard Worker     explicit InputConsumer(const std::shared_ptr<InputChannel>& channel,
38*38e8c45fSAndroid Build Coastguard Worker                            bool enableTouchResampling);
39*38e8c45fSAndroid Build Coastguard Worker 
40*38e8c45fSAndroid Build Coastguard Worker     /* Destroys the consumer and releases its input channel. */
41*38e8c45fSAndroid Build Coastguard Worker     ~InputConsumer();
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker     /* Gets the underlying input channel. */
getChannel()44*38e8c45fSAndroid Build Coastguard Worker     inline std::shared_ptr<InputChannel> getChannel() { return mChannel; }
45*38e8c45fSAndroid Build Coastguard Worker 
46*38e8c45fSAndroid Build Coastguard Worker     /* Consumes an input event from the input channel and copies its contents into
47*38e8c45fSAndroid Build Coastguard Worker      * an InputEvent object created using the specified factory.
48*38e8c45fSAndroid Build Coastguard Worker      *
49*38e8c45fSAndroid Build Coastguard Worker      * Tries to combine a series of move events into larger batches whenever possible.
50*38e8c45fSAndroid Build Coastguard Worker      *
51*38e8c45fSAndroid Build Coastguard Worker      * If consumeBatches is false, then defers consuming pending batched events if it
52*38e8c45fSAndroid Build Coastguard Worker      * is possible for additional samples to be added to them later.  Call hasPendingBatch()
53*38e8c45fSAndroid Build Coastguard Worker      * to determine whether a pending batch is available to be consumed.
54*38e8c45fSAndroid Build Coastguard Worker      *
55*38e8c45fSAndroid Build Coastguard Worker      * If consumeBatches is true, then events are still batched but they are consumed
56*38e8c45fSAndroid Build Coastguard Worker      * immediately as soon as the input channel is exhausted.
57*38e8c45fSAndroid Build Coastguard Worker      *
58*38e8c45fSAndroid Build Coastguard Worker      * The frameTime parameter specifies the time when the current display frame started
59*38e8c45fSAndroid Build Coastguard Worker      * rendering in the CLOCK_MONOTONIC time base, or -1 if unknown.
60*38e8c45fSAndroid Build Coastguard Worker      *
61*38e8c45fSAndroid Build Coastguard Worker      * The returned sequence number is never 0 unless the operation failed.
62*38e8c45fSAndroid Build Coastguard Worker      *
63*38e8c45fSAndroid Build Coastguard Worker      * Returns OK on success.
64*38e8c45fSAndroid Build Coastguard Worker      * Returns WOULD_BLOCK if there is no event present.
65*38e8c45fSAndroid Build Coastguard Worker      * Returns DEAD_OBJECT if the channel's peer has been closed.
66*38e8c45fSAndroid Build Coastguard Worker      * Returns NO_MEMORY if the event could not be created.
67*38e8c45fSAndroid Build Coastguard Worker      * Other errors probably indicate that the channel is broken.
68*38e8c45fSAndroid Build Coastguard Worker      */
69*38e8c45fSAndroid Build Coastguard Worker     status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, nsecs_t frameTime,
70*38e8c45fSAndroid Build Coastguard Worker                      uint32_t* outSeq, InputEvent** outEvent);
71*38e8c45fSAndroid Build Coastguard Worker 
72*38e8c45fSAndroid Build Coastguard Worker     /* Sends a finished signal to the publisher to inform it that the message
73*38e8c45fSAndroid Build Coastguard Worker      * with the specified sequence number has finished being process and whether
74*38e8c45fSAndroid Build Coastguard Worker      * the message was handled by the consumer.
75*38e8c45fSAndroid Build Coastguard Worker      *
76*38e8c45fSAndroid Build Coastguard Worker      * Returns OK on success.
77*38e8c45fSAndroid Build Coastguard Worker      * Returns BAD_VALUE if seq is 0.
78*38e8c45fSAndroid Build Coastguard Worker      * Other errors probably indicate that the channel is broken.
79*38e8c45fSAndroid Build Coastguard Worker      */
80*38e8c45fSAndroid Build Coastguard Worker     status_t sendFinishedSignal(uint32_t seq, bool handled);
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker     status_t sendTimeline(int32_t inputEventId,
83*38e8c45fSAndroid Build Coastguard Worker                           std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker     /* Returns true if there is a pending batch.
86*38e8c45fSAndroid Build Coastguard Worker      *
87*38e8c45fSAndroid Build Coastguard Worker      * Should be called after calling consume() with consumeBatches == false to determine
88*38e8c45fSAndroid Build Coastguard Worker      * whether consume() should be called again later on with consumeBatches == true.
89*38e8c45fSAndroid Build Coastguard Worker      */
90*38e8c45fSAndroid Build Coastguard Worker     bool hasPendingBatch() const;
91*38e8c45fSAndroid Build Coastguard Worker 
92*38e8c45fSAndroid Build Coastguard Worker     /* Returns the source of first pending batch if exist.
93*38e8c45fSAndroid Build Coastguard Worker      *
94*38e8c45fSAndroid Build Coastguard Worker      * Should be called after calling consume() with consumeBatches == false to determine
95*38e8c45fSAndroid Build Coastguard Worker      * whether consume() should be called again later on with consumeBatches == true.
96*38e8c45fSAndroid Build Coastguard Worker      */
97*38e8c45fSAndroid Build Coastguard Worker     int32_t getPendingBatchSource() const;
98*38e8c45fSAndroid Build Coastguard Worker 
99*38e8c45fSAndroid Build Coastguard Worker     /* Returns true when there is *likely* a pending batch or a pending event in the channel.
100*38e8c45fSAndroid Build Coastguard Worker      *
101*38e8c45fSAndroid Build Coastguard Worker      * This is only a performance hint and may return false negative results. Clients should not
102*38e8c45fSAndroid Build Coastguard Worker      * rely on availability of the message based on the return value.
103*38e8c45fSAndroid Build Coastguard Worker      */
104*38e8c45fSAndroid Build Coastguard Worker     bool probablyHasInput() const;
105*38e8c45fSAndroid Build Coastguard Worker 
106*38e8c45fSAndroid Build Coastguard Worker     std::string dump() const;
107*38e8c45fSAndroid Build Coastguard Worker 
108*38e8c45fSAndroid Build Coastguard Worker private:
109*38e8c45fSAndroid Build Coastguard Worker     // True if touch resampling is enabled.
110*38e8c45fSAndroid Build Coastguard Worker     const bool mResampleTouch;
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker     std::shared_ptr<InputChannel> mChannel;
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker     // TODO(b/311142655): delete this temporary tracing after the ANR bug is fixed
115*38e8c45fSAndroid Build Coastguard Worker     const std::string mProcessingTraceTag;
116*38e8c45fSAndroid Build Coastguard Worker     const std::string mLifetimeTraceTag;
117*38e8c45fSAndroid Build Coastguard Worker     const int32_t mLifetimeTraceCookie;
118*38e8c45fSAndroid Build Coastguard Worker 
119*38e8c45fSAndroid Build Coastguard Worker     // The current input message.
120*38e8c45fSAndroid Build Coastguard Worker     InputMessage mMsg;
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker     // True if mMsg contains a valid input message that was deferred from the previous
123*38e8c45fSAndroid Build Coastguard Worker     // call to consume and that still needs to be handled.
124*38e8c45fSAndroid Build Coastguard Worker     bool mMsgDeferred;
125*38e8c45fSAndroid Build Coastguard Worker 
126*38e8c45fSAndroid Build Coastguard Worker     // Batched motion events per device and source.
127*38e8c45fSAndroid Build Coastguard Worker     struct Batch {
128*38e8c45fSAndroid Build Coastguard Worker         std::vector<InputMessage> samples;
129*38e8c45fSAndroid Build Coastguard Worker     };
130*38e8c45fSAndroid Build Coastguard Worker     std::vector<Batch> mBatches;
131*38e8c45fSAndroid Build Coastguard Worker 
132*38e8c45fSAndroid Build Coastguard Worker     // Touch state per device and source, only for sources of class pointer.
133*38e8c45fSAndroid Build Coastguard Worker     struct History {
134*38e8c45fSAndroid Build Coastguard Worker         nsecs_t eventTime;
135*38e8c45fSAndroid Build Coastguard Worker         BitSet32 idBits;
136*38e8c45fSAndroid Build Coastguard Worker         int32_t idToIndex[MAX_POINTER_ID + 1];
137*38e8c45fSAndroid Build Coastguard Worker         PointerCoords pointers[MAX_POINTERS];
138*38e8c45fSAndroid Build Coastguard Worker 
initializeFromHistory139*38e8c45fSAndroid Build Coastguard Worker         void initializeFrom(const InputMessage& msg) {
140*38e8c45fSAndroid Build Coastguard Worker             eventTime = msg.body.motion.eventTime;
141*38e8c45fSAndroid Build Coastguard Worker             idBits.clear();
142*38e8c45fSAndroid Build Coastguard Worker             for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
143*38e8c45fSAndroid Build Coastguard Worker                 uint32_t id = msg.body.motion.pointers[i].properties.id;
144*38e8c45fSAndroid Build Coastguard Worker                 idBits.markBit(id);
145*38e8c45fSAndroid Build Coastguard Worker                 idToIndex[id] = i;
146*38e8c45fSAndroid Build Coastguard Worker                 pointers[i].copyFrom(msg.body.motion.pointers[i].coords);
147*38e8c45fSAndroid Build Coastguard Worker             }
148*38e8c45fSAndroid Build Coastguard Worker         }
149*38e8c45fSAndroid Build Coastguard Worker 
initializeFromHistory150*38e8c45fSAndroid Build Coastguard Worker         void initializeFrom(const History& other) {
151*38e8c45fSAndroid Build Coastguard Worker             eventTime = other.eventTime;
152*38e8c45fSAndroid Build Coastguard Worker             idBits = other.idBits; // temporary copy
153*38e8c45fSAndroid Build Coastguard Worker             for (size_t i = 0; i < other.idBits.count(); i++) {
154*38e8c45fSAndroid Build Coastguard Worker                 uint32_t id = idBits.clearFirstMarkedBit();
155*38e8c45fSAndroid Build Coastguard Worker                 int32_t index = other.idToIndex[id];
156*38e8c45fSAndroid Build Coastguard Worker                 idToIndex[id] = index;
157*38e8c45fSAndroid Build Coastguard Worker                 pointers[index].copyFrom(other.pointers[index]);
158*38e8c45fSAndroid Build Coastguard Worker             }
159*38e8c45fSAndroid Build Coastguard Worker             idBits = other.idBits; // final copy
160*38e8c45fSAndroid Build Coastguard Worker         }
161*38e8c45fSAndroid Build Coastguard Worker 
getPointerByIdHistory162*38e8c45fSAndroid Build Coastguard Worker         const PointerCoords& getPointerById(uint32_t id) const { return pointers[idToIndex[id]]; }
163*38e8c45fSAndroid Build Coastguard Worker 
hasPointerIdHistory164*38e8c45fSAndroid Build Coastguard Worker         bool hasPointerId(uint32_t id) const { return idBits.hasBit(id); }
165*38e8c45fSAndroid Build Coastguard Worker     };
166*38e8c45fSAndroid Build Coastguard Worker     struct TouchState {
167*38e8c45fSAndroid Build Coastguard Worker         int32_t deviceId;
168*38e8c45fSAndroid Build Coastguard Worker         int32_t source;
169*38e8c45fSAndroid Build Coastguard Worker         size_t historyCurrent;
170*38e8c45fSAndroid Build Coastguard Worker         size_t historySize;
171*38e8c45fSAndroid Build Coastguard Worker         History history[2];
172*38e8c45fSAndroid Build Coastguard Worker         History lastResample;
173*38e8c45fSAndroid Build Coastguard Worker 
initializeTouchState174*38e8c45fSAndroid Build Coastguard Worker         void initialize(int32_t incomingDeviceId, int32_t incomingSource) {
175*38e8c45fSAndroid Build Coastguard Worker             deviceId = incomingDeviceId;
176*38e8c45fSAndroid Build Coastguard Worker             source = incomingSource;
177*38e8c45fSAndroid Build Coastguard Worker             historyCurrent = 0;
178*38e8c45fSAndroid Build Coastguard Worker             historySize = 0;
179*38e8c45fSAndroid Build Coastguard Worker             lastResample.eventTime = 0;
180*38e8c45fSAndroid Build Coastguard Worker             lastResample.idBits.clear();
181*38e8c45fSAndroid Build Coastguard Worker         }
182*38e8c45fSAndroid Build Coastguard Worker 
addHistoryTouchState183*38e8c45fSAndroid Build Coastguard Worker         void addHistory(const InputMessage& msg) {
184*38e8c45fSAndroid Build Coastguard Worker             historyCurrent ^= 1;
185*38e8c45fSAndroid Build Coastguard Worker             if (historySize < 2) {
186*38e8c45fSAndroid Build Coastguard Worker                 historySize += 1;
187*38e8c45fSAndroid Build Coastguard Worker             }
188*38e8c45fSAndroid Build Coastguard Worker             history[historyCurrent].initializeFrom(msg);
189*38e8c45fSAndroid Build Coastguard Worker         }
190*38e8c45fSAndroid Build Coastguard Worker 
getHistoryTouchState191*38e8c45fSAndroid Build Coastguard Worker         const History* getHistory(size_t index) const {
192*38e8c45fSAndroid Build Coastguard Worker             return &history[(historyCurrent + index) & 1];
193*38e8c45fSAndroid Build Coastguard Worker         }
194*38e8c45fSAndroid Build Coastguard Worker 
recentCoordinatesAreIdenticalTouchState195*38e8c45fSAndroid Build Coastguard Worker         bool recentCoordinatesAreIdentical(uint32_t id) const {
196*38e8c45fSAndroid Build Coastguard Worker             // Return true if the two most recently received "raw" coordinates are identical
197*38e8c45fSAndroid Build Coastguard Worker             if (historySize < 2) {
198*38e8c45fSAndroid Build Coastguard Worker                 return false;
199*38e8c45fSAndroid Build Coastguard Worker             }
200*38e8c45fSAndroid Build Coastguard Worker             if (!getHistory(0)->hasPointerId(id) || !getHistory(1)->hasPointerId(id)) {
201*38e8c45fSAndroid Build Coastguard Worker                 return false;
202*38e8c45fSAndroid Build Coastguard Worker             }
203*38e8c45fSAndroid Build Coastguard Worker             float currentX = getHistory(0)->getPointerById(id).getX();
204*38e8c45fSAndroid Build Coastguard Worker             float currentY = getHistory(0)->getPointerById(id).getY();
205*38e8c45fSAndroid Build Coastguard Worker             float previousX = getHistory(1)->getPointerById(id).getX();
206*38e8c45fSAndroid Build Coastguard Worker             float previousY = getHistory(1)->getPointerById(id).getY();
207*38e8c45fSAndroid Build Coastguard Worker             if (currentX == previousX && currentY == previousY) {
208*38e8c45fSAndroid Build Coastguard Worker                 return true;
209*38e8c45fSAndroid Build Coastguard Worker             }
210*38e8c45fSAndroid Build Coastguard Worker             return false;
211*38e8c45fSAndroid Build Coastguard Worker         }
212*38e8c45fSAndroid Build Coastguard Worker     };
213*38e8c45fSAndroid Build Coastguard Worker     std::vector<TouchState> mTouchStates;
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     // Chain of batched sequence numbers.  When multiple input messages are combined into
216*38e8c45fSAndroid Build Coastguard Worker     // a batch, we append a record here that associates the last sequence number in the
217*38e8c45fSAndroid Build Coastguard Worker     // batch with the previous one.  When the finished signal is sent, we traverse the
218*38e8c45fSAndroid Build Coastguard Worker     // chain to individually finish all input messages that were part of the batch.
219*38e8c45fSAndroid Build Coastguard Worker     struct SeqChain {
220*38e8c45fSAndroid Build Coastguard Worker         uint32_t seq;   // sequence number of batched input message
221*38e8c45fSAndroid Build Coastguard Worker         uint32_t chain; // sequence number of previous batched input message
222*38e8c45fSAndroid Build Coastguard Worker     };
223*38e8c45fSAndroid Build Coastguard Worker     std::vector<SeqChain> mSeqChains;
224*38e8c45fSAndroid Build Coastguard Worker 
225*38e8c45fSAndroid Build Coastguard Worker     // The time at which each event with the sequence number 'seq' was consumed.
226*38e8c45fSAndroid Build Coastguard Worker     // This data is provided in 'finishInputEvent' so that the receiving end can measure the latency
227*38e8c45fSAndroid Build Coastguard Worker     // This collection is populated when the event is received, and the entries are erased when the
228*38e8c45fSAndroid Build Coastguard Worker     // events are finished. It should not grow infinitely because if an event is not ack'd, ANR
229*38e8c45fSAndroid Build Coastguard Worker     // will be raised for that connection, and no further events will be posted to that channel.
230*38e8c45fSAndroid Build Coastguard Worker     std::unordered_map<uint32_t /*seq*/, nsecs_t /*consumeTime*/> mConsumeTimes;
231*38e8c45fSAndroid Build Coastguard Worker 
232*38e8c45fSAndroid Build Coastguard Worker     status_t consumeBatch(InputEventFactoryInterface* factory, nsecs_t frameTime, uint32_t* outSeq,
233*38e8c45fSAndroid Build Coastguard Worker                           InputEvent** outEvent);
234*38e8c45fSAndroid Build Coastguard Worker     status_t consumeSamples(InputEventFactoryInterface* factory, Batch& batch, size_t count,
235*38e8c45fSAndroid Build Coastguard Worker                             uint32_t* outSeq, InputEvent** outEvent);
236*38e8c45fSAndroid Build Coastguard Worker 
237*38e8c45fSAndroid Build Coastguard Worker     void updateTouchState(InputMessage& msg);
238*38e8c45fSAndroid Build Coastguard Worker     void resampleTouchState(nsecs_t frameTime, MotionEvent* event, const InputMessage* next);
239*38e8c45fSAndroid Build Coastguard Worker 
240*38e8c45fSAndroid Build Coastguard Worker     ssize_t findBatch(int32_t deviceId, int32_t source) const;
241*38e8c45fSAndroid Build Coastguard Worker     ssize_t findTouchState(int32_t deviceId, int32_t source) const;
242*38e8c45fSAndroid Build Coastguard Worker 
243*38e8c45fSAndroid Build Coastguard Worker     nsecs_t getConsumeTime(uint32_t seq) const;
244*38e8c45fSAndroid Build Coastguard Worker     void popConsumeTime(uint32_t seq);
245*38e8c45fSAndroid Build Coastguard Worker     status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker     static void rewriteMessage(TouchState& state, InputMessage& msg);
248*38e8c45fSAndroid Build Coastguard Worker     static bool canAddSample(const Batch& batch, const InputMessage* msg);
249*38e8c45fSAndroid Build Coastguard Worker     static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time);
250*38e8c45fSAndroid Build Coastguard Worker 
251*38e8c45fSAndroid Build Coastguard Worker     static bool isTouchResamplingEnabled();
252*38e8c45fSAndroid Build Coastguard Worker };
253*38e8c45fSAndroid Build Coastguard Worker 
254*38e8c45fSAndroid Build Coastguard Worker } // namespace android
255