blob: 70d00d16f4e7e7d12ff738621719c03a98cba1bc [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 Ramireze37f8342024-08-28 18:42:21 +000019#include <functional>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000020#include <map>
21#include <memory>
22#include <optional>
23
24#include <input/Input.h>
Paul Ramirezb41d38e2024-07-16 17:44:20 +000025#include <input/InputTransport.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 /**
75 * @param callbacks are used to interact with InputConsumerNoResampling. They're called whenever
76 * the event is ready to consume.
77 * @param looper needs to be sp and not shared_ptr because it inherits from
78 * RefBase
Paul Ramireze37f8342024-08-28 18:42:21 +000079 * @param resamplerCreator callable that returns the resampling strategy to be used. If null, no
80 * resampling will be performed. resamplerCreator must never return nullptr.
Paul Ramirezbe9c5442024-07-10 00:12:41 +000081 */
Paul Ramireze37f8342024-08-28 18:42:21 +000082 explicit InputConsumerNoResampling(
83 const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
84 InputConsumerCallbacks& callbacks,
85 std::function<std::unique_ptr<Resampler>()> resamplerCreator);
Paul Ramirezbe9c5442024-07-10 00:12:41 +000086
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080087 ~InputConsumerNoResampling();
88
89 /**
90 * Must be called exactly once for each event received through the callbacks.
91 */
92 void finishInputEvent(uint32_t seq, bool handled);
93 void reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime, nsecs_t presentTime);
94 /**
Paul Ramirez00cf5d02024-09-05 17:10:12 +000095 * If you want to consume all events immediately (disable batching), then you still must call
96 * this. For requestedFrameTime, use a std::nullopt. It is not guaranteed that the consumption
97 * will occur at requestedFrameTime. The resampling strategy may modify it.
98 * @param requestedFrameTime the time up to which consume the events. When there's double (or
99 * triple) buffering, you may want to not consume all events currently available, because you
100 * could be still working on an older frame, but there could already have been events that
101 * arrived that are more recent.
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800102 * @return whether any events were actually consumed
103 */
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000104 bool consumeBatchedInputEvents(std::optional<nsecs_t> requestedFrameTime);
105
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800106 /**
107 * Returns true when there is *likely* a pending batch or a pending event in the channel.
108 *
109 * This is only a performance hint and may return false negative results. Clients should not
110 * rely on availability of the message based on the return value.
111 */
112 bool probablyHasInput() const;
113
114 std::string getName() { return mChannel->getName(); }
115
116 std::string dump() const;
117
118private:
119 std::shared_ptr<InputChannel> mChannel;
Paul Ramirez87f1c012024-09-18 18:23:14 +0000120 sp<Looper> mLooper;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800121 InputConsumerCallbacks& mCallbacks;
Paul Ramireze37f8342024-08-28 18:42:21 +0000122 const std::function<std::unique_ptr<Resampler>()> mResamplerCreator;
123
124 /**
125 * A map to manage multidevice resampling. Each contained resampler is never null. This map is
126 * only modified by handleMessages.
127 */
128 std::map<DeviceId, std::unique_ptr<Resampler>> mResamplers;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800129
130 // Looper-related infrastructure
131 /**
132 * This class is needed to associate the function "handleReceiveCallback" with the provided
133 * looper. The callback sent to the looper is RefBase - based, so we can't just send a reference
134 * of this class directly to the looper.
135 */
136 class LooperEventCallback : public LooperCallback {
137 public:
138 LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {}
139 int handleEvent(int /*fd*/, int events, void* /*data*/) override {
140 return mCallback(events);
141 }
142
143 private:
Siarhei Vishniakou362fa222024-10-17 14:19:52 -0700144 const std::function<int(int events)> mCallback;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800145 };
146 sp<LooperEventCallback> mCallback;
147 /**
148 * The actual code that executes when the looper encounters available data on the InputChannel.
149 */
150 int handleReceiveCallback(int events);
151 int mFdEvents;
152 void setFdEvents(int events);
153
154 void ensureCalledOnLooperThread(const char* func) const;
155
156 // Event-reading infrastructure
157 /**
158 * A fifo queue of events to be sent to the InputChannel. We can't send all InputMessages to
159 * the channel immediately when they are produced, because it's possible that the InputChannel
160 * is blocked (if the channel buffer is full). When that happens, we don't want to drop the
161 * events. Therefore, events should only be erased from the queue after they've been
162 * successfully written to the InputChannel.
163 */
164 std::queue<InputMessage> mOutboundQueue;
165 /**
166 * Try to send all of the events in mOutboundQueue over the InputChannel. Not all events might
167 * actually get sent, because it's possible that the channel is blocked.
168 */
169 void processOutboundEvents();
170
171 /**
172 * The time at which each event with the sequence number 'seq' was consumed.
173 * This data is provided in 'finishInputEvent' so that the receiving end can measure the latency
174 * This collection is populated when the event is received, and the entries are erased when the
175 * events are finished. It should not grow infinitely because if an event is not ack'd, ANR
176 * will be raised for that connection, and no further events will be posted to that channel.
177 */
178 std::unordered_map<uint32_t /*seq*/, nsecs_t /*consumeTime*/> mConsumeTimes;
179 /**
180 * Find and return the consumeTime associated with the provided sequence number. Crashes if
181 * the provided seq number is not found.
182 */
183 nsecs_t popConsumeTime(uint32_t seq);
184
185 // Event reading and processing
186 /**
187 * Read all of the available events from the InputChannel
188 */
189 std::vector<InputMessage> readAllMessages();
190
191 /**
192 * Send InputMessage to the corresponding InputConsumerCallbacks function.
193 * @param msg
194 */
195 void handleMessage(const InputMessage& msg) const;
196
197 // Batching
198 /**
199 * Batch messages that can be batched. When an unbatchable message is encountered, send it
200 * to the InputConsumerCallbacks immediately. If there are batches remaining,
Paul Ramireze37f8342024-08-28 18:42:21 +0000201 * notify InputConsumerCallbacks. If a resampleable ACTION_DOWN message is received, then a
202 * resampler is inserted for that deviceId in mResamplers. If a resampleable ACTION_UP or
203 * ACTION_CANCEL message is received then the resampler associated to that deviceId is erased
204 * from mResamplers.
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800205 */
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;
Paul Ramirez37242c82024-10-18 23:16:43 +0000214
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800215 /**
Paul Ramirez37242c82024-10-18 23:16:43 +0000216 * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages
217 * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency
218 * introduced by the resampler. Assumes that messages are queued in chronological order.
219 * @param requestedFrameTime The time up to which consume messages, as given by the inequality
220 * above. If std::nullopt, everything in messages will be consumed.
221 * @param messages the queue of messages to consume from.
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000222 */
223 std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent(
Paul Ramirez37242c82024-10-18 23:16:43 +0000224 const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000225
226 /**
227 * Consumes the batched input events, optionally allowing the caller to specify a device id
228 * and/or requestedFrameTime threshold. It is not guaranteed that consumption will occur at
229 * requestedFrameTime.
230 * @param deviceId The device id from which to consume events. If std::nullopt, consumes events
231 * from any device id.
232 * @param requestedFrameTime The time up to which consume the events. If std::nullopt, consumes
233 * input events with any timestamp.
234 * @return Whether or not any events were consumed.
235 */
236 bool consumeBatchedInputEvents(std::optional<DeviceId> deviceId,
237 std::optional<nsecs_t> requestedFrameTime);
Paul Ramirezb41d38e2024-07-16 17:44:20 +0000238 /**
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800239 * A map from a single sequence number to several sequence numbers. This is needed because of
240 * batching. When batching is enabled, a single MotionEvent will contain several samples. Each
241 * sample came from an individual InputMessage of Type::Motion, and therefore will have to be
242 * finished individually. Therefore, when the app calls "finish" on a (possibly batched)
243 * MotionEvent, we will need to check this map in case there are multiple sequence numbers
244 * associated with a single number that the app provided.
245 *
246 * For example:
247 * Suppose we received 4 InputMessage's of type Motion, with action MOVE:
248 * InputMessage(MOVE) InputMessage(MOVE) InputMessage(MOVE) InputMessage(MOVE)
249 * seq=10 seq=11 seq=12 seq=13
250 * The app consumed them all as a batch, which means that the app received a single MotionEvent
251 * with historySize=3 and seq = 10.
252 *
253 * This map will look like:
254 * {
255 * 10: [11, 12, 13],
256 * }
257 * So the sequence number 10 will have 3 other sequence numbers associated with it.
258 * When the app calls 'finish' for seq=10, we need to call 'finish' 4 times total, for sequence
259 * numbers 10, 11, 12, 13. The app is not aware of the sequence numbers of each sample inside
260 * the batched MotionEvent that it received.
261 */
262 std::map<uint32_t, std::vector<uint32_t>> mBatchedSequenceNumbers;
263};
264
265} // namespace android