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 <functional> 20*38e8c45fSAndroid Build Coastguard Worker #include <map> 21*38e8c45fSAndroid Build Coastguard Worker #include <memory> 22*38e8c45fSAndroid Build Coastguard Worker #include <optional> 23*38e8c45fSAndroid Build Coastguard Worker 24*38e8c45fSAndroid Build Coastguard Worker #include <input/Input.h> 25*38e8c45fSAndroid Build Coastguard Worker #include <input/InputTransport.h> 26*38e8c45fSAndroid Build Coastguard Worker #include <input/Resampler.h> 27*38e8c45fSAndroid Build Coastguard Worker #include <utils/Looper.h> 28*38e8c45fSAndroid Build Coastguard Worker 29*38e8c45fSAndroid Build Coastguard Worker namespace android { 30*38e8c45fSAndroid Build Coastguard Worker 31*38e8c45fSAndroid Build Coastguard Worker /** 32*38e8c45fSAndroid Build Coastguard Worker * An interface to receive batched input events. Even if you don't want batching, you still have to 33*38e8c45fSAndroid Build Coastguard Worker * use this interface, and some of the events will be batched if your implementation is slow to 34*38e8c45fSAndroid Build Coastguard Worker * handle the incoming input. The events received by these callbacks are never null. 35*38e8c45fSAndroid Build Coastguard Worker */ 36*38e8c45fSAndroid Build Coastguard Worker class InputConsumerCallbacks { 37*38e8c45fSAndroid Build Coastguard Worker public: ~InputConsumerCallbacks()38*38e8c45fSAndroid Build Coastguard Worker virtual ~InputConsumerCallbacks(){}; 39*38e8c45fSAndroid Build Coastguard Worker virtual void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) = 0; 40*38e8c45fSAndroid Build Coastguard Worker virtual void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) = 0; 41*38e8c45fSAndroid Build Coastguard Worker /** 42*38e8c45fSAndroid Build Coastguard Worker * When you receive this callback, you must (eventually) call "consumeBatchedInputEvents". 43*38e8c45fSAndroid Build Coastguard Worker * If you don't want batching, then call "consumeBatchedInputEvents" immediately with 44*38e8c45fSAndroid Build Coastguard Worker * std::nullopt requestedFrameTime to receive the pending motion event(s). 45*38e8c45fSAndroid Build Coastguard Worker * @param pendingBatchSource the source of the pending batch. 46*38e8c45fSAndroid Build Coastguard Worker */ 47*38e8c45fSAndroid Build Coastguard Worker virtual void onBatchedInputEventPending(int32_t pendingBatchSource) = 0; 48*38e8c45fSAndroid Build Coastguard Worker virtual void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) = 0; 49*38e8c45fSAndroid Build Coastguard Worker virtual void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) = 0; 50*38e8c45fSAndroid Build Coastguard Worker virtual void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) = 0; 51*38e8c45fSAndroid Build Coastguard Worker virtual void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) = 0; 52*38e8c45fSAndroid Build Coastguard Worker }; 53*38e8c45fSAndroid Build Coastguard Worker 54*38e8c45fSAndroid Build Coastguard Worker /** 55*38e8c45fSAndroid Build Coastguard Worker * Consumes input events from an input channel. 56*38e8c45fSAndroid Build Coastguard Worker * 57*38e8c45fSAndroid Build Coastguard Worker * This is a re-implementation of InputConsumer. At the moment it only supports resampling for 58*38e8c45fSAndroid Build Coastguard Worker * single pointer events. A lot of the higher-level logic has been folded into this class, to make 59*38e8c45fSAndroid Build Coastguard Worker * it easier to use. In the legacy class, InputConsumer, the consumption logic was partially handled 60*38e8c45fSAndroid Build Coastguard Worker * in the jni layer, as well as various actions like adding the fd to the Choreographer. 61*38e8c45fSAndroid Build Coastguard Worker * 62*38e8c45fSAndroid Build Coastguard Worker * TODO(b/297226446): use this instead of "InputConsumer": 63*38e8c45fSAndroid Build Coastguard Worker * - Add resampling for multiple pointer events. 64*38e8c45fSAndroid Build Coastguard Worker * - Allow various resampling strategies to be specified 65*38e8c45fSAndroid Build Coastguard Worker * - Delete the old "InputConsumer" and use this class instead, renaming it to "InputConsumer". 66*38e8c45fSAndroid Build Coastguard Worker * - Add tracing 67*38e8c45fSAndroid Build Coastguard Worker * - Update all tests to use the new InputConsumer 68*38e8c45fSAndroid Build Coastguard Worker * 69*38e8c45fSAndroid Build Coastguard Worker * This class is not thread-safe. We are currently allowing the constructor to run on any thread, 70*38e8c45fSAndroid Build Coastguard Worker * but all of the remaining APIs should be invoked on the looper thread only. 71*38e8c45fSAndroid Build Coastguard Worker */ 72*38e8c45fSAndroid Build Coastguard Worker class InputConsumerNoResampling final { 73*38e8c45fSAndroid Build Coastguard Worker public: 74*38e8c45fSAndroid Build Coastguard Worker /** 75*38e8c45fSAndroid Build Coastguard Worker * @param callbacks are used to interact with InputConsumerNoResampling. They're called whenever 76*38e8c45fSAndroid Build Coastguard Worker * the event is ready to consume. 77*38e8c45fSAndroid Build Coastguard Worker * @param looper needs to be sp and not shared_ptr because it inherits from 78*38e8c45fSAndroid Build Coastguard Worker * RefBase 79*38e8c45fSAndroid Build Coastguard Worker * @param resamplerCreator callable that returns the resampling strategy to be used. If null, no 80*38e8c45fSAndroid Build Coastguard Worker * resampling will be performed. resamplerCreator must never return nullptr. 81*38e8c45fSAndroid Build Coastguard Worker */ 82*38e8c45fSAndroid Build Coastguard Worker explicit InputConsumerNoResampling( 83*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InputChannel>& channel, sp<Looper> looper, 84*38e8c45fSAndroid Build Coastguard Worker InputConsumerCallbacks& callbacks, 85*38e8c45fSAndroid Build Coastguard Worker std::function<std::unique_ptr<Resampler>()> resamplerCreator); 86*38e8c45fSAndroid Build Coastguard Worker 87*38e8c45fSAndroid Build Coastguard Worker ~InputConsumerNoResampling(); 88*38e8c45fSAndroid Build Coastguard Worker 89*38e8c45fSAndroid Build Coastguard Worker /** 90*38e8c45fSAndroid Build Coastguard Worker * Must be called exactly once for each event received through the callbacks. 91*38e8c45fSAndroid Build Coastguard Worker */ 92*38e8c45fSAndroid Build Coastguard Worker void finishInputEvent(uint32_t seq, bool handled); 93*38e8c45fSAndroid Build Coastguard Worker void reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime, nsecs_t presentTime); 94*38e8c45fSAndroid Build Coastguard Worker /** 95*38e8c45fSAndroid Build Coastguard Worker * If you want to consume all events immediately (disable batching), then you still must call 96*38e8c45fSAndroid Build Coastguard Worker * this. For requestedFrameTime, use a std::nullopt. It is not guaranteed that the consumption 97*38e8c45fSAndroid Build Coastguard Worker * will occur at requestedFrameTime. The resampling strategy may modify it. 98*38e8c45fSAndroid Build Coastguard Worker * @param requestedFrameTime the time up to which consume the events. When there's double (or 99*38e8c45fSAndroid Build Coastguard Worker * triple) buffering, you may want to not consume all events currently available, because you 100*38e8c45fSAndroid Build Coastguard Worker * could be still working on an older frame, but there could already have been events that 101*38e8c45fSAndroid Build Coastguard Worker * arrived that are more recent. 102*38e8c45fSAndroid Build Coastguard Worker * @return whether any events were actually consumed 103*38e8c45fSAndroid Build Coastguard Worker */ 104*38e8c45fSAndroid Build Coastguard Worker bool consumeBatchedInputEvents(std::optional<nsecs_t> requestedFrameTime); 105*38e8c45fSAndroid Build Coastguard Worker 106*38e8c45fSAndroid Build Coastguard Worker /** 107*38e8c45fSAndroid Build Coastguard Worker * Returns true when there is *likely* a pending batch or a pending event in the channel. 108*38e8c45fSAndroid Build Coastguard Worker * 109*38e8c45fSAndroid Build Coastguard Worker * This is only a performance hint and may return false negative results. Clients should not 110*38e8c45fSAndroid Build Coastguard Worker * rely on availability of the message based on the return value. 111*38e8c45fSAndroid Build Coastguard Worker */ 112*38e8c45fSAndroid Build Coastguard Worker bool probablyHasInput() const; 113*38e8c45fSAndroid Build Coastguard Worker getName()114*38e8c45fSAndroid Build Coastguard Worker std::string getName() { return mChannel->getName(); } 115*38e8c45fSAndroid Build Coastguard Worker 116*38e8c45fSAndroid Build Coastguard Worker std::string dump() const; 117*38e8c45fSAndroid Build Coastguard Worker 118*38e8c45fSAndroid Build Coastguard Worker private: 119*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<InputChannel> mChannel; 120*38e8c45fSAndroid Build Coastguard Worker sp<Looper> mLooper; 121*38e8c45fSAndroid Build Coastguard Worker InputConsumerCallbacks& mCallbacks; 122*38e8c45fSAndroid Build Coastguard Worker const std::function<std::unique_ptr<Resampler>()> mResamplerCreator; 123*38e8c45fSAndroid Build Coastguard Worker 124*38e8c45fSAndroid Build Coastguard Worker /** 125*38e8c45fSAndroid Build Coastguard Worker * A map to manage multidevice resampling. Each contained resampler is never null. This map is 126*38e8c45fSAndroid Build Coastguard Worker * only modified by handleMessages. 127*38e8c45fSAndroid Build Coastguard Worker */ 128*38e8c45fSAndroid Build Coastguard Worker std::map<DeviceId, std::unique_ptr<Resampler>> mResamplers; 129*38e8c45fSAndroid Build Coastguard Worker 130*38e8c45fSAndroid Build Coastguard Worker // Looper-related infrastructure 131*38e8c45fSAndroid Build Coastguard Worker /** 132*38e8c45fSAndroid Build Coastguard Worker * This class is needed to associate the function "handleReceiveCallback" with the provided 133*38e8c45fSAndroid Build Coastguard Worker * looper. The callback sent to the looper is RefBase - based, so we can't just send a reference 134*38e8c45fSAndroid Build Coastguard Worker * of this class directly to the looper. 135*38e8c45fSAndroid Build Coastguard Worker */ 136*38e8c45fSAndroid Build Coastguard Worker class LooperEventCallback : public LooperCallback { 137*38e8c45fSAndroid Build Coastguard Worker public: LooperEventCallback(std::function<int (int events)> callback)138*38e8c45fSAndroid Build Coastguard Worker LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {} handleEvent(int,int events,void *)139*38e8c45fSAndroid Build Coastguard Worker int handleEvent(int /*fd*/, int events, void* /*data*/) override { 140*38e8c45fSAndroid Build Coastguard Worker return mCallback(events); 141*38e8c45fSAndroid Build Coastguard Worker } 142*38e8c45fSAndroid Build Coastguard Worker 143*38e8c45fSAndroid Build Coastguard Worker private: 144*38e8c45fSAndroid Build Coastguard Worker const std::function<int(int events)> mCallback; 145*38e8c45fSAndroid Build Coastguard Worker }; 146*38e8c45fSAndroid Build Coastguard Worker sp<LooperEventCallback> mCallback; 147*38e8c45fSAndroid Build Coastguard Worker /** 148*38e8c45fSAndroid Build Coastguard Worker * The actual code that executes when the looper encounters available data on the InputChannel. 149*38e8c45fSAndroid Build Coastguard Worker */ 150*38e8c45fSAndroid Build Coastguard Worker int handleReceiveCallback(int events); 151*38e8c45fSAndroid Build Coastguard Worker int mFdEvents; 152*38e8c45fSAndroid Build Coastguard Worker void setFdEvents(int events); 153*38e8c45fSAndroid Build Coastguard Worker 154*38e8c45fSAndroid Build Coastguard Worker void ensureCalledOnLooperThread(const char* func) const; 155*38e8c45fSAndroid Build Coastguard Worker 156*38e8c45fSAndroid Build Coastguard Worker // Event-reading infrastructure 157*38e8c45fSAndroid Build Coastguard Worker /** 158*38e8c45fSAndroid Build Coastguard Worker * A fifo queue of events to be sent to the InputChannel. We can't send all InputMessages to 159*38e8c45fSAndroid Build Coastguard Worker * the channel immediately when they are produced, because it's possible that the InputChannel 160*38e8c45fSAndroid Build Coastguard Worker * is blocked (if the channel buffer is full). When that happens, we don't want to drop the 161*38e8c45fSAndroid Build Coastguard Worker * events. Therefore, events should only be erased from the queue after they've been 162*38e8c45fSAndroid Build Coastguard Worker * successfully written to the InputChannel. 163*38e8c45fSAndroid Build Coastguard Worker */ 164*38e8c45fSAndroid Build Coastguard Worker std::queue<InputMessage> mOutboundQueue; 165*38e8c45fSAndroid Build Coastguard Worker /** 166*38e8c45fSAndroid Build Coastguard Worker * Try to send all of the events in mOutboundQueue over the InputChannel. Not all events might 167*38e8c45fSAndroid Build Coastguard Worker * actually get sent, because it's possible that the channel is blocked. 168*38e8c45fSAndroid Build Coastguard Worker */ 169*38e8c45fSAndroid Build Coastguard Worker void processOutboundEvents(); 170*38e8c45fSAndroid Build Coastguard Worker 171*38e8c45fSAndroid Build Coastguard Worker /** 172*38e8c45fSAndroid Build Coastguard Worker * The time at which each event with the sequence number 'seq' was consumed. 173*38e8c45fSAndroid Build Coastguard Worker * This data is provided in 'finishInputEvent' so that the receiving end can measure the latency 174*38e8c45fSAndroid Build Coastguard Worker * This collection is populated when the event is received, and the entries are erased when the 175*38e8c45fSAndroid Build Coastguard Worker * events are finished. It should not grow infinitely because if an event is not ack'd, ANR 176*38e8c45fSAndroid Build Coastguard Worker * will be raised for that connection, and no further events will be posted to that channel. 177*38e8c45fSAndroid Build Coastguard Worker */ 178*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<uint32_t /*seq*/, nsecs_t /*consumeTime*/> mConsumeTimes; 179*38e8c45fSAndroid Build Coastguard Worker /** 180*38e8c45fSAndroid Build Coastguard Worker * Find and return the consumeTime associated with the provided sequence number. Crashes if 181*38e8c45fSAndroid Build Coastguard Worker * the provided seq number is not found. 182*38e8c45fSAndroid Build Coastguard Worker */ 183*38e8c45fSAndroid Build Coastguard Worker nsecs_t popConsumeTime(uint32_t seq); 184*38e8c45fSAndroid Build Coastguard Worker 185*38e8c45fSAndroid Build Coastguard Worker // Event reading and processing 186*38e8c45fSAndroid Build Coastguard Worker /** 187*38e8c45fSAndroid Build Coastguard Worker * Read all of the available events from the InputChannel 188*38e8c45fSAndroid Build Coastguard Worker */ 189*38e8c45fSAndroid Build Coastguard Worker std::vector<InputMessage> readAllMessages(); 190*38e8c45fSAndroid Build Coastguard Worker 191*38e8c45fSAndroid Build Coastguard Worker /** 192*38e8c45fSAndroid Build Coastguard Worker * Send InputMessage to the corresponding InputConsumerCallbacks function. 193*38e8c45fSAndroid Build Coastguard Worker * @param msg 194*38e8c45fSAndroid Build Coastguard Worker */ 195*38e8c45fSAndroid Build Coastguard Worker void handleMessage(const InputMessage& msg) const; 196*38e8c45fSAndroid Build Coastguard Worker 197*38e8c45fSAndroid Build Coastguard Worker // Batching 198*38e8c45fSAndroid Build Coastguard Worker /** 199*38e8c45fSAndroid Build Coastguard Worker * Batch messages that can be batched. When an unbatchable message is encountered, send it 200*38e8c45fSAndroid Build Coastguard Worker * to the InputConsumerCallbacks immediately. If there are batches remaining, 201*38e8c45fSAndroid Build Coastguard Worker * notify InputConsumerCallbacks. If a resampleable ACTION_DOWN message is received, then a 202*38e8c45fSAndroid Build Coastguard Worker * resampler is inserted for that deviceId in mResamplers. If a resampleable ACTION_UP or 203*38e8c45fSAndroid Build Coastguard Worker * ACTION_CANCEL message is received then the resampler associated to that deviceId is erased 204*38e8c45fSAndroid Build Coastguard Worker * from mResamplers. 205*38e8c45fSAndroid Build Coastguard Worker */ 206*38e8c45fSAndroid Build Coastguard Worker void handleMessages(std::vector<InputMessage>&& messages); 207*38e8c45fSAndroid Build Coastguard Worker /** 208*38e8c45fSAndroid Build Coastguard Worker * Batched InputMessages, per deviceId. 209*38e8c45fSAndroid Build Coastguard Worker * For each device, we are storing a queue of batched messages. These will all be collapsed into 210*38e8c45fSAndroid Build Coastguard Worker * a single MotionEvent (up to a specific requestedFrameTime) when the consumer calls 211*38e8c45fSAndroid Build Coastguard Worker * `consumeBatchedInputEvents`. 212*38e8c45fSAndroid Build Coastguard Worker */ 213*38e8c45fSAndroid Build Coastguard Worker std::map<DeviceId, std::queue<InputMessage>> mBatches; 214*38e8c45fSAndroid Build Coastguard Worker 215*38e8c45fSAndroid Build Coastguard Worker /** 216*38e8c45fSAndroid Build Coastguard Worker * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages 217*38e8c45fSAndroid Build Coastguard Worker * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency 218*38e8c45fSAndroid Build Coastguard Worker * introduced by the resampler. Assumes that messages are queued in chronological order. 219*38e8c45fSAndroid Build Coastguard Worker * @param requestedFrameTime The time up to which consume messages, as given by the inequality 220*38e8c45fSAndroid Build Coastguard Worker * above. If std::nullopt, everything in messages will be consumed. 221*38e8c45fSAndroid Build Coastguard Worker * @param messages the queue of messages to consume from. 222*38e8c45fSAndroid Build Coastguard Worker */ 223*38e8c45fSAndroid Build Coastguard Worker std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent( 224*38e8c45fSAndroid Build Coastguard Worker const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages); 225*38e8c45fSAndroid Build Coastguard Worker 226*38e8c45fSAndroid Build Coastguard Worker /** 227*38e8c45fSAndroid Build Coastguard Worker * Consumes the batched input events, optionally allowing the caller to specify a device id 228*38e8c45fSAndroid Build Coastguard Worker * and/or requestedFrameTime threshold. It is not guaranteed that consumption will occur at 229*38e8c45fSAndroid Build Coastguard Worker * requestedFrameTime. 230*38e8c45fSAndroid Build Coastguard Worker * @param deviceId The device id from which to consume events. If std::nullopt, consumes events 231*38e8c45fSAndroid Build Coastguard Worker * from any device id. 232*38e8c45fSAndroid Build Coastguard Worker * @param requestedFrameTime The time up to which consume the events. If std::nullopt, consumes 233*38e8c45fSAndroid Build Coastguard Worker * input events with any timestamp. 234*38e8c45fSAndroid Build Coastguard Worker * @return Whether or not any events were consumed. 235*38e8c45fSAndroid Build Coastguard Worker */ 236*38e8c45fSAndroid Build Coastguard Worker bool consumeBatchedInputEvents(std::optional<DeviceId> deviceId, 237*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> requestedFrameTime); 238*38e8c45fSAndroid Build Coastguard Worker /** 239*38e8c45fSAndroid Build Coastguard Worker * A map from a single sequence number to several sequence numbers. This is needed because of 240*38e8c45fSAndroid Build Coastguard Worker * batching. When batching is enabled, a single MotionEvent will contain several samples. Each 241*38e8c45fSAndroid Build Coastguard Worker * sample came from an individual InputMessage of Type::Motion, and therefore will have to be 242*38e8c45fSAndroid Build Coastguard Worker * finished individually. Therefore, when the app calls "finish" on a (possibly batched) 243*38e8c45fSAndroid Build Coastguard Worker * MotionEvent, we will need to check this map in case there are multiple sequence numbers 244*38e8c45fSAndroid Build Coastguard Worker * associated with a single number that the app provided. 245*38e8c45fSAndroid Build Coastguard Worker * 246*38e8c45fSAndroid Build Coastguard Worker * For example: 247*38e8c45fSAndroid Build Coastguard Worker * Suppose we received 4 InputMessage's of type Motion, with action MOVE: 248*38e8c45fSAndroid Build Coastguard Worker * InputMessage(MOVE) InputMessage(MOVE) InputMessage(MOVE) InputMessage(MOVE) 249*38e8c45fSAndroid Build Coastguard Worker * seq=10 seq=11 seq=12 seq=13 250*38e8c45fSAndroid Build Coastguard Worker * The app consumed them all as a batch, which means that the app received a single MotionEvent 251*38e8c45fSAndroid Build Coastguard Worker * with historySize=3 and seq = 10. 252*38e8c45fSAndroid Build Coastguard Worker * 253*38e8c45fSAndroid Build Coastguard Worker * This map will look like: 254*38e8c45fSAndroid Build Coastguard Worker * { 255*38e8c45fSAndroid Build Coastguard Worker * 10: [11, 12, 13], 256*38e8c45fSAndroid Build Coastguard Worker * } 257*38e8c45fSAndroid Build Coastguard Worker * So the sequence number 10 will have 3 other sequence numbers associated with it. 258*38e8c45fSAndroid Build Coastguard Worker * When the app calls 'finish' for seq=10, we need to call 'finish' 4 times total, for sequence 259*38e8c45fSAndroid Build Coastguard Worker * numbers 10, 11, 12, 13. The app is not aware of the sequence numbers of each sample inside 260*38e8c45fSAndroid Build Coastguard Worker * the batched MotionEvent that it received. 261*38e8c45fSAndroid Build Coastguard Worker */ 262*38e8c45fSAndroid Build Coastguard Worker std::map<uint32_t, std::vector<uint32_t>> mBatchedSequenceNumbers; 263*38e8c45fSAndroid Build Coastguard Worker }; 264*38e8c45fSAndroid Build Coastguard Worker 265*38e8c45fSAndroid Build Coastguard Worker } // namespace android 266