| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 1 | /** | 
|  | 2 | * Copyright 2024 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #pragma once | 
|  | 18 |  | 
| Paul Ramirez | b41d38e | 2024-07-16 17:44:20 +0000 | [diff] [blame] | 19 | #include <input/InputTransport.h> | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 20 | #include <input/Resampler.h> | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 21 | #include <utils/Looper.h> | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 22 |  | 
|  | 23 | namespace android { | 
|  | 24 |  | 
|  | 25 | /** | 
|  | 26 | * An interface to receive batched input events. Even if you don't want batching, you still have to | 
|  | 27 | * use this interface, and some of the events will be batched if your implementation is slow to | 
| Paul Ramirez | 79655f2 | 2024-07-01 21:55:48 +0000 | [diff] [blame] | 28 | * handle the incoming input. The events received by these callbacks are never null. | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 29 | */ | 
|  | 30 | class InputConsumerCallbacks { | 
|  | 31 | public: | 
|  | 32 | virtual ~InputConsumerCallbacks(){}; | 
| Siarhei Vishniakou | 3891ec9 | 2024-03-15 13:29:57 -0700 | [diff] [blame] | 33 | virtual void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) = 0; | 
|  | 34 | virtual void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) = 0; | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 35 | /** | 
|  | 36 | * When you receive this callback, you must (eventually) call "consumeBatchedInputEvents". | 
|  | 37 | * If you don't want batching, then call "consumeBatchedInputEvents" immediately with | 
|  | 38 | * std::nullopt frameTime to receive the pending motion event(s). | 
|  | 39 | * @param pendingBatchSource the source of the pending batch. | 
|  | 40 | */ | 
|  | 41 | virtual void onBatchedInputEventPending(int32_t pendingBatchSource) = 0; | 
| Siarhei Vishniakou | 3891ec9 | 2024-03-15 13:29:57 -0700 | [diff] [blame] | 42 | virtual void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) = 0; | 
|  | 43 | virtual void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) = 0; | 
|  | 44 | virtual void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) = 0; | 
|  | 45 | virtual void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) = 0; | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 46 | }; | 
|  | 47 |  | 
|  | 48 | /** | 
|  | 49 | * Consumes input events from an input channel. | 
|  | 50 | * | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 51 | * This is a re-implementation of InputConsumer. At the moment it only supports resampling for | 
|  | 52 | * single pointer events. A lot of the higher-level logic has been folded into this class, to make | 
|  | 53 | * it easier to use. In the legacy class, InputConsumer, the consumption logic was partially handled | 
|  | 54 | * in the jni layer, as well as various actions like adding the fd to the Choreographer. | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 55 | * | 
|  | 56 | * TODO(b/297226446): use this instead of "InputConsumer": | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 57 | * - Add resampling for multiple pointer events. | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 58 | * - Allow various resampling strategies to be specified | 
|  | 59 | * - Delete the old "InputConsumer" and use this class instead, renaming it to "InputConsumer". | 
|  | 60 | * - Add tracing | 
|  | 61 | * - Update all tests to use the new InputConsumer | 
|  | 62 | * | 
|  | 63 | * This class is not thread-safe. We are currently allowing the constructor to run on any thread, | 
|  | 64 | * but all of the remaining APIs should be invoked on the looper thread only. | 
|  | 65 | */ | 
|  | 66 | class InputConsumerNoResampling final { | 
|  | 67 | public: | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 68 | /** | 
|  | 69 | * @param callbacks are used to interact with InputConsumerNoResampling. They're called whenever | 
|  | 70 | * the event is ready to consume. | 
|  | 71 | * @param looper needs to be sp and not shared_ptr because it inherits from | 
|  | 72 | * RefBase | 
|  | 73 | * @param resampler the resampling strategy to use. If null, no resampling will be | 
|  | 74 | * performed. | 
|  | 75 | */ | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 76 | explicit InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel, | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 77 | sp<Looper> looper, InputConsumerCallbacks& callbacks, | 
|  | 78 | std::unique_ptr<Resampler> resampler); | 
|  | 79 |  | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 80 | ~InputConsumerNoResampling(); | 
|  | 81 |  | 
|  | 82 | /** | 
|  | 83 | * Must be called exactly once for each event received through the callbacks. | 
|  | 84 | */ | 
|  | 85 | void finishInputEvent(uint32_t seq, bool handled); | 
|  | 86 | void reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime, nsecs_t presentTime); | 
|  | 87 | /** | 
|  | 88 | * If you want to consume all events immediately (disable batching), the you still must call | 
|  | 89 | * this. For frameTime, use a std::nullopt. | 
|  | 90 | * @param frameTime the time up to which consume the events. When there's double (or triple) | 
|  | 91 | * buffering, you may want to not consume all events currently available, because you could be | 
|  | 92 | * still working on an older frame, but there could already have been events that arrived that | 
|  | 93 | * are more recent. | 
|  | 94 | * @return whether any events were actually consumed | 
|  | 95 | */ | 
|  | 96 | bool consumeBatchedInputEvents(std::optional<nsecs_t> frameTime); | 
|  | 97 | /** | 
|  | 98 | * Returns true when there is *likely* a pending batch or a pending event in the channel. | 
|  | 99 | * | 
|  | 100 | * This is only a performance hint and may return false negative results. Clients should not | 
|  | 101 | * rely on availability of the message based on the return value. | 
|  | 102 | */ | 
|  | 103 | bool probablyHasInput() const; | 
|  | 104 |  | 
|  | 105 | std::string getName() { return mChannel->getName(); } | 
|  | 106 |  | 
|  | 107 | std::string dump() const; | 
|  | 108 |  | 
|  | 109 | private: | 
|  | 110 | std::shared_ptr<InputChannel> mChannel; | 
|  | 111 | sp<Looper> mLooper; | 
|  | 112 | InputConsumerCallbacks& mCallbacks; | 
| Paul Ramirez | be9c544 | 2024-07-10 00:12:41 +0000 | [diff] [blame^] | 113 | std::unique_ptr<Resampler> mResampler; | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 114 |  | 
|  | 115 | // Looper-related infrastructure | 
|  | 116 | /** | 
|  | 117 | * This class is needed to associate the function "handleReceiveCallback" with the provided | 
|  | 118 | * looper. The callback sent to the looper is RefBase - based, so we can't just send a reference | 
|  | 119 | * of this class directly to the looper. | 
|  | 120 | */ | 
|  | 121 | class LooperEventCallback : public LooperCallback { | 
|  | 122 | public: | 
|  | 123 | LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {} | 
|  | 124 | int handleEvent(int /*fd*/, int events, void* /*data*/) override { | 
|  | 125 | return mCallback(events); | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | private: | 
|  | 129 | std::function<int(int events)> mCallback; | 
|  | 130 | }; | 
|  | 131 | sp<LooperEventCallback> mCallback; | 
|  | 132 | /** | 
|  | 133 | * The actual code that executes when the looper encounters available data on the InputChannel. | 
|  | 134 | */ | 
|  | 135 | int handleReceiveCallback(int events); | 
|  | 136 | int mFdEvents; | 
|  | 137 | void setFdEvents(int events); | 
|  | 138 |  | 
|  | 139 | void ensureCalledOnLooperThread(const char* func) const; | 
|  | 140 |  | 
|  | 141 | // Event-reading infrastructure | 
|  | 142 | /** | 
|  | 143 | * A fifo queue of events to be sent to the InputChannel. We can't send all InputMessages to | 
|  | 144 | * the channel immediately when they are produced, because it's possible that the InputChannel | 
|  | 145 | * is blocked (if the channel buffer is full). When that happens, we don't want to drop the | 
|  | 146 | * events. Therefore, events should only be erased from the queue after they've been | 
|  | 147 | * successfully written to the InputChannel. | 
|  | 148 | */ | 
|  | 149 | std::queue<InputMessage> mOutboundQueue; | 
|  | 150 | /** | 
|  | 151 | * Try to send all of the events in mOutboundQueue over the InputChannel. Not all events might | 
|  | 152 | * actually get sent, because it's possible that the channel is blocked. | 
|  | 153 | */ | 
|  | 154 | void processOutboundEvents(); | 
|  | 155 |  | 
|  | 156 | /** | 
|  | 157 | * The time at which each event with the sequence number 'seq' was consumed. | 
|  | 158 | * This data is provided in 'finishInputEvent' so that the receiving end can measure the latency | 
|  | 159 | * This collection is populated when the event is received, and the entries are erased when the | 
|  | 160 | * events are finished. It should not grow infinitely because if an event is not ack'd, ANR | 
|  | 161 | * will be raised for that connection, and no further events will be posted to that channel. | 
|  | 162 | */ | 
|  | 163 | std::unordered_map<uint32_t /*seq*/, nsecs_t /*consumeTime*/> mConsumeTimes; | 
|  | 164 | /** | 
|  | 165 | * Find and return the consumeTime associated with the provided sequence number. Crashes if | 
|  | 166 | * the provided seq number is not found. | 
|  | 167 | */ | 
|  | 168 | nsecs_t popConsumeTime(uint32_t seq); | 
|  | 169 |  | 
|  | 170 | // Event reading and processing | 
|  | 171 | /** | 
|  | 172 | * Read all of the available events from the InputChannel | 
|  | 173 | */ | 
|  | 174 | std::vector<InputMessage> readAllMessages(); | 
|  | 175 |  | 
|  | 176 | /** | 
|  | 177 | * Send InputMessage to the corresponding InputConsumerCallbacks function. | 
|  | 178 | * @param msg | 
|  | 179 | */ | 
|  | 180 | void handleMessage(const InputMessage& msg) const; | 
|  | 181 |  | 
|  | 182 | // Batching | 
|  | 183 | /** | 
|  | 184 | * Batch messages that can be batched. When an unbatchable message is encountered, send it | 
|  | 185 | * to the InputConsumerCallbacks immediately. If there are batches remaining, | 
|  | 186 | * notify InputConsumerCallbacks. | 
|  | 187 | */ | 
|  | 188 | void handleMessages(std::vector<InputMessage>&& messages); | 
|  | 189 | /** | 
|  | 190 | * Batched InputMessages, per deviceId. | 
|  | 191 | * For each device, we are storing a queue of batched messages. These will all be collapsed into | 
|  | 192 | * a single MotionEvent (up to a specific frameTime) when the consumer calls | 
|  | 193 | * `consumeBatchedInputEvents`. | 
|  | 194 | */ | 
|  | 195 | std::map<DeviceId, std::queue<InputMessage>> mBatches; | 
|  | 196 | /** | 
| Paul Ramirez | b41d38e | 2024-07-16 17:44:20 +0000 | [diff] [blame] | 197 | * Creates a MotionEvent by consuming samples from the provided queue. If one message has | 
|  | 198 | * eventTime > frameTime, all subsequent messages in the queue will be skipped. It is assumed | 
|  | 199 | * that messages are queued in chronological order. In other words, only events that occurred | 
|  | 200 | * prior to the requested frameTime will be consumed. | 
|  | 201 | * @param frameTime the time up to which to consume events | 
|  | 202 | * @param messages the queue of messages to consume from | 
|  | 203 | */ | 
|  | 204 | std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent( | 
|  | 205 | const nsecs_t frameTime, std::queue<InputMessage>& messages); | 
|  | 206 | /** | 
| Siarhei Vishniakou | 2b92027 | 2024-02-27 19:49:51 -0800 | [diff] [blame] | 207 | * A map from a single sequence number to several sequence numbers. This is needed because of | 
|  | 208 | * batching. When batching is enabled, a single MotionEvent will contain several samples. Each | 
|  | 209 | * sample came from an individual InputMessage of Type::Motion, and therefore will have to be | 
|  | 210 | * finished individually. Therefore, when the app calls "finish" on a (possibly batched) | 
|  | 211 | * MotionEvent, we will need to check this map in case there are multiple sequence numbers | 
|  | 212 | * associated with a single number that the app provided. | 
|  | 213 | * | 
|  | 214 | * For example: | 
|  | 215 | * Suppose we received 4 InputMessage's of type Motion, with action MOVE: | 
|  | 216 | * InputMessage(MOVE)   InputMessage(MOVE)   InputMessage(MOVE)   InputMessage(MOVE) | 
|  | 217 | *    seq=10               seq=11               seq=12               seq=13 | 
|  | 218 | * The app consumed them all as a batch, which means that the app received a single MotionEvent | 
|  | 219 | * with historySize=3 and seq = 10. | 
|  | 220 | * | 
|  | 221 | * This map will look like: | 
|  | 222 | * { | 
|  | 223 | *   10: [11, 12, 13], | 
|  | 224 | * } | 
|  | 225 | * So the sequence number 10 will have 3 other sequence numbers associated with it. | 
|  | 226 | * When the app calls 'finish' for seq=10, we need to call 'finish' 4 times total, for sequence | 
|  | 227 | * numbers 10, 11, 12, 13. The app is not aware of the sequence numbers of each sample inside | 
|  | 228 | * the batched MotionEvent that it received. | 
|  | 229 | */ | 
|  | 230 | std::map<uint32_t, std::vector<uint32_t>> mBatchedSequenceNumbers; | 
|  | 231 | }; | 
|  | 232 |  | 
|  | 233 | } // namespace android |