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