blob: 65c2914b3cebbae6a59713f4be615964d923285b [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 Ramirezb41d38e2024-07-16 17:44:20 +000019#include <input/InputTransport.h>
Paul Ramirezbe9c5442024-07-10 00:12:41 +000020#include <input/Resampler.h>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080021#include <utils/Looper.h>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080022
23namespace 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 Ramirez79655f22024-07-01 21:55:48 +000028 * handle the incoming input. The events received by these callbacks are never null.
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080029 */
30class InputConsumerCallbacks {
31public:
32 virtual ~InputConsumerCallbacks(){};
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -070033 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 Vishniakou2b920272024-02-27 19:49:51 -080035 /**
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 Vishniakou3891ec92024-03-15 13:29:57 -070042 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 Vishniakou2b920272024-02-27 19:49:51 -080046};
47
48/**
49 * Consumes input events from an input channel.
50 *
Paul Ramirezbe9c5442024-07-10 00:12:41 +000051 * 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 Vishniakou2b920272024-02-27 19:49:51 -080055 *
56 * TODO(b/297226446): use this instead of "InputConsumer":
Paul Ramirezbe9c5442024-07-10 00:12:41 +000057 * - Add resampling for multiple pointer events.
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080058 * - 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 */
66class InputConsumerNoResampling final {
67public:
Paul Ramirezbe9c5442024-07-10 00:12:41 +000068 /**
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 Vishniakou2b920272024-02-27 19:49:51 -080076 explicit InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
Paul Ramirezbe9c5442024-07-10 00:12:41 +000077 sp<Looper> looper, InputConsumerCallbacks& callbacks,
78 std::unique_ptr<Resampler> resampler);
79
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080080 ~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
109private:
110 std::shared_ptr<InputChannel> mChannel;
111 sp<Looper> mLooper;
112 InputConsumerCallbacks& mCallbacks;
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000113 std::unique_ptr<Resampler> mResampler;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800114
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 Ramirezb41d38e2024-07-16 17:44:20 +0000197 * 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 Vishniakou2b920272024-02-27 19:49:51 -0800207 * 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