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