1*38e8c45fSAndroid Build Coastguard Worker /**
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2024 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include <cstdint>
18*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "InputTransport"
19*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_INPUT
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include <errno.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <fcntl.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <math.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <poll.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <sys/socket.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <android-base/properties.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <binder/Parcel.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
38*38e8c45fSAndroid Build Coastguard Worker
39*38e8c45fSAndroid Build Coastguard Worker #include <com_android_input_flags.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <input/InputConsumer.h>
41*38e8c45fSAndroid Build Coastguard Worker #include <input/PrintTools.h>
42*38e8c45fSAndroid Build Coastguard Worker #include <input/TraceTools.h>
43*38e8c45fSAndroid Build Coastguard Worker
44*38e8c45fSAndroid Build Coastguard Worker namespace input_flags = com::android::input::flags;
45*38e8c45fSAndroid Build Coastguard Worker
46*38e8c45fSAndroid Build Coastguard Worker namespace android {
47*38e8c45fSAndroid Build Coastguard Worker
48*38e8c45fSAndroid Build Coastguard Worker namespace {
49*38e8c45fSAndroid Build Coastguard Worker
50*38e8c45fSAndroid Build Coastguard Worker /**
51*38e8c45fSAndroid Build Coastguard Worker * Log debug messages relating to the consumer end of the transport channel.
52*38e8c45fSAndroid Build Coastguard Worker * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
53*38e8c45fSAndroid Build Coastguard Worker */
54*38e8c45fSAndroid Build Coastguard Worker
55*38e8c45fSAndroid Build Coastguard Worker const bool DEBUG_TRANSPORT_CONSUMER =
56*38e8c45fSAndroid Build Coastguard Worker __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
57*38e8c45fSAndroid Build Coastguard Worker
58*38e8c45fSAndroid Build Coastguard Worker const bool IS_DEBUGGABLE_BUILD =
59*38e8c45fSAndroid Build Coastguard Worker #if defined(__ANDROID__)
60*38e8c45fSAndroid Build Coastguard Worker android::base::GetBoolProperty("ro.debuggable", false);
61*38e8c45fSAndroid Build Coastguard Worker #else
62*38e8c45fSAndroid Build Coastguard Worker true;
63*38e8c45fSAndroid Build Coastguard Worker #endif
64*38e8c45fSAndroid Build Coastguard Worker
65*38e8c45fSAndroid Build Coastguard Worker /**
66*38e8c45fSAndroid Build Coastguard Worker * Log debug messages about touch event resampling.
67*38e8c45fSAndroid Build Coastguard Worker *
68*38e8c45fSAndroid Build Coastguard Worker * Enable this via "adb shell setprop log.tag.InputTransportResampling DEBUG".
69*38e8c45fSAndroid Build Coastguard Worker * This requires a restart on non-debuggable (e.g. user) builds, but should take effect immediately
70*38e8c45fSAndroid Build Coastguard Worker * on debuggable builds (e.g. userdebug).
71*38e8c45fSAndroid Build Coastguard Worker */
debugResampling()72*38e8c45fSAndroid Build Coastguard Worker bool debugResampling() {
73*38e8c45fSAndroid Build Coastguard Worker if (!IS_DEBUGGABLE_BUILD) {
74*38e8c45fSAndroid Build Coastguard Worker static const bool DEBUG_TRANSPORT_RESAMPLING =
75*38e8c45fSAndroid Build Coastguard Worker __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling",
76*38e8c45fSAndroid Build Coastguard Worker ANDROID_LOG_INFO);
77*38e8c45fSAndroid Build Coastguard Worker return DEBUG_TRANSPORT_RESAMPLING;
78*38e8c45fSAndroid Build Coastguard Worker }
79*38e8c45fSAndroid Build Coastguard Worker return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling", ANDROID_LOG_INFO);
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker
initializeKeyEvent(KeyEvent & event,const InputMessage & msg)82*38e8c45fSAndroid Build Coastguard Worker void initializeKeyEvent(KeyEvent& event, const InputMessage& msg) {
83*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
84*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
85*38e8c45fSAndroid Build Coastguard Worker msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
86*38e8c45fSAndroid Build Coastguard Worker msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
87*38e8c45fSAndroid Build Coastguard Worker msg.body.key.downTime, msg.body.key.eventTime);
88*38e8c45fSAndroid Build Coastguard Worker }
89*38e8c45fSAndroid Build Coastguard Worker
initializeFocusEvent(FocusEvent & event,const InputMessage & msg)90*38e8c45fSAndroid Build Coastguard Worker void initializeFocusEvent(FocusEvent& event, const InputMessage& msg) {
91*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
92*38e8c45fSAndroid Build Coastguard Worker }
93*38e8c45fSAndroid Build Coastguard Worker
initializeCaptureEvent(CaptureEvent & event,const InputMessage & msg)94*38e8c45fSAndroid Build Coastguard Worker void initializeCaptureEvent(CaptureEvent& event, const InputMessage& msg) {
95*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
96*38e8c45fSAndroid Build Coastguard Worker }
97*38e8c45fSAndroid Build Coastguard Worker
initializeDragEvent(DragEvent & event,const InputMessage & msg)98*38e8c45fSAndroid Build Coastguard Worker void initializeDragEvent(DragEvent& event, const InputMessage& msg) {
99*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
100*38e8c45fSAndroid Build Coastguard Worker msg.body.drag.isExiting);
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker
initializeMotionEvent(MotionEvent & event,const InputMessage & msg)103*38e8c45fSAndroid Build Coastguard Worker void initializeMotionEvent(MotionEvent& event, const InputMessage& msg) {
104*38e8c45fSAndroid Build Coastguard Worker uint32_t pointerCount = msg.body.motion.pointerCount;
105*38e8c45fSAndroid Build Coastguard Worker PointerProperties pointerProperties[pointerCount];
106*38e8c45fSAndroid Build Coastguard Worker PointerCoords pointerCoords[pointerCount];
107*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < pointerCount; i++) {
108*38e8c45fSAndroid Build Coastguard Worker pointerProperties[i] = msg.body.motion.pointers[i].properties;
109*38e8c45fSAndroid Build Coastguard Worker pointerCoords[i] = msg.body.motion.pointers[i].coords;
110*38e8c45fSAndroid Build Coastguard Worker }
111*38e8c45fSAndroid Build Coastguard Worker
112*38e8c45fSAndroid Build Coastguard Worker ui::Transform transform;
113*38e8c45fSAndroid Build Coastguard Worker transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
114*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
115*38e8c45fSAndroid Build Coastguard Worker ui::Transform displayTransform;
116*38e8c45fSAndroid Build Coastguard Worker displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
117*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
118*38e8c45fSAndroid Build Coastguard Worker 0, 0, 1});
119*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
120*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
121*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
122*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.edgeFlags, msg.body.motion.metaState,
123*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.buttonState, msg.body.motion.classification, transform,
124*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.xPrecision, msg.body.motion.yPrecision,
125*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
126*38e8c45fSAndroid Build Coastguard Worker displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
127*38e8c45fSAndroid Build Coastguard Worker pointerCount, pointerProperties, pointerCoords);
128*38e8c45fSAndroid Build Coastguard Worker }
129*38e8c45fSAndroid Build Coastguard Worker
addSample(MotionEvent & event,const InputMessage & msg)130*38e8c45fSAndroid Build Coastguard Worker void addSample(MotionEvent& event, const InputMessage& msg) {
131*38e8c45fSAndroid Build Coastguard Worker uint32_t pointerCount = msg.body.motion.pointerCount;
132*38e8c45fSAndroid Build Coastguard Worker PointerCoords pointerCoords[pointerCount];
133*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < pointerCount; i++) {
134*38e8c45fSAndroid Build Coastguard Worker pointerCoords[i] = msg.body.motion.pointers[i].coords;
135*38e8c45fSAndroid Build Coastguard Worker }
136*38e8c45fSAndroid Build Coastguard Worker
137*38e8c45fSAndroid Build Coastguard Worker event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
138*38e8c45fSAndroid Build Coastguard Worker event.addSample(msg.body.motion.eventTime, pointerCoords, msg.body.motion.eventId);
139*38e8c45fSAndroid Build Coastguard Worker }
140*38e8c45fSAndroid Build Coastguard Worker
initializeTouchModeEvent(TouchModeEvent & event,const InputMessage & msg)141*38e8c45fSAndroid Build Coastguard Worker void initializeTouchModeEvent(TouchModeEvent& event, const InputMessage& msg) {
142*38e8c45fSAndroid Build Coastguard Worker event.initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker
145*38e8c45fSAndroid Build Coastguard Worker // Nanoseconds per milliseconds.
146*38e8c45fSAndroid Build Coastguard Worker constexpr nsecs_t NANOS_PER_MS = 1000000;
147*38e8c45fSAndroid Build Coastguard Worker
148*38e8c45fSAndroid Build Coastguard Worker // Latency added during resampling. A few milliseconds doesn't hurt much but
149*38e8c45fSAndroid Build Coastguard Worker // reduces the impact of mispredicted touch positions.
150*38e8c45fSAndroid Build Coastguard Worker const std::chrono::duration RESAMPLE_LATENCY = 5ms;
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker // Minimum time difference between consecutive samples before attempting to resample.
153*38e8c45fSAndroid Build Coastguard Worker const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker // Maximum time difference between consecutive samples before attempting to resample
156*38e8c45fSAndroid Build Coastguard Worker // by extrapolation.
157*38e8c45fSAndroid Build Coastguard Worker const nsecs_t RESAMPLE_MAX_DELTA = 20 * NANOS_PER_MS;
158*38e8c45fSAndroid Build Coastguard Worker
159*38e8c45fSAndroid Build Coastguard Worker // Maximum time to predict forward from the last known state, to avoid predicting too
160*38e8c45fSAndroid Build Coastguard Worker // far into the future. This time is further bounded by 50% of the last time delta.
161*38e8c45fSAndroid Build Coastguard Worker const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
162*38e8c45fSAndroid Build Coastguard Worker
163*38e8c45fSAndroid Build Coastguard Worker /**
164*38e8c45fSAndroid Build Coastguard Worker * System property for enabling / disabling touch resampling.
165*38e8c45fSAndroid Build Coastguard Worker * Resampling extrapolates / interpolates the reported touch event coordinates to better
166*38e8c45fSAndroid Build Coastguard Worker * align them to the VSYNC signal, thus resulting in smoother scrolling performance.
167*38e8c45fSAndroid Build Coastguard Worker * Resampling is not needed (and should be disabled) on hardware that already
168*38e8c45fSAndroid Build Coastguard Worker * has touch events triggered by VSYNC.
169*38e8c45fSAndroid Build Coastguard Worker * Set to "1" to enable resampling (default).
170*38e8c45fSAndroid Build Coastguard Worker * Set to "0" to disable resampling.
171*38e8c45fSAndroid Build Coastguard Worker * Resampling is enabled by default.
172*38e8c45fSAndroid Build Coastguard Worker */
173*38e8c45fSAndroid Build Coastguard Worker const char* PROPERTY_RESAMPLING_ENABLED = "ro.input.resampling";
174*38e8c45fSAndroid Build Coastguard Worker
lerp(float a,float b,float alpha)175*38e8c45fSAndroid Build Coastguard Worker inline float lerp(float a, float b, float alpha) {
176*38e8c45fSAndroid Build Coastguard Worker return a + alpha * (b - a);
177*38e8c45fSAndroid Build Coastguard Worker }
178*38e8c45fSAndroid Build Coastguard Worker
isPointerEvent(int32_t source)179*38e8c45fSAndroid Build Coastguard Worker inline bool isPointerEvent(int32_t source) {
180*38e8c45fSAndroid Build Coastguard Worker return (source & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
181*38e8c45fSAndroid Build Coastguard Worker }
182*38e8c45fSAndroid Build Coastguard Worker
shouldResampleTool(ToolType toolType)183*38e8c45fSAndroid Build Coastguard Worker bool shouldResampleTool(ToolType toolType) {
184*38e8c45fSAndroid Build Coastguard Worker return toolType == ToolType::FINGER || toolType == ToolType::MOUSE ||
185*38e8c45fSAndroid Build Coastguard Worker toolType == ToolType::STYLUS || toolType == ToolType::UNKNOWN;
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker
188*38e8c45fSAndroid Build Coastguard Worker } // namespace
189*38e8c45fSAndroid Build Coastguard Worker
190*38e8c45fSAndroid Build Coastguard Worker using android::base::Result;
191*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
192*38e8c45fSAndroid Build Coastguard Worker
193*38e8c45fSAndroid Build Coastguard Worker // --- InputConsumer ---
194*38e8c45fSAndroid Build Coastguard Worker
InputConsumer(const std::shared_ptr<InputChannel> & channel)195*38e8c45fSAndroid Build Coastguard Worker InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel)
196*38e8c45fSAndroid Build Coastguard Worker : InputConsumer(channel, isTouchResamplingEnabled()) {}
197*38e8c45fSAndroid Build Coastguard Worker
InputConsumer(const std::shared_ptr<InputChannel> & channel,bool enableTouchResampling)198*38e8c45fSAndroid Build Coastguard Worker InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel,
199*38e8c45fSAndroid Build Coastguard Worker bool enableTouchResampling)
200*38e8c45fSAndroid Build Coastguard Worker : mResampleTouch(enableTouchResampling),
201*38e8c45fSAndroid Build Coastguard Worker mChannel(channel),
202*38e8c45fSAndroid Build Coastguard Worker mProcessingTraceTag(StringPrintf("InputConsumer processing on %s (%p)",
203*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), this)),
204*38e8c45fSAndroid Build Coastguard Worker mLifetimeTraceTag(StringPrintf("InputConsumer lifetime on %s (%p)",
205*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), this)),
206*38e8c45fSAndroid Build Coastguard Worker mLifetimeTraceCookie(
207*38e8c45fSAndroid Build Coastguard Worker static_cast<int32_t>(reinterpret_cast<std::uintptr_t>(this) & 0xFFFFFFFF)),
208*38e8c45fSAndroid Build Coastguard Worker mMsgDeferred(false) {
209*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_BEGIN(mLifetimeTraceTag.c_str(), /*cookie=*/mLifetimeTraceCookie);
210*38e8c45fSAndroid Build Coastguard Worker }
211*38e8c45fSAndroid Build Coastguard Worker
~InputConsumer()212*38e8c45fSAndroid Build Coastguard Worker InputConsumer::~InputConsumer() {
213*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_END(mLifetimeTraceTag.c_str(), /*cookie=*/mLifetimeTraceCookie);
214*38e8c45fSAndroid Build Coastguard Worker }
215*38e8c45fSAndroid Build Coastguard Worker
isTouchResamplingEnabled()216*38e8c45fSAndroid Build Coastguard Worker bool InputConsumer::isTouchResamplingEnabled() {
217*38e8c45fSAndroid Build Coastguard Worker return property_get_bool(PROPERTY_RESAMPLING_ENABLED, true);
218*38e8c45fSAndroid Build Coastguard Worker }
219*38e8c45fSAndroid Build Coastguard Worker
consume(InputEventFactoryInterface * factory,bool consumeBatches,nsecs_t frameTime,uint32_t * outSeq,InputEvent ** outEvent)220*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
221*38e8c45fSAndroid Build Coastguard Worker nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
222*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
223*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
224*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), toString(consumeBatches), frameTime);
225*38e8c45fSAndroid Build Coastguard Worker
226*38e8c45fSAndroid Build Coastguard Worker *outSeq = 0;
227*38e8c45fSAndroid Build Coastguard Worker *outEvent = nullptr;
228*38e8c45fSAndroid Build Coastguard Worker
229*38e8c45fSAndroid Build Coastguard Worker // Fetch the next input message.
230*38e8c45fSAndroid Build Coastguard Worker // Loop until an event can be returned or no additional events are received.
231*38e8c45fSAndroid Build Coastguard Worker while (!*outEvent) {
232*38e8c45fSAndroid Build Coastguard Worker if (mMsgDeferred) {
233*38e8c45fSAndroid Build Coastguard Worker // mMsg contains a valid input message from the previous call to consume
234*38e8c45fSAndroid Build Coastguard Worker // that has not yet been processed.
235*38e8c45fSAndroid Build Coastguard Worker mMsgDeferred = false;
236*38e8c45fSAndroid Build Coastguard Worker } else {
237*38e8c45fSAndroid Build Coastguard Worker // Receive a fresh message.
238*38e8c45fSAndroid Build Coastguard Worker android::base::Result<InputMessage> result = mChannel->receiveMessage();
239*38e8c45fSAndroid Build Coastguard Worker if (result.ok()) {
240*38e8c45fSAndroid Build Coastguard Worker mMsg = std::move(result.value());
241*38e8c45fSAndroid Build Coastguard Worker const auto [_, inserted] =
242*38e8c45fSAndroid Build Coastguard Worker mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
243*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
244*38e8c45fSAndroid Build Coastguard Worker mMsg.header.seq);
245*38e8c45fSAndroid Build Coastguard Worker
246*38e8c45fSAndroid Build Coastguard Worker // Trace the event processing timeline - event was just read from the socket
247*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_BEGIN(mProcessingTraceTag.c_str(), /*cookie=*/mMsg.header.seq);
248*38e8c45fSAndroid Build Coastguard Worker } else {
249*38e8c45fSAndroid Build Coastguard Worker // Consume the next batched event unless batches are being held for later.
250*38e8c45fSAndroid Build Coastguard Worker if (consumeBatches || result.error().code() != WOULD_BLOCK) {
251*38e8c45fSAndroid Build Coastguard Worker result = android::base::Error(
252*38e8c45fSAndroid Build Coastguard Worker consumeBatch(factory, frameTime, outSeq, outEvent));
253*38e8c45fSAndroid Build Coastguard Worker if (*outEvent) {
254*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
255*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ consumed batch event, seq=%u",
256*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), *outSeq);
257*38e8c45fSAndroid Build Coastguard Worker break;
258*38e8c45fSAndroid Build Coastguard Worker }
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker return result.error().code();
261*38e8c45fSAndroid Build Coastguard Worker }
262*38e8c45fSAndroid Build Coastguard Worker }
263*38e8c45fSAndroid Build Coastguard Worker
264*38e8c45fSAndroid Build Coastguard Worker switch (mMsg.header.type) {
265*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::KEY: {
266*38e8c45fSAndroid Build Coastguard Worker KeyEvent* keyEvent = factory->createKeyEvent();
267*38e8c45fSAndroid Build Coastguard Worker if (!keyEvent) return NO_MEMORY;
268*38e8c45fSAndroid Build Coastguard Worker
269*38e8c45fSAndroid Build Coastguard Worker initializeKeyEvent(*keyEvent, mMsg);
270*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
271*38e8c45fSAndroid Build Coastguard Worker *outEvent = keyEvent;
272*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
273*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ consumed key event, seq=%u",
274*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), *outSeq);
275*38e8c45fSAndroid Build Coastguard Worker break;
276*38e8c45fSAndroid Build Coastguard Worker }
277*38e8c45fSAndroid Build Coastguard Worker
278*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::MOTION: {
279*38e8c45fSAndroid Build Coastguard Worker ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
280*38e8c45fSAndroid Build Coastguard Worker if (batchIndex >= 0) {
281*38e8c45fSAndroid Build Coastguard Worker Batch& batch = mBatches[batchIndex];
282*38e8c45fSAndroid Build Coastguard Worker if (canAddSample(batch, &mMsg)) {
283*38e8c45fSAndroid Build Coastguard Worker batch.samples.push_back(mMsg);
284*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
285*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ appended to batch event",
286*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str());
287*38e8c45fSAndroid Build Coastguard Worker break;
288*38e8c45fSAndroid Build Coastguard Worker } else if (isPointerEvent(mMsg.body.motion.source) &&
289*38e8c45fSAndroid Build Coastguard Worker mMsg.body.motion.action == AMOTION_EVENT_ACTION_CANCEL) {
290*38e8c45fSAndroid Build Coastguard Worker // No need to process events that we are going to cancel anyways
291*38e8c45fSAndroid Build Coastguard Worker const size_t count = batch.samples.size();
292*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++) {
293*38e8c45fSAndroid Build Coastguard Worker const InputMessage& msg = batch.samples[i];
294*38e8c45fSAndroid Build Coastguard Worker sendFinishedSignal(msg.header.seq, false);
295*38e8c45fSAndroid Build Coastguard Worker }
296*38e8c45fSAndroid Build Coastguard Worker batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
297*38e8c45fSAndroid Build Coastguard Worker mBatches.erase(mBatches.begin() + batchIndex);
298*38e8c45fSAndroid Build Coastguard Worker } else {
299*38e8c45fSAndroid Build Coastguard Worker // We cannot append to the batch in progress, so we need to consume
300*38e8c45fSAndroid Build Coastguard Worker // the previous batch right now and defer the new message until later.
301*38e8c45fSAndroid Build Coastguard Worker mMsgDeferred = true;
302*38e8c45fSAndroid Build Coastguard Worker status_t result = consumeSamples(factory, batch, batch.samples.size(),
303*38e8c45fSAndroid Build Coastguard Worker outSeq, outEvent);
304*38e8c45fSAndroid Build Coastguard Worker mBatches.erase(mBatches.begin() + batchIndex);
305*38e8c45fSAndroid Build Coastguard Worker if (result) {
306*38e8c45fSAndroid Build Coastguard Worker return result;
307*38e8c45fSAndroid Build Coastguard Worker }
308*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
309*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ consumed batch event and "
310*38e8c45fSAndroid Build Coastguard Worker "deferred current event, seq=%u",
311*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), *outSeq);
312*38e8c45fSAndroid Build Coastguard Worker break;
313*38e8c45fSAndroid Build Coastguard Worker }
314*38e8c45fSAndroid Build Coastguard Worker }
315*38e8c45fSAndroid Build Coastguard Worker
316*38e8c45fSAndroid Build Coastguard Worker // Start a new batch if needed.
317*38e8c45fSAndroid Build Coastguard Worker if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE ||
318*38e8c45fSAndroid Build Coastguard Worker mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
319*38e8c45fSAndroid Build Coastguard Worker Batch batch;
320*38e8c45fSAndroid Build Coastguard Worker batch.samples.push_back(mMsg);
321*38e8c45fSAndroid Build Coastguard Worker mBatches.push_back(batch);
322*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
323*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ started batch event",
324*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str());
325*38e8c45fSAndroid Build Coastguard Worker break;
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker
328*38e8c45fSAndroid Build Coastguard Worker MotionEvent* motionEvent = factory->createMotionEvent();
329*38e8c45fSAndroid Build Coastguard Worker if (!motionEvent) return NO_MEMORY;
330*38e8c45fSAndroid Build Coastguard Worker
331*38e8c45fSAndroid Build Coastguard Worker updateTouchState(mMsg);
332*38e8c45fSAndroid Build Coastguard Worker initializeMotionEvent(*motionEvent, mMsg);
333*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
334*38e8c45fSAndroid Build Coastguard Worker *outEvent = motionEvent;
335*38e8c45fSAndroid Build Coastguard Worker
336*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
337*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ consumed motion event, seq=%u",
338*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), *outSeq);
339*38e8c45fSAndroid Build Coastguard Worker break;
340*38e8c45fSAndroid Build Coastguard Worker }
341*38e8c45fSAndroid Build Coastguard Worker
342*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FINISHED:
343*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TIMELINE: {
344*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Consumed a " << ftl::enum_string(mMsg.header.type)
345*38e8c45fSAndroid Build Coastguard Worker << " message, which should never be seen by "
346*38e8c45fSAndroid Build Coastguard Worker "InputConsumer on "
347*38e8c45fSAndroid Build Coastguard Worker << mChannel->getName();
348*38e8c45fSAndroid Build Coastguard Worker break;
349*38e8c45fSAndroid Build Coastguard Worker }
350*38e8c45fSAndroid Build Coastguard Worker
351*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FOCUS: {
352*38e8c45fSAndroid Build Coastguard Worker FocusEvent* focusEvent = factory->createFocusEvent();
353*38e8c45fSAndroid Build Coastguard Worker if (!focusEvent) return NO_MEMORY;
354*38e8c45fSAndroid Build Coastguard Worker
355*38e8c45fSAndroid Build Coastguard Worker initializeFocusEvent(*focusEvent, mMsg);
356*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
357*38e8c45fSAndroid Build Coastguard Worker *outEvent = focusEvent;
358*38e8c45fSAndroid Build Coastguard Worker break;
359*38e8c45fSAndroid Build Coastguard Worker }
360*38e8c45fSAndroid Build Coastguard Worker
361*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::CAPTURE: {
362*38e8c45fSAndroid Build Coastguard Worker CaptureEvent* captureEvent = factory->createCaptureEvent();
363*38e8c45fSAndroid Build Coastguard Worker if (!captureEvent) return NO_MEMORY;
364*38e8c45fSAndroid Build Coastguard Worker
365*38e8c45fSAndroid Build Coastguard Worker initializeCaptureEvent(*captureEvent, mMsg);
366*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
367*38e8c45fSAndroid Build Coastguard Worker *outEvent = captureEvent;
368*38e8c45fSAndroid Build Coastguard Worker break;
369*38e8c45fSAndroid Build Coastguard Worker }
370*38e8c45fSAndroid Build Coastguard Worker
371*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::DRAG: {
372*38e8c45fSAndroid Build Coastguard Worker DragEvent* dragEvent = factory->createDragEvent();
373*38e8c45fSAndroid Build Coastguard Worker if (!dragEvent) return NO_MEMORY;
374*38e8c45fSAndroid Build Coastguard Worker
375*38e8c45fSAndroid Build Coastguard Worker initializeDragEvent(*dragEvent, mMsg);
376*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
377*38e8c45fSAndroid Build Coastguard Worker *outEvent = dragEvent;
378*38e8c45fSAndroid Build Coastguard Worker break;
379*38e8c45fSAndroid Build Coastguard Worker }
380*38e8c45fSAndroid Build Coastguard Worker
381*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TOUCH_MODE: {
382*38e8c45fSAndroid Build Coastguard Worker TouchModeEvent* touchModeEvent = factory->createTouchModeEvent();
383*38e8c45fSAndroid Build Coastguard Worker if (!touchModeEvent) return NO_MEMORY;
384*38e8c45fSAndroid Build Coastguard Worker
385*38e8c45fSAndroid Build Coastguard Worker initializeTouchModeEvent(*touchModeEvent, mMsg);
386*38e8c45fSAndroid Build Coastguard Worker *outSeq = mMsg.header.seq;
387*38e8c45fSAndroid Build Coastguard Worker *outEvent = touchModeEvent;
388*38e8c45fSAndroid Build Coastguard Worker break;
389*38e8c45fSAndroid Build Coastguard Worker }
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker }
392*38e8c45fSAndroid Build Coastguard Worker return OK;
393*38e8c45fSAndroid Build Coastguard Worker }
394*38e8c45fSAndroid Build Coastguard Worker
consumeBatch(InputEventFactoryInterface * factory,nsecs_t frameTime,uint32_t * outSeq,InputEvent ** outEvent)395*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory, nsecs_t frameTime,
396*38e8c45fSAndroid Build Coastguard Worker uint32_t* outSeq, InputEvent** outEvent) {
397*38e8c45fSAndroid Build Coastguard Worker status_t result;
398*38e8c45fSAndroid Build Coastguard Worker for (size_t i = mBatches.size(); i > 0;) {
399*38e8c45fSAndroid Build Coastguard Worker i--;
400*38e8c45fSAndroid Build Coastguard Worker Batch& batch = mBatches[i];
401*38e8c45fSAndroid Build Coastguard Worker if (frameTime < 0) {
402*38e8c45fSAndroid Build Coastguard Worker result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent);
403*38e8c45fSAndroid Build Coastguard Worker mBatches.erase(mBatches.begin() + i);
404*38e8c45fSAndroid Build Coastguard Worker return result;
405*38e8c45fSAndroid Build Coastguard Worker }
406*38e8c45fSAndroid Build Coastguard Worker
407*38e8c45fSAndroid Build Coastguard Worker nsecs_t sampleTime = frameTime;
408*38e8c45fSAndroid Build Coastguard Worker if (mResampleTouch) {
409*38e8c45fSAndroid Build Coastguard Worker sampleTime -= std::chrono::nanoseconds(RESAMPLE_LATENCY).count();
410*38e8c45fSAndroid Build Coastguard Worker }
411*38e8c45fSAndroid Build Coastguard Worker ssize_t split = findSampleNoLaterThan(batch, sampleTime);
412*38e8c45fSAndroid Build Coastguard Worker if (split < 0) {
413*38e8c45fSAndroid Build Coastguard Worker continue;
414*38e8c45fSAndroid Build Coastguard Worker }
415*38e8c45fSAndroid Build Coastguard Worker
416*38e8c45fSAndroid Build Coastguard Worker result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
417*38e8c45fSAndroid Build Coastguard Worker const InputMessage* next;
418*38e8c45fSAndroid Build Coastguard Worker if (batch.samples.empty()) {
419*38e8c45fSAndroid Build Coastguard Worker mBatches.erase(mBatches.begin() + i);
420*38e8c45fSAndroid Build Coastguard Worker next = nullptr;
421*38e8c45fSAndroid Build Coastguard Worker } else {
422*38e8c45fSAndroid Build Coastguard Worker next = &batch.samples[0];
423*38e8c45fSAndroid Build Coastguard Worker }
424*38e8c45fSAndroid Build Coastguard Worker if (!result && mResampleTouch) {
425*38e8c45fSAndroid Build Coastguard Worker resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
426*38e8c45fSAndroid Build Coastguard Worker }
427*38e8c45fSAndroid Build Coastguard Worker return result;
428*38e8c45fSAndroid Build Coastguard Worker }
429*38e8c45fSAndroid Build Coastguard Worker
430*38e8c45fSAndroid Build Coastguard Worker return WOULD_BLOCK;
431*38e8c45fSAndroid Build Coastguard Worker }
432*38e8c45fSAndroid Build Coastguard Worker
consumeSamples(InputEventFactoryInterface * factory,Batch & batch,size_t count,uint32_t * outSeq,InputEvent ** outEvent)433*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory, Batch& batch,
434*38e8c45fSAndroid Build Coastguard Worker size_t count, uint32_t* outSeq, InputEvent** outEvent) {
435*38e8c45fSAndroid Build Coastguard Worker MotionEvent* motionEvent = factory->createMotionEvent();
436*38e8c45fSAndroid Build Coastguard Worker if (!motionEvent) return NO_MEMORY;
437*38e8c45fSAndroid Build Coastguard Worker
438*38e8c45fSAndroid Build Coastguard Worker uint32_t chain = 0;
439*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++) {
440*38e8c45fSAndroid Build Coastguard Worker InputMessage& msg = batch.samples[i];
441*38e8c45fSAndroid Build Coastguard Worker updateTouchState(msg);
442*38e8c45fSAndroid Build Coastguard Worker if (i) {
443*38e8c45fSAndroid Build Coastguard Worker SeqChain seqChain;
444*38e8c45fSAndroid Build Coastguard Worker seqChain.seq = msg.header.seq;
445*38e8c45fSAndroid Build Coastguard Worker seqChain.chain = chain;
446*38e8c45fSAndroid Build Coastguard Worker mSeqChains.push_back(seqChain);
447*38e8c45fSAndroid Build Coastguard Worker addSample(*motionEvent, msg);
448*38e8c45fSAndroid Build Coastguard Worker } else {
449*38e8c45fSAndroid Build Coastguard Worker initializeMotionEvent(*motionEvent, msg);
450*38e8c45fSAndroid Build Coastguard Worker }
451*38e8c45fSAndroid Build Coastguard Worker chain = msg.header.seq;
452*38e8c45fSAndroid Build Coastguard Worker }
453*38e8c45fSAndroid Build Coastguard Worker batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count);
454*38e8c45fSAndroid Build Coastguard Worker
455*38e8c45fSAndroid Build Coastguard Worker *outSeq = chain;
456*38e8c45fSAndroid Build Coastguard Worker *outEvent = motionEvent;
457*38e8c45fSAndroid Build Coastguard Worker return OK;
458*38e8c45fSAndroid Build Coastguard Worker }
459*38e8c45fSAndroid Build Coastguard Worker
updateTouchState(InputMessage & msg)460*38e8c45fSAndroid Build Coastguard Worker void InputConsumer::updateTouchState(InputMessage& msg) {
461*38e8c45fSAndroid Build Coastguard Worker if (!mResampleTouch || !isPointerEvent(msg.body.motion.source)) {
462*38e8c45fSAndroid Build Coastguard Worker return;
463*38e8c45fSAndroid Build Coastguard Worker }
464*38e8c45fSAndroid Build Coastguard Worker
465*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId = msg.body.motion.deviceId;
466*38e8c45fSAndroid Build Coastguard Worker int32_t source = msg.body.motion.source;
467*38e8c45fSAndroid Build Coastguard Worker
468*38e8c45fSAndroid Build Coastguard Worker // Update the touch state history to incorporate the new input message.
469*38e8c45fSAndroid Build Coastguard Worker // If the message is in the past relative to the most recently produced resampled
470*38e8c45fSAndroid Build Coastguard Worker // touch, then use the resampled time and coordinates instead.
471*38e8c45fSAndroid Build Coastguard Worker switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
472*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_DOWN: {
473*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
474*38e8c45fSAndroid Build Coastguard Worker if (index < 0) {
475*38e8c45fSAndroid Build Coastguard Worker mTouchStates.push_back({});
476*38e8c45fSAndroid Build Coastguard Worker index = mTouchStates.size() - 1;
477*38e8c45fSAndroid Build Coastguard Worker }
478*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
479*38e8c45fSAndroid Build Coastguard Worker touchState.initialize(deviceId, source);
480*38e8c45fSAndroid Build Coastguard Worker touchState.addHistory(msg);
481*38e8c45fSAndroid Build Coastguard Worker break;
482*38e8c45fSAndroid Build Coastguard Worker }
483*38e8c45fSAndroid Build Coastguard Worker
484*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_MOVE: {
485*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
486*38e8c45fSAndroid Build Coastguard Worker if (index >= 0) {
487*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
488*38e8c45fSAndroid Build Coastguard Worker touchState.addHistory(msg);
489*38e8c45fSAndroid Build Coastguard Worker rewriteMessage(touchState, msg);
490*38e8c45fSAndroid Build Coastguard Worker }
491*38e8c45fSAndroid Build Coastguard Worker break;
492*38e8c45fSAndroid Build Coastguard Worker }
493*38e8c45fSAndroid Build Coastguard Worker
494*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_POINTER_DOWN: {
495*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
496*38e8c45fSAndroid Build Coastguard Worker if (index >= 0) {
497*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
498*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
499*38e8c45fSAndroid Build Coastguard Worker rewriteMessage(touchState, msg);
500*38e8c45fSAndroid Build Coastguard Worker }
501*38e8c45fSAndroid Build Coastguard Worker break;
502*38e8c45fSAndroid Build Coastguard Worker }
503*38e8c45fSAndroid Build Coastguard Worker
504*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_POINTER_UP: {
505*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
506*38e8c45fSAndroid Build Coastguard Worker if (index >= 0) {
507*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
508*38e8c45fSAndroid Build Coastguard Worker rewriteMessage(touchState, msg);
509*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
510*38e8c45fSAndroid Build Coastguard Worker }
511*38e8c45fSAndroid Build Coastguard Worker break;
512*38e8c45fSAndroid Build Coastguard Worker }
513*38e8c45fSAndroid Build Coastguard Worker
514*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_SCROLL: {
515*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
516*38e8c45fSAndroid Build Coastguard Worker if (index >= 0) {
517*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
518*38e8c45fSAndroid Build Coastguard Worker rewriteMessage(touchState, msg);
519*38e8c45fSAndroid Build Coastguard Worker }
520*38e8c45fSAndroid Build Coastguard Worker break;
521*38e8c45fSAndroid Build Coastguard Worker }
522*38e8c45fSAndroid Build Coastguard Worker
523*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_UP:
524*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_CANCEL: {
525*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(deviceId, source);
526*38e8c45fSAndroid Build Coastguard Worker if (index >= 0) {
527*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
528*38e8c45fSAndroid Build Coastguard Worker rewriteMessage(touchState, msg);
529*38e8c45fSAndroid Build Coastguard Worker mTouchStates.erase(mTouchStates.begin() + index);
530*38e8c45fSAndroid Build Coastguard Worker }
531*38e8c45fSAndroid Build Coastguard Worker break;
532*38e8c45fSAndroid Build Coastguard Worker }
533*38e8c45fSAndroid Build Coastguard Worker }
534*38e8c45fSAndroid Build Coastguard Worker }
535*38e8c45fSAndroid Build Coastguard Worker
536*38e8c45fSAndroid Build Coastguard Worker /**
537*38e8c45fSAndroid Build Coastguard Worker * Replace the coordinates in msg with the coordinates in lastResample, if necessary.
538*38e8c45fSAndroid Build Coastguard Worker *
539*38e8c45fSAndroid Build Coastguard Worker * If lastResample is no longer valid for a specific pointer (i.e. the lastResample time
540*38e8c45fSAndroid Build Coastguard Worker * is in the past relative to msg and the past two events do not contain identical coordinates),
541*38e8c45fSAndroid Build Coastguard Worker * then invalidate the lastResample data for that pointer.
542*38e8c45fSAndroid Build Coastguard Worker * If the two past events have identical coordinates, then lastResample data for that pointer will
543*38e8c45fSAndroid Build Coastguard Worker * remain valid, and will be used to replace these coordinates. Thus, if a certain coordinate x0 is
544*38e8c45fSAndroid Build Coastguard Worker * resampled to the new value x1, then x1 will always be used to replace x0 until some new value
545*38e8c45fSAndroid Build Coastguard Worker * not equal to x0 is received.
546*38e8c45fSAndroid Build Coastguard Worker */
rewriteMessage(TouchState & state,InputMessage & msg)547*38e8c45fSAndroid Build Coastguard Worker void InputConsumer::rewriteMessage(TouchState& state, InputMessage& msg) {
548*38e8c45fSAndroid Build Coastguard Worker nsecs_t eventTime = msg.body.motion.eventTime;
549*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
550*38e8c45fSAndroid Build Coastguard Worker uint32_t id = msg.body.motion.pointers[i].properties.id;
551*38e8c45fSAndroid Build Coastguard Worker if (state.lastResample.idBits.hasBit(id)) {
552*38e8c45fSAndroid Build Coastguard Worker if (eventTime < state.lastResample.eventTime ||
553*38e8c45fSAndroid Build Coastguard Worker state.recentCoordinatesAreIdentical(id)) {
554*38e8c45fSAndroid Build Coastguard Worker PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
555*38e8c45fSAndroid Build Coastguard Worker const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
556*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
557*38e8c45fSAndroid Build Coastguard Worker resampleCoords.getX(), resampleCoords.getY(), msgCoords.getX(),
558*38e8c45fSAndroid Build Coastguard Worker msgCoords.getY());
559*38e8c45fSAndroid Build Coastguard Worker msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
560*38e8c45fSAndroid Build Coastguard Worker msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
561*38e8c45fSAndroid Build Coastguard Worker msgCoords.isResampled = true;
562*38e8c45fSAndroid Build Coastguard Worker } else {
563*38e8c45fSAndroid Build Coastguard Worker state.lastResample.idBits.clearBit(id);
564*38e8c45fSAndroid Build Coastguard Worker }
565*38e8c45fSAndroid Build Coastguard Worker }
566*38e8c45fSAndroid Build Coastguard Worker }
567*38e8c45fSAndroid Build Coastguard Worker }
568*38e8c45fSAndroid Build Coastguard Worker
resampleTouchState(nsecs_t sampleTime,MotionEvent * event,const InputMessage * next)569*38e8c45fSAndroid Build Coastguard Worker void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
570*38e8c45fSAndroid Build Coastguard Worker const InputMessage* next) {
571*38e8c45fSAndroid Build Coastguard Worker if (!mResampleTouch || !(isPointerEvent(event->getSource())) ||
572*38e8c45fSAndroid Build Coastguard Worker event->getAction() != AMOTION_EVENT_ACTION_MOVE) {
573*38e8c45fSAndroid Build Coastguard Worker return;
574*38e8c45fSAndroid Build Coastguard Worker }
575*38e8c45fSAndroid Build Coastguard Worker
576*38e8c45fSAndroid Build Coastguard Worker ssize_t index = findTouchState(event->getDeviceId(), event->getSource());
577*38e8c45fSAndroid Build Coastguard Worker if (index < 0) {
578*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, no touch state for device.");
579*38e8c45fSAndroid Build Coastguard Worker return;
580*38e8c45fSAndroid Build Coastguard Worker }
581*38e8c45fSAndroid Build Coastguard Worker
582*38e8c45fSAndroid Build Coastguard Worker TouchState& touchState = mTouchStates[index];
583*38e8c45fSAndroid Build Coastguard Worker if (touchState.historySize < 1) {
584*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, no history for device.");
585*38e8c45fSAndroid Build Coastguard Worker return;
586*38e8c45fSAndroid Build Coastguard Worker }
587*38e8c45fSAndroid Build Coastguard Worker
588*38e8c45fSAndroid Build Coastguard Worker // Ensure that the current sample has all of the pointers that need to be reported.
589*38e8c45fSAndroid Build Coastguard Worker const History* current = touchState.getHistory(0);
590*38e8c45fSAndroid Build Coastguard Worker size_t pointerCount = event->getPointerCount();
591*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pointerCount; i++) {
592*38e8c45fSAndroid Build Coastguard Worker uint32_t id = event->getPointerId(i);
593*38e8c45fSAndroid Build Coastguard Worker if (!current->idBits.hasBit(id)) {
594*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id);
595*38e8c45fSAndroid Build Coastguard Worker return;
596*38e8c45fSAndroid Build Coastguard Worker }
597*38e8c45fSAndroid Build Coastguard Worker if (!shouldResampleTool(event->getToolType(i))) {
598*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(),
599*38e8c45fSAndroid Build Coastguard Worker "Not resampled, containing unsupported tool type at pointer %d", id);
600*38e8c45fSAndroid Build Coastguard Worker return;
601*38e8c45fSAndroid Build Coastguard Worker }
602*38e8c45fSAndroid Build Coastguard Worker }
603*38e8c45fSAndroid Build Coastguard Worker
604*38e8c45fSAndroid Build Coastguard Worker // Find the data to use for resampling.
605*38e8c45fSAndroid Build Coastguard Worker const History* other;
606*38e8c45fSAndroid Build Coastguard Worker History future;
607*38e8c45fSAndroid Build Coastguard Worker float alpha;
608*38e8c45fSAndroid Build Coastguard Worker if (next) {
609*38e8c45fSAndroid Build Coastguard Worker // Interpolate between current sample and future sample.
610*38e8c45fSAndroid Build Coastguard Worker // So current->eventTime <= sampleTime <= future.eventTime.
611*38e8c45fSAndroid Build Coastguard Worker future.initializeFrom(*next);
612*38e8c45fSAndroid Build Coastguard Worker other = &future;
613*38e8c45fSAndroid Build Coastguard Worker nsecs_t delta = future.eventTime - current->eventTime;
614*38e8c45fSAndroid Build Coastguard Worker if (delta < RESAMPLE_MIN_DELTA) {
615*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, delta time is too small: %" PRId64 " ns.",
616*38e8c45fSAndroid Build Coastguard Worker delta);
617*38e8c45fSAndroid Build Coastguard Worker return;
618*38e8c45fSAndroid Build Coastguard Worker }
619*38e8c45fSAndroid Build Coastguard Worker alpha = float(sampleTime - current->eventTime) / delta;
620*38e8c45fSAndroid Build Coastguard Worker } else if (touchState.historySize >= 2) {
621*38e8c45fSAndroid Build Coastguard Worker // Extrapolate future sample using current sample and past sample.
622*38e8c45fSAndroid Build Coastguard Worker // So other->eventTime <= current->eventTime <= sampleTime.
623*38e8c45fSAndroid Build Coastguard Worker other = touchState.getHistory(1);
624*38e8c45fSAndroid Build Coastguard Worker nsecs_t delta = current->eventTime - other->eventTime;
625*38e8c45fSAndroid Build Coastguard Worker if (delta < RESAMPLE_MIN_DELTA) {
626*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, delta time is too small: %" PRId64 " ns.",
627*38e8c45fSAndroid Build Coastguard Worker delta);
628*38e8c45fSAndroid Build Coastguard Worker return;
629*38e8c45fSAndroid Build Coastguard Worker } else if (delta > RESAMPLE_MAX_DELTA) {
630*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, delta time is too large: %" PRId64 " ns.",
631*38e8c45fSAndroid Build Coastguard Worker delta);
632*38e8c45fSAndroid Build Coastguard Worker return;
633*38e8c45fSAndroid Build Coastguard Worker }
634*38e8c45fSAndroid Build Coastguard Worker nsecs_t maxPredict = current->eventTime + std::min(delta / 2, RESAMPLE_MAX_PREDICTION);
635*38e8c45fSAndroid Build Coastguard Worker if (sampleTime > maxPredict) {
636*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(),
637*38e8c45fSAndroid Build Coastguard Worker "Sample time is too far in the future, adjusting prediction "
638*38e8c45fSAndroid Build Coastguard Worker "from %" PRId64 " to %" PRId64 " ns.",
639*38e8c45fSAndroid Build Coastguard Worker sampleTime - current->eventTime, maxPredict - current->eventTime);
640*38e8c45fSAndroid Build Coastguard Worker sampleTime = maxPredict;
641*38e8c45fSAndroid Build Coastguard Worker }
642*38e8c45fSAndroid Build Coastguard Worker alpha = float(current->eventTime - sampleTime) / delta;
643*38e8c45fSAndroid Build Coastguard Worker } else {
644*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, insufficient data.");
645*38e8c45fSAndroid Build Coastguard Worker return;
646*38e8c45fSAndroid Build Coastguard Worker }
647*38e8c45fSAndroid Build Coastguard Worker
648*38e8c45fSAndroid Build Coastguard Worker if (current->eventTime == sampleTime) {
649*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, 2 events with identical times.");
650*38e8c45fSAndroid Build Coastguard Worker return;
651*38e8c45fSAndroid Build Coastguard Worker }
652*38e8c45fSAndroid Build Coastguard Worker
653*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pointerCount; i++) {
654*38e8c45fSAndroid Build Coastguard Worker uint32_t id = event->getPointerId(i);
655*38e8c45fSAndroid Build Coastguard Worker if (!other->idBits.hasBit(id)) {
656*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(), "Not resampled, the other doesn't have pointer id %d.", id);
657*38e8c45fSAndroid Build Coastguard Worker return;
658*38e8c45fSAndroid Build Coastguard Worker }
659*38e8c45fSAndroid Build Coastguard Worker }
660*38e8c45fSAndroid Build Coastguard Worker
661*38e8c45fSAndroid Build Coastguard Worker // Resample touch coordinates.
662*38e8c45fSAndroid Build Coastguard Worker History oldLastResample;
663*38e8c45fSAndroid Build Coastguard Worker oldLastResample.initializeFrom(touchState.lastResample);
664*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.eventTime = sampleTime;
665*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.idBits.clear();
666*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pointerCount; i++) {
667*38e8c45fSAndroid Build Coastguard Worker uint32_t id = event->getPointerId(i);
668*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.idToIndex[id] = i;
669*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.idBits.markBit(id);
670*38e8c45fSAndroid Build Coastguard Worker if (oldLastResample.hasPointerId(id) && touchState.recentCoordinatesAreIdentical(id)) {
671*38e8c45fSAndroid Build Coastguard Worker // We maintain the previously resampled value for this pointer (stored in
672*38e8c45fSAndroid Build Coastguard Worker // oldLastResample) when the coordinates for this pointer haven't changed since then.
673*38e8c45fSAndroid Build Coastguard Worker // This way we don't introduce artificial jitter when pointers haven't actually moved.
674*38e8c45fSAndroid Build Coastguard Worker // The isResampled flag isn't cleared as the values don't reflect what the device is
675*38e8c45fSAndroid Build Coastguard Worker // actually reporting.
676*38e8c45fSAndroid Build Coastguard Worker
677*38e8c45fSAndroid Build Coastguard Worker // We know here that the coordinates for the pointer haven't changed because we
678*38e8c45fSAndroid Build Coastguard Worker // would've cleared the resampled bit in rewriteMessage if they had. We can't modify
679*38e8c45fSAndroid Build Coastguard Worker // lastResample in place because the mapping from pointer ID to index may have changed.
680*38e8c45fSAndroid Build Coastguard Worker touchState.lastResample.pointers[i] = oldLastResample.getPointerById(id);
681*38e8c45fSAndroid Build Coastguard Worker continue;
682*38e8c45fSAndroid Build Coastguard Worker }
683*38e8c45fSAndroid Build Coastguard Worker
684*38e8c45fSAndroid Build Coastguard Worker PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
685*38e8c45fSAndroid Build Coastguard Worker const PointerCoords& currentCoords = current->getPointerById(id);
686*38e8c45fSAndroid Build Coastguard Worker resampledCoords = currentCoords;
687*38e8c45fSAndroid Build Coastguard Worker resampledCoords.isResampled = true;
688*38e8c45fSAndroid Build Coastguard Worker const PointerCoords& otherCoords = other->getPointerById(id);
689*38e8c45fSAndroid Build Coastguard Worker resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
690*38e8c45fSAndroid Build Coastguard Worker lerp(currentCoords.getX(), otherCoords.getX(), alpha));
691*38e8c45fSAndroid Build Coastguard Worker resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
692*38e8c45fSAndroid Build Coastguard Worker lerp(currentCoords.getY(), otherCoords.getY(), alpha));
693*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugResampling(),
694*38e8c45fSAndroid Build Coastguard Worker "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
695*38e8c45fSAndroid Build Coastguard Worker "other (%0.3f, %0.3f), alpha %0.3f",
696*38e8c45fSAndroid Build Coastguard Worker id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
697*38e8c45fSAndroid Build Coastguard Worker currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
698*38e8c45fSAndroid Build Coastguard Worker }
699*38e8c45fSAndroid Build Coastguard Worker
700*38e8c45fSAndroid Build Coastguard Worker event->addSample(sampleTime, touchState.lastResample.pointers, event->getId());
701*38e8c45fSAndroid Build Coastguard Worker }
702*38e8c45fSAndroid Build Coastguard Worker
sendFinishedSignal(uint32_t seq,bool handled)703*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
704*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
705*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
706*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), seq, toString(handled));
707*38e8c45fSAndroid Build Coastguard Worker
708*38e8c45fSAndroid Build Coastguard Worker if (!seq) {
709*38e8c45fSAndroid Build Coastguard Worker ALOGE("Attempted to send a finished signal with sequence number 0.");
710*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
711*38e8c45fSAndroid Build Coastguard Worker }
712*38e8c45fSAndroid Build Coastguard Worker
713*38e8c45fSAndroid Build Coastguard Worker // Send finished signals for the batch sequence chain first.
714*38e8c45fSAndroid Build Coastguard Worker size_t seqChainCount = mSeqChains.size();
715*38e8c45fSAndroid Build Coastguard Worker if (seqChainCount) {
716*38e8c45fSAndroid Build Coastguard Worker uint32_t currentSeq = seq;
717*38e8c45fSAndroid Build Coastguard Worker uint32_t chainSeqs[seqChainCount];
718*38e8c45fSAndroid Build Coastguard Worker size_t chainIndex = 0;
719*38e8c45fSAndroid Build Coastguard Worker for (size_t i = seqChainCount; i > 0;) {
720*38e8c45fSAndroid Build Coastguard Worker i--;
721*38e8c45fSAndroid Build Coastguard Worker const SeqChain& seqChain = mSeqChains[i];
722*38e8c45fSAndroid Build Coastguard Worker if (seqChain.seq == currentSeq) {
723*38e8c45fSAndroid Build Coastguard Worker currentSeq = seqChain.chain;
724*38e8c45fSAndroid Build Coastguard Worker chainSeqs[chainIndex++] = currentSeq;
725*38e8c45fSAndroid Build Coastguard Worker mSeqChains.erase(mSeqChains.begin() + i);
726*38e8c45fSAndroid Build Coastguard Worker }
727*38e8c45fSAndroid Build Coastguard Worker }
728*38e8c45fSAndroid Build Coastguard Worker status_t status = OK;
729*38e8c45fSAndroid Build Coastguard Worker while (!status && chainIndex > 0) {
730*38e8c45fSAndroid Build Coastguard Worker chainIndex--;
731*38e8c45fSAndroid Build Coastguard Worker status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
732*38e8c45fSAndroid Build Coastguard Worker }
733*38e8c45fSAndroid Build Coastguard Worker if (status) {
734*38e8c45fSAndroid Build Coastguard Worker // An error occurred so at least one signal was not sent, reconstruct the chain.
735*38e8c45fSAndroid Build Coastguard Worker for (;;) {
736*38e8c45fSAndroid Build Coastguard Worker SeqChain seqChain;
737*38e8c45fSAndroid Build Coastguard Worker seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
738*38e8c45fSAndroid Build Coastguard Worker seqChain.chain = chainSeqs[chainIndex];
739*38e8c45fSAndroid Build Coastguard Worker mSeqChains.push_back(seqChain);
740*38e8c45fSAndroid Build Coastguard Worker if (!chainIndex) break;
741*38e8c45fSAndroid Build Coastguard Worker chainIndex--;
742*38e8c45fSAndroid Build Coastguard Worker }
743*38e8c45fSAndroid Build Coastguard Worker return status;
744*38e8c45fSAndroid Build Coastguard Worker }
745*38e8c45fSAndroid Build Coastguard Worker }
746*38e8c45fSAndroid Build Coastguard Worker
747*38e8c45fSAndroid Build Coastguard Worker // Send finished signal for the last message in the batch.
748*38e8c45fSAndroid Build Coastguard Worker return sendUnchainedFinishedSignal(seq, handled);
749*38e8c45fSAndroid Build Coastguard Worker }
750*38e8c45fSAndroid Build Coastguard Worker
sendTimeline(int32_t inputEventId,std::array<nsecs_t,GraphicsTimeline::SIZE> graphicsTimeline)751*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::sendTimeline(int32_t inputEventId,
752*38e8c45fSAndroid Build Coastguard Worker std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline) {
753*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TRANSPORT_CONSUMER,
754*38e8c45fSAndroid Build Coastguard Worker "channel '%s' consumer ~ sendTimeline: inputEventId=%" PRId32
755*38e8c45fSAndroid Build Coastguard Worker ", gpuCompletedTime=%" PRId64 ", presentTime=%" PRId64,
756*38e8c45fSAndroid Build Coastguard Worker mChannel->getName().c_str(), inputEventId,
757*38e8c45fSAndroid Build Coastguard Worker graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
758*38e8c45fSAndroid Build Coastguard Worker graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
759*38e8c45fSAndroid Build Coastguard Worker
760*38e8c45fSAndroid Build Coastguard Worker InputMessage msg;
761*38e8c45fSAndroid Build Coastguard Worker msg.header.type = InputMessage::Type::TIMELINE;
762*38e8c45fSAndroid Build Coastguard Worker msg.header.seq = 0;
763*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.eventId = inputEventId;
764*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.graphicsTimeline = std::move(graphicsTimeline);
765*38e8c45fSAndroid Build Coastguard Worker return mChannel->sendMessage(&msg);
766*38e8c45fSAndroid Build Coastguard Worker }
767*38e8c45fSAndroid Build Coastguard Worker
getConsumeTime(uint32_t seq) const768*38e8c45fSAndroid Build Coastguard Worker nsecs_t InputConsumer::getConsumeTime(uint32_t seq) const {
769*38e8c45fSAndroid Build Coastguard Worker auto it = mConsumeTimes.find(seq);
770*38e8c45fSAndroid Build Coastguard Worker // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
771*38e8c45fSAndroid Build Coastguard Worker // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
772*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
773*38e8c45fSAndroid Build Coastguard Worker seq);
774*38e8c45fSAndroid Build Coastguard Worker return it->second;
775*38e8c45fSAndroid Build Coastguard Worker }
776*38e8c45fSAndroid Build Coastguard Worker
popConsumeTime(uint32_t seq)777*38e8c45fSAndroid Build Coastguard Worker void InputConsumer::popConsumeTime(uint32_t seq) {
778*38e8c45fSAndroid Build Coastguard Worker mConsumeTimes.erase(seq);
779*38e8c45fSAndroid Build Coastguard Worker }
780*38e8c45fSAndroid Build Coastguard Worker
sendUnchainedFinishedSignal(uint32_t seq,bool handled)781*38e8c45fSAndroid Build Coastguard Worker status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
782*38e8c45fSAndroid Build Coastguard Worker InputMessage msg;
783*38e8c45fSAndroid Build Coastguard Worker msg.header.type = InputMessage::Type::FINISHED;
784*38e8c45fSAndroid Build Coastguard Worker msg.header.seq = seq;
785*38e8c45fSAndroid Build Coastguard Worker msg.body.finished.handled = handled;
786*38e8c45fSAndroid Build Coastguard Worker msg.body.finished.consumeTime = getConsumeTime(seq);
787*38e8c45fSAndroid Build Coastguard Worker status_t result = mChannel->sendMessage(&msg);
788*38e8c45fSAndroid Build Coastguard Worker if (result == OK) {
789*38e8c45fSAndroid Build Coastguard Worker // Remove the consume time if the socket write succeeded. We will not need to ack this
790*38e8c45fSAndroid Build Coastguard Worker // message anymore. If the socket write did not succeed, we will try again and will still
791*38e8c45fSAndroid Build Coastguard Worker // need consume time.
792*38e8c45fSAndroid Build Coastguard Worker popConsumeTime(seq);
793*38e8c45fSAndroid Build Coastguard Worker
794*38e8c45fSAndroid Build Coastguard Worker // Trace the event processing timeline - event was just finished
795*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_END(mProcessingTraceTag.c_str(), /*cookie=*/seq);
796*38e8c45fSAndroid Build Coastguard Worker }
797*38e8c45fSAndroid Build Coastguard Worker return result;
798*38e8c45fSAndroid Build Coastguard Worker }
799*38e8c45fSAndroid Build Coastguard Worker
hasPendingBatch() const800*38e8c45fSAndroid Build Coastguard Worker bool InputConsumer::hasPendingBatch() const {
801*38e8c45fSAndroid Build Coastguard Worker return !mBatches.empty();
802*38e8c45fSAndroid Build Coastguard Worker }
803*38e8c45fSAndroid Build Coastguard Worker
getPendingBatchSource() const804*38e8c45fSAndroid Build Coastguard Worker int32_t InputConsumer::getPendingBatchSource() const {
805*38e8c45fSAndroid Build Coastguard Worker if (mBatches.empty()) {
806*38e8c45fSAndroid Build Coastguard Worker return AINPUT_SOURCE_CLASS_NONE;
807*38e8c45fSAndroid Build Coastguard Worker }
808*38e8c45fSAndroid Build Coastguard Worker
809*38e8c45fSAndroid Build Coastguard Worker const Batch& batch = mBatches[0];
810*38e8c45fSAndroid Build Coastguard Worker const InputMessage& head = batch.samples[0];
811*38e8c45fSAndroid Build Coastguard Worker return head.body.motion.source;
812*38e8c45fSAndroid Build Coastguard Worker }
813*38e8c45fSAndroid Build Coastguard Worker
probablyHasInput() const814*38e8c45fSAndroid Build Coastguard Worker bool InputConsumer::probablyHasInput() const {
815*38e8c45fSAndroid Build Coastguard Worker return hasPendingBatch() || mChannel->probablyHasInput();
816*38e8c45fSAndroid Build Coastguard Worker }
817*38e8c45fSAndroid Build Coastguard Worker
findBatch(int32_t deviceId,int32_t source) const818*38e8c45fSAndroid Build Coastguard Worker ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const {
819*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mBatches.size(); i++) {
820*38e8c45fSAndroid Build Coastguard Worker const Batch& batch = mBatches[i];
821*38e8c45fSAndroid Build Coastguard Worker const InputMessage& head = batch.samples[0];
822*38e8c45fSAndroid Build Coastguard Worker if (head.body.motion.deviceId == deviceId && head.body.motion.source == source) {
823*38e8c45fSAndroid Build Coastguard Worker return i;
824*38e8c45fSAndroid Build Coastguard Worker }
825*38e8c45fSAndroid Build Coastguard Worker }
826*38e8c45fSAndroid Build Coastguard Worker return -1;
827*38e8c45fSAndroid Build Coastguard Worker }
828*38e8c45fSAndroid Build Coastguard Worker
findTouchState(int32_t deviceId,int32_t source) const829*38e8c45fSAndroid Build Coastguard Worker ssize_t InputConsumer::findTouchState(int32_t deviceId, int32_t source) const {
830*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mTouchStates.size(); i++) {
831*38e8c45fSAndroid Build Coastguard Worker const TouchState& touchState = mTouchStates[i];
832*38e8c45fSAndroid Build Coastguard Worker if (touchState.deviceId == deviceId && touchState.source == source) {
833*38e8c45fSAndroid Build Coastguard Worker return i;
834*38e8c45fSAndroid Build Coastguard Worker }
835*38e8c45fSAndroid Build Coastguard Worker }
836*38e8c45fSAndroid Build Coastguard Worker return -1;
837*38e8c45fSAndroid Build Coastguard Worker }
838*38e8c45fSAndroid Build Coastguard Worker
canAddSample(const Batch & batch,const InputMessage * msg)839*38e8c45fSAndroid Build Coastguard Worker bool InputConsumer::canAddSample(const Batch& batch, const InputMessage* msg) {
840*38e8c45fSAndroid Build Coastguard Worker const InputMessage& head = batch.samples[0];
841*38e8c45fSAndroid Build Coastguard Worker uint32_t pointerCount = msg->body.motion.pointerCount;
842*38e8c45fSAndroid Build Coastguard Worker if (head.body.motion.pointerCount != pointerCount ||
843*38e8c45fSAndroid Build Coastguard Worker head.body.motion.action != msg->body.motion.action) {
844*38e8c45fSAndroid Build Coastguard Worker return false;
845*38e8c45fSAndroid Build Coastguard Worker }
846*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pointerCount; i++) {
847*38e8c45fSAndroid Build Coastguard Worker if (head.body.motion.pointers[i].properties != msg->body.motion.pointers[i].properties) {
848*38e8c45fSAndroid Build Coastguard Worker return false;
849*38e8c45fSAndroid Build Coastguard Worker }
850*38e8c45fSAndroid Build Coastguard Worker }
851*38e8c45fSAndroid Build Coastguard Worker return true;
852*38e8c45fSAndroid Build Coastguard Worker }
853*38e8c45fSAndroid Build Coastguard Worker
findSampleNoLaterThan(const Batch & batch,nsecs_t time)854*38e8c45fSAndroid Build Coastguard Worker ssize_t InputConsumer::findSampleNoLaterThan(const Batch& batch, nsecs_t time) {
855*38e8c45fSAndroid Build Coastguard Worker size_t numSamples = batch.samples.size();
856*38e8c45fSAndroid Build Coastguard Worker size_t index = 0;
857*38e8c45fSAndroid Build Coastguard Worker while (index < numSamples && batch.samples[index].body.motion.eventTime <= time) {
858*38e8c45fSAndroid Build Coastguard Worker index += 1;
859*38e8c45fSAndroid Build Coastguard Worker }
860*38e8c45fSAndroid Build Coastguard Worker return ssize_t(index) - 1;
861*38e8c45fSAndroid Build Coastguard Worker }
862*38e8c45fSAndroid Build Coastguard Worker
dump() const863*38e8c45fSAndroid Build Coastguard Worker std::string InputConsumer::dump() const {
864*38e8c45fSAndroid Build Coastguard Worker std::string out;
865*38e8c45fSAndroid Build Coastguard Worker out = out + "mResampleTouch = " + toString(mResampleTouch) + "\n";
866*38e8c45fSAndroid Build Coastguard Worker out = out + "mChannel = " + mChannel->getName() + "\n";
867*38e8c45fSAndroid Build Coastguard Worker out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n";
868*38e8c45fSAndroid Build Coastguard Worker if (mMsgDeferred) {
869*38e8c45fSAndroid Build Coastguard Worker out = out + "mMsg : " + ftl::enum_string(mMsg.header.type) + "\n";
870*38e8c45fSAndroid Build Coastguard Worker }
871*38e8c45fSAndroid Build Coastguard Worker out += "Batches:\n";
872*38e8c45fSAndroid Build Coastguard Worker for (const Batch& batch : mBatches) {
873*38e8c45fSAndroid Build Coastguard Worker out += " Batch:\n";
874*38e8c45fSAndroid Build Coastguard Worker for (const InputMessage& msg : batch.samples) {
875*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf(" Message %" PRIu32 ": %s ", msg.header.seq,
876*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(msg.header.type).c_str());
877*38e8c45fSAndroid Build Coastguard Worker switch (msg.header.type) {
878*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::KEY: {
879*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("action=%s keycode=%" PRId32,
880*38e8c45fSAndroid Build Coastguard Worker KeyEvent::actionToString(
881*38e8c45fSAndroid Build Coastguard Worker msg.body.key.action),
882*38e8c45fSAndroid Build Coastguard Worker msg.body.key.keyCode);
883*38e8c45fSAndroid Build Coastguard Worker break;
884*38e8c45fSAndroid Build Coastguard Worker }
885*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::MOTION: {
886*38e8c45fSAndroid Build Coastguard Worker out = out + "action=" + MotionEvent::actionToString(msg.body.motion.action);
887*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
888*38e8c45fSAndroid Build Coastguard Worker const float x = msg.body.motion.pointers[i].coords.getX();
889*38e8c45fSAndroid Build Coastguard Worker const float y = msg.body.motion.pointers[i].coords.getY();
890*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("\n Pointer %" PRIu32
891*38e8c45fSAndroid Build Coastguard Worker " : x=%.1f y=%.1f",
892*38e8c45fSAndroid Build Coastguard Worker i, x, y);
893*38e8c45fSAndroid Build Coastguard Worker }
894*38e8c45fSAndroid Build Coastguard Worker break;
895*38e8c45fSAndroid Build Coastguard Worker }
896*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FINISHED: {
897*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("handled=%s, consumeTime=%" PRId64,
898*38e8c45fSAndroid Build Coastguard Worker toString(msg.body.finished.handled),
899*38e8c45fSAndroid Build Coastguard Worker msg.body.finished.consumeTime);
900*38e8c45fSAndroid Build Coastguard Worker break;
901*38e8c45fSAndroid Build Coastguard Worker }
902*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FOCUS: {
903*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("hasFocus=%s",
904*38e8c45fSAndroid Build Coastguard Worker toString(msg.body.focus.hasFocus));
905*38e8c45fSAndroid Build Coastguard Worker break;
906*38e8c45fSAndroid Build Coastguard Worker }
907*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::CAPTURE: {
908*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("hasCapture=%s",
909*38e8c45fSAndroid Build Coastguard Worker toString(msg.body.capture
910*38e8c45fSAndroid Build Coastguard Worker .pointerCaptureEnabled));
911*38e8c45fSAndroid Build Coastguard Worker break;
912*38e8c45fSAndroid Build Coastguard Worker }
913*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::DRAG: {
914*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("x=%.1f y=%.1f, isExiting=%s",
915*38e8c45fSAndroid Build Coastguard Worker msg.body.drag.x, msg.body.drag.y,
916*38e8c45fSAndroid Build Coastguard Worker toString(msg.body.drag.isExiting));
917*38e8c45fSAndroid Build Coastguard Worker break;
918*38e8c45fSAndroid Build Coastguard Worker }
919*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TIMELINE: {
920*38e8c45fSAndroid Build Coastguard Worker const nsecs_t gpuCompletedTime =
921*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline
922*38e8c45fSAndroid Build Coastguard Worker .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME];
923*38e8c45fSAndroid Build Coastguard Worker const nsecs_t presentTime =
924*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME];
925*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("inputEventId=%" PRId32
926*38e8c45fSAndroid Build Coastguard Worker ", gpuCompletedTime=%" PRId64
927*38e8c45fSAndroid Build Coastguard Worker ", presentTime=%" PRId64,
928*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.eventId, gpuCompletedTime,
929*38e8c45fSAndroid Build Coastguard Worker presentTime);
930*38e8c45fSAndroid Build Coastguard Worker break;
931*38e8c45fSAndroid Build Coastguard Worker }
932*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TOUCH_MODE: {
933*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf("isInTouchMode=%s",
934*38e8c45fSAndroid Build Coastguard Worker toString(msg.body.touchMode.isInTouchMode));
935*38e8c45fSAndroid Build Coastguard Worker break;
936*38e8c45fSAndroid Build Coastguard Worker }
937*38e8c45fSAndroid Build Coastguard Worker }
938*38e8c45fSAndroid Build Coastguard Worker out += "\n";
939*38e8c45fSAndroid Build Coastguard Worker }
940*38e8c45fSAndroid Build Coastguard Worker }
941*38e8c45fSAndroid Build Coastguard Worker if (mBatches.empty()) {
942*38e8c45fSAndroid Build Coastguard Worker out += " <empty>\n";
943*38e8c45fSAndroid Build Coastguard Worker }
944*38e8c45fSAndroid Build Coastguard Worker out += "mSeqChains:\n";
945*38e8c45fSAndroid Build Coastguard Worker for (const SeqChain& chain : mSeqChains) {
946*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf(" chain: seq = %" PRIu32 " chain=%" PRIu32, chain.seq,
947*38e8c45fSAndroid Build Coastguard Worker chain.chain);
948*38e8c45fSAndroid Build Coastguard Worker }
949*38e8c45fSAndroid Build Coastguard Worker if (mSeqChains.empty()) {
950*38e8c45fSAndroid Build Coastguard Worker out += " <empty>\n";
951*38e8c45fSAndroid Build Coastguard Worker }
952*38e8c45fSAndroid Build Coastguard Worker out += "mConsumeTimes:\n";
953*38e8c45fSAndroid Build Coastguard Worker for (const auto& [seq, consumeTime] : mConsumeTimes) {
954*38e8c45fSAndroid Build Coastguard Worker out += android::base::StringPrintf(" seq = %" PRIu32 " consumeTime = %" PRId64, seq,
955*38e8c45fSAndroid Build Coastguard Worker consumeTime);
956*38e8c45fSAndroid Build Coastguard Worker }
957*38e8c45fSAndroid Build Coastguard Worker if (mConsumeTimes.empty()) {
958*38e8c45fSAndroid Build Coastguard Worker out += " <empty>\n";
959*38e8c45fSAndroid Build Coastguard Worker }
960*38e8c45fSAndroid Build Coastguard Worker return out;
961*38e8c45fSAndroid Build Coastguard Worker }
962*38e8c45fSAndroid Build Coastguard Worker
963*38e8c45fSAndroid Build Coastguard Worker } // namespace android
964