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